diff options
author | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2014-12-05 16:32:56 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2015-01-08 22:08:19 +0100 |
commit | 9d7b27f5bf44a46707e6d50ebf51ecf73f91dd1b (patch) | |
tree | 69ec84f34655b892c8bc855aa9a378a4bb2716fa /src/qml/compiler/qqmlirbuilder.cpp | |
parent | bede2a3ac794120be65fa50bfbc8ed04082c10e0 (diff) |
Clean up JS .import/.pragma directive scanning
There's a scanner in QQmlJS::Lexer::scanDirectives that can parse those, so
let's get rid of extra parser that operates on a string. Instead this way we
can do the scanning all in one shot, avoid detaching a copy of the source code
string and (most importantly) bring the parser closer to the copy in Qt
Creator, which uses the directives approach to extract imports and pragma.
Change-Id: Iff6eb8d91a45d8a70f383f953115692be48259de
Reviewed-by: Fawzi Mohamed <fawzi.mohamed@theqtcompany.com>
Diffstat (limited to 'src/qml/compiler/qqmlirbuilder.cpp')
-rw-r--r-- | src/qml/compiler/qqmlirbuilder.cpp | 285 |
1 files changed, 39 insertions, 246 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 07ea2a6fff..dc2389c30e 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -216,60 +216,6 @@ static void replaceWithSpace(QString &str, int idx, int n) *data++ = space; } -#define CHECK_LINE if (l.tokenStartLine() != startLine) return; -#define CHECK_TOKEN(t) if (token != QQmlJSGrammar:: t) return; - -static const int uriTokens[] = { - QQmlJSGrammar::T_IDENTIFIER, - QQmlJSGrammar::T_PROPERTY, - QQmlJSGrammar::T_SIGNAL, - QQmlJSGrammar::T_READONLY, - QQmlJSGrammar::T_ON, - QQmlJSGrammar::T_BREAK, - QQmlJSGrammar::T_CASE, - QQmlJSGrammar::T_CATCH, - QQmlJSGrammar::T_CONTINUE, - QQmlJSGrammar::T_DEFAULT, - QQmlJSGrammar::T_DELETE, - QQmlJSGrammar::T_DO, - QQmlJSGrammar::T_ELSE, - QQmlJSGrammar::T_FALSE, - QQmlJSGrammar::T_FINALLY, - QQmlJSGrammar::T_FOR, - QQmlJSGrammar::T_FUNCTION, - QQmlJSGrammar::T_IF, - QQmlJSGrammar::T_IN, - QQmlJSGrammar::T_INSTANCEOF, - QQmlJSGrammar::T_NEW, - QQmlJSGrammar::T_NULL, - QQmlJSGrammar::T_RETURN, - QQmlJSGrammar::T_SWITCH, - QQmlJSGrammar::T_THIS, - QQmlJSGrammar::T_THROW, - QQmlJSGrammar::T_TRUE, - QQmlJSGrammar::T_TRY, - QQmlJSGrammar::T_TYPEOF, - QQmlJSGrammar::T_VAR, - QQmlJSGrammar::T_VOID, - QQmlJSGrammar::T_WHILE, - QQmlJSGrammar::T_CONST, - QQmlJSGrammar::T_DEBUGGER, - QQmlJSGrammar::T_RESERVED_WORD, - QQmlJSGrammar::T_WITH, - - QQmlJSGrammar::EOF_SYMBOL -}; -static inline bool isUriToken(int token) -{ - const int *current = uriTokens; - while (*current != QQmlJSGrammar::EOF_SYMBOL) { - if (*current == token) - return true; - ++current; - } - return false; -} - void Document::collectTypeReferences() { foreach (Object *obj, objects) { @@ -296,198 +242,6 @@ void Document::collectTypeReferences() } } -void Document::extractScriptMetaData(QString &script, QQmlJS::DiagnosticMessage *error) -{ - Q_ASSERT(error); - - const QString js(QLatin1String(".js")); - const QString library(QLatin1String("library")); - - QQmlJS::MemoryPool *pool = jsParserEngine.pool(); - - QQmlJS::Lexer l(0); - l.setCode(script, 0); - - int token = l.lex(); - - while (true) { - if (token != QQmlJSGrammar::T_DOT) - return; - - int startOffset = l.tokenOffset(); - int startLine = l.tokenStartLine(); - int startColumn = l.tokenStartColumn(); - - error->loc.startLine = startLine + 1; // 0-based, adjust to be 1-based - - token = l.lex(); - - CHECK_LINE; - - if (token == QQmlJSGrammar::T_IMPORT) { - - // .import <URI> <Version> as <Identifier> - // .import <file.js> as <Identifier> - - token = l.lex(); - - CHECK_LINE; - QV4::CompiledData::Import *import = pool->New<QV4::CompiledData::Import>(); - - if (token == QQmlJSGrammar::T_STRING_LITERAL) { - - QString file = l.tokenText(); - - if (!file.endsWith(js)) { - error->message = QCoreApplication::translate("QQmlParser","Imported file must be a script"); - error->loc.startColumn = l.tokenStartColumn(); - return; - } - - bool invalidImport = false; - - token = l.lex(); - - if ((token != QQmlJSGrammar::T_AS) || (l.tokenStartLine() != startLine)) { - invalidImport = true; - } else { - token = l.lex(); - - if ((token != QQmlJSGrammar::T_IDENTIFIER) || (l.tokenStartLine() != startLine)) - invalidImport = true; - } - - - if (invalidImport) { - error->message = QCoreApplication::translate("QQmlParser","File import requires a qualifier"); - error->loc.startColumn = l.tokenStartColumn(); - return; - } - - int endOffset = l.tokenLength() + l.tokenOffset(); - - QString importId = script.mid(l.tokenOffset(), l.tokenLength()); - - token = l.lex(); - - if (!importId.at(0).isUpper() || (l.tokenStartLine() == startLine)) { - error->message = QCoreApplication::translate("QQmlParser","Invalid import qualifier"); - error->loc.startColumn = l.tokenStartColumn(); - return; - } - - replaceWithSpace(script, startOffset, endOffset - startOffset); - - import->type = QV4::CompiledData::Import::ImportScript; - import->uriIndex = registerString(file); - import->qualifierIndex = registerString(importId); - import->location.line = startLine; - import->location.column = startColumn; - imports << import; - } else { - // URI - QString uri; - - while (true) { - if (!isUriToken(token)) { - error->message = QCoreApplication::translate("QQmlParser","Invalid module URI"); - error->loc.startColumn = l.tokenStartColumn(); - return; - } - - uri.append(l.tokenText()); - - token = l.lex(); - CHECK_LINE; - if (token != QQmlJSGrammar::T_DOT) - break; - - uri.append(QLatin1Char('.')); - - token = l.lex(); - CHECK_LINE; - } - - if (token != QQmlJSGrammar::T_NUMERIC_LITERAL) { - error->message = QCoreApplication::translate("QQmlParser","Module import requires a version"); - error->loc.startColumn = l.tokenStartColumn(); - return; - } - - int vmaj, vmin; - IRBuilder::extractVersion(QStringRef(&script, l.tokenOffset(), l.tokenLength()), - &vmaj, &vmin); - - bool invalidImport = false; - - token = l.lex(); - - if ((token != QQmlJSGrammar::T_AS) || (l.tokenStartLine() != startLine)) { - invalidImport = true; - } else { - token = l.lex(); - - if ((token != QQmlJSGrammar::T_IDENTIFIER) || (l.tokenStartLine() != startLine)) - invalidImport = true; - } - - - if (invalidImport) { - error->message = QCoreApplication::translate("QQmlParser","Module import requires a qualifier"); - error->loc.startColumn = l.tokenStartColumn(); - return; - } - - int endOffset = l.tokenLength() + l.tokenOffset(); - - QString importId = script.mid(l.tokenOffset(), l.tokenLength()); - - token = l.lex(); - - if (!importId.at(0).isUpper() || (l.tokenStartLine() == startLine)) { - error->message = QCoreApplication::translate("QQmlParser","Invalid import qualifier"); - error->loc.startColumn = l.tokenStartColumn(); - return; - } - - replaceWithSpace(script, startOffset, endOffset - startOffset); - - import->type = QV4::CompiledData::Import::ImportLibrary; - import->uriIndex = registerString(uri); - import->majorVersion = vmaj; - import->minorVersion = vmin; - import->qualifierIndex = registerString(importId); - import->location.line = startLine; - import->location.column = startColumn; - imports << import; - } - } else if (token == QQmlJSGrammar::T_PRAGMA) { - token = l.lex(); - - CHECK_TOKEN(T_IDENTIFIER); - CHECK_LINE; - - QString pragmaValue = script.mid(l.tokenOffset(), l.tokenLength()); - int endOffset = l.tokenLength() + l.tokenOffset(); - - if (pragmaValue == library) { - unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary; - replaceWithSpace(script, startOffset, endOffset - startOffset); - } else { - return; - } - - token = l.lex(); - if (l.tokenStartLine() == startLine) - return; - - } else { - return; - } - } - return; -} - void Document::removeScriptPragmas(QString &script) { const QString pragma(QLatin1String("pragma")); @@ -541,6 +295,45 @@ Document::Document(bool debugMode) { } +ScriptDirectivesCollector::ScriptDirectivesCollector(QQmlJS::Engine *engine, QV4::Compiler::JSUnitGenerator *unitGenerator) + : engine(engine) + , jsGenerator(unitGenerator) + , hasPragmaLibrary(false) +{ +} + +void ScriptDirectivesCollector::pragmaLibrary() +{ + hasPragmaLibrary = true; +} + +void ScriptDirectivesCollector::importFile(const QString &jsfile, const QString &module, int lineNumber, int column) +{ + QV4::CompiledData::Import *import = engine->pool()->New<QV4::CompiledData::Import>(); + import->type = QV4::CompiledData::Import::ImportScript; + import->uriIndex = jsGenerator->registerString(jsfile); + import->qualifierIndex = jsGenerator->registerString(module); + import->location.line = lineNumber; + import->location.column = column; + imports << import; +} + +void ScriptDirectivesCollector::importModule(const QString &uri, const QString &version, const QString &module, int lineNumber, int column) +{ + QV4::CompiledData::Import *import = engine->pool()->New<QV4::CompiledData::Import>(); + import->type = QV4::CompiledData::Import::ImportLibrary; + import->uriIndex = jsGenerator->registerString(uri); + int vmaj; + int vmin; + IRBuilder::extractVersion(QStringRef(&version), &vmaj, &vmin); + import->majorVersion = vmaj; + import->minorVersion = vmin; + import->qualifierIndex = jsGenerator->registerString(module); + import->location.line = lineNumber; + import->location.column = column; + imports << import; +} + IRBuilder::IRBuilder(const QSet<QString> &illegalNames) : illegalNames(illegalNames) , _object(0) |