aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@digia.com>2013-07-02 09:53:45 +0200
committerChristian Kandeler <christian.kandeler@digia.com>2013-07-03 17:11:05 +0200
commit97b1e430240845bfa285e6e6574640cbb333b9f8 (patch)
tree5efeeaf3dc652c52603ddf2b7bee325ba128e453
parent8e7fe3fdd97e64893a51dc577f2a45c5a2ff64f2 (diff)
Make built-in JavaScript extensions available on demand.
This entails the following: - Project files can get access to built-in extensions in all contexts via import statements such as "import qbs.TextFile". - In turn, the automatic injection of these extensions in rules and probes no longer happens, i.e. one always has to explicitly import the required extension. Change-Id: Ib1e42c078354c564e417f80dd47897c7f41e7569 Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
-rw-r--r--share/qbs/imports/qbs/probes/PathProbe.qbs1
-rw-r--r--share/qbs/imports/qbs/probes/PkgConfigProbe.qbs1
-rw-r--r--share/qbs/modules/cpp/DarwinGCC.qbs2
-rw-r--r--share/qbs/modules/cpp/ios-gcc.qbs1
-rw-r--r--share/share.qbs1
-rw-r--r--src/lib/buildgraph/buildgraph.cpp2
-rw-r--r--src/lib/buildgraph/jscommandexecutor.cpp9
-rw-r--r--src/lib/buildgraph/projectbuilddata.cpp1
-rw-r--r--src/lib/jsextensions/domxml.cpp2
-rw-r--r--src/lib/jsextensions/domxml.h5
-rw-r--r--src/lib/jsextensions/file.cpp14
-rw-r--r--src/lib/jsextensions/file.h12
-rw-r--r--src/lib/jsextensions/jsextensions.cpp65
-rw-r--r--src/lib/jsextensions/jsextensions.h59
-rw-r--r--src/lib/jsextensions/jsextensions.pri6
-rw-r--r--src/lib/jsextensions/process.cpp2
-rw-r--r--src/lib/jsextensions/process.h3
-rw-r--r--src/lib/jsextensions/textfile.cpp2
-rw-r--r--src/lib/jsextensions/textfile.h4
-rw-r--r--src/lib/language/evaluator.cpp2
-rw-r--r--src/lib/language/filecontext.h10
-rw-r--r--src/lib/language/itemreaderastvisitor.cpp22
-rw-r--r--src/lib/language/language.cpp6
-rw-r--r--src/lib/language/language.h3
-rw-r--r--src/lib/language/moduleloader.cpp8
-rw-r--r--src/lib/language/projectresolver.cpp3
-rw-r--r--src/lib/language/testdata/erroneous/reserved_name_in_import.qbs4
-rw-r--r--src/lib/language/tst_language.cpp2
-rw-r--r--src/lib/lib.qbs2
-rw-r--r--src/lib/tools/persistence.cpp2
-rw-r--r--tests/auto/blackbox/testdata/dependenciesProperty/dependenciesProperty.qbs1
-rw-r--r--tests/auto/blackbox/testdata/productproperties/header.qbs1
-rw-r--r--tests/auto/blackbox/testdata/qt5plugin/plugin.qbs1
-rw-r--r--tests/auto/blackbox/testdata/ruleConditions/modules/narfzort/narfzort.qbs1
-rw-r--r--tests/auto/blackbox/testdata/trackFileTags/after/project.qbs1
-rw-r--r--tests/auto/blackbox/testdata/trackFileTags/before/project.qbs1
-rw-r--r--tests/manual/genmoc_cpp/moc_cpp.qbs1
-rw-r--r--tests/manual/transformers/transformers.qbs3
38 files changed, 223 insertions, 43 deletions
diff --git a/share/qbs/imports/qbs/probes/PathProbe.qbs b/share/qbs/imports/qbs/probes/PathProbe.qbs
index 05f27ad16..dff8a10e8 100644
--- a/share/qbs/imports/qbs/probes/PathProbe.qbs
+++ b/share/qbs/imports/qbs/probes/PathProbe.qbs
@@ -1,4 +1,5 @@
import qbs 1.0
+import qbs.File
import qbs.fileinfo as FileInfo
import "utils.js" as Utils
diff --git a/share/qbs/imports/qbs/probes/PkgConfigProbe.qbs b/share/qbs/imports/qbs/probes/PkgConfigProbe.qbs
index aca42f0de..c47a6ada2 100644
--- a/share/qbs/imports/qbs/probes/PkgConfigProbe.qbs
+++ b/share/qbs/imports/qbs/probes/PkgConfigProbe.qbs
@@ -1,4 +1,5 @@
import qbs 1.0
+import qbs.Process
import qbs.fileinfo as FileInfo
import "utils.js" as Utils
diff --git a/share/qbs/modules/cpp/DarwinGCC.qbs b/share/qbs/modules/cpp/DarwinGCC.qbs
index df21a98f4..b7f793f5f 100644
--- a/share/qbs/modules/cpp/DarwinGCC.qbs
+++ b/share/qbs/modules/cpp/DarwinGCC.qbs
@@ -1,4 +1,6 @@
import qbs 1.0
+import qbs.Process
+import qbs.TextFile
import qbs.fileinfo as FileInfo
import '../utils.js' as ModUtils
import "bundle-tools.js" as BundleTools
diff --git a/share/qbs/modules/cpp/ios-gcc.qbs b/share/qbs/modules/cpp/ios-gcc.qbs
index 79b49e316..e8aa01cd7 100644
--- a/share/qbs/modules/cpp/ios-gcc.qbs
+++ b/share/qbs/modules/cpp/ios-gcc.qbs
@@ -1,4 +1,5 @@
import qbs 1.0
+import qbs.File
import qbs.fileinfo as FileInfo
import '../utils.js' as ModUtils
import 'darwin-tools.js' as DarwinTools
diff --git a/share/share.qbs b/share/share.qbs
index 1cefa5af1..66fc5f4d4 100644
--- a/share/share.qbs
+++ b/share/share.qbs
@@ -1,4 +1,5 @@
import qbs
+import qbs.File
Product {
name: "qbs resources"
diff --git a/src/lib/buildgraph/buildgraph.cpp b/src/lib/buildgraph/buildgraph.cpp
index a52005b4d..3b5bda27e 100644
--- a/src/lib/buildgraph/buildgraph.cpp
+++ b/src/lib/buildgraph/buildgraph.cpp
@@ -32,6 +32,7 @@
#include "projectbuilddata.h"
#include "productbuilddata.h"
+#include <jsextensions/jsextensions.h>
#include <jsextensions/moduleproperties.h>
#include <language/language.h>
#include <language/scriptengine.h>
@@ -213,6 +214,7 @@ void setupScriptEngineForProduct(ScriptEngine *engine, const ResolvedProductCons
productScriptValue.setProperty(QLatin1String("moduleName"), rule->module->name);
engine->import(rule->jsImports, targetObject, targetObject);
+ JsExtensions::setupExtensions(rule->jsExtensions, targetObject);
}
bool findPath(Artifact *u, Artifact *v, QList<Artifact*> &path)
diff --git a/src/lib/buildgraph/jscommandexecutor.cpp b/src/lib/buildgraph/jscommandexecutor.cpp
index 93ecfe157..9d8e5af55 100644
--- a/src/lib/buildgraph/jscommandexecutor.cpp
+++ b/src/lib/buildgraph/jscommandexecutor.cpp
@@ -34,10 +34,6 @@
#include "command.h"
#include "transformer.h"
-#include <jsextensions/domxml.h>
-#include <jsextensions/file.h>
-#include <jsextensions/process.h>
-#include <jsextensions/textfile.h>
#include <language/language.h>
#include <language/scriptengine.h>
#include <logging/logger.h>
@@ -123,11 +119,6 @@ public:
ScriptEngine * scriptEngine = m_enginesPerThread.value(currentThread);
if (!scriptEngine) {
scriptEngine = new ScriptEngine(m_logger);
- const QScriptValue extensionObject = scriptEngine->globalObject();
- File::init(extensionObject);
- TextFile::init(extensionObject);
- Process::init(extensionObject);
- DomXml::init(extensionObject);
m_enginesPerThread.insert(currentThread, scriptEngine);
} else {
scriptEngine->setLogger(m_logger);
diff --git a/src/lib/buildgraph/projectbuilddata.cpp b/src/lib/buildgraph/projectbuilddata.cpp
index 14e20d2df..fbcbf4796 100644
--- a/src/lib/buildgraph/projectbuilddata.cpp
+++ b/src/lib/buildgraph/projectbuilddata.cpp
@@ -329,6 +329,7 @@ void BuildDataResolver::resolveProductBuildData(const ResolvedProductPtr &produc
transformer->inputs = inputArtifacts;
const RulePtr rule = Rule::create();
rule->jsImports = rtrafo->jsImports;
+ rule->jsExtensions = rtrafo->jsExtensions;
ResolvedModulePtr module = ResolvedModule::create();
module->name = rtrafo->module->name;
rule->module = module;
diff --git a/src/lib/jsextensions/domxml.cpp b/src/lib/jsextensions/domxml.cpp
index 514e83411..a4a0c80da 100644
--- a/src/lib/jsextensions/domxml.cpp
+++ b/src/lib/jsextensions/domxml.cpp
@@ -36,7 +36,7 @@
namespace qbs {
namespace Internal {
-void DomXml::init(QScriptValue extensionObject)
+void initializeJsExtensionXml(QScriptValue extensionObject)
{
QScriptEngine *engine = extensionObject.engine();
QScriptValue obj = engine->newQMetaObject(&XmlDomDocument::staticMetaObject, engine->newFunction(&XmlDomDocument::ctor));
diff --git a/src/lib/jsextensions/domxml.h b/src/lib/jsextensions/domxml.h
index bfa8ddf9a..4b82a6db6 100644
--- a/src/lib/jsextensions/domxml.h
+++ b/src/lib/jsextensions/domxml.h
@@ -42,10 +42,7 @@ namespace Internal {
class XmlDomDocument;
-namespace DomXml
-{
- void init(QScriptValue extensionObject);
-}
+void initializeJsExtensionXml(QScriptValue extensionObject);
class XmlDomNode: public QObject, public QScriptable
{
diff --git a/src/lib/jsextensions/file.cpp b/src/lib/jsextensions/file.cpp
index 1962fa2ea..4d7515482 100644
--- a/src/lib/jsextensions/file.cpp
+++ b/src/lib/jsextensions/file.cpp
@@ -38,7 +38,19 @@
namespace qbs {
namespace Internal {
-void File::init(QScriptValue extensionObject)
+class File
+{
+ friend void initializeJsExtensionFile(QScriptValue extensionObject);
+
+private:
+ static QScriptValue js_ctor(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue js_copy(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue js_exists(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue js_remove(QScriptContext *context, QScriptEngine *engine);
+};
+
+
+void initializeJsExtensionFile(QScriptValue extensionObject)
{
QScriptEngine *engine = extensionObject.engine();
QScriptValue fileObj = engine->newFunction(File::js_ctor);
diff --git a/src/lib/jsextensions/file.h b/src/lib/jsextensions/file.h
index c27d35b4e..a19f63c46 100644
--- a/src/lib/jsextensions/file.h
+++ b/src/lib/jsextensions/file.h
@@ -36,17 +36,7 @@
namespace qbs {
namespace Internal {
-class File
-{
-public:
- static void init(QScriptValue extensionObject);
-
-private:
- static QScriptValue js_ctor(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue js_copy(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue js_exists(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue js_remove(QScriptContext *context, QScriptEngine *engine);
-};
+void initializeJsExtensionFile(QScriptValue extensionObject);
} // namespace Internal
} // namespace qbs
diff --git a/src/lib/jsextensions/jsextensions.cpp b/src/lib/jsextensions/jsextensions.cpp
new file mode 100644
index 000000000..15923e6df
--- /dev/null
+++ b/src/lib/jsextensions/jsextensions.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "jsextensions.h"
+
+#include "domxml.h"
+#include "file.h"
+#include "process.h"
+#include "textfile.h"
+
+namespace qbs {
+namespace Internal {
+
+void JsExtensions::setupExtensions(const QStringList &names, QScriptValue scope)
+{
+ foreach (const QString &name, names)
+ initializers().value(name)(scope);
+}
+
+bool JsExtensions::hasExtension(const QString &name)
+{
+ return initializers().contains(name);
+}
+
+JsExtensions::InitializerMap JsExtensions::initializers()
+{
+ if (m_initializers.isEmpty()) {
+ m_initializers.insert(QLatin1String("File"), &initializeJsExtensionFile);
+ m_initializers.insert(QLatin1String("Process"), &initializeJsExtensionProcess);
+ m_initializers.insert(QLatin1String("Xml"), &initializeJsExtensionXml);
+ m_initializers.insert(QLatin1String("TextFile"), &initializeJsExtensionTextFile);
+ }
+ return m_initializers;
+}
+
+JsExtensions::InitializerMap JsExtensions::m_initializers;
+
+} // namespace Internal
+} // namespace qbs
diff --git a/src/lib/jsextensions/jsextensions.h b/src/lib/jsextensions/jsextensions.h
new file mode 100644
index 000000000..b54e1d259
--- /dev/null
+++ b/src/lib/jsextensions/jsextensions.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_JSEXTENSIONS_H
+#define QBS_JSEXTENSIONS_H
+
+#include <QHash>
+#include <QStringList>
+
+QT_BEGIN_NAMESPACE
+class QScriptValue;
+QT_END_NAMESPACE
+
+namespace qbs {
+namespace Internal {
+
+class JsExtensions
+{
+public:
+ static void setupExtensions(const QStringList &names, QScriptValue scope);
+ static bool hasExtension(const QString &name);
+
+private:
+ typedef QHash<QString, void (*)(QScriptValue)> InitializerMap;
+ static InitializerMap initializers();
+
+ static InitializerMap m_initializers;
+};
+
+} // namespace Internal
+} // namespace qbs
+
+#endif // Include guard.
diff --git a/src/lib/jsextensions/jsextensions.pri b/src/lib/jsextensions/jsextensions.pri
index a46fe97c8..21c97ef64 100644
--- a/src/lib/jsextensions/jsextensions.pri
+++ b/src/lib/jsextensions/jsextensions.pri
@@ -5,11 +5,13 @@ HEADERS += \
$$PWD/textfile.h \
$$PWD/process.h \
$$PWD/moduleproperties.h \
- $$PWD/domxml.h
+ $$PWD/domxml.h \
+ $$PWD/jsextensions.h
SOURCES += \
$$PWD/file.cpp \
$$PWD/textfile.cpp \
$$PWD/process.cpp \
$$PWD/moduleproperties.cpp \
- $$PWD/domxml.cpp
+ $$PWD/domxml.cpp \
+ $$PWD/jsextensions.cpp
diff --git a/src/lib/jsextensions/process.cpp b/src/lib/jsextensions/process.cpp
index 3938192d6..42f59fd7d 100644
--- a/src/lib/jsextensions/process.cpp
+++ b/src/lib/jsextensions/process.cpp
@@ -41,7 +41,7 @@
namespace qbs {
namespace Internal {
-void Process::init(QScriptValue extensionObject)
+void initializeJsExtensionProcess(QScriptValue extensionObject)
{
QScriptEngine *engine = extensionObject.engine();
QScriptValue obj = engine->newQMetaObject(&Process::staticMetaObject, engine->newFunction(&Process::ctor));
diff --git a/src/lib/jsextensions/process.h b/src/lib/jsextensions/process.h
index b2a99daa9..702513b96 100644
--- a/src/lib/jsextensions/process.h
+++ b/src/lib/jsextensions/process.h
@@ -42,13 +42,12 @@ QT_END_NAMESPACE
namespace qbs {
namespace Internal {
+void initializeJsExtensionProcess(QScriptValue extensionObject);
class Process : public QObject, public QScriptable
{
Q_OBJECT
public:
- static void init(QScriptValue extensionObject);
-
static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine);
Process(QScriptContext *context);
~Process();
diff --git a/src/lib/jsextensions/textfile.cpp b/src/lib/jsextensions/textfile.cpp
index ea42b55b9..794f5e4e9 100644
--- a/src/lib/jsextensions/textfile.cpp
+++ b/src/lib/jsextensions/textfile.cpp
@@ -39,7 +39,7 @@
namespace qbs {
namespace Internal {
-void TextFile::init(QScriptValue extensionObject)
+void initializeJsExtensionTextFile(QScriptValue extensionObject)
{
QScriptEngine *engine = extensionObject.engine();
QScriptValue obj = engine->newQMetaObject(&TextFile::staticMetaObject, engine->newFunction(&TextFile::ctor));
diff --git a/src/lib/jsextensions/textfile.h b/src/lib/jsextensions/textfile.h
index aac838091..2874f18bd 100644
--- a/src/lib/jsextensions/textfile.h
+++ b/src/lib/jsextensions/textfile.h
@@ -42,13 +42,13 @@ QT_END_NAMESPACE
namespace qbs {
namespace Internal {
+void initializeJsExtensionTextFile(QScriptValue extensionObject);
+
class TextFile : public QObject, public QScriptable
{
Q_OBJECT
Q_ENUMS(OpenMode)
public:
- static void init(QScriptValue extensionObject);
-
enum OpenMode { ReadOnly, WriteOnly, ReadWrite };
static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine);
TextFile(QScriptContext *context, const QString &file, OpenMode mode = ReadOnly, const QString &codec = QLatin1String("UTF8"));
diff --git a/src/lib/language/evaluator.cpp b/src/lib/language/evaluator.cpp
index 43a8580a8..117962fcc 100644
--- a/src/lib/language/evaluator.cpp
+++ b/src/lib/language/evaluator.cpp
@@ -33,6 +33,7 @@
#include "filecontext.h"
#include "filetags.h"
#include "item.h"
+#include <jsextensions/jsextensions.h>
#include <logging/translator.h>
#include <tools/error.h>
#include <tools/qbsassert.h>
@@ -184,6 +185,7 @@ QScriptValue Evaluator::fileScope(const FileContextConstPtr &file)
result.setProperty(QLatin1String("filePath"), file->filePath());
result.setProperty(QLatin1String("path"), file->dirPath());
m_scriptEngine->import(file->jsImports(), result, result);
+ JsExtensions::setupExtensions(file->jsExtensions(), result);
return result;
}
diff --git a/src/lib/language/filecontext.h b/src/lib/language/filecontext.h
index 3f4b96aeb..1d3d2ca5e 100644
--- a/src/lib/language/filecontext.h
+++ b/src/lib/language/filecontext.h
@@ -33,6 +33,8 @@
#include "item.h"
#include "jsimports.h"
+#include <QStringList>
+
namespace qbs {
namespace Internal {
@@ -48,11 +50,14 @@ public:
QString filePath() const;
QString dirPath() const;
JsImports jsImports() const;
+ QStringList jsExtensions() const;
+
Item *idScope() const;
private:
QString m_filePath;
JsImports m_jsImports;
+ QStringList m_jsExtensions;
Item *m_idScope;
};
@@ -66,6 +71,11 @@ inline JsImports FileContext::jsImports() const
return m_jsImports;
}
+inline QStringList FileContext::jsExtensions() const
+{
+ return m_jsExtensions;
+}
+
inline Item *FileContext::idScope() const
{
return m_idScope;
diff --git a/src/lib/language/itemreaderastvisitor.cpp b/src/lib/language/itemreaderastvisitor.cpp
index 24bfb3936..efb1171a2 100644
--- a/src/lib/language/itemreaderastvisitor.cpp
+++ b/src/lib/language/itemreaderastvisitor.cpp
@@ -32,6 +32,7 @@
#include "builtindeclarations.h"
#include "identifiersearch.h"
#include "itemreader.h"
+#include <jsextensions/jsextensions.h>
#include <parser/qmljsast_p.h>
#include <tools/error.h>
#include <tools/fileinfo.h>
@@ -134,6 +135,23 @@ bool ItemReaderASTVisitor::visit(AST::UiImportList *uiImportList)
toCodeLocation(import->importIdToken));
}
} else {
+ if (importUri.count() == 2 && importUri.first() == QLatin1String("qbs")) {
+ const QString extensionName = importUri.last();
+ if (JsExtensions::hasExtension(extensionName)) {
+ if (Q_UNLIKELY(!import->importId.isNull())) {
+ throw ErrorInfo(Tr::tr("Import of built-in extension '%1' "
+ "must not have 'as' specifier.").arg(extensionName));
+ }
+ if (Q_UNLIKELY(m_file->m_jsExtensions.contains(extensionName))) {
+ m_reader->logger().printWarning(Tr::tr("Built-in extension '%1' already "
+ "imported.").arg(extensionName));
+ } else {
+ m_file->m_jsExtensions << extensionName;
+ }
+ continue;
+ }
+ }
+
if (Q_UNLIKELY(import->importId.isNull())) {
throw ErrorInfo(Tr::tr("Imports require 'as <Name>'"),
toCodeLocation(import->importToken));
@@ -144,6 +162,10 @@ bool ItemReaderASTVisitor::visit(AST::UiImportList *uiImportList)
throw ErrorInfo(Tr::tr("Can't import into the same name more than once."),
toCodeLocation(import->importIdToken));
}
+ if (Q_UNLIKELY(JsExtensions::hasExtension(as))) {
+ throw ErrorInfo(Tr::tr("Cannot use the name of built-in extension '%1' in an 'as' "
+ "specifier.").arg(as));
+ }
importAsNames.insert(as);
}
diff --git a/src/lib/language/language.cpp b/src/lib/language/language.cpp
index 8be684693..8711bd0c5 100644
--- a/src/lib/language/language.cpp
+++ b/src/lib/language/language.cpp
@@ -35,6 +35,7 @@
#include <buildgraph/productbuilddata.h>
#include <buildgraph/projectbuilddata.h>
#include <buildgraph/rulegraph.h> // TODO: Move to language?
+#include <jsextensions/jsextensions.h>
#include <logging/translator.h>
#include <tools/hostosinfo.h>
#include <tools/error.h>
@@ -251,6 +252,7 @@ void ResolvedModule::load(PersistentPool &pool)
setupBuildEnvironmentScript = pool.idLoadString();
setupRunEnvironmentScript = pool.idLoadString();
pool.stream() >> jsImports
+ >> jsExtensions
>> setupBuildEnvironmentScript
>> setupRunEnvironmentScript;
}
@@ -262,6 +264,7 @@ void ResolvedModule::store(PersistentPool &pool) const
pool.storeString(setupBuildEnvironmentScript);
pool.storeString(setupRunEnvironmentScript);
pool.stream() << jsImports
+ << jsExtensions
<< setupBuildEnvironmentScript
<< setupRunEnvironmentScript;
}
@@ -285,6 +288,7 @@ void Rule::load(PersistentPool &pool)
script = pool.idLoadS<PrepareScript>();
module = pool.idLoadS<ResolvedModule>();
pool.stream() >> jsImports
+ >> jsExtensions
>> inputs
>> usings
>> explicitlyDependsOn
@@ -298,6 +302,7 @@ void Rule::store(PersistentPool &pool) const
pool.store(script);
pool.store(module);
pool.stream() << jsImports
+ << jsExtensions
<< inputs
<< usings
<< explicitlyDependsOn
@@ -494,6 +499,7 @@ static QProcessEnvironment getProcessEnvironment(ScriptEngine *engine, EnvType e
// handle imports
engine->import(module->jsImports, scope, scope);
+ JsExtensions::setupExtensions(module->jsExtensions, scope);
// expose properties of direct module dependencies
QScriptValue scriptValue;
diff --git a/src/lib/language/language.h b/src/lib/language/language.h
index e1a549855..d142ba1bf 100644
--- a/src/lib/language/language.h
+++ b/src/lib/language/language.h
@@ -210,6 +210,7 @@ public:
QString name;
QStringList moduleDependencies;
JsImports jsImports;
+ QStringList jsExtensions;
QString setupBuildEnvironmentScript;
QString setupRunEnvironmentScript;
@@ -236,6 +237,7 @@ public:
ResolvedModuleConstPtr module;
JsImports jsImports;
+ QStringList jsExtensions;
PrepareScriptConstPtr script;
FileTags inputs;
FileTags usings;
@@ -268,6 +270,7 @@ public:
QList<SourceArtifactPtr> outputs;
PrepareScriptConstPtr transform;
JsImports jsImports;
+ QStringList jsExtensions;
private:
ResolvedTransformer() {}
diff --git a/src/lib/language/moduleloader.cpp b/src/lib/language/moduleloader.cpp
index d8d0d48ce..aaa6e5c09 100644
--- a/src/lib/language/moduleloader.cpp
+++ b/src/lib/language/moduleloader.cpp
@@ -36,10 +36,6 @@
#include "item.h"
#include "itemreader.h"
#include "scriptengine.h"
-#include <jsextensions/domxml.h>
-#include <jsextensions/file.h>
-#include <jsextensions/process.h>
-#include <jsextensions/textfile.h>
#include <language/language.h>
#include <language/scriptengine.h>
#include <logging/logger.h>
@@ -820,10 +816,6 @@ void ModuleLoader::resolveProbe(Item *parent, Item *probe)
}
}
QScriptValue scope = m_engine->newObject();
- File::init(scope);
- Process::init(scope);
- TextFile::init(scope);
- DomXml::init(scope);
m_engine->currentContext()->pushScope(m_evaluator->scriptValue(parent));
m_engine->currentContext()->pushScope(scope);
m_engine->currentContext()->pushScope(m_evaluator->fileScope(configureScript->file()));
diff --git a/src/lib/language/projectresolver.cpp b/src/lib/language/projectresolver.cpp
index 2c67de70b..1b2c092ea 100644
--- a/src/lib/language/projectresolver.cpp
+++ b/src/lib/language/projectresolver.cpp
@@ -325,6 +325,7 @@ void ProjectResolver::resolveModule(const QStringList &moduleName, Item *item,
// TODO: instead of jsImports, we need the file context for both setup scripts separately.
// ATM the setup scripts must be in the first file of the inheritance chain.
module->jsImports = item->file()->jsImports();
+ module->jsExtensions = item->file()->jsExtensions();
foreach (const Item::Module &m, item->modules())
module->moduleDependencies += ModuleLoader::fullModuleName(m.name);
@@ -501,6 +502,7 @@ void ProjectResolver::resolveRule(Item *item, ProjectContext *projectContext)
}
rule->jsImports = item->file()->jsImports();
+ rule->jsExtensions = item->file()->jsExtensions();
rule->script = prepareScript;
rule->multiplex = m_evaluator->boolValue(item, "multiplex", false);
rule->inputs = m_evaluator->fileTagsValue(item, "inputs");
@@ -609,6 +611,7 @@ void ProjectResolver::resolveTransformer(Item *item, ProjectContext *projectCont
ResolvedTransformer::Ptr rtrafo = ResolvedTransformer::create();
rtrafo->module = m_moduleContext ? m_moduleContext->module : projectContext->dummyModule;
rtrafo->jsImports = item->file()->jsImports();
+ rtrafo->jsExtensions = item->file()->jsExtensions();
rtrafo->inputs = m_evaluator->stringListValue(item, "inputs");
for (int i = 0; i < rtrafo->inputs.count(); ++i)
rtrafo->inputs[i] = FileInfo::resolvePath(m_productContext->product->sourceDirectory, rtrafo->inputs.at(i));
diff --git a/src/lib/language/testdata/erroneous/reserved_name_in_import.qbs b/src/lib/language/testdata/erroneous/reserved_name_in_import.qbs
new file mode 100644
index 000000000..3940109d0
--- /dev/null
+++ b/src/lib/language/testdata/erroneous/reserved_name_in_import.qbs
@@ -0,0 +1,4 @@
+import qbs
+import "../idusagebase.qbs" as TextFile
+
+Product { }
diff --git a/src/lib/language/tst_language.cpp b/src/lib/language/tst_language.cpp
index cb9cc90ef..56fb75311 100644
--- a/src/lib/language/tst_language.cpp
+++ b/src/lib/language/tst_language.cpp
@@ -294,6 +294,8 @@ void TestLanguage::erroneousFiles_data()
<< "does not exist";
QTest::newRow("invalid_property_type")
<< "Unknown type 'nonsense' in property declaration.";
+ QTest::newRow("reserved_name_in_import")
+ << "Cannot use the name of built-in extension 'TextFile' in an 'as' specifier.";
QTest::newRow("throw_in_property_binding")
<< "something is wrong";
}
diff --git a/src/lib/lib.qbs b/src/lib/lib.qbs
index 9e8bc27d8..69c11e709 100644
--- a/src/lib/lib.qbs
+++ b/src/lib/lib.qbs
@@ -126,6 +126,8 @@ Product {
files: [
"file.cpp",
"file.h",
+ "jsextensions.cpp",
+ "jsextensions.h",
"moduleproperties.cpp",
"moduleproperties.h",
"process.cpp",
diff --git a/src/lib/tools/persistence.cpp b/src/lib/tools/persistence.cpp
index 0488d579b..d891b1d1e 100644
--- a/src/lib/tools/persistence.cpp
+++ b/src/lib/tools/persistence.cpp
@@ -40,7 +40,7 @@
namespace qbs {
namespace Internal {
-static const char QBS_PERSISTENCE_MAGIC[] = "QBSPERSISTENCE-42";
+static const char QBS_PERSISTENCE_MAGIC[] = "QBSPERSISTENCE-43";
PersistentPool::PersistentPool(const Logger &logger) : m_logger(logger)
{
diff --git a/tests/auto/blackbox/testdata/dependenciesProperty/dependenciesProperty.qbs b/tests/auto/blackbox/testdata/dependenciesProperty/dependenciesProperty.qbs
index 96058f107..136e3e032 100644
--- a/tests/auto/blackbox/testdata/dependenciesProperty/dependenciesProperty.qbs
+++ b/tests/auto/blackbox/testdata/dependenciesProperty/dependenciesProperty.qbs
@@ -1,4 +1,5 @@
import qbs 1.0
+import qbs.TextFile
import qbs.fileinfo as FileInfo
Project {
diff --git a/tests/auto/blackbox/testdata/productproperties/header.qbs b/tests/auto/blackbox/testdata/productproperties/header.qbs
index 76e20eb83..51757b29e 100644
--- a/tests/auto/blackbox/testdata/productproperties/header.qbs
+++ b/tests/auto/blackbox/testdata/productproperties/header.qbs
@@ -1,4 +1,5 @@
import qbs 1.0
+import qbs.TextFile
Product {
name: "blubb_header"
diff --git a/tests/auto/blackbox/testdata/qt5plugin/plugin.qbs b/tests/auto/blackbox/testdata/qt5plugin/plugin.qbs
index eeced83b2..14e2c49df 100644
--- a/tests/auto/blackbox/testdata/qt5plugin/plugin.qbs
+++ b/tests/auto/blackbox/testdata/qt5plugin/plugin.qbs
@@ -1,4 +1,5 @@
import qbs.base
+import qbs.File
import qbs.fileinfo as FileInfo
DynamicLibrary {
diff --git a/tests/auto/blackbox/testdata/ruleConditions/modules/narfzort/narfzort.qbs b/tests/auto/blackbox/testdata/ruleConditions/modules/narfzort/narfzort.qbs
index fa2654959..62d7f8fe1 100644
--- a/tests/auto/blackbox/testdata/ruleConditions/modules/narfzort/narfzort.qbs
+++ b/tests/auto/blackbox/testdata/ruleConditions/modules/narfzort/narfzort.qbs
@@ -1,4 +1,5 @@
import qbs 1.0
+import qbs.TextFile
Module {
property bool buildZort: true
diff --git a/tests/auto/blackbox/testdata/trackFileTags/after/project.qbs b/tests/auto/blackbox/testdata/trackFileTags/after/project.qbs
index 5d4dd9eb2..e770c6212 100644
--- a/tests/auto/blackbox/testdata/trackFileTags/after/project.qbs
+++ b/tests/auto/blackbox/testdata/trackFileTags/after/project.qbs
@@ -1,4 +1,5 @@
import qbs 1.0
+import qbs.TextFile
Project {
Product {
diff --git a/tests/auto/blackbox/testdata/trackFileTags/before/project.qbs b/tests/auto/blackbox/testdata/trackFileTags/before/project.qbs
index 9a19670cf..dbe4df6c3 100644
--- a/tests/auto/blackbox/testdata/trackFileTags/before/project.qbs
+++ b/tests/auto/blackbox/testdata/trackFileTags/before/project.qbs
@@ -1,4 +1,5 @@
import qbs 1.0
+import qbs.TextFile
Project {
Product {
diff --git a/tests/manual/genmoc_cpp/moc_cpp.qbs b/tests/manual/genmoc_cpp/moc_cpp.qbs
index e16955eab..ccbd70ba1 100644
--- a/tests/manual/genmoc_cpp/moc_cpp.qbs
+++ b/tests/manual/genmoc_cpp/moc_cpp.qbs
@@ -1,4 +1,5 @@
import qbs 1.0
+import qbs.TextFile
import qbs.fileinfo as FileInfo
Project {
diff --git a/tests/manual/transformers/transformers.qbs b/tests/manual/transformers/transformers.qbs
index 12aa66bc8..08444f975 100644
--- a/tests/manual/transformers/transformers.qbs
+++ b/tests/manual/transformers/transformers.qbs
@@ -1,4 +1,7 @@
import qbs 1.0
+import qbs.File
+import qbs.TextFile
+import qbs.Xml
import qbs.fileinfo as FileInfo
Project {