10#include <private/qqmljsast_p.h>
12#include <QtCore/qstringview.h>
17using namespace Qt::Literals::StringLiterals;
22
23
30
31
32
35 return QStringList() <<
"*.qml";
39
40
41
42
43
44
47 static const QSet<QString> topic_commands{
55 if (!in.open(QIODevice::ReadOnly)) {
56 location.error(QStringLiteral(
"Cannot open QML file '%1'").arg(filePath));
60 QString document = in.readAll();
63 QString newCode = std::move(document);
64 const QStringList pragmas = extractPragmas(newCode);
66 QQmlJS::Engine engine{};
67 QQmlJS::Lexer lexer{&engine};
68 lexer.setCode(newCode, 1);
70 QQmlJS::Parser parser{&engine};
73 QQmlJS::AST::UiProgram *ast = parser.ast();
74 QmlDocVisitor visitor(filePath, newCode, &engine, topic_commands + CodeParser::common_meta_commands,
76 visitor.setSingletonPragmaFound(pragmas.contains(
"singleton"_L1));
77 QQmlJS::AST::Node::accept(ast, &visitor);
79 Location(filePath).warning(
"Could not analyze QML file, output is incomplete.");
81 const auto &messages = parser.diagnosticMessages();
82 for (
const auto &msg : messages) {
83 qCDebug(lcQdoc,
"%s: %d: %d: QML syntax error: %s", qUtf8Printable(filePath),
84 msg.loc.startLine, msg.loc.startColumn, qUtf8Printable(msg.message));
89
90
91
92
95 QChar *data = str.data() + idx;
96 const QChar space(QLatin1Char(
' '));
97 for (
int ii = 0; ii < n; ++ii)
102
103
104
105
106
107
108
109
110
111
112
121
122
123
124
127 static constexpr QLatin1StringView pragma{
"pragma"_L1};
129 qsizetype startOffset = lexer.tokenOffset();
130 qsizetype startLine = lexer.tokenStartLine();
132 int token = lexer.lex();
134 if (token != QQmlJSGrammar::T_IDENTIFIER || lexer.tokenStartLine() != startLine
135 || script.mid(lexer.tokenOffset(), lexer.tokenLength()) != pragma)
140 if (token != QQmlJSGrammar::T_IDENTIFIER || lexer.tokenStartLine() != startLine)
143 const QString pragmaValue{script.mid(lexer.tokenOffset(), lexer.tokenLength()).toString()};
144 const qsizetype endOffset = lexer.tokenLength() + lexer.tokenOffset();
147 if (lexer.tokenStartLine() == startLine)
150 if (pragmaValue ==
"library"_L1) {
154 endOffset - startOffset,
163
164
165
166
169 qsizetype startOffset = lexer.tokenOffset();
170 qsizetype startLine = lexer.tokenStartLine();
172 int token = lexer.lex();
174 if (token != QQmlJSGrammar::T_IDENTIFIER || lexer.tokenStartLine() != startLine)
177 const QString pragmaValue{script.mid(lexer.tokenOffset(), lexer.tokenLength()).toString()};
178 qsizetype endOffset = lexer.tokenLength() + lexer.tokenOffset();
181 if (lexer.tokenStartLine() == startLine)
184 if (pragmaValue ==
"library"_L1 || pragmaValue ==
"singleton"_L1) {
188 endOffset - startOffset,
197
198
199
200
201
202
203
204
208 QQmlJS::Lexer lexer(
nullptr);
209 lexer.setCode(script, 0);
211 int token = lexer.lex();
214 if (token == QQmlJSGrammar::T_DOT) {
215 auto pragmaInfo = processDotPragma(lexer, script);
219 pragmas.append(pragmaInfo->value);
220 replaceWithSpace(script, pragmaInfo->startOffset, pragmaInfo->length);
221 token = pragmaInfo->nextToken;
222 }
else if (token == QQmlJSGrammar::T_PRAGMA) {
223 auto pragmaInfo = processPragma(lexer, script);
227 pragmas.append(pragmaInfo->value);
228 replaceWithSpace(script, pragmaInfo->startOffset, pragmaInfo->length);
229 token = pragmaInfo->nextToken;
The Location class provides a way to mark a location in a file.
QStringList sourceFileNameFilter() override
Returns a string list containing "*.qml".
void parseSourceFile(const Location &location, const QString &filePath, CppCodeParser &) override
Parses the source file at filePath and inserts the contents into the database.
QStringList extractPragmas(QString &script) const
Copy & paste from src/declarative/qml/qdeclarativescriptparser.cpp, then modified to return pragma in...
#define COMMAND_QMLSIGNAL
#define COMMAND_QMLSINGLETONTYPE
#define COMMAND_QMLPROPERTYGROUP
#define COMMAND_QMLPROPERTY
#define COMMAND_QMLATTACHEDPROPERTY
#define COMMAND_QMLBASICTYPE
#define COMMAND_QMLMETHOD
#define COMMAND_QMLVALUETYPE
#define COMMAND_QMLATTACHEDMETHOD
#define COMMAND_QMLATTACHEDSIGNAL
static std::optional< PragmaInfo > processPragma(QQmlJS::Lexer &lexer, const QStringView script)
Processes a "pragma <value>" declaration (QML syntax).
static std::optional< PragmaInfo > processDotPragma(QQmlJS::Lexer &lexer, const QStringView script)
Processes a ".pragma <value>" declaration (JavaScript syntax).
void replaceWithSpace(QString &str, int idx, int n)
Copy and paste from src/declarative/qml/qdeclarativescriptparser.cpp.
Container for the result of processing a pragma declaration.