aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/parser')
-rw-r--r--src/qml/parser/qqmljs.g130
-rw-r--r--src/qml/parser/qqmljsast.cpp6
-rw-r--r--src/qml/parser/qqmljsast_p.h30
-rw-r--r--src/qml/parser/qqmljsastfwd_p.h4
-rw-r--r--src/qml/parser/qqmljsastvisitor_p.h2
-rw-r--r--src/qml/parser/qqmljsengine_p.h22
-rw-r--r--src/qml/parser/qqmljslexer.cpp121
-rw-r--r--src/qml/parser/qqmljslexer_p.h10
8 files changed, 232 insertions, 93 deletions
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index 0c947b541b..daaa402ef1 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -58,6 +58,7 @@
%token T_MINUS "-" T_MINUS_EQ "-=" T_MINUS_MINUS "--"
%token T_NEW "new" T_NOT "!" T_NOT_EQ "!="
%token T_NOT_EQ_EQ "!==" T_NUMERIC_LITERAL "numeric literal" T_OR "|"
+%token T_VERSION_NUMBER "version number"
%token T_OR_EQ "|=" T_OR_OR "||" T_PLUS "+"
%token T_PLUS_EQ "+=" T_PLUS_PLUS "++" T_QUESTION "?"
%token T_RBRACE "}" T_RBRACKET "]" T_REMAINDER "%"
@@ -245,6 +246,7 @@
#include <private/qqmljsgrammar_p.h>
#include <private/qqmljsast_p.h>
#include <private/qqmljsengine_p.h>
+#include <private/qqmljsdiagnosticmessage_p.h>
#include <QtCore/qlist.h>
#include <QtCore/qstring.h>
@@ -314,6 +316,7 @@ public:
AST::UiArrayMemberList *UiArrayMemberList;
AST::UiQualifiedId *UiQualifiedId;
AST::UiEnumMemberList *UiEnumMemberList;
+ AST::UiVersionSpecifier *UiVersionSpecifier;
};
public:
@@ -365,7 +368,7 @@ public:
inline DiagnosticMessage diagnosticMessage() const
{
for (const DiagnosticMessage &d : diagnostic_messages) {
- if (d.kind != DiagnosticMessage::Warning)
+ if (d.type != QtWarningMsg)
return d;
}
@@ -376,10 +379,10 @@ public:
{ return diagnosticMessage().message; }
inline int errorLineNumber() const
- { return diagnosticMessage().loc.startLine; }
+ { return diagnosticMessage().line; }
inline int errorColumnNumber() const
- { return diagnosticMessage().loc.startColumn; }
+ { return diagnosticMessage().column; }
protected:
bool parse(int startToken);
@@ -403,11 +406,22 @@ protected:
void pushToken(int token);
int lookaheadToken(Lexer *lexer);
+ static DiagnosticMessage compileError(const AST::SourceLocation &location,
+ const QString &message, QtMsgType kind = QtCriticalMsg)
+ {
+ DiagnosticMessage error;
+ error.line = location.startLine;
+ error.column = location.startColumn;
+ error.message = message;
+ error.type = kind;
+ return error;
+ }
+
void syntaxError(const AST::SourceLocation &location, const char *message) {
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location, QLatin1String(message)));
+ diagnostic_messages.append(compileError(location, QLatin1String(message)));
}
void syntaxError(const AST::SourceLocation &location, const QString &message) {
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location, message));
+ diagnostic_messages.append(compileError(location, message));
}
protected:
@@ -790,20 +804,47 @@ UiImport: UiImportHead T_SEMICOLON;
} break;
./
-UiImport: UiImportHead T_NUMERIC_LITERAL T_AUTOMATIC_SEMICOLON;
-UiImport: UiImportHead T_NUMERIC_LITERAL T_SEMICOLON;
+UiVersionSpecifier: T_VERSION_NUMBER T_DOT T_VERSION_NUMBER;
/.
case $rule_number: {
- sym(1).UiImport->versionToken = loc(2);
+ auto version = new (pool) AST::UiVersionSpecifier(sym(1).dval, sym(3).dval);
+ version->majorToken = loc(1);
+ version->minorToken = loc(3);
+ sym(1).UiVersionSpecifier = version;
+ } break;
+./
+
+
+UiVersionSpecifier: T_VERSION_NUMBER;
+/.
+ case $rule_number: {
+ auto version = new (pool) AST::UiVersionSpecifier(sym(1).dval, 0);
+ version->majorToken = loc(1);
+ sym(1).UiVersionSpecifier = version;
+ } break;
+./
+
+UiImport: UiImportHead UiVersionSpecifier T_AUTOMATIC_SEMICOLON;
+UiImport: UiImportHead UiVersionSpecifier T_SEMICOLON;
+/.
+ case $rule_number: {
+ auto versionToken = loc(2);
+ auto version = sym(2).UiVersionSpecifier;
+ sym(1).UiImport->version = version;
+ if (version->minorToken.isValid()) {
+ versionToken.length += version->minorToken.length + (version->minorToken.offset - versionToken.offset - versionToken.length);
+ }
+ sym(1).UiImport->versionToken = versionToken;
sym(1).UiImport->semicolonToken = loc(3);
} break;
./
-UiImport: UiImportHead T_NUMERIC_LITERAL T_AS QmlIdentifier T_AUTOMATIC_SEMICOLON;
-UiImport: UiImportHead T_NUMERIC_LITERAL T_AS QmlIdentifier T_SEMICOLON;
+UiImport: UiImportHead UiVersionSpecifier T_AS QmlIdentifier T_AUTOMATIC_SEMICOLON;
+UiImport: UiImportHead UiVersionSpecifier T_AS QmlIdentifier T_SEMICOLON;
/.
case $rule_number: {
sym(1).UiImport->versionToken = loc(2);
+ sym(1).UiImport->version = sym(2).UiVersionSpecifier;
sym(1).UiImport->asToken = loc(3);
sym(1).UiImport->importIdToken = loc(4);
sym(1).UiImport->importId = stringRef(4);
@@ -840,7 +881,7 @@ UiImportHead: T_IMPORT ImportId;
if (node) {
node->importToken = loc(1);
} else {
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ diagnostic_messages.append(compileError(loc(1),
QLatin1String("Expected a qualified name id or a string literal")));
return false; // ### remove me
@@ -1110,6 +1151,23 @@ UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T
} break;
./
+UiObjectMember: T_READONLY T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_AUTOMATIC_SEMICOLON;
+UiObjectMember: T_READONLY T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_SEMICOLON;
+/.
+ case $rule_number: {
+ AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(5).UiQualifiedId->finish(), stringRef(7));
+ node->isReadonlyMember = true;
+ node->readonlyToken = loc(1);
+ node->typeModifier = stringRef(3);
+ node->propertyToken = loc(2);
+ node->typeModifierToken = loc(3);
+ node->typeToken = loc(5);
+ node->identifierToken = loc(7);
+ node->semicolonToken = loc(8);
+ sym(1).Node = node;
+ } break;
+./
+
UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_AUTOMATIC_SEMICOLON;
UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_SEMICOLON;
/.
@@ -1221,6 +1279,34 @@ UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T
} break;
./
+UiObjectMember: T_READONLY T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET;
+/.
+ case $rule_number: {
+ AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(5).UiQualifiedId->finish(), stringRef(7));
+ node->isReadonlyMember = true;
+ node->readonlyToken = loc(1);
+ node->typeModifier = stringRef(3);
+ node->propertyToken = loc(2);
+ node->typeModifierToken = loc(3);
+ node->typeToken = loc(5);
+ node->identifierToken = loc(7);
+ node->semicolonToken = loc(8); // insert a fake ';' before ':'
+
+ AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(7));
+ propertyName->identifierToken = loc(7);
+ propertyName->next = 0;
+
+ AST::UiArrayBinding *binding = new (pool) AST::UiArrayBinding(propertyName, sym(10).UiArrayMemberList->finish());
+ binding->colonToken = loc(8);
+ binding->lbracketToken = loc(9);
+ binding->rbracketToken = loc(11);
+
+ node->binding = binding;
+
+ sym(1).Node = node;
+ } break;
+./
+
UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_COLON ExpressionStatementLookahead UiQualifiedId UiObjectInitializer;
/.
case $rule_number: {
@@ -1287,8 +1373,8 @@ UiQualifiedId: MemberExpression;
/.
case $rule_number: {
if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) {
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken,
- QLatin1String("Ignored annotation")));
+ diagnostic_messages.append(compileError(mem->lbracketToken,
+ QLatin1String("Ignored annotation"), QtWarningMsg));
sym(1).Expression = mem->base;
}
@@ -1298,7 +1384,7 @@ UiQualifiedId: MemberExpression;
} else {
sym(1).UiQualifiedId = 0;
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ diagnostic_messages.append(compileError(loc(1),
QLatin1String("Expected a qualified name id")));
return false; // ### recover
@@ -1545,7 +1631,7 @@ RegularExpressionLiteral: T_DIVIDE_EQ;
scan_regexp: {
bool rx = lexer->scanRegExp(prefix);
if (!rx) {
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ diagnostic_messages.append(compileError(location(lexer), lexer->errorMessage()));
return false;
}
@@ -1773,10 +1859,6 @@ PropertyDefinition: PropertyName T_COLON AssignmentExpression_In;
/.
case $rule_number: {
AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(1).PropertyName, sym(3).Expression);
- if (auto *f = asAnonymousFunctionDefinition(sym(3).Expression)) {
- if (!AST::cast<AST::ComputedPropertyName *>(sym(1).PropertyName))
- f->name = driver->newStringRef(sym(1).PropertyName->asString());
- }
if (auto *c = asAnonymousClassDefinition(sym(3).Expression)) {
if (!AST::cast<AST::ComputedPropertyName *>(sym(1).PropertyName))
c->name = driver->newStringRef(sym(1).PropertyName->asString());
@@ -4379,7 +4461,7 @@ ExportSpecifier: IdentifierName T_AS IdentifierName;
yylloc.length = 0;
//const QString msg = QCoreApplication::translate("QQmlParser", "Missing `;'");
- //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg));
+ //diagnostic_messages.append(compileError(yyloc, msg, QtWarningMsg));
first_token = &token_buffer[0];
last_token = &token_buffer[1];
@@ -4416,7 +4498,7 @@ ExportSpecifier: IdentifierName T_AS IdentifierName;
msg = QCoreApplication::translate("QQmlParser", "Syntax error");
else
msg = QCoreApplication::translate("QQmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token]));
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+ diagnostic_messages.append(compileError(token_buffer[0].loc, msg));
action = errorState;
goto _Lcheck_token;
@@ -4447,7 +4529,7 @@ ExportSpecifier: IdentifierName T_AS IdentifierName;
qDebug() << "Parse error, trying to recover (2).";
#endif
const QString msg = QCoreApplication::translate("QQmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk]));
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+ diagnostic_messages.append(compileError(token_buffer[0].loc, msg));
pushToken(*tk);
goto _Lcheck_token;
@@ -4462,7 +4544,7 @@ ExportSpecifier: IdentifierName T_AS IdentifierName;
int a = t_action(errorState, tk);
if (a > 0 && t_action(a, yytoken)) {
const QString msg = QCoreApplication::translate("QQmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk]));
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+ diagnostic_messages.append(compileError(token_buffer[0].loc, msg));
pushToken(tk);
goto _Lcheck_token;
@@ -4470,7 +4552,7 @@ ExportSpecifier: IdentifierName T_AS IdentifierName;
}
const QString msg = QCoreApplication::translate("QQmlParser", "Syntax error");
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+ diagnostic_messages.append(compileError(token_buffer[0].loc, msg));
}
return false;
diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp
index e5817ab763..1bc0e6e364 100644
--- a/src/qml/parser/qqmljsast.cpp
+++ b/src/qml/parser/qqmljsast.cpp
@@ -1472,6 +1472,12 @@ LeftHandSideExpression *LeftHandSideExpression::leftHandSideExpressionCast()
return this;
}
+void UiVersionSpecifier::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+ visitor->endVisit(this);
+}
} } // namespace QQmlJS::AST
QT_END_NAMESPACE
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index b81553776d..606137b67d 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -234,7 +234,6 @@ public:
Kind_PatternProperty,
Kind_PatternPropertyList,
-
Kind_UiArrayBinding,
Kind_UiImport,
Kind_UiObjectBinding,
@@ -251,7 +250,8 @@ public:
Kind_UiSourceElement,
Kind_UiHeaderItemList,
Kind_UiEnumDeclaration,
- Kind_UiEnumMemberList
+ Kind_UiEnumMemberList,
+ Kind_UiVersionSpecifier
};
inline Node() {}
@@ -492,7 +492,30 @@ public:
SourceLocation literalToken;
};
-class QML_PARSER_EXPORT StringLiteral: public LeftHandSideExpression
+class QML_PARSER_EXPORT UiVersionSpecifier : public Node
+{
+public:
+ QQMLJS_DECLARE_AST_NODE(UiVersionSpecifier)
+
+ UiVersionSpecifier(int majorum, int minorum) : majorVersion(majorum), minorVersion(minorum) { kind = K; }
+
+ void accept0(Visitor *visitor) override;
+
+ SourceLocation firstSourceLocation() const override { return majorToken; }
+
+ SourceLocation lastSourceLocation() const override
+ {
+ return minorToken.isValid() ? minorToken : majorToken;
+ }
+
+ // attributes:
+ int majorVersion;
+ int minorVersion;
+ SourceLocation majorToken;
+ SourceLocation minorToken;
+};
+
+class QML_PARSER_EXPORT StringLiteral : public LeftHandSideExpression
{
public:
QQMLJS_DECLARE_AST_NODE(StringLiteral)
@@ -2855,6 +2878,7 @@ public:
SourceLocation asToken;
SourceLocation importIdToken;
SourceLocation semicolonToken;
+ UiVersionSpecifier *version = nullptr;
};
class QML_PARSER_EXPORT UiObjectMember: public Node
diff --git a/src/qml/parser/qqmljsastfwd_p.h b/src/qml/parser/qqmljsastfwd_p.h
index e9caa918d5..6fe108e425 100644
--- a/src/qml/parser/qqmljsastfwd_p.h
+++ b/src/qml/parser/qqmljsastfwd_p.h
@@ -178,8 +178,10 @@ class UiQualifiedId;
class UiHeaderItemList;
class UiEnumDeclaration;
class UiEnumMemberList;
+class UiVersionSpecifier;
-} } // namespace AST
+} // namespace AST
+} // namespace QQmlJS
QT_END_NAMESPACE
diff --git a/src/qml/parser/qqmljsastvisitor_p.h b/src/qml/parser/qqmljsastvisitor_p.h
index 9115449a46..f3732cbba8 100644
--- a/src/qml/parser/qqmljsastvisitor_p.h
+++ b/src/qml/parser/qqmljsastvisitor_p.h
@@ -111,6 +111,7 @@ public:
virtual bool visit(UiQualifiedId *) { return true; }
virtual bool visit(UiEnumDeclaration *) { return true; }
virtual bool visit(UiEnumMemberList *) { return true; }
+ virtual bool visit(UiVersionSpecifier *) { return true; }
virtual void endVisit(UiProgram *) {}
virtual void endVisit(UiImport *) {}
@@ -129,6 +130,7 @@ public:
virtual void endVisit(UiQualifiedId *) {}
virtual void endVisit(UiEnumDeclaration *) {}
virtual void endVisit(UiEnumMemberList *) { }
+ virtual void endVisit(UiVersionSpecifier *) {}
// QQmlJS
virtual bool visit(ThisExpression *) { return true; }
diff --git a/src/qml/parser/qqmljsengine_p.h b/src/qml/parser/qqmljsengine_p.h
index b7f7da9478..6a754fc236 100644
--- a/src/qml/parser/qqmljsengine_p.h
+++ b/src/qml/parser/qqmljsengine_p.h
@@ -91,28 +91,6 @@ public:
}
};
-
-class QML_PARSER_EXPORT DiagnosticMessage
-{
-public:
- enum Kind { Hint, Warning, Error };
-
- DiagnosticMessage() {}
-
- DiagnosticMessage(Kind kind, const AST::SourceLocation &loc, const QString &message)
- : kind(kind), loc(loc), message(message) {}
-
- bool isWarning() const
- { return kind == Warning; }
-
- bool isError() const
- { return kind == Error; }
-
- Kind kind = Error;
- AST::SourceLocation loc;
- QString message;
-};
-
class QML_PARSER_EXPORT Engine
{
Lexer *_lexer;
diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp
index c53b13f64d..165925d2a2 100644
--- a/src/qml/parser/qqmljslexer.cpp
+++ b/src/qml/parser/qqmljslexer.cpp
@@ -42,9 +42,12 @@
#include "qqmljsmemorypool_p.h"
#include "qqmljskeywords_p.h"
+#include <private/qqmljsdiagnosticmessage_p.h>
+
#include <QtCore/qcoreapplication.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qdebug.h>
+#include <QtCore/QScopedValueRollback>
QT_BEGIN_NAMESPACE
Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
@@ -269,16 +272,29 @@ int Lexer::lex()
++_bracesCount;
Q_FALLTHROUGH();
case T_SEMICOLON:
+ _importState = ImportState::NoQmlImport;
+ Q_FALLTHROUGH();
case T_QUESTION:
case T_COLON:
case T_TILDE:
_delimited = true;
break;
+ case T_AUTOMATIC_SEMICOLON:
+ case T_AS:
+ _importState = ImportState::NoQmlImport;
+ Q_FALLTHROUGH();
default:
if (isBinop(_tokenKind))
_delimited = true;
break;
+ case T_IMPORT:
+ if (qmlMode() || (_handlingDirectives && previousTokenKind == T_DOT))
+ _importState = ImportState::SawImport;
+ if (isBinop(_tokenKind))
+ _delimited = true;
+ break;
+
case T_IF:
case T_FOR:
case T_WHILE:
@@ -618,6 +634,8 @@ again:
return T_DIVIDE_;
case '.':
+ if (_importState == ImportState::SawImport)
+ return T_DOT;
if (isDecimalDigit(_char.unicode()))
return scanNumber(ch);
if (_char == QLatin1Char('.')) {
@@ -728,7 +746,10 @@ again:
case '7':
case '8':
case '9':
- return scanNumber(ch);
+ if (_importState == ImportState::SawImport)
+ return scanVersionNumber(ch);
+ else
+ return scanNumber(ch);
default: {
uint c = ch.unicode();
@@ -1146,6 +1167,26 @@ int Lexer::scanNumber(QChar ch)
return T_NUMERIC_LITERAL;
}
+int Lexer::scanVersionNumber(QChar ch)
+{
+ if (ch == QLatin1Char('0')) {
+ _tokenValue = 0;
+ return T_VERSION_NUMBER;
+ }
+
+ int acc = 0;
+ acc += ch.digitValue();
+
+ while (_char.isDigit()) {
+ acc *= 10;
+ acc += _char.digitValue();
+ scanChar(); // consume the digit
+ }
+
+ _tokenValue = acc;
+ return T_VERSION_NUMBER;
+}
+
bool Lexer::scanRegExp(RegExpBodyPrefix prefix)
{
_tokenText.resize(0);
@@ -1402,6 +1443,13 @@ static inline bool isUriToken(int token)
bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
{
+ auto setError = [error, this](QString message) {
+ error->message = std::move(message);
+ error->line = tokenStartLine();
+ error->column = tokenStartColumn();
+ };
+
+ QScopedValueRollback<bool> directivesGuard(_handlingDirectives, true);
Q_ASSERT(!_qmlMode);
lex(); // fetch the first token
@@ -1422,9 +1470,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
if (! (directiveName == QLatin1String("pragma") ||
directiveName == QLatin1String("import"))) {
- error->message = QCoreApplication::translate("QQmlParser", "Syntax error");
- error->loc.startLine = tokenStartLine();
- error->loc.startColumn = tokenStartColumn();
+ setError(QCoreApplication::translate("QQmlParser", "Syntax error"));
return false; // not a valid directive name
}
@@ -1432,9 +1478,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
if (directiveName == QLatin1String("pragma")) {
// .pragma library
if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("library"))) {
- error->message = QCoreApplication::translate("QQmlParser", "Syntax error");
- error->loc.startLine = tokenStartLine();
- error->loc.startColumn = tokenStartColumn();
+ setError(QCoreApplication::translate("QQmlParser", "Syntax error"));
return false; // expected `library
}
@@ -1456,20 +1500,15 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
pathOrUri = tokenText();
if (!pathOrUri.endsWith(QLatin1String("js"))) {
- error->message = QCoreApplication::translate("QQmlParser","Imported file must be a script");
- error->loc.startLine = tokenStartLine();
- error->loc.startColumn = tokenStartColumn();
+ setError(QCoreApplication::translate("QQmlParser","Imported file must be a script"));
return false;
}
} else if (_tokenKind == T_IDENTIFIER) {
- // .import T_IDENTIFIER (. T_IDENTIFIER)* T_NUMERIC_LITERAL as T_IDENTIFIER
-
+ // .import T_IDENTIFIER (. T_IDENTIFIER)* T_VERSION_NUMBER . T_VERSION_NUMBER as T_IDENTIFIER
while (true) {
if (!isUriToken(_tokenKind)) {
- error->message = QCoreApplication::translate("QQmlParser","Invalid module URI");
- error->loc.startLine = tokenStartLine();
- error->loc.startColumn = tokenStartColumn();
+ setError(QCoreApplication::translate("QQmlParser","Invalid module URI"));
return false;
}
@@ -1477,9 +1516,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
lex();
if (tokenStartLine() != lineNumber) {
- error->message = QCoreApplication::translate("QQmlParser","Invalid module URI");
- error->loc.startLine = tokenStartLine();
- error->loc.startColumn = tokenStartColumn();
+ setError(QCoreApplication::translate("QQmlParser","Invalid module URI"));
return false;
}
if (_tokenKind != QQmlJSGrammar::T_DOT)
@@ -1489,21 +1526,30 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
lex();
if (tokenStartLine() != lineNumber) {
- error->message = QCoreApplication::translate("QQmlParser","Invalid module URI");
- error->loc.startLine = tokenStartLine();
- error->loc.startColumn = tokenStartColumn();
+ setError(QCoreApplication::translate("QQmlParser","Invalid module URI"));
return false;
}
}
- if (_tokenKind != T_NUMERIC_LITERAL) {
- error->message = QCoreApplication::translate("QQmlParser","Module import requires a version");
- error->loc.startLine = tokenStartLine();
- error->loc.startColumn = tokenStartColumn();
+ if (_tokenKind != T_VERSION_NUMBER) {
+ setError(QCoreApplication::translate("QQmlParser","Module import requires a version"));
return false; // expected the module version number
}
version = tokenText();
+ lex();
+ if (_tokenKind != T_DOT) {
+ setError(QCoreApplication::translate( "QQmlParser", "Module import requires a minor version (missing dot)"));
+ return false; // expected the module version number
+ }
+ version += QLatin1Char('.');
+
+ lex();
+ if (_tokenKind != T_VERSION_NUMBER) {
+ setError(QCoreApplication::translate( "QQmlParser", "Module import requires a minor version (missing number)"));
+ return false; // expected the module version number
+ }
+ version += tokenText();
}
//
@@ -1511,34 +1557,27 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
//
if (! (lex() == T_AS && tokenStartLine() == lineNumber)) {
if (fileImport)
- error->message = QCoreApplication::translate("QQmlParser", "File import requires a qualifier");
+ setError(QCoreApplication::translate("QQmlParser", "File import requires a qualifier"));
else
- error->message = QCoreApplication::translate("QQmlParser", "Module import requires a qualifier");
+ setError(QCoreApplication::translate("QQmlParser", "Module import requires a qualifier"));
if (tokenStartLine() != lineNumber) {
- error->loc.startLine = lineNumber;
- error->loc.startColumn = column;
- } else {
- error->loc.startLine = tokenStartLine();
- error->loc.startColumn = tokenStartColumn();
+ error->line = lineNumber;
+ error->line = column;
}
return false; // expected `as'
}
if (lex() != T_IDENTIFIER || tokenStartLine() != lineNumber) {
if (fileImport)
- error->message = QCoreApplication::translate("QQmlParser", "File import requires a qualifier");
+ setError(QCoreApplication::translate("QQmlParser", "File import requires a qualifier"));
else
- error->message = QCoreApplication::translate("QQmlParser", "Module import requires a qualifier");
- error->loc.startLine = tokenStartLine();
- error->loc.startColumn = tokenStartColumn();
+ setError(QCoreApplication::translate("QQmlParser", "Module import requires a qualifier"));
return false; // expected module name
}
const QString module = tokenText();
if (!module.at(0).isUpper()) {
- error->message = QCoreApplication::translate("QQmlParser","Invalid import qualifier");
- error->loc.startLine = tokenStartLine();
- error->loc.startColumn = tokenStartColumn();
+ setError(QCoreApplication::translate("QQmlParser","Invalid import qualifier"));
return false;
}
@@ -1549,9 +1588,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
}
if (tokenStartLine() != lineNumber) {
- error->message = QCoreApplication::translate("QQmlParser", "Syntax error");
- error->loc.startLine = tokenStartLine();
- error->loc.startColumn = tokenStartColumn();
+ setError(QCoreApplication::translate("QQmlParser", "Syntax error"));
return false; // the directives cannot span over multiple lines
}
diff --git a/src/qml/parser/qqmljslexer_p.h b/src/qml/parser/qqmljslexer_p.h
index 51152bfd6e..e2ee4ae351 100644
--- a/src/qml/parser/qqmljslexer_p.h
+++ b/src/qml/parser/qqmljslexer_p.h
@@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE
namespace QQmlJS {
class Engine;
-class DiagnosticMessage;
+struct DiagnosticMessage;
class Directives;
class QML_PARSER_EXPORT Lexer: public QQmlJSGrammar
@@ -124,6 +124,11 @@ public:
StaticIsKeyword = 0x4
};
+ enum class ImportState {
+ SawImport,
+ NoQmlImport
+ };
+
public:
Lexer(Engine *engine);
@@ -188,6 +193,7 @@ private:
inline void scanChar();
int scanToken();
int scanNumber(QChar ch);
+ int scanVersionNumber(QChar ch);
enum ScanStringMode {
SingleQuote = '\'',
DoubleQuote = '"',
@@ -242,6 +248,7 @@ private:
int _tokenLength;
int _tokenLine;
int _tokenColumn;
+ ImportState _importState = ImportState::NoQmlImport;
bool _validTokenText;
bool _prohibitAutomaticSemicolon;
@@ -253,6 +260,7 @@ private:
bool _skipLinefeed = false;
int _generatorLevel = 0;
bool _staticIsKeyword = false;
+ bool _handlingDirectives = false;
};
} // end of namespace QQmlJS