aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@digia.com>2014-03-21 12:24:22 +0100
committerChristian Kandeler <christian.kandeler@digia.com>2014-03-25 16:12:42 +0100
commitc0e86b13594631188d457e0a360799e7de73777d (patch)
tree07a1d0fde7f4287ba5c27bd6177798b1ffd5147c
parent9ec57f633d8a8dabf75539d07c82617c28943162 (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.cpp6
-rw-r--r--src/lib/corelib/language/asttools.h1
-rw-r--r--src/lib/corelib/language/builtindeclarations.cpp6
-rw-r--r--src/lib/corelib/language/evaluatorscriptclass.cpp3
-rw-r--r--src/lib/corelib/language/filecontextbase.h14
-rw-r--r--src/lib/corelib/language/itemreaderastvisitor.cpp41
-rw-r--r--src/lib/corelib/language/itemreaderastvisitor.h6
-rw-r--r--src/lib/corelib/language/moduleloader.cpp2
-rw-r--r--src/lib/corelib/language/projectresolver.cpp8
-rw-r--r--src/lib/corelib/language/tst_language.cpp10
-rw-r--r--src/lib/corelib/language/value.cpp19
-rw-r--r--src/lib/corelib/language/value.h8
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;