diff options
author | Joerg Bornemann <joerg.bornemann@digia.com> | 2014-03-21 12:24:22 +0100 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@digia.com> | 2014-03-25 16:12:42 +0100 |
commit | c0e86b13594631188d457e0a360799e7de73777d (patch) | |
tree | 07a1d0fde7f4287ba5c27bd6177798b1ffd5147c | |
parent | 9ec57f633d8a8dabf75539d07c82617c28943162 (diff) |
turn JSSourceValue::m_sourceCode into a QStringRef
Change-Id: Ie79c4dc2cc998558f826133a2a8bf08a73190f2d
Reviewed-by: Christian Kandeler <christian.kandeler@digia.com>
-rw-r--r-- | src/lib/corelib/language/asttools.cpp | 6 | ||||
-rw-r--r-- | src/lib/corelib/language/asttools.h | 1 | ||||
-rw-r--r-- | src/lib/corelib/language/builtindeclarations.cpp | 6 | ||||
-rw-r--r-- | src/lib/corelib/language/evaluatorscriptclass.cpp | 3 | ||||
-rw-r--r-- | src/lib/corelib/language/filecontextbase.h | 14 | ||||
-rw-r--r-- | src/lib/corelib/language/itemreaderastvisitor.cpp | 41 | ||||
-rw-r--r-- | src/lib/corelib/language/itemreaderastvisitor.h | 6 | ||||
-rw-r--r-- | src/lib/corelib/language/moduleloader.cpp | 2 | ||||
-rw-r--r-- | src/lib/corelib/language/projectresolver.cpp | 8 | ||||
-rw-r--r-- | src/lib/corelib/language/tst_language.cpp | 10 | ||||
-rw-r--r-- | src/lib/corelib/language/value.cpp | 19 | ||||
-rw-r--r-- | src/lib/corelib/language/value.h | 8 |
12 files changed, 90 insertions, 34 deletions
diff --git a/src/lib/corelib/language/asttools.cpp b/src/lib/corelib/language/asttools.cpp index c394fc187..f1aec7d9b 100644 --- a/src/lib/corelib/language/asttools.cpp +++ b/src/lib/corelib/language/asttools.cpp @@ -54,5 +54,11 @@ QString textOf(const QString &source, QbsQmlJS::AST::Node *node) node->lastSourceLocation().end() - node->firstSourceLocation().begin()); } +QStringRef textRefOf(const QString &source, QbsQmlJS::AST::Node *node) +{ + const quint32 firstBegin = node->firstSourceLocation().begin(); + return source.midRef(firstBegin, node->lastSourceLocation().end() - firstBegin); +} + } // namespace Internal } // namespace qbs diff --git a/src/lib/corelib/language/asttools.h b/src/lib/corelib/language/asttools.h index cb0f0b852..9a84c2ade 100644 --- a/src/lib/corelib/language/asttools.h +++ b/src/lib/corelib/language/asttools.h @@ -40,6 +40,7 @@ namespace Internal { QStringList toStringList(QbsQmlJS::AST::UiQualifiedId *qid); CodeLocation toCodeLocation(const QString &filePath, QbsQmlJS::AST::SourceLocation location); QString textOf(const QString &source, QbsQmlJS::AST::Node *node); +QStringRef textRefOf(const QString &source, QbsQmlJS::AST::Node *node); } // namespace Internal } // namespace qbs diff --git a/src/lib/corelib/language/builtindeclarations.cpp b/src/lib/corelib/language/builtindeclarations.cpp index b4cf7cda2..4f5e84f7d 100644 --- a/src/lib/corelib/language/builtindeclarations.cpp +++ b/src/lib/corelib/language/builtindeclarations.cpp @@ -83,8 +83,10 @@ void BuiltinDeclarations::setupItemForBuiltinType(Item *item) const if (!value) { JSSourceValuePtr sourceValue = JSSourceValue::create(); sourceValue->setFile(item->file()); - sourceValue->setSourceCode(pd.initialValueSource().isEmpty() ? - QLatin1String("undefined") : pd.initialValueSource()); + static const QString undefinedKeyword = QLatin1String("undefined"); + sourceValue->setSourceCode(pd.initialValueSource().isEmpty() + ? QStringRef(&undefinedKeyword) + : QStringRef(&pd.initialValueSource())); value = sourceValue; } } diff --git a/src/lib/corelib/language/evaluatorscriptclass.cpp b/src/lib/corelib/language/evaluatorscriptclass.cpp index 74677ff56..4b3f11f00 100644 --- a/src/lib/corelib/language/evaluatorscriptclass.cpp +++ b/src/lib/corelib/language/evaluatorscriptclass.cpp @@ -150,6 +150,7 @@ private: // Clone value but without alternatives. JSSourceValuePtr outerValue = JSSourceValue::create(); outerValue->setFile(value->file()); + outerValue->setHasFunctionForm(value->hasFunctionForm()); outerValue->setSourceCode(value->sourceCode()); outerValue->setBaseValue(value->baseValue()); outerValue->setLocation(value->location()); @@ -185,7 +186,7 @@ private: } pushScope(extraScope); const CodeLocation valueLocation = value->location(); - *result = engine->evaluate(value->sourceCode(), valueLocation.fileName(), + *result = engine->evaluate(value->sourceCodeForEvaluation(), valueLocation.fileName(), valueLocation.line()); popScopes(); } diff --git a/src/lib/corelib/language/filecontextbase.h b/src/lib/corelib/language/filecontextbase.h index d56692d8e..2d31b7227 100644 --- a/src/lib/corelib/language/filecontextbase.h +++ b/src/lib/corelib/language/filecontextbase.h @@ -43,6 +43,9 @@ public: void setFilePath(const QString &filePath); QString filePath() const; + void setContent(const QString &content); + const QString &content() const; + void setJsImports(const JsImports &jsImports); JsImports jsImports() const; @@ -59,6 +62,7 @@ protected: FileContextBase(const FileContextBase &other); QString m_filePath; + QString m_content; JsImports m_jsImports; QStringList m_jsExtensions; QStringList m_searchPaths; @@ -74,6 +78,16 @@ inline QString FileContextBase::filePath() const return m_filePath; } +inline void FileContextBase::setContent(const QString &content) +{ + m_content = content; +} + +inline const QString &FileContextBase::content() const +{ + return m_content; +} + inline void FileContextBase::setJsImports(const JsImports &jsImports) { m_jsImports = jsImports; diff --git a/src/lib/corelib/language/itemreaderastvisitor.cpp b/src/lib/corelib/language/itemreaderastvisitor.cpp index d362a677e..bb3ba0c89 100644 --- a/src/lib/corelib/language/itemreaderastvisitor.cpp +++ b/src/lib/corelib/language/itemreaderastvisitor.cpp @@ -53,6 +53,7 @@ ItemReaderASTVisitor::ItemReaderASTVisitor(ItemReader *reader, ItemReaderResult : m_reader(reader) , m_readerResult(result) , m_languageVersion(ImportVersion::fromString(reader->builtins()->languageVersion())) + , m_file(FileContext::create()) , m_item(0) , m_sourceValue(0) { @@ -62,16 +63,24 @@ ItemReaderASTVisitor::~ItemReaderASTVisitor() { } +void ItemReaderASTVisitor::setFilePath(const QString &filePath) +{ + m_file->setFilePath(filePath); +} + +void ItemReaderASTVisitor::setSourceCode(const QString &sourceCode) +{ + m_file->setContent(sourceCode); +} + bool ItemReaderASTVisitor::visit(AST::UiProgram *ast) { Q_UNUSED(ast); m_sourceValue.clear(); - m_file = FileContext::create(); - m_file->m_filePath = m_filePath; m_file->m_searchPaths = m_reader->searchPaths(); if (Q_UNLIKELY(!ast->members->member)) - throw ErrorInfo(Tr::tr("No root item found in %1.").arg(m_filePath)); + throw ErrorInfo(Tr::tr("No root item found in %1.").arg(m_file->filePath())); return true; } @@ -120,7 +129,7 @@ bool ItemReaderASTVisitor::visit(AST::UiImportList *uiImportList) foreach (const QString &searchPath, m_reader->searchPaths()) collectPrototypes(searchPath + QLatin1String("/imports"), QString()); - const QString path = FileInfo::path(m_filePath); + const QString path = FileInfo::path(m_file->filePath()); // files in the same directory are available as prototypes collectPrototypes(path, QString()); @@ -200,7 +209,7 @@ bool ItemReaderASTVisitor::visit(AST::UiImportList *uiImportList) QFileInfo fi(filePath); if (Q_UNLIKELY(!fi.exists())) throw ErrorInfo(Tr::tr("Can't find imported file %0.").arg(filePath), - CodeLocation(m_filePath, import->fileNameToken.startLine, + CodeLocation(m_file->filePath(), import->fileNameToken.startLine, import->fileNameToken.startColumn)); filePath = fi.canonicalFilePath(); if (fi.isDir()) { @@ -215,7 +224,7 @@ bool ItemReaderASTVisitor::visit(AST::UiImportList *uiImportList) m_typeNameToFile.insert(QStringList(as), filePath); } else { throw ErrorInfo(Tr::tr("Can only import .qbs and .js files"), - CodeLocation(m_filePath, import->fileNameToken.startLine, + CodeLocation(m_file->filePath(), import->fileNameToken.startLine, import->fileNameToken.startColumn)); } } @@ -404,7 +413,7 @@ bool ItemReaderASTVisitor::visit(AST::FunctionDeclaration *ast) f.setName(ast->name.toString()); // remove the name - QString funcNoName = textOf(m_sourceCode, ast); + QString funcNoName = textOf(m_file->content(), ast); funcNoName.replace(QRegExp(QLatin1String("^(\\s*function\\s*)\\w*")), QLatin1String("(\\1")); funcNoName.append(QLatin1Char(')')); f.setSourceCode(funcNoName); @@ -419,15 +428,10 @@ bool ItemReaderASTVisitor::visitStatement(AST::Statement *statement) QBS_CHECK(statement); QBS_CHECK(m_sourceValue); - QString sourceCode = textOf(m_sourceCode, statement); - if (AST::cast<AST::Block *>(statement)) { - // rewrite blocks to be able to use return statements in property assignments - sourceCode.prepend(QLatin1String("(function()")); - sourceCode.append(QLatin1String(")()")); + if (AST::cast<AST::Block *>(statement)) m_sourceValue->m_flags |= JSSourceValue::HasFunctionForm; - } - m_sourceValue->setSourceCode(sourceCode); + m_sourceValue->setSourceCode(textRefOf(m_file->content(), statement)); m_sourceValue->setLocation(toCodeLocation(statement->firstSourceLocation())); bool usesBase, usesOuter; @@ -444,7 +448,7 @@ bool ItemReaderASTVisitor::visitStatement(AST::Statement *statement) CodeLocation ItemReaderASTVisitor::toCodeLocation(AST::SourceLocation location) const { - return CodeLocation(m_filePath, location.startLine, location.startColumn); + return CodeLocation(m_file->filePath(), location.startLine, location.startColumn); } Item *ItemReaderASTVisitor::targetItemForBinding(Item *item, @@ -474,7 +478,7 @@ void ItemReaderASTVisitor::checkImportVersion(const AST::SourceLocation &version { if (!versionToken.length) return; - const QString importVersionString = m_sourceCode.mid(versionToken.offset, versionToken.length); + const QString importVersionString = m_file->content().mid(versionToken.offset, versionToken.length); const ImportVersion importVersion = ImportVersion::fromString(importVersionString, toCodeLocation(versionToken)); if (Q_UNLIKELY(importVersion != m_languageVersion)) @@ -624,7 +628,8 @@ private: value = JSSourceValue::create(); value->setFile(conditionalValue->file()); item->setProperty(propertyName, value); - value->setSourceCode(QLatin1String("undefined")); + static const QString undefinedKeyword = QLatin1String("undefined"); + value->setSourceCode(QStringRef(&undefinedKeyword)); } m_alternative.value = conditionalValue; value->addAlternative(m_alternative); @@ -642,7 +647,7 @@ void ItemReaderASTVisitor::handlePropertiesBlock(Item *item, const Item *block) throw ErrorInfo(Tr::tr("Properties.condition must be a value binding."), block->location()); JSSourceValuePtr srcval = value.staticCast<JSSourceValue>(); - const QString condition = srcval->sourceCode(); + const QString condition = srcval->sourceCodeForEvaluation(); PropertiesBlockConverter convertBlock(condition, item, block, &m_readerResult->conditionalValuesPerScopeItem[item]); convertBlock(); diff --git a/src/lib/corelib/language/itemreaderastvisitor.h b/src/lib/corelib/language/itemreaderastvisitor.h index b8800608a..8053d8a33 100644 --- a/src/lib/corelib/language/itemreaderastvisitor.h +++ b/src/lib/corelib/language/itemreaderastvisitor.h @@ -48,8 +48,8 @@ public: ItemReaderASTVisitor(ItemReader *reader, ItemReaderResult *result); ~ItemReaderASTVisitor(); - void setFilePath(const QString &filePath) { m_filePath = filePath; } - void setSourceCode(const QString &sourceCode) { m_sourceCode = sourceCode; } + void setFilePath(const QString &filePath); + void setSourceCode(const QString &sourceCode); bool visit(QbsQmlJS::AST::UiProgram *ast); bool visit(QbsQmlJS::AST::UiImportList *uiImportList); @@ -79,8 +79,6 @@ private: ItemReader *m_reader; ItemReaderResult *m_readerResult; const ImportVersion m_languageVersion; - QString m_filePath; - QString m_sourceCode; FileContextPtr m_file; QHash<QStringList, QString> m_typeNameToFile; Item *m_item; diff --git a/src/lib/corelib/language/moduleloader.cpp b/src/lib/corelib/language/moduleloader.cpp index acb7fcfa2..3fa102c64 100644 --- a/src/lib/corelib/language/moduleloader.cpp +++ b/src/lib/corelib/language/moduleloader.cpp @@ -955,7 +955,7 @@ void ModuleLoader::resolveProbe(Item *parent, Item *probe) m_engine->currentContext()->pushScope(m_evaluator->fileScope(configureScript->file())); foreach (const ProbeProperty &b, probeBindings) scope.setProperty(b.first, b.second); - QScriptValue sv = m_engine->evaluate(configureScript->sourceCode()); + QScriptValue sv = m_engine->evaluate(configureScript->sourceCodeForEvaluation()); if (Q_UNLIKELY(m_engine->hasErrorOrException(sv))) throw ErrorInfo(sv.toString(), configureScript->location()); foreach (const ProbeProperty &b, probeBindings) { diff --git a/src/lib/corelib/language/projectresolver.cpp b/src/lib/corelib/language/projectresolver.cpp index 528be2a8e..47c62318c 100644 --- a/src/lib/corelib/language/projectresolver.cpp +++ b/src/lib/corelib/language/projectresolver.cpp @@ -133,7 +133,7 @@ QString ProjectResolver::verbatimValue(const ValueConstPtr &value) const QString result; if (value && value->type() == Value::JSSourceValueType) { const JSSourceValueConstPtr sourceValue = value.staticCast<const JSSourceValue>(); - result = sourceValue->sourceCode(); + result = sourceValue->sourceCodeForEvaluation(); } return result; } @@ -535,14 +535,14 @@ static QString sourceCodeAsFunction(const JSSourceValueConstPtr &value, const QString args = decl.functionArgumentNames().join(QLatin1String(",")); if (value->hasFunctionForm()) { // Insert the argument list. - QString code = value->sourceCode(); + QString code = value->sourceCodeForEvaluation(); code.insert(10, args); // Remove the function application "()" that has been // added in ItemReaderASTVisitor::visitStatement. return code.left(code.length() - 2); } else { return QLatin1String("(function(") + args + QLatin1String("){return ") - + value->sourceCode() + QLatin1String(";})"); + + value->sourceCode().toString() + QLatin1String(";})"); } } @@ -694,7 +694,7 @@ void ProjectResolver::resolveRuleArtifactBinding(const RuleArtifactPtr &ruleArti JSSourceValuePtr sourceValue = it.value().staticCast<JSSourceValue>(); RuleArtifact::Binding rab; rab.name = name; - rab.code = sourceValue->sourceCode(); + rab.code = sourceValue->sourceCodeForEvaluation(); rab.location = sourceValue->location(); ruleArtifact->bindings += rab; } else { diff --git a/src/lib/corelib/language/tst_language.cpp b/src/lib/corelib/language/tst_language.cpp index 71436c3a3..ff19b8afe 100644 --- a/src/lib/corelib/language/tst_language.cpp +++ b/src/lib/corelib/language/tst_language.cpp @@ -724,17 +724,25 @@ void TestLanguage::invalidBindingInDisabledItem() class JSSourceValueCreator { FileContextPtr m_fileContext; + QList<QString *> m_strings; public: JSSourceValueCreator(const FileContextPtr &fileContext) : m_fileContext(fileContext) { } + ~JSSourceValueCreator() + { + qDeleteAll(m_strings); + } + JSSourceValuePtr create(const QString &sourceCode) { JSSourceValuePtr value = JSSourceValue::create(); value->setFile(m_fileContext); - value->setSourceCode(sourceCode); + QString *str = new QString(sourceCode); + m_strings += str; + value->setSourceCode(QStringRef(str)); return value; } }; diff --git a/src/lib/corelib/language/value.cpp b/src/lib/corelib/language/value.cpp index f9e64182f..806905d5c 100644 --- a/src/lib/corelib/language/value.cpp +++ b/src/lib/corelib/language/value.cpp @@ -57,6 +57,25 @@ JSSourceValue::~JSSourceValue() { } +QString JSSourceValue::sourceCodeForEvaluation() const +{ + if (!hasFunctionForm()) + return m_sourceCode.toString(); + + // rewrite blocks to be able to use return statements in property assignments + static const QString prefix = "(function()"; + static const QString suffix = ")()"; + return prefix + m_sourceCode.toString() + suffix; +} + +void JSSourceValue::setHasFunctionForm(bool b) +{ + if (b) + m_flags |= HasFunctionForm; + else + m_flags &= ~HasFunctionForm; +} + ItemValue::ItemValue(Item *item) : Value(ItemValueType) diff --git a/src/lib/corelib/language/value.h b/src/lib/corelib/language/value.h index c8c83b35d..ca3e6fcc1 100644 --- a/src/lib/corelib/language/value.h +++ b/src/lib/corelib/language/value.h @@ -91,8 +91,9 @@ public: void apply(ValueHandler *handler) { handler->handle(this); } - void setSourceCode(const QString &sourceCode) { m_sourceCode = sourceCode; } - const QString &sourceCode() const { return m_sourceCode; } + void setSourceCode(const QStringRef &sourceCode) { m_sourceCode = sourceCode; } + const QStringRef &sourceCode() const { return m_sourceCode; } + QString sourceCodeForEvaluation() const; void setLocation(const CodeLocation &location) { m_location = location; } CodeLocation location() const { return m_location; } @@ -103,6 +104,7 @@ public: bool sourceUsesBase() const { return m_flags.testFlag(SourceUsesBase); } bool sourceUsesOuter() const { return m_flags.testFlag(SourceUsesOuter); } bool hasFunctionForm() const { return m_flags.testFlag(HasFunctionForm); } + void setHasFunctionForm(bool b); const JSSourceValuePtr &baseValue() const { return m_baseValue; } void setBaseValue(const JSSourceValuePtr &v) { m_baseValue = v; } @@ -119,7 +121,7 @@ public: void addAlternative(const Alternative &alternative) { m_alternatives.append(alternative); } private: - QString m_sourceCode; + QStringRef m_sourceCode; CodeLocation m_location; FileContextPtr m_file; Flags m_flags; |