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
m_isValid
=
false
;
501
self
.
containingObject
().
addError
(
std
::
move
(
msg
));
502
}
503
504
void
QmlFile
::
writeOut
(
const
DomItem
&
self
,
OutWriter
&
ow
)
const
505
{
506
ensurePopulated
();
507
for
(
const
DomItem
&
p
:
self
.
field
(
Fields
::
pragmas
).
values
()) {
508
p
.
writeOut
(
ow
);
509
}
510
auto
imports
=
self
.
field
(
Fields
::
imports
).
values
();
511
512
if
(
ow
.
lineWriter
.
options
().
sortImports
) {
513
std
::
stable_sort
(
imports
.
begin
(),
imports
.
end
(),
514
[](
const
DomItem
&
item1
,
const
DomItem
&
item2
) {
515
const
auto
uri1
=
item1
[
Fields
::
uri
].
toString
();
516
const
auto
uri2
=
item2
[
Fields
::
uri
].
toString
();
517
return
uri1
<
uri2
;
518
});
519
}
520
521
for
(
const
DomItem
&
i
:
imports
) {
522
i
.
writeOut
(
ow
);
523
}
524
ow
.
ensureNewline
(2);
525
DomItem
mainC
=
self
.
field
(
Fields
::
components
).
key
(
QString
()).
index
(0);
526
mainC
.
writeOut
(
ow
);
527
}
528
529
std
::
shared_ptr
<
OwningItem
>
GlobalScope
::
doCopy
(
const
DomItem
&
self
)
const
530
{
531
auto
res
=
std
::
make_shared
<
GlobalScope
>(
532
canonicalFilePath
(
self
),
lastDataUpdateAt
(),
revision
());
533
return
res
;
534
}
535
536
bool
GlobalScope
::
iterateDirectSubpaths
(
const
DomItem
&
self
,
DirectVisitor
visitor
)
const
537
{
538
bool
cont
=
ExternalOwningItem
::
iterateDirectSubpaths
(
self
,
visitor
);
539
return
cont
;
540
}
541
542
void
QmltypesFile
::
ensureInModuleIndex
(
const
DomItem
&
self
)
const
543
{
544
auto
it
=
m_uris
.
begin
();
545
auto
end
=
m_uris
.
end
();
546
DomItem
env
=
self
.
environment
();
547
if
(
std
::
shared_ptr
<
DomEnvironment
>
envPtr
=
env
.
ownerAs
<
DomEnvironment
>()) {
548
while
(
it
!=
end
) {
549
QString
uri
=
it
.
key
();
550
for
(
int
majorV
:
it
.
value
()) {
551
auto
mIndex
=
envPtr
->
moduleIndexWithUri
(
env
,
uri
,
majorV
,
EnvLookup
::
Normal
,
552
Changeable
::
Writable
);
553
mIndex
->
addQmltypeFilePath
(
self
.
canonicalPath
());
554
}
555
++
it
;
556
}
557
}
558
}
559
560
bool
QmltypesFile
::
iterateDirectSubpaths
(
const
DomItem
&
self
,
DirectVisitor
visitor
)
const
561
{
562
bool
cont
=
ExternalOwningItem
::
iterateDirectSubpaths
(
self
,
visitor
);
563
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
components
,
m_components
);
564
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
exports
,
m_exports
);
565
cont
=
cont
&&
visitor
(
PathEls
::
Field
(
Fields
::
uris
), [
this
, &
self
]() {
566
return
self
.
subMapItem
(
Map
::
fromMapRef
<
QSet
<
int
>>(
567
self
.
pathFromOwner
().
withField
(
Fields
::
uris
),
m_uris
,
568
[](
const
DomItem
&
map
,
const
PathEls
::
PathComponent
&
p
,
569
const
QSet
<
int
> &
el
) {
570
QList
<
int
>
l
(
el
.
cbegin
(),
el
.
cend
());
571
std
::
sort
(
l
.
begin
(),
l
.
end
());
572
return
map
.
subListItem
(
List
::
fromQList
<
int
>(
573
map
.
pathFromOwner
().
withComponent
(
p
),
l
,
574
[](
const
DomItem
&
list
,
const
PathEls
::
PathComponent
&
p
,
575
int
el
) {
return
list
.
subDataItem
(
p
,
el
); }));
576
}));
577
});
578
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
imports
,
m_imports
);
579
return
cont
;
580
}
581
582
QmlDirectory
::
QmlDirectory
(
583
const
QString
&
filePath
,
const
QStringList
&
dirList
,
const
QDateTime
&
lastDataUpdateAt
,
584
int
derivedFrom
)
585
:
ExternalOwningItem
(
filePath
,
lastDataUpdateAt
,
Paths
::
qmlDirectoryPath
(
filePath
),
derivedFrom
,
586
dirList
.
join
(
QLatin1Char
(
'\n'
)))
587
{
588
for
(
const
QString
&
f
:
dirList
) {
589
addQmlFilePath
(
f
);
590
}
591
}
592
593
bool
QmlDirectory
::
iterateDirectSubpaths
(
const
DomItem
&
self
,
DirectVisitor
visitor
)
const
594
{
595
bool
cont
=
ExternalOwningItem
::
iterateDirectSubpaths
(
self
,
visitor
);
596
cont
=
cont
&&
self
.
invokeVisitorOnField
(
visitor
,
Fields
::
exports
,
m_exports
);
597
cont
=
cont
&&
visitor
(
PathEls
::
Field
(
Fields
::
qmlFiles
), [
this
, &
self
]() ->
DomItem
{
598
QDir
baseDir
(
canonicalFilePath
());
599
return
self
.
subMapItem
(
Map
(
600
self
.
pathFromOwner
().
withField
(
Fields
::
qmlFiles
),
601
[
this
,
baseDir
](
const
DomItem
&
map
,
const
QString
&
key
) ->
DomItem
{
602
QList
<
Path
>
res
;
603
auto
it
=
m_qmlFiles
.
find
(
key
);
604
while
(
it
!=
m_qmlFiles
.
end
() &&
it
.
key
() ==
key
) {
605
res
.
append
(
Paths
::
qmlFilePath
(
606
QFileInfo
(
baseDir
.
filePath
(
it
.
value
()))
607
.
canonicalFilePath
()));
608
++
it
;
609
}
610
return
map
.
subReferencesItem
(
PathEls
::
Key
(
key
),
res
);
611
},
612
[
this
](
const
DomItem
&) {
613
auto
keys
=
m_qmlFiles
.
keys
();
614
return
QSet
<
QString
>(
keys
.
begin
(),
keys
.
end
());
615
},
616
u"List<Reference>"_s));
617
});
618
return
cont
;
619
}
620
621
bool
QmlDirectory
::
addQmlFilePath
(
const
QString
&
relativePath
)
622
{
623
static
const
QRegularExpression
qmlFileRegularExpression
{
624
QRegularExpression
::
anchoredPattern
(
625
uR"((?<compName>[a-zA-z0-9_]+)\.(?:qml|qmlannotation|ui\.qml))")
626
};
627
QRegularExpressionMatch
m
=
qmlFileRegularExpression
.
match
(
relativePath
);
628
if
(
m
.
hasMatch
() && !
m_qmlFiles
.
values
(
m
.
captured
(u"compName")).
contains
(
relativePath
)) {
629
m_qmlFiles
.
insert
(
m
.
captured
(u"compName"),
relativePath
);
630
Export
e
;
631
QDir
dir
(
canonicalFilePath
());
632
QFileInfo
fInfo
(
dir
.
filePath
(
relativePath
));
633
e
.
exportSourcePath
=
canonicalPath
();
634
e
.
typeName
=
m
.
captured
(u"compName");
635
e
.
typePath
=
Paths
::
qmlFileObjectPath
(
fInfo
.
canonicalFilePath
());
636
e
.
uri
=
QLatin1String
(
"file://"
) +
canonicalFilePath
();
637
m_exports
.
insert
(
e
.
typeName
,
e
);
638
return
true
;
639
}
640
return
false
;
641
}
642
643
}
// end namespace Dom
644
}
// end namespace QQmlJS
645
646
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