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
.
dvValueField
(
visitor
,
Fields
::
uri
,
uri
().
toString
());
247
cont
=
cont
&&
self
.
dvValueField
(
visitor
,
Fields
::
designerSupported
,
designerSupported
());
248
cont
=
cont
&&
self
.
dvReferencesField
(
visitor
,
Fields
::
qmltypesFiles
,
m_qmltypesFilePaths
);
249
cont
=
cont
&&
self
.
dvWrapField
(
visitor
,
Fields
::
exports
,
m_exports
);
250
cont
=
cont
&&
self
.
dvWrapField
(
visitor
,
Fields
::
imports
,
m_imports
);
251
cont
=
cont
&&
self
.
dvItemField
(
visitor
,
Fields
::
plugins
, [
this
, &
self
]() {
252
QStringList
cNames
=
classNames
();
253
return
self
.
subListItem
(
List
::
fromQListRef
<
QQmlDirParser
::
Plugin
>(
254
self
.
pathFromOwner
().
withField
(
Fields
::
plugins
),
m_plugins
,
255
[
cNames
](
const
DomItem
&
list
,
const
PathEls
::
PathComponent
&
p
,
256
const
QQmlDirParser
::
Plugin
&
plugin
) {
257
return
list
.
subDataItem
(
p
,
pluginData
(
plugin
,
cNames
));
258
}));
259
});
260
// add qmlfiles as map because this way they are presented the same way as
261
// the qmlfiles in a directory
262
cont
=
cont
&&
self
.
dvItemField
(
visitor
,
Fields
::
qmlFiles
, [
this
, &
self
]() {
263
const
QMap
<
QString
,
QString
>
typeFileMap
=
qmlFiles
();
264
return
self
.
subMapItem
(
Map
(
265
self
.
pathFromOwner
().
withField
(
Fields
::
qmlFiles
),
266
[
typeFileMap
](
const
DomItem
&
map
,
const
QString
&
typeV
) {
267
QString
path
=
typeFileMap
.
value
(
typeV
);
268
if
(
path
.
isEmpty
())
269
return
DomItem
();
270
else
271
return
map
.
subReferencesItem
(
272
PathEls
::
Key
(
typeV
),
273
QList
<
Path
>({
Paths
::
qmlFileObjectPath
(
path
) }));
274
},
275
[
typeFileMap
](
const
DomItem
&) {
276
return
QSet
<
QString
>(
typeFileMap
.
keyBegin
(),
typeFileMap
.
keyEnd
());
277
},
278
QStringLiteral
(u"QList<Reference>")));
279
});
280
cont
=
cont
&&
self
.
dvWrapField
(
visitor
,
Fields
::
autoExports
,
m_autoExports
);
281
return
cont
;
282
}
283
284
QMap
<
QString
,
QString
>
QmldirFile
::
qmlFiles
()
const
285
{
286
// add qmlfiles as map because this way they are presented the same way as
287
// the qmlfiles in a directory which gives them as fileName->list of references to files
288
// this is done only to ensure that they are loaded as dependencies
289
QMap
<
QString
,
QString
>
res
;
290
for
(
const
auto
&
e
:
m_exports
)
291
res
.
insert
(
e
.
typeName
+
QStringLiteral
(u"-") +
e
.
version
.
stringValue
(),
292
e
.
typePath
[2].
headName
());
293
return
res
;
294
}
295
296
JsFile
::
JsFile
(
297
const
QString
&
filePath
,
const
QString
&
code
,
const
QDateTime
&
lastDataUpdateAt
,
298
int
derivedFrom
)
299
:
ExternalOwningItem
(
filePath
,
lastDataUpdateAt
,
Paths
::
qmlFilePath
(
filePath
),
derivedFrom
,
300
code
)
301
{
302
m_engine
=
std
::
make_shared
<
QQmlJS
::
Engine
>();
303
LegacyDirectivesCollector
directivesCollector
(*
this
);
304
m_engine
->
setDirectives
(&
directivesCollector
);
305
306
QQmlJS
::
Lexer
lexer
(
m_engine
.
get
());
307
lexer
.
setCode
(
code
,
/*lineno = */
1,
/*qmlMode=*/
false
);
308
QQmlJS
::
Parser
parser
(
m_engine
.
get
());
309
310
bool
isESM
=
filePath
.
endsWith
(u".mjs",
Qt
::
CaseInsensitive
);
311
bool
isValid
=
isESM
?
parser
.
parseModule
() :
parser
.
parseProgram
();
312
setIsValid
(
isValid
);
313
314
const
auto
diagnostics
=
parser
.
diagnosticMessages
();
315
for
(
const
DiagnosticMessage
&
msg
:
diagnostics
) {
316
addErrorLocal
(
317
std
::
move
(
myParsingErrors
().
errorMessage
(
msg
).
withFile
(
filePath
).
withPath
(
m_path
)));
318
}
319
320
auto
astComments
=
std
::
make_shared
<
AstComments
>(
m_engine
);
321
322
CommentCollector
collector
;
323
collector
.
collectComments
(
m_engine
,
parser
.
rootNode
(),
astComments
);
324
m_script
=
std
::
make_shared
<
ScriptExpression
>(
code
,
m_engine
,
parser
.
rootNode
(),
astComments
,
325
isESM
?
ScriptExpression
::
ExpressionType
::
ESMCode
326
:
ScriptExpression
::
ExpressionType
::
JSCode
);
327
}
328
329
ErrorGroups
JsFile
::
myParsingErrors
()
330
{
331
static
ErrorGroups
res
= { {
DomItem
::
domErrorGroup
,
NewErrorGroup
(
"JsFile"
),
332
NewErrorGroup
(
"Parsing"
) } };
333
return
res
;
334
}
335
336
bool
JsFile
::
iterateDirectSubpaths
(
const
DomItem
&
self
,
DirectVisitor
visitor
)
const
337
{
338
bool
cont
=
ExternalOwningItem
::
iterateDirectSubpaths
(
self
,
visitor
);
339
cont
=
cont
&&
self
.
dvWrapField
(
visitor
,
Fields
::
fileLocationsTree
,
m_fileLocationsTree
);
340
if
(
m_script
)
341
cont
=
cont
&&
self
.
dvItemField
(
visitor
,
Fields
::
expression
, [
this
, &
self
]() {
342
return
self
.
subOwnerItem
(
PathEls
::
Field
(
Fields
::
expression
),
m_script
);
343
});
344
return
cont
;
345
}
346
347
void
JsFile
::
writeOut
(
const
DomItem
&
self
,
OutWriter
&
ow
)
const
348
{
349
writeOutDirectives
(
self
,
ow
);
350
ow
.
ensureNewline
(2);
351
if
(
DomItem
script
=
self
.
field
(
Fields
::
expression
)) {
352
ow
.
ensureNewline
();
353
script
.
writeOut
(
ow
);
354
}
355
}
356
357
void
JsFile
::
addFileImport
(
const
QString
&
jsfile
,
const
QString
&
module
)
358
{
359
LegacyImport
import
;
360
import
.
fileName
=
jsfile
;
361
import
.
asIdentifier
=
module
;
362
m_imports
.
append
(
std
::
move
(
import
));
363
}
364
365
void
JsFile
::
addModuleImport
(
const
QString
&
uri
,
const
QString
&
version
,
const
QString
&
module
)
366
{
367
LegacyImport
import
;
368
import
.
uri
=
uri
;
369
import
.
version
=
version
;
370
import
.
asIdentifier
=
module
;
371
m_imports
.
append
(
std
::
move
(
import
));
372
}
373
374
void
JsFile
::
LegacyPragmaLibrary
::
writeOut
(
const
DomItem
&
self
,
OutWriter
&
lw
)
const
375
{
376
Q_UNUSED
(
self
);
377
lw
.
write
(u".pragma").
ensureSpace
().
write
(u"library").
ensureNewline
();
378
}
379
380
void
JsFile
::
LegacyImport
::
writeOut
(
const
DomItem
&
self
,
OutWriter
&
lw
)
const
381
{
382
const
auto
fLoc
=
FileLocations
::
treeOf
(
self
);
383
// either filename or module uri must be present
384
Q_ASSERT
(!
fileName
.
isEmpty
() || !
uri
.
isEmpty
());
385
386
lw
.
write
(u".import").
ensureSpace
();
387
if
(!
uri
.
isEmpty
()) {
388
lw
.
write
(
uri
).
ensureSpace
();
389
if
(!
version
.
isEmpty
()) {
390
lw
.
write
(
version
).
ensureSpace
();
391
}
392
}
else
{
393
lw
.
write
(u"\"").
write
(
fileName
).
write
(u"\"").
ensureSpace
();
394
}
395
lw
.
writeRegion
(
fLoc
,
AsTokenRegion
).
ensureSpace
().
write
(
asIdentifier
);
396
397
lw
.
ensureNewline
();
398
}
399
400
/*!
401
* \internal JsFile::writeOutDirectives
402
* \brief Performs writeOut of the .js Directives (.import, .pragma)
403
*
404
* Watch out!
405
* Currently directives in .js files do not have representative AST::Node-s (see QTBUG-119770),
406
* which makes it hard to preserve attached comments during the WriteOut process,
407
* because currently they are being attached to the first AST::Node.
408
* In case when the first AST::Node is absent, they are not collected, hence lost.
409
*/
410
void
JsFile
::
writeOutDirectives
(
const
DomItem
&
self
,
OutWriter
&
ow
)
const
411
{
412
if
(
m_pragmaLibrary
.
has_value
()) {
413
m_pragmaLibrary
->
writeOut
(
self
,
ow
);
414
}
415
for
(
const
auto
&
import
:
m_imports
) {
416
import
.
writeOut
(
self
,
ow
);
417
}
418
}
419
420
std
::
shared_ptr
<
OwningItem
>
QmlFile
::
doCopy
(
const
DomItem
&)
const
421
{
422
auto
res
=
std
::
make_shared
<
QmlFile
>(*
this
);
423
return
res
;
424
}
425
426
/*!
427
\class QmlFile
428
429
A QmlFile, when loaded in a DomEnvironment that has the DomCreationOption::WithSemanticAnalysis,
430
will be lazily constructed. That means that its member m_lazyMembers is uninitialized, and will
431
only be populated when it is accessed (through a getter, a setter or the DomItem interface).
432
433
The reason for the laziness is that the qqmljsscopes are created lazily and at the same time as
434
the Dom QmlFile representations. So instead of eagerly generating all qqmljsscopes when
435
constructing the Dom, the QmlFile itself becomes lazy and will only be populated on demand at
436
the same time as the corresponding qqmljsscopes.
437
438
The QDeferredFactory<QQmlJSScope> will, when the qqmljsscope is populated, take care of
439
populating all fields of the QmlFile.
440
Therefore, population of the QmlFile is done by populating the qqmljsscope.
441
442
*/
443
444
QmlFile
::
QmlFile
(
445
const
QString
&
filePath
,
const
QString
&
code
,
const
QDateTime
&
lastDataUpdateAt
,
446
int
derivedFrom
,
RecoveryOption
option
)
447
:
ExternalOwningItem
(
filePath
,
lastDataUpdateAt
,
Paths
::
qmlFilePath
(
filePath
),
derivedFrom
,
448
code
),
449
m_engine
(
new
QQmlJS
::
Engine
)
450
{
451
QQmlJS
::
Lexer
lexer
(
m_engine
.
get
());
452
lexer
.
setCode
(
code
,
/*lineno = */
1,
/*qmlMode=*/
true
);
453
QQmlJS
::
Parser
parser
(
m_engine
.
get
());
454
if
(
option
==
EnableParserRecovery
) {
455
parser
.
setIdentifierInsertionEnabled
(
true
);
456
parser
.
setIncompleteBindingsEnabled
(
true
);
457
}
458
m_isValid
=
parser
.
parse
();
459
const
auto
diagnostics
=
parser
.
diagnosticMessages
();
460
for
(
const
DiagnosticMessage
&
msg
:
diagnostics
) {
461
addErrorLocal
(
462
std
::
move
(
myParsingErrors
().
errorMessage
(
msg
).
withFile
(
filePath
).
withPath
(
m_path
)));
463
}
464
m_ast
=
parser
.
ast
();
465
}
466
467
ErrorGroups
QmlFile
::
myParsingErrors
()
468
{
469
static
ErrorGroups
res
= { {
DomItem
::
domErrorGroup
,
NewErrorGroup
(
"QmlFile"
),
470
NewErrorGroup
(
"Parsing"
) } };
471
return
res
;
472
}
473
474
bool
QmlFile
::
iterateDirectSubpaths
(
const
DomItem
&
self
,
DirectVisitor
visitor
)
const
475
{
476
auto
&
members
=
lazyMembers
();
477
bool
cont
=
ExternalOwningItem
::
iterateDirectSubpaths
(
self
,
visitor
);
478
cont
=
cont
&&
self
.
dvWrapField
(
visitor
,
Fields
::
components
,
members
.
m_components
);
479
cont
=
cont
&&
self
.
dvWrapField
(
visitor
,
Fields
::
pragmas
,
members
.
m_pragmas
);
480
cont
=
cont
&&
self
.
dvWrapField
(
visitor
,
Fields
::
imports
,
members
.
m_imports
);
481
cont
=
cont
&&
self
.
dvWrapField
(
visitor
,
Fields
::
importScope
,
members
.
m_importScope
);
482
cont
=
cont
483
&&
self
.
dvWrapField
(
visitor
,
Fields
::
fileLocationsTree
,
members
.
m_fileLocationsTree
);
484
cont
=
cont
&&
self
.
dvWrapField
(
visitor
,
Fields
::
comments
,
members
.
m_comments
);
485
cont
=
cont
&&
self
.
dvWrapField
(
visitor
,
Fields
::
astComments
,
members
.
m_astComments
);
486
return
cont
;
487
}
488
489
DomItem
QmlFile
::
field
(
const
DomItem
&
self
,
QStringView
name
)
const
490
{
491
ensurePopulated
();
492
if
(
name
==
Fields
::
components
)
493
return
self
.
wrapField
(
Fields
::
components
,
lazyMembers
().
m_components
);
494
return
DomBase
::
field
(
self
,
name
);
495
}
496
497
void
QmlFile
::
addError
(
const
DomItem
&
self
,
ErrorMessage
&&
msg
)
498
{
499
self
.
containingObject
().
addError
(
std
::
move
(
msg
));
500
}
501
502
void
QmlFile
::
writeOut
(
const
DomItem
&
self
,
OutWriter
&
ow
)
const
503
{
504
ensurePopulated
();
505
for
(
const
DomItem
&
p
:
self
.
field
(
Fields
::
pragmas
).
values
()) {
506
p
.
writeOut
(
ow
);
507
}
508
auto
imports
=
self
.
field
(
Fields
::
imports
).
values
();
509
510
if
(
ow
.
lineWriter
.
options
().
sortImports
) {
511
std
::
stable_sort
(
imports
.
begin
(),
imports
.
end
(),
512
[](
const
DomItem
&
item1
,
const
DomItem
&
item2
) {
513
const
auto
uri1
=
item1
[
Fields
::
uri
].
toString
();
514
const
auto
uri2
=
item2
[
Fields
::
uri
].
toString
();
515
return
uri1
<
uri2
;
516
});
517
}
518
519
for
(
const
DomItem
&
i
:
imports
) {
520
i
.
writeOut
(
ow
);
521
}
522
ow
.
ensureNewline
(2);
523
DomItem
mainC
=
self
.
field
(
Fields
::
components
).
key
(
QString
()).
index
(0);
524
mainC
.
writeOut
(
ow
);
525
}
526
527
std
::
shared_ptr
<
OwningItem
>
GlobalScope
::
doCopy
(
const
DomItem
&
self
)
const
528
{
529
auto
res
=
std
::
make_shared
<
GlobalScope
>(
530
canonicalFilePath
(
self
),
lastDataUpdateAt
(),
revision
());
531
return
res
;
532
}
533
534
bool
GlobalScope
::
iterateDirectSubpaths
(
const
DomItem
&
self
,
DirectVisitor
visitor
)
const
535
{
536
bool
cont
=
ExternalOwningItem
::
iterateDirectSubpaths
(
self
,
visitor
);
537
return
cont
;
538
}
539
540
void
QmltypesFile
::
ensureInModuleIndex
(
const
DomItem
&
self
)
const
541
{
542
auto
it
=
m_uris
.
begin
();
543
auto
end
=
m_uris
.
end
();
544
DomItem
env
=
self
.
environment
();
545
if
(
std
::
shared_ptr
<
DomEnvironment
>
envPtr
=
env
.
ownerAs
<
DomEnvironment
>()) {
546
while
(
it
!=
end
) {
547
QString
uri
=
it
.
key
();
548
for
(
int
majorV
:
it
.
value
()) {
549
auto
mIndex
=
envPtr
->
moduleIndexWithUri
(
env
,
uri
,
majorV
,
EnvLookup
::
Normal
,
550
Changeable
::
Writable
);
551
mIndex
->
addQmltypeFilePath
(
self
.
canonicalPath
());
552
}
553
++
it
;
554
}
555
}
556
}
557
558
bool
QmltypesFile
::
iterateDirectSubpaths
(
const
DomItem
&
self
,
DirectVisitor
visitor
)
const
559
{
560
bool
cont
=
ExternalOwningItem
::
iterateDirectSubpaths
(
self
,
visitor
);
561
cont
=
cont
&&
self
.
dvWrapField
(
visitor
,
Fields
::
components
,
m_components
);
562
cont
=
cont
&&
self
.
dvWrapField
(
visitor
,
Fields
::
exports
,
m_exports
);
563
cont
=
cont
&&
self
.
dvItemField
(
visitor
,
Fields
::
uris
, [
this
, &
self
]() {
564
return
self
.
subMapItem
(
Map
::
fromMapRef
<
QSet
<
int
>>(
565
self
.
pathFromOwner
().
withField
(
Fields
::
uris
),
m_uris
,
566
[](
const
DomItem
&
map
,
const
PathEls
::
PathComponent
&
p
,
const
QSet
<
int
> &
el
) {
567
QList
<
int
>
l
(
el
.
cbegin
(),
el
.
cend
());
568
std
::
sort
(
l
.
begin
(),
l
.
end
());
569
return
map
.
subListItem
(
570
List
::
fromQList
<
int
>(
map
.
pathFromOwner
().
withComponent
(
p
),
l
,
571
[](
const
DomItem
&
list
,
const
PathEls
::
PathComponent
&
p
,
572
int
el
) {
return
list
.
subDataItem
(
p
,
el
); }));
573
}));
574
});
575
cont
=
cont
&&
self
.
dvWrapField
(
visitor
,
Fields
::
imports
,
m_imports
);
576
return
cont
;
577
}
578
579
QmlDirectory
::
QmlDirectory
(
580
const
QString
&
filePath
,
const
QStringList
&
dirList
,
const
QDateTime
&
lastDataUpdateAt
,
581
int
derivedFrom
)
582
:
ExternalOwningItem
(
filePath
,
lastDataUpdateAt
,
Paths
::
qmlDirectoryPath
(
filePath
),
derivedFrom
,
583
dirList
.
join
(
QLatin1Char
(
'\n'
)))
584
{
585
for
(
const
QString
&
f
:
dirList
) {
586
addQmlFilePath
(
f
);
587
}
588
}
589
590
bool
QmlDirectory
::
iterateDirectSubpaths
(
const
DomItem
&
self
,
DirectVisitor
visitor
)
const
591
{
592
bool
cont
=
ExternalOwningItem
::
iterateDirectSubpaths
(
self
,
visitor
);
593
cont
=
cont
&&
self
.
dvWrapField
(
visitor
,
Fields
::
exports
,
m_exports
);
594
cont
=
cont
&&
self
.
dvItemField
(
visitor
,
Fields
::
qmlFiles
, [
this
, &
self
]() ->
DomItem
{
595
QDir
baseDir
(
canonicalFilePath
());
596
return
self
.
subMapItem
(
Map
(
597
self
.
pathFromOwner
().
withField
(
Fields
::
qmlFiles
),
598
[
this
,
baseDir
](
const
DomItem
&
map
,
const
QString
&
key
) ->
DomItem
{
599
QList
<
Path
>
res
;
600
auto
it
=
m_qmlFiles
.
find
(
key
);
601
while
(
it
!=
m_qmlFiles
.
end
() &&
it
.
key
() ==
key
) {
602
res
.
append
(
Paths
::
qmlFilePath
(
603
QFileInfo
(
baseDir
.
filePath
(
it
.
value
())).
canonicalFilePath
()));
604
++
it
;
605
}
606
return
map
.
subReferencesItem
(
PathEls
::
Key
(
key
),
res
);
607
},
608
[
this
](
const
DomItem
&) {
609
auto
keys
=
m_qmlFiles
.
keys
();
610
return
QSet
<
QString
>(
keys
.
begin
(),
keys
.
end
());
611
},
612
u"List<Reference>"_s));
613
});
614
return
cont
;
615
}
616
617
bool
QmlDirectory
::
addQmlFilePath
(
const
QString
&
relativePath
)
618
{
619
static
const
QRegularExpression
qmlFileRegularExpression
{
620
QRegularExpression
::
anchoredPattern
(
621
uR"((?<compName>[a-zA-z0-9_]+)\.(?:qml|qmlannotation|ui\.qml))")
622
};
623
QRegularExpressionMatch
m
=
qmlFileRegularExpression
.
match
(
relativePath
);
624
if
(
m
.
hasMatch
() && !
m_qmlFiles
.
values
(
m
.
captured
(u"compName")).
contains
(
relativePath
)) {
625
m_qmlFiles
.
insert
(
m
.
captured
(u"compName"),
relativePath
);
626
Export
e
;
627
QDir
dir
(
canonicalFilePath
());
628
QFileInfo
fInfo
(
dir
.
filePath
(
relativePath
));
629
e
.
exportSourcePath
=
canonicalPath
();
630
e
.
typeName
=
m
.
captured
(u"compName");
631
e
.
typePath
=
Paths
::
qmlFileObjectPath
(
fInfo
.
canonicalFilePath
());
632
e
.
uri
=
QLatin1String
(
"file://"
) +
canonicalFilePath
();
633
m_exports
.
insert
(
e
.
typeName
,
e
);
634
return
true
;
635
}
636
return
false
;
637
}
638
639
}
// end namespace Dom
640
}
// end namespace QQmlJS
641
642
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:26
NewErrorGroup
#define NewErrorGroup(name)
Definition
qqmldomerrormessage_p.h:44
qtdeclarative
src
qmldom
qqmldomexternalitems.cpp
Generated on
for Qt by
1.14.0