Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmldomexternalitems.cpp
Go to the documentation of this file.
1
// Copyright (C) 2020 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4
#
include
"qqmldomtop_p.h"
5
#
include
"qqmldomoutwriter_p.h"
6
#
include
"qqmldomcomments_p.h"
7
#
include
"qqmldommock_p.h"
8
#
include
"qqmldomelements_p.h"
9
#
include
"qqmldom_utils_p.h"
10
11
#
include
<
QtQml
/
private
/
qqmljslexer_p
.
h
>
12
#
include
<
QtQml
/
private
/
qqmljsparser_p
.
h
>
13
#
include
<
QtQml
/
private
/
qqmljsengine_p
.
h
>
14
#
include
<
QtQml
/
private
/
qqmljsastvisitor_p
.
h
>
15
#
include
<
QtQml
/
private
/
qqmljsast_p
.
h
>
16
#
include
<
QtCore
/
QDir
>
17
#
include
<
QtCore
/
QScopeGuard
>
18
#
include
<
QtCore
/
QFileInfo
>
19
#
include
<
QtCore
/
QRegularExpressionMatch
>
20
21
#
include
<
algorithm
>
22
23
QT_BEGIN_NAMESPACE
24
25
using
namespace
Qt::StringLiterals;
26
27
namespace
QQmlJS
{
28
namespace
Dom
{
29
30
ExternalOwningItem
::
ExternalOwningItem
(
31
const
QString
&
filePath
,
const
QDateTime
&
lastDataUpdateAt
,
const
Path
&
path
,
32
int
derivedFrom
,
const
QString
&
code
)
33
:
OwningItem
(
derivedFrom
,
lastDataUpdateAt
),
34
m_canonicalFilePath
(
filePath
),
35
m_code
(
code
),
36
m_path
(
path
)
37
{}
38
39
QString
ExternalOwningItem
::
canonicalFilePath
(
const
DomItem
&)
const
40
{
41
return
m_canonicalFilePath
;
42
}
43
44
QString
ExternalOwningItem
::
canonicalFilePath
()
const
45
{
46
return
m_canonicalFilePath
;
47
}
48
49
Path
ExternalOwningItem
::
canonicalPath
(
const
DomItem
&)
const
50
{
51
return
m_path
;
52
}
53
54
Path
ExternalOwningItem
::
canonicalPath
()
const
55
{
56
return
m_path
;
57
}
58
59
ErrorGroups
QmldirFile
::
myParsingErrors
()
60
{
61
static
ErrorGroups
res
= { {
DomItem
::
domErrorGroup
,
NewErrorGroup
(
"Qmldir"
),
62
NewErrorGroup
(
"Parsing"
) } };
63
return
res
;
64
}
65
66
std
::
shared_ptr
<
QmldirFile
>
QmldirFile
::
fromPathAndCode
(
const
QString
&
path
,
const
QString
&
code
)
67
{
68
QString
canonicalFilePath
=
QFileInfo
(
path
).
canonicalFilePath
();
69
70
QDateTime
dataUpdate
=
QDateTime
::
currentDateTimeUtc
();
71
auto
res
=
std
::
make_shared
<
QmldirFile
>(
canonicalFilePath
,
code
,
dataUpdate
);
72
73
if
(
canonicalFilePath
.
isEmpty
() && !
path
.
isEmpty
())
74
res
->
addErrorLocal
(
75
myParsingErrors
().
error
(
tr
(
"QmldirFile started from invalid path '%1'"
).
arg
(
path
)));
76
res
->
parse
();
77
return
res
;
78
}
79
80
void
QmldirFile
::
parse
()
81
{
82
if
(
canonicalFilePath
().
isEmpty
()) {
83
addErrorLocal
(
myParsingErrors
().
error
(
tr
(
"canonicalFilePath is empty"
)));
84
setIsValid
(
false
);
85
}
else
{
86
m_qmldir
.
parse
(
m_code
);
87
setFromQmldir
();
88
}
89
}
90
91
void
QmldirFile
::
setFromQmldir
()
92
{
93
m_uri
=
QmlUri
::
fromUriString
(
m_qmldir
.
typeNamespace
());
94
if
(
m_uri
.
isValid
())
95
m_uri
=
QmlUri
::
fromDirectoryString
(
canonicalFilePath
());
96
Path
exportsPath
=
Path
::
fromField
(
Fields
::
exports
);
97
QDir
baseDir
=
QFileInfo
(
canonicalFilePath
()).
dir
();
98
int
majorVersion
=
Version
::
Undefined
;
99
bool
ok
;
100
int
vNr
=
QFileInfo
(
baseDir
.
dirName
()).
suffix
().
toInt
(&
ok
);
101
if
(
ok
&&
vNr
> 0)
// accept 0?
102
majorVersion
=
vNr
;
103
Path
exportSource
=
canonicalPath
();
104
for
(
auto
const
&
el
:
m_qmldir
.
components
()) {
105
QString
exportFilePath
=
baseDir
.
filePath
(
el
.
fileName
);
106
QString
canonicalExportFilePath
=
QFileInfo
(
exportFilePath
).
canonicalFilePath
();
107
if
(
canonicalExportFilePath
.
isEmpty
())
// file does not exist (yet? assuming it might be
108
// created where we expect it)
109
canonicalExportFilePath
=
exportFilePath
;
110
Export
exp
;
111
exp
.
exportSourcePath
=
exportSource
;
112
exp
.
isSingleton
=
el
.
singleton
;
113
exp
.
isInternal
=
el
.
internal
;
114
exp
.
version
=
115
Version
((
el
.
version
.
hasMajorVersion
() ?
el
.
version
.
majorVersion
() :
majorVersion
),
116
el
.
version
.
hasMinorVersion
() ?
el
.
version
.
minorVersion
() : 0);
117
exp
.
typeName
=
el
.
typeName
;
118
exp
.
typePath
=
Paths
::
qmlFileObjectPath
(
canonicalExportFilePath
);
119
exp
.
uri
=
uri
().
toString
();
120
m_exports
.
insert
(
exp
.
typeName
,
exp
);
121
if
(
exp
.
version
.
majorVersion
> 0)
122
m_majorVersions
.
insert
(
exp
.
version
.
majorVersion
);
123
}
124
for
(
auto
const
&
el
:
m_qmldir
.
scripts
()) {
125
QString
exportFilePath
=
baseDir
.
filePath
(
el
.
fileName
);
126
QString
canonicalExportFilePath
=
QFileInfo
(
exportFilePath
).
canonicalFilePath
();
127
if
(
canonicalExportFilePath
.
isEmpty
())
// file does not exist (yet? assuming it might be
128
// created where we expect it)
129
canonicalExportFilePath
=
exportFilePath
;
130
Export
exp
;
131
exp
.
exportSourcePath
=
exportSource
;
132
exp
.
isSingleton
=
true
;
133
exp
.
isInternal
=
false
;
134
exp
.
version
=
135
Version
((
el
.
version
.
hasMajorVersion
() ?
el
.
version
.
majorVersion
() :
majorVersion
),
136
el
.
version
.
hasMinorVersion
() ?
el
.
version
.
minorVersion
() : 0);
137
exp
.
typePath
=
Paths
::
jsFilePath
(
canonicalExportFilePath
).
withField
(
Fields
::
rootComponent
);
138
exp
.
uri
=
uri
().
toString
();
139
exp
.
typeName
=
el
.
nameSpace
;
140
m_exports
.
insert
(
exp
.
typeName
,
exp
);
141
if
(
exp
.
version
.
majorVersion
> 0)
142
m_majorVersions
.
insert
(
exp
.
version
.
majorVersion
);
143
}
144
for
(
QQmlDirParser
::
Import
const
&
imp
:
m_qmldir
.
imports
()) {
145
QString
uri
=
imp
.
module
;
146
bool
isAutoImport
=
imp
.
flags
&
QQmlDirParser
::
Import
::
Auto
;
147
Version
v
;
148
if
(
isAutoImport
)
149
v
=
Version
(
majorVersion
,
int
(
Version
::
Latest
));
150
else
{
151
v
=
Version
((
imp
.
version
.
hasMajorVersion
() ?
imp
.
version
.
majorVersion
()
152
:
int
(
Version
::
Latest
)),
153
(
imp
.
version
.
hasMinorVersion
() ?
imp
.
version
.
minorVersion
()
154
:
int
(
Version
::
Latest
)));
155
}
156
m_imports
.
append
(
Import
(
QmlUri
::
fromUriString
(
uri
),
v
));
157
m_autoExports
.
append
(
158
ModuleAutoExport
{
Import
(
QmlUri
::
fromUriString
(
uri
),
v
),
isAutoImport
});
159
}
160
for
(
QQmlDirParser
::
Import
const
&
imp
:
m_qmldir
.
dependencies
()) {
161
QString
uri
=
imp
.
module
;
162
if
(
imp
.
flags
&
QQmlDirParser
::
Import
::
Auto
) {
163
qCDebug
(
QQmlJSDomImporting
) <<
"QmldirFile::setFromQmlDir: ignoring initial version"
164
" 'auto' in depends command, using latest version"
165
" instead."
;
166
}
167
Version
v
=
Version
(
168
(
imp
.
version
.
hasMajorVersion
() ?
imp
.
version
.
majorVersion
() :
int
(
Version
::
Latest
)),
169
(
imp
.
version
.
hasMinorVersion
() ?
imp
.
version
.
minorVersion
()
170
:
int
(
Version
::
Latest
)));
171
m_imports
.
append
(
Import
(
QmlUri
::
fromUriString
(
uri
),
v
));
172
}
173
bool
hasInvalidTypeinfo
=
false
;
174
for
(
auto
const
&
el
:
m_qmldir
.
typeInfos
()) {
175
QString
elStr
=
el
;
176
QFileInfo
elPath
(
elStr
);
177
if
(
elPath
.
isRelative
())
178
elPath
=
QFileInfo
(
baseDir
.
filePath
(
elStr
));
179
QString
typeInfoPath
=
elPath
.
canonicalFilePath
();
180
if
(
typeInfoPath
.
isEmpty
()) {
181
hasInvalidTypeinfo
=
true
;
182
typeInfoPath
=
elPath
.
absoluteFilePath
();
183
}
184
m_qmltypesFilePaths
.
append
(
Paths
::
qmltypesFilePath
(
typeInfoPath
));
185
}
186
if
(
m_qmltypesFilePaths
.
isEmpty
() ||
hasInvalidTypeinfo
) {
187
// add all type info files in the directory...
188
for
(
QFileInfo
const
&
entry
:
189
baseDir
.
entryInfoList
(
QStringList
({
QLatin1String
(
"*.qmltypes"
) }),
190
QDir
::
Filter
::
Readable
|
QDir
::
Filter
::
Files
)) {
191
Path
p
=
Paths
::
qmltypesFilePath
(
entry
.
canonicalFilePath
());
192
if
(!
m_qmltypesFilePaths
.
contains
(
p
))
193
m_qmltypesFilePaths
.
append
(
p
);
194
}
195
}
196
bool
hasErrors
=
false
;
197
for
(
auto
const
&
el
:
m_qmldir
.
errors
(
uri
().
toString
())) {
198
ErrorMessage
msg
=
myParsingErrors
().
errorMessage
(
el
);
199
if
(
msg
.
level
==
ErrorLevel
::
Error
||
msg
.
level
==
ErrorLevel
::
Fatal
)
200
hasErrors
=
true
;
201
addErrorLocal
(
std
::
move
(
msg
));
202
}
203
setIsValid
(!
hasErrors
);
// consider it valid also with errors?
204
m_plugins
=
m_qmldir
.
plugins
();
205
}
206
207
QList
<
ModuleAutoExport
>
QmldirFile
::
autoExports
()
const
208
{
209
return
m_autoExports
;
210
}
211
212
void
QmldirFile
::
setAutoExports
(
const
QList
<
ModuleAutoExport
> &
autoExport
)
213
{
214
m_autoExports
=
autoExport
;
215
}
216
217
void
QmldirFile
::
ensureInModuleIndex
(
const
DomItem
&
self
,
const
QString
&
uri
)
const
218
{
219
// ModuleIndex keeps the various sources of types from a given module uri import
220
// this method ensures that all major versions that are contained in this qmldir
221
// file actually have a ModuleIndex. This is required so that when importing the
222
// latest version the correct "lastest major version" is found, for example for
223
// qml only modules (qmltypes files also register their versions)
224
DomItem
env
=
self
.
environment
();
225
if
(
std
::
shared_ptr
<
DomEnvironment
>
envPtr
=
env
.
ownerAs
<
DomEnvironment
>()) {
226
for
(
int
majorV
:
m_majorVersions
) {
227
auto
mIndex
=
envPtr
->
moduleIndexWithUri
(
env
,
uri
,
majorV
,
EnvLookup
::
Normal
,
228
Changeable
::
Writable
);
229
}
230
}
231
}
232
233
QCborValue
pluginData
(
const
QQmlDirParser::Plugin &pl,
const
QStringList &cNames)
234
{
235
QCborArray names;
236
for
(
const
QString &n : cNames)
237
names.append(n);
238
return
QCborMap({ { QCborValue(QStringView(Fields::name)), pl.name },
239
{ QStringView(Fields::path), pl.path },
240
{ QStringView(Fields::classNames), names } });
241
}
242
243
bool
QmldirFile
::
iterateDirectSubpaths
(
const
DomItem
&
self
,
DirectVisitor
visitor
)
const
244
{
245
bool
cont
=
ExternalOwningItem
::
iterateDirectSubpaths
(
self
,
visitor
);
246
cont
=
cont
&&
self
.
invokeVisitorOnValue
(
visitor
,
PathEls
::
Field
(
Fields
::
uri
),
uri
().
toString
());
247
cont
=
cont
&&
self
.
invokeVisitorOnValue
(
visitor
,
PathEls
::
Field
(
Fields
::
designerSupported
),
248
designerSupported
());
249
cont
=
cont
&&
self
.
invokeVisitorOnReferences
(
visitor
,
Fields
::
qmltypesFiles
,
m_qmltypesFilePaths
);
250
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
exports
,
m_exports
);
251
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
imports
,
m_imports
);
252
cont
=
cont
&&
visitor
(
PathEls
::
Field
(
Fields
::
plugins
), [
this
, &
self
]() {
253
QStringList
cNames
=
classNames
();
254
return
self
.
subListItem
(
List
::
fromQListRef
<
QQmlDirParser
::
Plugin
>(
255
self
.
pathFromOwner
().
withField
(
Fields
::
plugins
),
m_plugins
,
256
[
cNames
](
const
DomItem
&
list
,
const
PathEls
::
PathComponent
&
p
,
257
const
QQmlDirParser
::
Plugin
&
plugin
) {
258
return
list
.
subDataItem
(
p
,
pluginData
(
plugin
,
cNames
));
259
}));
260
});
261
// add qmlfiles as map because this way they are presented the same way as
262
// the qmlfiles in a directory
263
cont
=
cont
&&
visitor
(
PathEls
::
Field
(
Fields
::
qmlFiles
), [
this
, &
self
]() {
264
const
QMap
<
QString
,
QString
>
typeFileMap
=
qmlFiles
();
265
return
self
.
subMapItem
(
Map
(
266
self
.
pathFromOwner
().
withField
(
Fields
::
qmlFiles
),
267
[
typeFileMap
](
const
DomItem
&
map
,
const
QString
&
typeV
) {
268
QString
path
=
typeFileMap
.
value
(
typeV
);
269
if
(
path
.
isEmpty
())
270
return
DomItem
();
271
else
272
return
map
.
subReferencesItem
(
273
PathEls
::
Key
(
typeV
),
274
QList
<
Path
>({
Paths
::
qmlFileObjectPath
(
path
) }));
275
},
276
[
typeFileMap
](
const
DomItem
&) {
277
return
QSet
<
QString
>(
typeFileMap
.
keyBegin
(),
typeFileMap
.
keyEnd
());
278
},
279
QStringLiteral
(u"QList<Reference>")));
280
});
281
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
autoExports
,
m_autoExports
);
282
return
cont
;
283
}
284
285
QMap
<
QString
,
QString
>
QmldirFile
::
qmlFiles
()
const
286
{
287
// add qmlfiles as map because this way they are presented the same way as
288
// the qmlfiles in a directory which gives them as fileName->list of references to files
289
// this is done only to ensure that they are loaded as dependencies
290
QMap
<
QString
,
QString
>
res
;
291
for
(
const
auto
&
e
:
m_exports
)
292
res
.
insert
(
e
.
typeName
+
QStringLiteral
(u"-") +
e
.
version
.
stringValue
(),
293
e
.
typePath
[2].
headName
());
294
return
res
;
295
}
296
297
JsFile
::
JsFile
(
298
const
QString
&
filePath
,
const
QString
&
code
,
const
QDateTime
&
lastDataUpdateAt
,
299
int
derivedFrom
)
300
:
ExternalOwningItem
(
filePath
,
lastDataUpdateAt
,
Paths
::
qmlFilePath
(
filePath
),
derivedFrom
,
301
code
)
302
{
303
m_engine
=
std
::
make_shared
<
QQmlJS
::
Engine
>();
304
LegacyDirectivesCollector
directivesCollector
(*
this
);
305
m_engine
->
setDirectives
(&
directivesCollector
);
306
307
QQmlJS
::
Lexer
lexer
(
m_engine
.
get
());
308
lexer
.
setCode
(
code
,
/*lineno = */
1,
/*qmlMode=*/
false
);
309
QQmlJS
::
Parser
parser
(
m_engine
.
get
());
310
311
bool
isESM
=
filePath
.
endsWith
(u".mjs",
Qt
::
CaseInsensitive
);
312
bool
isValid
=
isESM
?
parser
.
parseModule
() :
parser
.
parseProgram
();
313
setIsValid
(
isValid
);
314
315
const
auto
diagnostics
=
parser
.
diagnosticMessages
();
316
for
(
const
DiagnosticMessage
&
msg
:
diagnostics
) {
317
addErrorLocal
(
318
std
::
move
(
myParsingErrors
().
errorMessage
(
msg
).
withFile
(
filePath
).
withPath
(
m_path
)));
319
}
320
321
auto
astComments
=
std
::
make_shared
<
AstComments
>(
m_engine
);
322
323
CommentCollector
collector
;
324
collector
.
collectComments
(
m_engine
,
parser
.
rootNode
(),
astComments
);
325
m_script
=
std
::
make_shared
<
ScriptExpression
>(
code
,
m_engine
,
parser
.
rootNode
(),
astComments
,
326
isESM
?
ScriptExpression
::
ExpressionType
::
ESMCode
327
:
ScriptExpression
::
ExpressionType
::
JSCode
);
328
}
329
330
ErrorGroups
JsFile
::
myParsingErrors
()
331
{
332
static
ErrorGroups
res
= { {
DomItem
::
domErrorGroup
,
NewErrorGroup
(
"JsFile"
),
333
NewErrorGroup
(
"Parsing"
) } };
334
return
res
;
335
}
336
337
bool
JsFile
::
iterateDirectSubpaths
(
const
DomItem
&
self
,
DirectVisitor
visitor
)
const
338
{
339
bool
cont
=
ExternalOwningItem
::
iterateDirectSubpaths
(
self
,
visitor
);
340
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
fileLocationsTree
,
m_fileLocationsTree
);
341
if
(
m_script
)
342
cont
=
cont
&&
visitor
(
PathEls
::
Field
(
Fields
::
expression
), [
this
, &
self
]() {
343
return
self
.
subOwnerItem
(
PathEls
::
Field
(
Fields
::
expression
),
m_script
);
344
});
345
return
cont
;
346
}
347
348
void
JsFile
::
writeOut
(
const
DomItem
&
self
,
OutWriter
&
ow
)
const
349
{
350
writeOutDirectives
(
self
,
ow
);
351
ow
.
ensureNewline
(2);
352
if
(
DomItem
script
=
self
.
field
(
Fields
::
expression
)) {
353
ow
.
ensureNewline
();
354
script
.
writeOut
(
ow
);
355
}
356
}
357
358
void
JsFile
::
addFileImport
(
const
QString
&
jsfile
,
const
QString
&
module
)
359
{
360
LegacyImport
import
;
361
import
.
fileName
=
jsfile
;
362
import
.
asIdentifier
=
module
;
363
m_imports
.
append
(
std
::
move
(
import
));
364
}
365
366
void
JsFile
::
addModuleImport
(
const
QString
&
uri
,
const
QString
&
version
,
const
QString
&
module
)
367
{
368
LegacyImport
import
;
369
import
.
uri
=
uri
;
370
import
.
version
=
version
;
371
import
.
asIdentifier
=
module
;
372
m_imports
.
append
(
std
::
move
(
import
));
373
}
374
375
void
JsFile
::
LegacyPragmaLibrary
::
writeOut
(
const
DomItem
&
self
,
OutWriter
&
lw
)
const
376
{
377
Q_UNUSED
(
self
);
378
lw
.
write
(u".pragma").
ensureSpace
().
write
(u"library").
ensureNewline
();
379
}
380
381
void
JsFile
::
LegacyImport
::
writeOut
(
const
DomItem
&
self
,
OutWriter
&
lw
)
const
382
{
383
const
auto
fLoc
=
FileLocations
::
treeOf
(
self
);
384
// either filename or module uri must be present
385
Q_ASSERT
(!
fileName
.
isEmpty
() || !
uri
.
isEmpty
());
386
387
lw
.
write
(u".import").
ensureSpace
();
388
if
(!
uri
.
isEmpty
()) {
389
lw
.
write
(
uri
).
ensureSpace
();
390
if
(!
version
.
isEmpty
()) {
391
lw
.
write
(
version
).
ensureSpace
();
392
}
393
}
else
{
394
lw
.
write
(u"\"").
write
(
fileName
).
write
(u"\"").
ensureSpace
();
395
}
396
lw
.
writeRegion
(
fLoc
,
AsTokenRegion
).
ensureSpace
().
write
(
asIdentifier
);
397
398
lw
.
ensureNewline
();
399
}
400
401
/*!
402
* \internal JsFile::writeOutDirectives
403
* \brief Performs writeOut of the .js Directives (.import, .pragma)
404
*
405
* Watch out!
406
* Currently directives in .js files do not have representative AST::Node-s (see QTBUG-119770),
407
* which makes it hard to preserve attached comments during the WriteOut process,
408
* because currently they are being attached to the first AST::Node.
409
* In case when the first AST::Node is absent, they are not collected, hence lost.
410
*/
411
void
JsFile
::
writeOutDirectives
(
const
DomItem
&
self
,
OutWriter
&
ow
)
const
412
{
413
if
(
m_pragmaLibrary
.
has_value
()) {
414
m_pragmaLibrary
->
writeOut
(
self
,
ow
);
415
}
416
for
(
const
auto
&
import
:
m_imports
) {
417
import
.
writeOut
(
self
,
ow
);
418
}
419
}
420
421
std
::
shared_ptr
<
OwningItem
>
QmlFile
::
doCopy
(
const
DomItem
&)
const
422
{
423
auto
res
=
std
::
make_shared
<
QmlFile
>(*
this
);
424
return
res
;
425
}
426
427
/*!
428
\class QmlFile
429
430
A QmlFile, when loaded in a DomEnvironment that has the DomCreationOption::WithSemanticAnalysis,
431
will be lazily constructed. That means that its member m_lazyMembers is uninitialized, and will
432
only be populated when it is accessed (through a getter, a setter or the DomItem interface).
433
434
The reason for the laziness is that the qqmljsscopes are created lazily and at the same time as
435
the Dom QmlFile representations. So instead of eagerly generating all qqmljsscopes when
436
constructing the Dom, the QmlFile itself becomes lazy and will only be populated on demand at
437
the same time as the corresponding qqmljsscopes.
438
439
The QDeferredFactory<QQmlJSScope> will, when the qqmljsscope is populated, take care of
440
populating all fields of the QmlFile.
441
Therefore, population of the QmlFile is done by populating the qqmljsscope.
442
443
*/
444
445
QmlFile
::
QmlFile
(
446
const
QString
&
filePath
,
const
QString
&
code
,
const
QDateTime
&
lastDataUpdateAt
,
447
int
derivedFrom
,
RecoveryOption
option
)
448
:
ExternalOwningItem
(
filePath
,
lastDataUpdateAt
,
Paths
::
qmlFilePath
(
filePath
),
derivedFrom
,
449
code
),
450
m_engine
(
new
QQmlJS
::
Engine
)
451
{
452
QQmlJS
::
Lexer
lexer
(
m_engine
.
get
());
453
lexer
.
setCode
(
code
,
/*lineno = */
1,
/*qmlMode=*/
true
);
454
QQmlJS
::
Parser
parser
(
m_engine
.
get
());
455
if
(
option
==
EnableParserRecovery
) {
456
parser
.
setIdentifierInsertionEnabled
(
true
);
457
parser
.
setIncompleteBindingsEnabled
(
true
);
458
}
459
m_isValid
=
parser
.
parse
();
460
const
auto
diagnostics
=
parser
.
diagnosticMessages
();
461
for
(
const
DiagnosticMessage
&
msg
:
diagnostics
) {
462
addErrorLocal
(
463
std
::
move
(
myParsingErrors
().
errorMessage
(
msg
).
withFile
(
filePath
).
withPath
(
m_path
)));
464
}
465
m_ast
=
parser
.
ast
();
466
}
467
468
ErrorGroups
QmlFile
::
myParsingErrors
()
469
{
470
static
ErrorGroups
res
= { {
DomItem
::
domErrorGroup
,
NewErrorGroup
(
"QmlFile"
),
471
NewErrorGroup
(
"Parsing"
) } };
472
return
res
;
473
}
474
475
bool
QmlFile
::
iterateDirectSubpaths
(
const
DomItem
&
self
,
DirectVisitor
visitor
)
const
476
{
477
auto
&
members
=
lazyMembers
();
478
bool
cont
=
ExternalOwningItem
::
iterateDirectSubpaths
(
self
,
visitor
);
479
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
components
,
members
.
m_components
);
480
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
pragmas
,
members
.
m_pragmas
);
481
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
imports
,
members
.
m_imports
);
482
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
importScope
,
members
.
m_importScope
);
483
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
fileLocationsTree
,
484
members
.
m_fileLocationsTree
);
485
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
comments
,
members
.
m_comments
);
486
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
astComments
,
members
.
m_astComments
);
487
return
cont
;
488
}
489
490
DomItem
QmlFile
::
field
(
const
DomItem
&
self
,
QStringView
name
)
const
491
{
492
ensurePopulated
();
493
if
(
name
==
Fields
::
components
)
494
return
self
.
wrap
(
PathEls
::
Field
(
Fields
::
components
),
lazyMembers
().
m_components
);
495
return
DomBase
::
field
(
self
,
name
);
496
}
497
498
void
QmlFile
::
addError
(
const
DomItem
&
self
,
ErrorMessage
&&
msg
)
499
{
500
self
.
containingObject
().
addError
(
std
::
move
(
msg
));
501
}
502
503
void
QmlFile
::
writeOut
(
const
DomItem
&
self
,
OutWriter
&
ow
)
const
504
{
505
ensurePopulated
();
506
for
(
const
DomItem
&
p
:
self
.
field
(
Fields
::
pragmas
).
values
()) {
507
p
.
writeOut
(
ow
);
508
}
509
auto
imports
=
self
.
field
(
Fields
::
imports
).
values
();
510
511
if
(
ow
.
lineWriter
.
options
().
sortImports
) {
512
std
::
stable_sort
(
imports
.
begin
(),
imports
.
end
(),
513
[](
const
DomItem
&
item1
,
const
DomItem
&
item2
) {
514
const
auto
uri1
=
item1
[
Fields
::
uri
].
toString
();
515
const
auto
uri2
=
item2
[
Fields
::
uri
].
toString
();
516
return
uri1
<
uri2
;
517
});
518
}
519
520
for
(
const
DomItem
&
i
:
imports
) {
521
i
.
writeOut
(
ow
);
522
}
523
ow
.
ensureNewline
(2);
524
DomItem
mainC
=
self
.
field
(
Fields
::
components
).
key
(
QString
()).
index
(0);
525
mainC
.
writeOut
(
ow
);
526
}
527
528
std
::
shared_ptr
<
OwningItem
>
GlobalScope
::
doCopy
(
const
DomItem
&
self
)
const
529
{
530
auto
res
=
std
::
make_shared
<
GlobalScope
>(
531
canonicalFilePath
(
self
),
lastDataUpdateAt
(),
revision
());
532
return
res
;
533
}
534
535
bool
GlobalScope
::
iterateDirectSubpaths
(
const
DomItem
&
self
,
DirectVisitor
visitor
)
const
536
{
537
bool
cont
=
ExternalOwningItem
::
iterateDirectSubpaths
(
self
,
visitor
);
538
return
cont
;
539
}
540
541
void
QmltypesFile
::
ensureInModuleIndex
(
const
DomItem
&
self
)
const
542
{
543
auto
it
=
m_uris
.
begin
();
544
auto
end
=
m_uris
.
end
();
545
DomItem
env
=
self
.
environment
();
546
if
(
std
::
shared_ptr
<
DomEnvironment
>
envPtr
=
env
.
ownerAs
<
DomEnvironment
>()) {
547
while
(
it
!=
end
) {
548
QString
uri
=
it
.
key
();
549
for
(
int
majorV
:
it
.
value
()) {
550
auto
mIndex
=
envPtr
->
moduleIndexWithUri
(
env
,
uri
,
majorV
,
EnvLookup
::
Normal
,
551
Changeable
::
Writable
);
552
mIndex
->
addQmltypeFilePath
(
self
.
canonicalPath
());
553
}
554
++
it
;
555
}
556
}
557
}
558
559
bool
QmltypesFile
::
iterateDirectSubpaths
(
const
DomItem
&
self
,
DirectVisitor
visitor
)
const
560
{
561
bool
cont
=
ExternalOwningItem
::
iterateDirectSubpaths
(
self
,
visitor
);
562
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
components
,
m_components
);
563
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
exports
,
m_exports
);
564
cont
=
cont
&&
visitor
(
PathEls
::
Field
(
Fields
::
uris
), [
this
, &
self
]() {
565
return
self
.
subMapItem
(
Map
::
fromMapRef
<
QSet
<
int
>>(
566
self
.
pathFromOwner
().
withField
(
Fields
::
uris
),
m_uris
,
567
[](
const
DomItem
&
map
,
const
PathEls
::
PathComponent
&
p
,
568
const
QSet
<
int
> &
el
) {
569
QList
<
int
>
l
(
el
.
cbegin
(),
el
.
cend
());
570
std
::
sort
(
l
.
begin
(),
l
.
end
());
571
return
map
.
subListItem
(
List
::
fromQList
<
int
>(
572
map
.
pathFromOwner
().
withComponent
(
p
),
l
,
573
[](
const
DomItem
&
list
,
const
PathEls
::
PathComponent
&
p
,
574
int
el
) {
return
list
.
subDataItem
(
p
,
el
); }));
575
}));
576
});
577
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
imports
,
m_imports
);
578
return
cont
;
579
}
580
581
QmlDirectory
::
QmlDirectory
(
582
const
QString
&
filePath
,
const
QStringList
&
dirList
,
const
QDateTime
&
lastDataUpdateAt
,
583
int
derivedFrom
)
584
:
ExternalOwningItem
(
filePath
,
lastDataUpdateAt
,
Paths
::
qmlDirectoryPath
(
filePath
),
derivedFrom
,
585
dirList
.
join
(
QLatin1Char
(
'\n'
)))
586
{
587
for
(
const
QString
&
f
:
dirList
) {
588
addQmlFilePath
(
f
);
589
}
590
}
591
592
bool
QmlDirectory
::
iterateDirectSubpaths
(
const
DomItem
&
self
,
DirectVisitor
visitor
)
const
593
{
594
bool
cont
=
ExternalOwningItem
::
iterateDirectSubpaths
(
self
,
visitor
);
595
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
exports
,
m_exports
);
596
cont
=
cont
&&
visitor
(
PathEls
::
Field
(
Fields
::
qmlFiles
), [
this
, &
self
]() ->
DomItem
{
597
QDir
baseDir
(
canonicalFilePath
());
598
return
self
.
subMapItem
(
Map
(
599
self
.
pathFromOwner
().
withField
(
Fields
::
qmlFiles
),
600
[
this
,
baseDir
](
const
DomItem
&
map
,
const
QString
&
key
) ->
DomItem
{
601
QList
<
Path
>
res
;
602
auto
it
=
m_qmlFiles
.
find
(
key
);
603
while
(
it
!=
m_qmlFiles
.
end
() &&
it
.
key
() ==
key
) {
604
res
.
append
(
Paths
::
qmlFilePath
(
605
QFileInfo
(
baseDir
.
filePath
(
it
.
value
()))
606
.
canonicalFilePath
()));
607
++
it
;
608
}
609
return
map
.
subReferencesItem
(
PathEls
::
Key
(
key
),
res
);
610
},
611
[
this
](
const
DomItem
&) {
612
auto
keys
=
m_qmlFiles
.
keys
();
613
return
QSet
<
QString
>(
keys
.
begin
(),
keys
.
end
());
614
},
615
u"List<Reference>"_s));
616
});
617
return
cont
;
618
}
619
620
bool
QmlDirectory
::
addQmlFilePath
(
const
QString
&
relativePath
)
621
{
622
static
const
QRegularExpression
qmlFileRegularExpression
{
623
QRegularExpression
::
anchoredPattern
(
624
uR"((?<compName>[a-zA-z0-9_]+)\.(?:qml|qmlannotation|ui\.qml))")
625
};
626
QRegularExpressionMatch
m
=
qmlFileRegularExpression
.
match
(
relativePath
);
627
if
(
m
.
hasMatch
() && !
m_qmlFiles
.
values
(
m
.
captured
(u"compName")).
contains
(
relativePath
)) {
628
m_qmlFiles
.
insert
(
m
.
captured
(u"compName"),
relativePath
);
629
Export
e
;
630
QDir
dir
(
canonicalFilePath
());
631
QFileInfo
fInfo
(
dir
.
filePath
(
relativePath
));
632
e
.
exportSourcePath
=
canonicalPath
();
633
e
.
typeName
=
m
.
captured
(u"compName");
634
e
.
typePath
=
Paths
::
qmlFileObjectPath
(
fInfo
.
canonicalFilePath
());
635
e
.
uri
=
QLatin1String
(
"file://"
) +
canonicalFilePath
();
636
m_exports
.
insert
(
e
.
typeName
,
e
);
637
return
true
;
638
}
639
return
false
;
640
}
641
642
}
// end namespace Dom
643
}
// end namespace QQmlJS
644
645
QT_END_NAMESPACE
QQmlJS::Dom
Definition
qqmljsimportvisitor_p.h:38
QQmlJS::Dom::pluginData
QCborValue pluginData(const QQmlDirParser::Plugin &pl, const QStringList &cNames)
Definition
qqmldomexternalitems.cpp:233
QQmlJS
Definition
qv4bytecodegenerator_p.h:27
NewErrorGroup
#define NewErrorGroup(name)
Definition
qqmldomerrormessage_p.h:44
qtdeclarative
src
qmldom
qqmldomexternalitems.cpp
Generated on
for Qt by
1.16.1