diff options
Diffstat (limited to 'src/qml/parser/qqmljslexer.cpp')
-rw-r--r-- | src/qml/parser/qqmljslexer.cpp | 123 |
1 files changed, 80 insertions, 43 deletions
diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp index c53b13f64d..1e0ac72bd1 100644 --- a/src/qml/parser/qqmljslexer.cpp +++ b/src/qml/parser/qqmljslexer.cpp @@ -39,12 +39,15 @@ #include "qqmljslexer_p.h" #include "qqmljsengine_p.h" -#include "qqmljsmemorypool_p.h" #include "qqmljskeywords_p.h" +#include <private/qqmljsdiagnosticmessage_p.h> +#include <private/qqmljsmemorypool_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 } |