aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@theqtcompany.com>2015-07-31 12:20:13 +0200
committerChristian Kandeler <christian.kandeler@theqtcompany.com>2015-07-31 12:20:13 +0200
commit43ddde70dd61f9adb2c3b20ee86522494538ca0e (patch)
tree18e6fca3eb8e2122f2dc273acc5f875d32ba3760 /src
parent92cf9460c46d707aeac02ef8f6597a4037df0964 (diff)
parent33c9a2721b76e8a7affa19e924cbaf4e4c91060b (diff)
Merge branch 1.4 into master.
Diffstat (limited to 'src')
-rw-r--r--src/app/qbs-setup-android/android-setup.cpp19
-rw-r--r--src/app/qbs-setup-toolchains/msvcinfo.h15
-rw-r--r--src/app/qbs-setup-toolchains/msvcprobe.cpp21
-rw-r--r--src/app/qbs-setup-toolchains/probe.cpp83
-rw-r--r--src/app/qbs-setup-toolchains/vsenvironmentdetector.cpp2
-rw-r--r--src/lib/corelib/api/languageinfo.cpp6
-rw-r--r--src/lib/corelib/api/runenvironment.cpp1
-rw-r--r--src/lib/corelib/buildgraph/buildgraph.cpp2
-rw-r--r--src/lib/corelib/buildgraph/buildgraphloader.cpp3
-rw-r--r--src/lib/corelib/buildgraph/depscanner.cpp2
-rw-r--r--src/lib/corelib/buildgraph/executor.cpp1
-rw-r--r--src/lib/corelib/buildgraph/productinstaller.cpp8
-rw-r--r--src/lib/corelib/buildgraph/projectbuilddata.cpp2
-rw-r--r--src/lib/corelib/buildgraph/qtmocscanner.cpp1
-rw-r--r--src/lib/corelib/buildgraph/rulesapplicator.cpp5
-rw-r--r--src/lib/corelib/buildgraph/timestampsupdater.cpp2
-rw-r--r--src/lib/corelib/buildgraph/transformer.cpp1
-rw-r--r--src/lib/corelib/corelib.qbs4
-rw-r--r--src/lib/corelib/jsextensions/jsextensions.cpp2
-rw-r--r--src/lib/corelib/jsextensions/jsextensions.pri2
-rw-r--r--src/lib/corelib/jsextensions/moduleproperties.cpp1
-rw-r--r--src/lib/corelib/jsextensions/temporarydir.cpp76
-rw-r--r--src/lib/corelib/jsextensions/temporarydir.h60
-rw-r--r--src/lib/corelib/language/artifactproperties.h3
-rw-r--r--src/lib/corelib/language/builtindeclarations.cpp50
-rw-r--r--src/lib/corelib/language/builtindeclarations.h16
-rw-r--r--src/lib/corelib/language/evaluator.cpp6
-rw-r--r--src/lib/corelib/language/evaluator.h13
-rw-r--r--src/lib/corelib/language/evaluatorscriptclass.cpp1
-rw-r--r--src/lib/corelib/language/evaluatorscriptclass.h3
-rw-r--r--src/lib/corelib/language/filecontext.cpp10
-rw-r--r--src/lib/corelib/language/filecontext.h18
-rw-r--r--src/lib/corelib/language/filecontextbase.h72
-rw-r--r--src/lib/corelib/language/functiondeclaration.h2
-rw-r--r--src/lib/corelib/language/item.cpp75
-rw-r--r--src/lib/corelib/language/item.h198
-rw-r--r--src/lib/corelib/language/itemdeclaration.h2
-rw-r--r--src/lib/corelib/language/itemobserver.h2
-rw-r--r--src/lib/corelib/language/itemreader.cpp130
-rw-r--r--src/lib/corelib/language/itemreader.h34
-rw-r--r--src/lib/corelib/language/itemreaderastvisitor.cpp82
-rw-r--r--src/lib/corelib/language/itemreaderastvisitor.h32
-rw-r--r--src/lib/corelib/language/itemreadervisitorstate.cpp168
-rw-r--r--src/lib/corelib/language/itemreadervisitorstate.h69
-rw-r--r--src/lib/corelib/language/jsimports.h2
-rw-r--r--src/lib/corelib/language/language.cpp5
-rw-r--r--src/lib/corelib/language/language.h8
-rw-r--r--src/lib/corelib/language/language.pri2
-rw-r--r--src/lib/corelib/language/loader.cpp44
-rw-r--r--src/lib/corelib/language/loader.h15
-rw-r--r--src/lib/corelib/language/moduleloader.cpp37
-rw-r--r--src/lib/corelib/language/moduleloader.h10
-rw-r--r--src/lib/corelib/language/modulemerger.cpp14
-rw-r--r--src/lib/corelib/language/modulemerger.h5
-rw-r--r--src/lib/corelib/language/projectresolver.cpp12
-rw-r--r--src/lib/corelib/language/projectresolver.h7
-rw-r--r--src/lib/corelib/language/propertydeclaration.cpp2
-rw-r--r--src/lib/corelib/language/propertydeclaration.h9
-rw-r--r--src/lib/corelib/language/propertymapinternal.cpp2
-rw-r--r--src/lib/corelib/language/resolvedfilecontext.h2
-rw-r--r--src/lib/corelib/language/scriptengine.cpp58
-rw-r--r--src/lib/corelib/language/scriptengine.h10
-rw-r--r--src/lib/corelib/language/scriptpropertyobserver.h7
-rw-r--r--src/lib/corelib/language/testdata/import-collection/imports/Collection/file1.js1
-rw-r--r--src/lib/corelib/language/testdata/import-collection/imports/Collection/file2.js1
-rw-r--r--src/lib/corelib/language/testdata/import-collection/product.qbs6
-rw-r--r--src/lib/corelib/language/testdata/import-collection/project.qbs6
-rw-r--r--src/lib/corelib/language/testdata/moduleproperties.qbs7
-rw-r--r--src/lib/corelib/language/testdata/modules/dummy/dummy.qbs1
-rw-r--r--src/lib/corelib/language/tst_language.cpp26
-rw-r--r--src/lib/corelib/language/tst_language.h11
-rw-r--r--src/lib/corelib/language/value.cpp4
-rw-r--r--src/lib/corelib/language/value.h6
-rw-r--r--src/lib/corelib/tools/fileinfo.cpp6
-rw-r--r--src/lib/corelib/tools/hostosinfo.h21
-rw-r--r--src/lib/corelib/tools/tst_tools.h4
76 files changed, 920 insertions, 736 deletions
diff --git a/src/app/qbs-setup-android/android-setup.cpp b/src/app/qbs-setup-android/android-setup.cpp
index 60b6d4aaa..ca58b5a7f 100644
--- a/src/app/qbs-setup-android/android-setup.cpp
+++ b/src/app/qbs-setup-android/android-setup.cpp
@@ -113,20 +113,20 @@ static QString detectPlatform(const QString &sdkDir)
static QStringList expectedArchs()
{
- return QStringList({
- QStringLiteral("arm64"),
- QStringLiteral("armv5"),
- QStringLiteral("armv7"),
- QStringLiteral("mipsel"),
- QStringLiteral("mips64el"),
- QStringLiteral("x86"),
- QStringLiteral("x86_64")});
+ return QStringList()
+ << QStringLiteral("arm64")
+ << QStringLiteral("armv5")
+ << QStringLiteral("armv7")
+ << QStringLiteral("mipsel")
+ << QStringLiteral("mips64el")
+ << QStringLiteral("x86")
+ << QStringLiteral("x86_64");
}
static QString subProfileName(const QString &mainProfileName, const QString &arch)
{
- return mainProfileName + QLatin1Char('_') + arch;
+ return mainProfileName + QLatin1Char('-') + arch;
}
void setupSdk(qbs::Settings *settings, const QString &profileName, const QString &sdkDirPath)
@@ -159,6 +159,7 @@ void setupNdk(qbs::Settings *settings, const QString &profileName, const QString
Profile mainProfile(profileName, settings);
mainProfile.setValue(qls("Android.ndk.ndkDir"), QDir::cleanPath(ndkDirPath));
mainProfile.setValue(qls("Android.sdk.ndkDir"), QDir::cleanPath(ndkDirPath));
+ mainProfile.setValue(qls("qbs.toolchain"), QStringList() << qls("gcc"));
foreach (const QString &arch, expectedArchs()) {
Profile p(subProfileName(profileName, arch), settings);
p.removeProfile();
diff --git a/src/app/qbs-setup-toolchains/msvcinfo.h b/src/app/qbs-setup-toolchains/msvcinfo.h
index 0344c72f9..dbd8d2bcb 100644
--- a/src/app/qbs-setup-toolchains/msvcinfo.h
+++ b/src/app/qbs-setup-toolchains/msvcinfo.h
@@ -31,6 +31,7 @@
#ifndef QBS_MSVCINFO_H
#define QBS_MSVCINFO_H
+#include <QDir>
#include <QHash>
#include <QProcessEnvironment>
#include <QStringList>
@@ -40,16 +41,30 @@ class MSVC
public:
QString version;
QString installPath;
+ QString pathPrefix;
QStringList architectures;
typedef QHash<QString, QProcessEnvironment> EnvironmentPerArch;
EnvironmentPerArch environments;
+
+ QString clPath(const QString &arch = QString()) {
+ return QDir::cleanPath(
+ installPath + QLatin1Char('/') +
+ pathPrefix + QLatin1Char('/') +
+ arch + QLatin1Char('/') +
+ QLatin1String("cl.exe"));
+ }
};
class WinSDK : public MSVC
{
public:
bool isDefault;
+
+ WinSDK()
+ {
+ pathPrefix = QLatin1String("bin");
+ }
};
#endif // QBS_MSVCINFO_H
diff --git a/src/app/qbs-setup-toolchains/msvcprobe.cpp b/src/app/qbs-setup-toolchains/msvcprobe.cpp
index 87c90bd01..3e2a7f216 100644
--- a/src/app/qbs-setup-toolchains/msvcprobe.cpp
+++ b/src/app/qbs-setup-toolchains/msvcprobe.cpp
@@ -72,11 +72,6 @@ static void addMSVCPlatform(const MSVC &msvc, Settings *settings, QList<Profile>
p.setValue(QLatin1String("cpp.toolchainInstallPath"), installPath);
p.setValue(QLatin1String("qbs.toolchain"), QStringList(QLatin1String("msvc")));
p.setValue(QLatin1String("qbs.architecture"), canonicalArchitecture(architecture));
- if (msvc.version.toInt() >= 2013) {
- const QStringList flags(QLatin1String("/FS"));
- p.setValue(QLatin1String("cpp.platformCFlags"), flags);
- p.setValue(QLatin1String("cpp.platformCxxFlags"), flags);
- }
const QProcessEnvironment compilerEnvironment = msvc.environments.value(architecture);
setCompilerVersion(installPath + QLatin1String("/cl.exe"), QStringList(QLatin1String("msvc")),
p, compilerEnvironment);
@@ -84,12 +79,20 @@ static void addMSVCPlatform(const MSVC &msvc, Settings *settings, QList<Profile>
profiles << p;
}
-static void findSupportedArchitectures(MSVC *msvc, const QString &pathPrefix = QString())
+static void findSupportedArchitectures(MSVC *msvc)
{
- if (QFile::exists(msvc->installPath + pathPrefix + QLatin1String("/cl.exe")))
+ if (QFile::exists(msvc->clPath())
+ || QFile::exists(msvc->clPath(QLatin1String("amd64_x86"))))
msvc->architectures += QLatin1String("x86");
- if (QFile::exists(msvc->installPath + pathPrefix + QLatin1String("/amd64/cl.exe")))
+ if (QFile::exists(msvc->clPath(QLatin1String("amd64")))
+ || QFile::exists(msvc->clPath(QLatin1String("x86_amd64"))))
msvc->architectures += QLatin1String("x86_64");
+ if (QFile::exists(msvc->clPath(QLatin1String("ia64")))
+ || QFile::exists(msvc->clPath(QLatin1String("x86_ia64"))))
+ msvc->architectures += QLatin1String("ia64");
+ if (QFile::exists(msvc->clPath(QLatin1String("x86_arm")))
+ || QFile::exists(msvc->clPath(QLatin1String("amd64_arm"))))
+ msvc->architectures += QLatin1String("armv7");
}
static QString wow6432Key()
@@ -123,7 +126,7 @@ void msvcProbe(Settings *settings, QList<Profile> &profiles)
continue;
if (sdk.installPath.endsWith(QLatin1Char('\\')))
sdk.installPath.chop(1);
- findSupportedArchitectures(&sdk, QLatin1String("/bin"));
+ findSupportedArchitectures(&sdk);
if (sdk.isDefault)
defaultWinSDK = sdk;
winSDKs += sdk;
diff --git a/src/app/qbs-setup-toolchains/probe.cpp b/src/app/qbs-setup-toolchains/probe.cpp
index 531bbf0c1..b20ab7229 100644
--- a/src/app/qbs-setup-toolchains/probe.cpp
+++ b/src/app/qbs-setup-toolchains/probe.cpp
@@ -120,50 +120,36 @@ static QString gccMachineName(const QString &compilerFilePath)
return qsystem(compilerFilePath, QStringList() << QLatin1String("-dumpmachine")).trimmed();
}
-static void setupCompilerPathByLanguage(Profile &profile, const QStringList &toolchainTypes,
- const QString &toolchainInstallPath, const QString &toolchainPrefix)
+static QStringList standardCompilerFileNames()
{
- QVariantMap m;
- if (toolchainTypes.contains(QLatin1String("clang"))) {
- m[QLatin1String("c")] = m[QLatin1String("objc")] = QLatin1String("clang");
- m[QLatin1String("cpp")] = m[QLatin1String("objcpp")] = QLatin1String("clang++");
- } else if (toolchainTypes.contains(QLatin1String("gcc"))) {
- m[QLatin1String("c")] = m[QLatin1String("objc")] = QLatin1String("gcc");
- m[QLatin1String("cpp")] = m[QLatin1String("objcpp")] = QLatin1String("g++");
- } else {
- qDebug("WARNING: unexpected toolchain %s", qPrintable(toJSLiteral(toolchainTypes)));
- return;
- }
-
- const QString toolchainPathPrefix = toolchainInstallPath + QLatin1Char('/') + toolchainPrefix;
- for (QVariantMap::iterator it = m.begin(); it != m.end();) {
- const QString filePath = HostOsInfo::appendExecutableSuffix(toolchainPathPrefix
- + it.value().toString());
- if (QFile::exists(filePath)) {
- it.value() = filePath;
- ++it;
- continue;
- }
- qDebug("WARNING: Compiler %s for file tag %s not found.",
- qPrintable(QDir::toNativeSeparators(filePath)), qPrintable(it.key()));
- it = m.erase(it);
- }
- if (!m.isEmpty())
- profile.setValue(QLatin1String("cpp.compilerPathByLanguage"), m);
+ return QStringList() << QStringLiteral("gcc") << QStringLiteral("g++")
+ << QStringLiteral("clang") << QStringLiteral("clang++");
}
static void setCommonProperties(Profile &profile, const QString &compilerFilePath,
- const QString &toolchainPrefix, const QStringList &toolchainTypes,
- const QString &architecture)
+ const QStringList &toolchainTypes, const QString &architecture)
{
- QFileInfo cfi(compilerFilePath);
- const QString toolchainInstallPath = cfi.absolutePath();
- profile.setValue(QLatin1String("cpp.toolchainInstallPath"), toolchainInstallPath);
- profile.setValue(QLatin1String("cpp.compilerName"), cfi.fileName());
+ const QFileInfo cfi(compilerFilePath);
+ const QString compilerName = QFileInfo(compilerFilePath).fileName();
+ if (!standardCompilerFileNames().contains(compilerName))
+ qWarning("%s", qPrintable(
+ QString::fromLatin1("'%1' is not a standard compiler file name; "
+ "you must set the cpp.cCompilerName and "
+ "cpp.cxxCompilerName properties of this profile "
+ "manually").arg(compilerName)));
+
+
+ if (toolchainTypes.contains(QStringLiteral("mingw")))
+ profile.setValue(QStringLiteral("qbs.targetOS"), QStringList(QStringLiteral("windows")));
+
+ const QString prefix = compilerName.left(compilerName.lastIndexOf(QLatin1Char('-')) + 1);
+ if (!prefix.isEmpty())
+ profile.setValue(QLatin1String("cpp.toolchainPrefix"), prefix);
+
+ profile.setValue(QLatin1String("cpp.toolchainInstallPath"), cfi.absolutePath());
profile.setValue(QLatin1String("qbs.toolchain"), toolchainTypes);
profile.setValue(QLatin1String("qbs.architecture"), canonicalArchitecture(architecture));
setCompilerVersion(compilerFilePath, toolchainTypes, profile);
- setupCompilerPathByLanguage(profile, toolchainTypes, toolchainInstallPath, toolchainPrefix);
}
class ToolPathSetup
@@ -200,10 +186,8 @@ static Profile createGccProfile(const QString &compilerFilePath, Settings *setti
{
const QString machineName = gccMachineName(compilerFilePath);
const QStringList compilerTriplet = machineName.split(QLatin1Char('-'));
- const bool isMingw = toolchainTypes.contains(QLatin1String("mingw"));
- const bool isClang = toolchainTypes.contains(QLatin1String("clang"));
- if (isMingw) {
+ if (toolchainTypes.contains(QLatin1String("mingw"))) {
if (!validMinGWMachines().contains(machineName)) {
throw ErrorInfo(Tr::tr("Detected gcc platform '%1' is not supported.")
.arg(machineName));
@@ -215,27 +199,14 @@ static Profile createGccProfile(const QString &compilerFilePath, Settings *setti
Profile profile(!profileName.isEmpty() ? profileName : machineName, settings);
profile.removeProfile();
- if (isMingw) {
- profile.setValue(QLatin1String("qbs.targetOS"), QStringList(QLatin1String("windows")));
- }
-
- const QString compilerName = QFileInfo(compilerFilePath).fileName();
- QString toolchainPrefix;
- if (compilerName.contains(QLatin1Char('-'))) {
- QStringList nameParts = compilerName.split(QLatin1Char('-'));
- profile.setValue(QLatin1String("cpp.compilerName"), nameParts.takeLast());
- toolchainPrefix = nameParts.join(QLatin1Char('-')) + QLatin1Char('-');
- profile.setValue(QLatin1String("cpp.toolchainPrefix"), toolchainPrefix);
- }
- profile.setValue(QLatin1String("cpp.linkerName"),
- isClang ? QLatin1String("clang++") : QLatin1String("g++"));
- setCommonProperties(profile, compilerFilePath, toolchainPrefix, toolchainTypes,
- compilerTriplet.first());
+ setCommonProperties(profile, compilerFilePath, toolchainTypes, compilerTriplet.first());
// Check whether auxiliary tools reside within the toolchain's install path.
// This might not be the case when using icecc or another compiler wrapper.
const QString compilerDirPath = QFileInfo(compilerFilePath).absolutePath();
- const ToolPathSetup toolPathSetup(&profile, compilerDirPath, toolchainPrefix);
+ const ToolPathSetup toolPathSetup(&profile, compilerDirPath,
+ profile.value(QStringLiteral("cpp.toolchainPrefix"))
+ .toString());
toolPathSetup.apply(QLatin1String("ar"), QLatin1String("cpp.archiverPath"));
toolPathSetup.apply(QLatin1String("nm"), QLatin1String("cpp.nmPath"));
if (HostOsInfo::isOsxHost())
diff --git a/src/app/qbs-setup-toolchains/vsenvironmentdetector.cpp b/src/app/qbs-setup-toolchains/vsenvironmentdetector.cpp
index 7fa6dfef5..bbd76c35c 100644
--- a/src/app/qbs-setup-toolchains/vsenvironmentdetector.cpp
+++ b/src/app/qbs-setup-toolchains/vsenvironmentdetector.cpp
@@ -118,6 +118,8 @@ static void batPrintVars(QTextStream &s, const QStringList &varnames)
static QString vcArchitecture(const QString &arch)
{
+ if (arch == QLatin1String("armv7"))
+ return QLatin1String("arm");
if (arch == QLatin1String("x86_64"))
return QLatin1String("amd64");
return arch;
diff --git a/src/lib/corelib/api/languageinfo.cpp b/src/lib/corelib/api/languageinfo.cpp
index c885a1917..197e340b2 100644
--- a/src/lib/corelib/api/languageinfo.cpp
+++ b/src/lib/corelib/api/languageinfo.cpp
@@ -32,6 +32,8 @@
#include <language/builtindeclarations.h>
+#include <QStringList>
+
namespace qbs {
LanguageInfo::LanguageInfo()
@@ -40,7 +42,7 @@ LanguageInfo::LanguageInfo()
QByteArray LanguageInfo::qmlTypeInfo()
{
- Internal::BuiltinDeclarations builtins;
+ const Internal::BuiltinDeclarations &builtins = Internal::BuiltinDeclarations::instance();
// Header:
QByteArray result;
@@ -57,7 +59,7 @@ QByteArray LanguageInfo::qmlTypeInfo()
result.append(" exports: [ \"qbs/");
result.append(utf8TypeName);
result.append(" ");
- result.append(builtins.languageVersion().toUtf8());
+ result.append(builtins.languageVersion().toString().toUtf8());
result.append("\" ]\n");
result.append(" prototype: \"QQuickItem\"\n");
diff --git a/src/lib/corelib/api/runenvironment.cpp b/src/lib/corelib/api/runenvironment.cpp
index 0113c440d..94272e0d2 100644
--- a/src/lib/corelib/api/runenvironment.cpp
+++ b/src/lib/corelib/api/runenvironment.cpp
@@ -33,6 +33,7 @@
#include <api/projectdata.h>
#include <buildgraph/productinstaller.h>
#include <language/language.h>
+#include <language/propertymapinternal.h>
#include <language/scriptengine.h>
#include <logging/logger.h>
#include <logging/translator.h>
diff --git a/src/lib/corelib/buildgraph/buildgraph.cpp b/src/lib/corelib/buildgraph/buildgraph.cpp
index bb8e86cc4..05226e7f0 100644
--- a/src/lib/corelib/buildgraph/buildgraph.cpp
+++ b/src/lib/corelib/buildgraph/buildgraph.cpp
@@ -39,11 +39,13 @@
#include <jsextensions/moduleproperties.h>
#include <language/language.h>
#include <language/preparescriptobserver.h>
+#include <language/propertymapinternal.h>
#include <language/resolvedfilecontext.h>
#include <language/scriptengine.h>
#include <logging/logger.h>
#include <logging/translator.h>
#include <tools/error.h>
+#include <tools/fileinfo.h>
#include <tools/scripttools.h>
#include <tools/qbsassert.h>
diff --git a/src/lib/corelib/buildgraph/buildgraphloader.cpp b/src/lib/corelib/buildgraph/buildgraphloader.cpp
index f487badb8..a2f18bda8 100644
--- a/src/lib/corelib/buildgraph/buildgraphloader.cpp
+++ b/src/lib/corelib/buildgraph/buildgraphloader.cpp
@@ -39,10 +39,13 @@
#include "projectbuilddata.h"
#include "rulesevaluationcontext.h"
#include "transformer.h"
+
#include <language/artifactproperties.h>
#include <language/language.h>
#include <language/loader.h>
+#include <language/propertymapinternal.h>
#include <logging/translator.h>
+#include <tools/fileinfo.h>
#include <tools/persistence.h>
#include <tools/propertyfinder.h>
#include <tools/qbsassert.h>
diff --git a/src/lib/corelib/buildgraph/depscanner.cpp b/src/lib/corelib/buildgraph/depscanner.cpp
index 7bc996a87..311793f98 100644
--- a/src/lib/corelib/buildgraph/depscanner.cpp
+++ b/src/lib/corelib/buildgraph/depscanner.cpp
@@ -36,9 +36,11 @@
#include <tools/error.h>
#include <logging/translator.h>
#include <language/language.h>
+#include <language/propertymapinternal.h>
#include <language/scriptengine.h>
#include <jsextensions/moduleproperties.h>
#include <plugins/scanner/scanner.h>
+#include <tools/fileinfo.h>
#include <QVariantMap>
#include <QSet>
diff --git a/src/lib/corelib/buildgraph/executor.cpp b/src/lib/corelib/buildgraph/executor.cpp
index 2780a52a6..0bdffe74c 100644
--- a/src/lib/corelib/buildgraph/executor.cpp
+++ b/src/lib/corelib/buildgraph/executor.cpp
@@ -44,6 +44,7 @@
#include <buildgraph/transformer.h>
#include <language/language.h>
+#include <language/propertymapinternal.h>
#include <language/scriptengine.h>
#include <logging/translator.h>
#include <tools/error.h>
diff --git a/src/lib/corelib/buildgraph/productinstaller.cpp b/src/lib/corelib/buildgraph/productinstaller.cpp
index b94239f63..8f54b4358 100644
--- a/src/lib/corelib/buildgraph/productinstaller.cpp
+++ b/src/lib/corelib/buildgraph/productinstaller.cpp
@@ -31,7 +31,9 @@
#include "artifact.h"
#include "productbuilddata.h"
+
#include <language/language.h>
+#include <language/propertymapinternal.h>
#include <logging/translator.h>
#include <tools/qbsassert.h>
#include <tools/error.h>
@@ -121,13 +123,13 @@ QString ProductInstaller::targetFilePath(const TopLevelProject *project,
// This has the same effect as if installSourceBase would equal the directory of the file.
targetFilePath = FileInfo::fileName(sourceFilePath);
} else {
- const QString localAbsBasePath = QDir::cleanPath(productSourceDir + QLatin1Char('/')
- + installSourceBase);
+ const QString localAbsBasePath = FileInfo::resolvePath(QDir::cleanPath(productSourceDir),
+ QDir::cleanPath(installSourceBase));
targetFilePath = sourceFilePath;
if (!targetFilePath.startsWith(localAbsBasePath)) {
throw ErrorInfo(Tr::tr("Cannot install '%1', because it doesn't start with the"
" value of qbs.installSourceBase '%2'.").arg(sourceFilePath,
- installSourceBase));
+ localAbsBasePath));
}
targetFilePath.remove(0, localAbsBasePath.length() + 1);
diff --git a/src/lib/corelib/buildgraph/projectbuilddata.cpp b/src/lib/corelib/buildgraph/projectbuilddata.cpp
index e505fae5a..619a17ca6 100644
--- a/src/lib/corelib/buildgraph/projectbuilddata.cpp
+++ b/src/lib/corelib/buildgraph/projectbuilddata.cpp
@@ -38,11 +38,13 @@
#include "rulenode.h"
#include "rulesevaluationcontext.h"
#include "transformer.h"
+
#include <language/language.h>
#include <language/preparescriptobserver.h>
#include <language/scriptengine.h>
#include <logging/translator.h>
#include <tools/error.h>
+#include <tools/fileinfo.h>
#include <tools/persistence.h>
#include <tools/qbsassert.h>
diff --git a/src/lib/corelib/buildgraph/qtmocscanner.cpp b/src/lib/corelib/buildgraph/qtmocscanner.cpp
index 5b3e13ea6..d74e646d2 100644
--- a/src/lib/corelib/buildgraph/qtmocscanner.cpp
+++ b/src/lib/corelib/buildgraph/qtmocscanner.cpp
@@ -34,6 +34,7 @@
#include "productbuilddata.h"
#include "scanresultcache.h"
#include <logging/translator.h>
+#include <tools/fileinfo.h>
#include <tools/scannerpluginmanager.h>
#include <tools/scripttools.h>
diff --git a/src/lib/corelib/buildgraph/rulesapplicator.cpp b/src/lib/corelib/buildgraph/rulesapplicator.cpp
index df8f6cd66..d514047a9 100644
--- a/src/lib/corelib/buildgraph/rulesapplicator.cpp
+++ b/src/lib/corelib/buildgraph/rulesapplicator.cpp
@@ -37,14 +37,17 @@
#include "qtmocscanner.h"
#include "rulesevaluationcontext.h"
#include "transformer.h"
+
#include <jsextensions/moduleproperties.h>
#include <language/artifactproperties.h>
#include <language/builtindeclarations.h>
#include <language/language.h>
#include <language/preparescriptobserver.h>
+#include <language/propertymapinternal.h>
#include <language/scriptengine.h>
#include <logging/translator.h>
#include <tools/error.h>
+#include <tools/fileinfo.h>
#include <tools/scripttools.h>
#include <tools/qbsassert.h>
@@ -387,7 +390,7 @@ class ArtifactBindingsExtractor
{
QSet<QString> s;
foreach (const PropertyDeclaration &pd,
- BuiltinDeclarations().declarationsForType(
+ BuiltinDeclarations::instance().declarationsForType(
QLatin1String("Artifact")).properties()) {
s.insert(pd.name());
}
diff --git a/src/lib/corelib/buildgraph/timestampsupdater.cpp b/src/lib/corelib/buildgraph/timestampsupdater.cpp
index 994afac50..43c450199 100644
--- a/src/lib/corelib/buildgraph/timestampsupdater.cpp
+++ b/src/lib/corelib/buildgraph/timestampsupdater.cpp
@@ -33,7 +33,9 @@
#include "artifactvisitor.h"
#include "productbuilddata.h"
#include "projectbuilddata.h"
+
#include <language/language.h>
+#include <tools/fileinfo.h>
#include <tools/filetime.h>
#include <tools/qbsassert.h>
diff --git a/src/lib/corelib/buildgraph/transformer.cpp b/src/lib/corelib/buildgraph/transformer.cpp
index 37f15e44c..c0ad6ed07 100644
--- a/src/lib/corelib/buildgraph/transformer.cpp
+++ b/src/lib/corelib/buildgraph/transformer.cpp
@@ -37,6 +37,7 @@
#include <language/scriptengine.h>
#include <logging/translator.h>
#include <tools/error.h>
+#include <tools/fileinfo.h>
#include <tools/persistence.h>
#include <tools/scripttools.h>
#include <tools/qbsassert.h>
diff --git a/src/lib/corelib/corelib.qbs b/src/lib/corelib/corelib.qbs
index d0b42354b..c2a524d19 100644
--- a/src/lib/corelib/corelib.qbs
+++ b/src/lib/corelib/corelib.qbs
@@ -175,6 +175,8 @@ QbsLibrary {
"moduleproperties.h",
"process.cpp",
"process.h",
+ "temporarydir.cpp",
+ "temporarydir.h",
"textfile.cpp",
"textfile.h",
"domxml.cpp",
@@ -230,6 +232,8 @@ QbsLibrary {
"itemreader.h",
"itemreaderastvisitor.cpp",
"itemreaderastvisitor.h",
+ "itemreadervisitorstate.cpp",
+ "itemreadervisitorstate.h",
"jsimports.h",
"language.cpp",
"language.h",
diff --git a/src/lib/corelib/jsextensions/jsextensions.cpp b/src/lib/corelib/jsextensions/jsextensions.cpp
index f0ff91007..317ce67fb 100644
--- a/src/lib/corelib/jsextensions/jsextensions.cpp
+++ b/src/lib/corelib/jsextensions/jsextensions.cpp
@@ -34,6 +34,7 @@
#include "file.h"
#include "process.h"
#include "propertylist.h"
+#include "temporarydir.h"
#include "textfile.h"
#include <QScriptEngine>
@@ -68,6 +69,7 @@ JsExtensions::InitializerMap JsExtensions::initializers()
m_initializers.insert(QLatin1String("File"), &initializeJsExtensionFile);
m_initializers.insert(QLatin1String("Process"), &initializeJsExtensionProcess);
m_initializers.insert(QLatin1String("Xml"), &initializeJsExtensionXml);
+ m_initializers.insert(QLatin1String("TemporaryDir"), &initializeJsExtensionTemporaryDir);
m_initializers.insert(QLatin1String("TextFile"), &initializeJsExtensionTextFile);
m_initializers.insert(QLatin1String("PropertyList"), &initializeJsExtensionPropertyList);
}
diff --git a/src/lib/corelib/jsextensions/jsextensions.pri b/src/lib/corelib/jsextensions/jsextensions.pri
index 228675e8d..e32f01111 100644
--- a/src/lib/corelib/jsextensions/jsextensions.pri
+++ b/src/lib/corelib/jsextensions/jsextensions.pri
@@ -2,6 +2,7 @@ QT += xml
HEADERS += \
$$PWD/file.h \
+ $$PWD/temporarydir.h \
$$PWD/textfile.h \
$$PWD/process.h \
$$PWD/moduleproperties.h \
@@ -10,6 +11,7 @@ HEADERS += \
SOURCES += \
$$PWD/file.cpp \
+ $$PWD/temporarydir.cpp \
$$PWD/textfile.cpp \
$$PWD/process.cpp \
$$PWD/moduleproperties.cpp \
diff --git a/src/lib/corelib/jsextensions/moduleproperties.cpp b/src/lib/corelib/jsextensions/moduleproperties.cpp
index 6ae8322e6..d83fc34e9 100644
--- a/src/lib/corelib/jsextensions/moduleproperties.cpp
+++ b/src/lib/corelib/jsextensions/moduleproperties.cpp
@@ -32,6 +32,7 @@
#include <buildgraph/artifact.h>
#include <language/language.h>
+#include <language/propertymapinternal.h>
#include <language/scriptengine.h>
#include <logging/translator.h>
#include <tools/error.h>
diff --git a/src/lib/corelib/jsextensions/temporarydir.cpp b/src/lib/corelib/jsextensions/temporarydir.cpp
new file mode 100644
index 000000000..e01796eac
--- /dev/null
+++ b/src/lib/corelib/jsextensions/temporarydir.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt.io/licensing
+**
+** 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 The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "temporarydir.h"
+
+#include <QScriptEngine>
+#include <QScriptValue>
+#include <QTemporaryDir>
+
+namespace qbs {
+namespace Internal {
+
+void initializeJsExtensionTemporaryDir(QScriptValue extensionObject)
+{
+ QScriptEngine *engine = extensionObject.engine();
+ QScriptValue obj = engine->newQMetaObject(&TemporaryDir::staticMetaObject,
+ engine->newFunction(&TemporaryDir::ctor));
+ extensionObject.setProperty(QLatin1String("TemporaryDir"), obj);
+}
+
+QScriptValue TemporaryDir::ctor(QScriptContext *context, QScriptEngine *engine)
+{
+ TemporaryDir *t = new TemporaryDir(context);
+ QScriptValue obj = engine->newQObject(t, QScriptEngine::ScriptOwnership);
+ return obj;
+}
+
+TemporaryDir::TemporaryDir(QScriptContext *context)
+{
+ Q_UNUSED(context);
+}
+
+bool TemporaryDir::isValid() const
+{
+ return dir.isValid();
+}
+
+QString TemporaryDir::path() const
+{
+ return dir.path();
+}
+
+bool TemporaryDir::remove()
+{
+ return dir.remove();
+}
+
+} // namespace Internal
+} // namespace qbs
diff --git a/src/lib/corelib/jsextensions/temporarydir.h b/src/lib/corelib/jsextensions/temporarydir.h
new file mode 100644
index 000000000..b2ab71cc8
--- /dev/null
+++ b/src/lib/corelib/jsextensions/temporarydir.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt.io/licensing
+**
+** 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 The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_TEMPORARYDIR_H
+#define QBS_TEMPORARYDIR_H
+
+#include <QObject>
+#include <QScriptable>
+#include <QTemporaryDir>
+#include <QVariant>
+
+namespace qbs {
+namespace Internal {
+
+void initializeJsExtensionTemporaryDir(QScriptValue extensionObject);
+
+class TemporaryDir : public QObject, public QScriptable
+{
+ Q_OBJECT
+public:
+ static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine);
+ TemporaryDir(QScriptContext *context);
+ Q_INVOKABLE bool isValid() const;
+ Q_INVOKABLE QString path() const;
+ Q_INVOKABLE bool remove();
+private:
+ QTemporaryDir dir;
+};
+
+} // namespace Internal
+} // namespace qbs
+
+#endif // QBS_TEMPORARYDIR_H
diff --git a/src/lib/corelib/language/artifactproperties.h b/src/lib/corelib/language/artifactproperties.h
index 6a09c3022..242936bf7 100644
--- a/src/lib/corelib/language/artifactproperties.h
+++ b/src/lib/corelib/language/artifactproperties.h
@@ -31,8 +31,9 @@
#ifndef QBS_ARTIFACTPROPERTIES_H
#define QBS_ARTIFACTPROPERTIES_H
-#include "language.h"
+#include "filetags.h"
#include "forward_decls.h"
+
#include <tools/persistentobject.h>
namespace qbs {
diff --git a/src/lib/corelib/language/builtindeclarations.cpp b/src/lib/corelib/language/builtindeclarations.cpp
index e826f3981..973ae7a7b 100644
--- a/src/lib/corelib/language/builtindeclarations.cpp
+++ b/src/lib/corelib/language/builtindeclarations.cpp
@@ -31,18 +31,21 @@
#include "builtindeclarations.h"
#include "deprecationinfo.h"
-#include "item.h"
#include <logging/translator.h>
-#include <tools/error.h>
+
+#include <QStringList>
namespace qbs {
namespace Internal {
+class AClassWithPublicConstructor : public BuiltinDeclarations { };
+Q_GLOBAL_STATIC(AClassWithPublicConstructor, theInstance)
+
const char QBS_LANGUAGE_VERSION[] = "1.0";
BuiltinDeclarations::BuiltinDeclarations()
- : m_languageVersion(QLatin1String(QBS_LANGUAGE_VERSION))
+ : m_languageVersion(Version::fromString(QLatin1String(QBS_LANGUAGE_VERSION)))
{
addArtifactItem();
addDependsItem();
@@ -61,7 +64,12 @@ BuiltinDeclarations::BuiltinDeclarations()
addScannerItem();
}
-QString BuiltinDeclarations::languageVersion() const
+const BuiltinDeclarations &BuiltinDeclarations::instance()
+{
+ return *theInstance;
+}
+
+Version BuiltinDeclarations::languageVersion() const
{
return m_languageVersion;
}
@@ -81,40 +89,6 @@ ItemDeclaration BuiltinDeclarations::declarationsForType(const QString &typeName
return m_builtins.value(typeName);
}
-void BuiltinDeclarations::setupItemForBuiltinType(Item *item, Logger logger) const
-{
- foreach (const PropertyDeclaration &pd, declarationsForType(item->typeName()).properties()) {
- item->m_propertyDeclarations.insert(pd.name(), pd);
- ValuePtr &value = item->m_properties[pd.name()];
- if (!value) {
- JSSourceValuePtr sourceValue = JSSourceValue::create();
- sourceValue->setFile(item->file());
- static const QString undefinedKeyword = QLatin1String("undefined");
- sourceValue->setSourceCode(pd.initialValueSource().isEmpty()
- ? QStringRef(&undefinedKeyword)
- : QStringRef(&pd.initialValueSource()));
- value = sourceValue;
- } else if (pd.isDeprecated()) {
- const DeprecationInfo &di = pd.deprecationInfo();
- if (di.removalVersion() <= Version::qbsVersion()) {
- QString message = Tr::tr("The property '%1' is no longer valid for %2 items. "
- "It was removed in qbs %3.")
- .arg(pd.name(), item->typeName(), di.removalVersion().toString());
- ErrorInfo error(message, value->location());
- if (!di.additionalUserInfo().isEmpty())
- error.append(di.additionalUserInfo());
- throw error;
- }
- QString warning = Tr::tr("The property '%1' is deprecated and will be removed in "
- "qbs %2.").arg(pd.name(), di.removalVersion().toString());
- ErrorInfo error(warning, value->location());
- if (!di.additionalUserInfo().isEmpty())
- error.append(di.additionalUserInfo());
- logger.printWarning(error);
- }
- }
-}
-
void BuiltinDeclarations::insert(const ItemDeclaration &decl)
{
m_builtins.insert(decl.typeName(), decl);
diff --git a/src/lib/corelib/language/builtindeclarations.h b/src/lib/corelib/language/builtindeclarations.h
index 99b71c38a..01a403d1d 100644
--- a/src/lib/corelib/language/builtindeclarations.h
+++ b/src/lib/corelib/language/builtindeclarations.h
@@ -33,26 +33,26 @@
#include "itemdeclaration.h"
-#include <logging/logger.h>
+#include <tools/version.h>
-#include <QByteArray>
#include <QMap>
+#include <QString>
namespace qbs {
namespace Internal {
-class Item;
-
class BuiltinDeclarations
{
public:
- BuiltinDeclarations();
+ static const BuiltinDeclarations &instance();
- QString languageVersion() const;
+ Version languageVersion() const;
bool containsType(const QString &typeName) const;
QStringList allTypeNames() const;
ItemDeclaration declarationsForType(const QString &typeName) const;
- void setupItemForBuiltinType(qbs::Internal::Item *item, Logger logger) const;
+
+protected:
+ BuiltinDeclarations();
private:
void insert(const ItemDeclaration &decl);
@@ -73,7 +73,7 @@ private:
void addTransformerItem();
void addScannerItem();
- QString m_languageVersion;
+ const Version m_languageVersion;
QMap<QString, ItemDeclaration> m_builtins;
};
diff --git a/src/lib/corelib/language/evaluator.cpp b/src/lib/corelib/language/evaluator.cpp
index c8a2398f7..eedb6e497 100644
--- a/src/lib/corelib/language/evaluator.cpp
+++ b/src/lib/corelib/language/evaluator.cpp
@@ -29,23 +29,25 @@
****************************************************************************/
#include "evaluator.h"
+
#include "evaluationdata.h"
#include "evaluatorscriptclass.h"
#include "filecontext.h"
#include "filetags.h"
#include "item.h"
+#include "scriptengine.h"
+
#include <jsextensions/jsextensions.h>
#include <logging/translator.h>
#include <tools/error.h>
#include <tools/scripttools.h>
#include <tools/qbsassert.h>
+
#include <QDebug>
-#include <QScriptEngine>
namespace qbs {
namespace Internal {
-
Evaluator::Evaluator(ScriptEngine *scriptEngine, const Logger &logger)
: m_scriptEngine(scriptEngine)
, m_scriptClass(new EvaluatorScriptClass(scriptEngine, logger))
diff --git a/src/lib/corelib/language/evaluator.h b/src/lib/corelib/language/evaluator.h
index 9781f5956..6806ce65c 100644
--- a/src/lib/corelib/language/evaluator.h
+++ b/src/lib/corelib/language/evaluator.h
@@ -33,16 +33,16 @@
#include "forward_decls.h"
#include "itemobserver.h"
-#include <language/scriptengine.h>
#include <QHash>
#include <QScriptValue>
namespace qbs {
namespace Internal {
-class FileTags;
-
class EvaluatorScriptClass;
+class FileTags;
+class Logger;
+class ScriptEngine;
class Evaluator : private ItemObserver
{
@@ -52,7 +52,7 @@ public:
Evaluator(ScriptEngine *scriptEngine, const Logger &logger);
virtual ~Evaluator();
- ScriptEngine *engine() const;
+ ScriptEngine *engine() const { return m_scriptEngine; }
QScriptValue property(const Item *item, const QString &name);
QScriptValue value(const Item *item, const QString &name, bool *propertySet = 0);
@@ -82,11 +82,6 @@ private:
mutable QHash<FileContextConstPtr, QScriptValue> m_fileScopeMap;
};
-inline ScriptEngine *Evaluator::engine() const
-{
- return m_scriptEngine;
-}
-
} // namespace Internal
} // namespace qbs
diff --git a/src/lib/corelib/language/evaluatorscriptclass.cpp b/src/lib/corelib/language/evaluatorscriptclass.cpp
index 06aa9a3f8..e9e6d8d36 100644
--- a/src/lib/corelib/language/evaluatorscriptclass.cpp
+++ b/src/lib/corelib/language/evaluatorscriptclass.cpp
@@ -30,7 +30,6 @@
#include "evaluatorscriptclass.h"
-#include "builtinvalue.h"
#include "evaluationdata.h"
#include "evaluator.h"
#include "filecontext.h"
diff --git a/src/lib/corelib/language/evaluatorscriptclass.h b/src/lib/corelib/language/evaluatorscriptclass.h
index cfc2da748..7dcda5619 100644
--- a/src/lib/corelib/language/evaluatorscriptclass.h
+++ b/src/lib/corelib/language/evaluatorscriptclass.h
@@ -31,8 +31,9 @@
#ifndef QBS_EVALUATORSCRIPTCLASS_H
#define QBS_EVALUATORSCRIPTCLASS_H
-#include "value.h"
#include "builtinvalue.h"
+#include "forward_decls.h"
+
#include <logging/logger.h>
#include <QScriptClass>
diff --git a/src/lib/corelib/language/filecontext.cpp b/src/lib/corelib/language/filecontext.cpp
index cf6784be8..d8760f31a 100644
--- a/src/lib/corelib/language/filecontext.cpp
+++ b/src/lib/corelib/language/filecontext.cpp
@@ -30,6 +30,8 @@
#include "filecontext.h"
+#include "item.h"
+
namespace qbs {
namespace Internal {
@@ -43,5 +45,13 @@ FileContextPtr FileContext::create()
return FileContextPtr(new FileContext);
}
+void FileContext::ensureIdScope(ItemPool *itemPool)
+{
+ if (!m_idScope) {
+ m_idScope = Item::create(itemPool);
+ m_idScope->setTypeName(QLatin1String("IdScope"));
+ }
+}
+
} // namespace Internal
} // namespace qbs
diff --git a/src/lib/corelib/language/filecontext.h b/src/lib/corelib/language/filecontext.h
index 3d669e0c6..14219cd5b 100644
--- a/src/lib/corelib/language/filecontext.h
+++ b/src/lib/corelib/language/filecontext.h
@@ -32,31 +32,27 @@
#define QBS_FILECONTEXT_H
#include "filecontextbase.h"
-#include "item.h"
+#include "forward_decls.h"
namespace qbs {
namespace Internal {
+class Item;
+class ItemPool;
class FileContext : public FileContextBase
{
- friend class ItemReaderASTVisitor;
-
- FileContext();
-
public:
static FileContextPtr create();
- Item *idScope() const;
+ Item *idScope() const { return m_idScope; }
+ void ensureIdScope(ItemPool *itemPool);
private:
+ FileContext();
+
Item *m_idScope;
};
-inline Item *FileContext::idScope() const
-{
- return m_idScope;
-}
-
} // namespace Internal
} // namespace qbs
diff --git a/src/lib/corelib/language/filecontextbase.h b/src/lib/corelib/language/filecontextbase.h
index eec9f9f9e..aa2bbbfbe 100644
--- a/src/lib/corelib/language/filecontextbase.h
+++ b/src/lib/corelib/language/filecontextbase.h
@@ -38,23 +38,21 @@ namespace Internal {
class FileContextBase
{
- friend class ItemReaderASTVisitor;
-
public:
- void setFilePath(const QString &filePath);
- QString filePath() const;
+ void setFilePath(const QString &filePath) { m_filePath = filePath; }
+ QString filePath() const { return m_filePath; }
- void setContent(const QString &content);
- const QString &content() const;
+ void setContent(const QString &content) { m_content = content; }
+ const QString &content() const { return m_content; }
- void setJsImports(const JsImports &jsImports);
- JsImports jsImports() const;
+ void addJsImport(const JsImport &jsImport) { m_jsImports << jsImport; }
+ JsImports jsImports() const { return m_jsImports; }
- void setJsExtensions(const QStringList &extensions);
- QStringList jsExtensions() const;
+ void addJsExtension(const QString &extension) { m_jsExtensions << extension; }
+ QStringList jsExtensions() const { return m_jsExtensions; }
- void setSearchPaths(const QStringList &paths);
- QStringList searchPaths() const;
+ void setSearchPaths(const QStringList &paths) { m_searchPaths = paths; }
+ QStringList searchPaths() const { return m_searchPaths; }
QString dirPath() const;
@@ -69,56 +67,6 @@ protected:
QStringList m_searchPaths;
};
-inline void FileContextBase::setFilePath(const QString &filePath)
-{
- m_filePath = filePath;
-}
-
-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;
-}
-
-inline JsImports FileContextBase::jsImports() const
-{
- return m_jsImports;
-}
-
-inline void FileContextBase::setJsExtensions(const QStringList &extensions)
-{
- m_jsExtensions = extensions;
-}
-
-inline QStringList FileContextBase::jsExtensions() const
-{
- return m_jsExtensions;
-}
-
-inline void FileContextBase::setSearchPaths(const QStringList &paths)
-{
- m_searchPaths = paths;
-}
-
-inline QStringList FileContextBase::searchPaths() const
-{
- return m_searchPaths;
-}
-
} // namespace Internal
} // namespace qbs
diff --git a/src/lib/corelib/language/functiondeclaration.h b/src/lib/corelib/language/functiondeclaration.h
index f0e0be62d..dcf63e2ee 100644
--- a/src/lib/corelib/language/functiondeclaration.h
+++ b/src/lib/corelib/language/functiondeclaration.h
@@ -33,6 +33,8 @@
#include <tools/codelocation.h>
+#include <QString>
+
namespace qbs {
namespace Internal {
diff --git a/src/lib/corelib/language/item.cpp b/src/lib/corelib/language/item.cpp
index e2df88925..57ea4742b 100644
--- a/src/lib/corelib/language/item.cpp
+++ b/src/lib/corelib/language/item.cpp
@@ -29,8 +29,15 @@
****************************************************************************/
#include "item.h"
-#include "itempool.h"
+
+#include "builtindeclarations.h"
+#include "deprecationinfo.h"
#include "filecontext.h"
+#include "itemobserver.h"
+#include "itempool.h"
+#include "value.h"
+
+#include <logging/logger.h>
#include <logging/translator.h>
#include <tools/error.h>
#include <tools/qbsassert.h>
@@ -62,9 +69,9 @@ Item *Item::create(ItemPool *pool)
return pool->allocateItem();
}
-Item *Item::clone(ItemPool *pool) const
+Item *Item::clone() const
{
- Item *dup = create(pool);
+ Item *dup = create(pool());
dup->m_id = m_id;
dup->m_typeName = m_typeName;
dup->m_location = m_location;
@@ -80,7 +87,7 @@ Item *Item::clone(ItemPool *pool) const
dup->m_children.reserve(m_children.count());
foreach (const Item *child, m_children) {
- Item *clonedChild = child->clone(pool);
+ Item *clonedChild = child->clone();
clonedChild->m_parent = dup;
dup->m_children.append(clonedChild);
}
@@ -145,7 +152,7 @@ VariantValuePtr Item::variantProperty(const QString &name) const
return v.staticCast<VariantValue>();
}
-const PropertyDeclaration Item::propertyDeclaration(const QString &name) const
+PropertyDeclaration Item::propertyDeclaration(const QString &name) const
{
const PropertyDeclaration decl = m_propertyDeclarations.value(name);
return (!decl.isValid() && m_prototype) ? m_prototype->propertyDeclaration(name) : decl;
@@ -163,6 +170,13 @@ void Item::setPropertyObserver(ItemObserver *observer) const
m_propertyObserver = observer;
}
+void Item::setProperty(const QString &name, const ValuePtr &value)
+{
+ m_properties.insert(name, value);
+ if (m_propertyObserver)
+ m_propertyObserver->onItemPropertyChanged(this);
+}
+
void Item::dump() const
{
dump(0);
@@ -175,6 +189,46 @@ bool Item::isPresentModule() const
return v && v->type() == Value::JSSourceValueType;
}
+void Item::setupForBuiltinType(Logger &logger)
+{
+ const BuiltinDeclarations &builtins = BuiltinDeclarations::instance();
+ foreach (const PropertyDeclaration &pd, builtins.declarationsForType(typeName()).properties()) {
+ m_propertyDeclarations.insert(pd.name(), pd);
+ ValuePtr &value = m_properties[pd.name()];
+ if (!value) {
+ JSSourceValuePtr sourceValue = JSSourceValue::create();
+ sourceValue->setFile(file());
+ static const QString undefinedKeyword = QLatin1String("undefined");
+ sourceValue->setSourceCode(pd.initialValueSource().isEmpty()
+ ? QStringRef(&undefinedKeyword)
+ : QStringRef(&pd.initialValueSource()));
+ value = sourceValue;
+ } else if (pd.isDeprecated()) {
+ const DeprecationInfo &di = pd.deprecationInfo();
+ if (di.removalVersion() <= Version::qbsVersion()) {
+ QString message = Tr::tr("The property '%1' is no longer valid for %2 items. "
+ "It was removed in qbs %3.")
+ .arg(pd.name(), typeName(), di.removalVersion().toString());
+ ErrorInfo error(message, value->location());
+ if (!di.additionalUserInfo().isEmpty())
+ error.append(di.additionalUserInfo());
+ throw error;
+ }
+ QString warning = Tr::tr("The property '%1' is deprecated and will be removed in "
+ "qbs %2.").arg(pd.name(), di.removalVersion().toString());
+ ErrorInfo error(warning, value->location());
+ if (!di.additionalUserInfo().isEmpty())
+ error.append(di.additionalUserInfo());
+ logger.printWarning(error);
+ }
+ }
+}
+
+void Item::copyProperty(const QString &propertyName, Item *target) const
+{
+ target->setProperty(propertyName, property(propertyName));
+}
+
static const char *valueType(const Value *v)
{
switch (v->type()) {
@@ -248,5 +302,16 @@ Item *Item::child(const QString &type, bool checkForMultiple) const
return child;
}
+void Item::addChild(Item *parent, Item *child)
+{
+ parent->m_children.append(child);
+ child->setParent(parent);
+}
+
+void Item::setPropertyDeclaration(const QString &name, const PropertyDeclaration &declaration)
+{
+ m_propertyDeclarations.insert(name, declaration);
+}
+
} // namespace Internal
} // namespace qbs
diff --git a/src/lib/corelib/language/item.h b/src/lib/corelib/language/item.h
index cdf4905cd..bf926dae4 100644
--- a/src/lib/corelib/language/item.h
+++ b/src/lib/corelib/language/item.h
@@ -32,30 +32,24 @@
#define QBS_ITEM_H
#include "forward_decls.h"
-#include "itemobserver.h"
-#include "value.h"
#include "functiondeclaration.h"
#include "propertydeclaration.h"
#include "qualifiedid.h"
#include <parser/qmljsmemorypool_p.h>
#include <tools/codelocation.h>
#include <tools/error.h>
-#include <tools/weakpointer.h>
#include <QList>
#include <QMap>
-#include <QSharedPointer>
-#include <QStringList>
namespace qbs {
namespace Internal {
-
+class ItemObserver;
class ItemPool;
-class ProjectFile;
+class Logger;
class Item : public QbsQmlJS::Managed
{
- friend class BuiltinDeclarations;
friend class ItemPool;
friend class ItemReaderASTVisitor;
Q_DISABLE_COPY(Item)
@@ -80,24 +74,24 @@ public:
typedef QMap<QString, ValuePtr> PropertyMap;
static Item *create(ItemPool *pool);
- Item *clone(ItemPool *pool) const;
- ItemPool *pool() const;
-
- const QString &id() const;
- const QString &typeName() const;
- const CodeLocation &location() const;
- Item *prototype() const;
- Item *scope() const;
- bool isModuleInstance() const;
- Item *outerItem() const;
- Item *parent() const;
- const FileContextPtr file() const;
- QList<Item *> children() const;
+ Item *clone() const;
+ ItemPool *pool() const { return m_pool; }
+
+ const QString &id() const { return m_id; }
+ const QString &typeName() const { return m_typeName; }
+ const CodeLocation &location() const { return m_location; }
+ Item *prototype() const { return m_prototype; }
+ Item *scope() const { return m_scope; }
+ bool isModuleInstance() const { return m_moduleInstance; }
+ Item *outerItem() const { return m_outerItem; }
+ Item *parent() const { return m_parent; }
+ const FileContextPtr file() const { return m_file; }
+ QList<Item *> children() const { return m_children; }
Item *child(const QString &type, bool checkForMultiple = true) const;
- const PropertyMap &properties() const;
- const PropertyDeclarationMap &propertyDeclarations() const;
- const PropertyDeclaration propertyDeclaration(const QString &name) const;
- const Modules &modules() const;
+ const PropertyMap &properties() const { return m_properties; }
+ const PropertyDeclarationMap &propertyDeclarations() const { return m_propertyDeclarations; }
+ PropertyDeclaration propertyDeclaration(const QString &name) const;
+ const Modules &modules() const { return m_modules; }
void addModule(const Module &module);
void removeModules() { m_modules.clear(); }
void setModules(const Modules &modules) { m_modules = modules; }
@@ -113,18 +107,20 @@ public:
void setProperties(const PropertyMap &props) { m_properties = props; }
void removeProperty(const QString &name);
void setPropertyDeclaration(const QString &name, const PropertyDeclaration &declaration);
- void setTypeName(const QString &name);
- void setLocation(const CodeLocation &location);
- void setPrototype(Item *prototype);
- void setFile(const FileContextPtr &file);
- void setScope(Item *item);
- void setModuleInstanceFlag(bool b);
- void setOuterItem(Item *item);
- void setChildren(const QList<Item *> &children);
- void setParent(Item *item);
+ void setTypeName(const QString &name) { m_typeName = name; }
+ void setLocation(const CodeLocation &location) { m_location = location; }
+ void setPrototype(Item *prototype) { m_prototype = prototype; }
+ void setFile(const FileContextPtr &file) { m_file = file; }
+ void setScope(Item *item) { m_scope = item; }
+ void setModuleInstanceFlag(bool b) { m_moduleInstance = b; }
+ void setOuterItem(Item *item) { m_outerItem = item; }
+ void setChildren(const QList<Item *> &children) { m_children = children; }
+ void setParent(Item *item) { m_parent = item; }
static void addChild(Item *parent, Item *child);
void dump() const;
bool isPresentModule() const;
+ void setupForBuiltinType(Logger &logger);
+ void copyProperty(const QString &propertyName, Item *target) const;
void setDelayedError(const ErrorInfo &e) { m_delayedError = e; }
ErrorInfo delayedError() const { return m_delayedError; }
@@ -151,140 +147,6 @@ private:
ErrorInfo m_delayedError;
};
-inline ItemPool *Item::pool() const
-{
- return m_pool;
-}
-
-inline const QString &Item::id() const
-{
- return m_id;
-}
-
-inline const QString &Item::typeName() const
-{
- return m_typeName;
-}
-
-inline const CodeLocation &Item::location() const
-{
- return m_location;
-}
-
-inline Item *Item::prototype() const
-{
- return m_prototype;
-}
-
-inline Item *Item::scope() const
-{
- return m_scope;
-}
-
-inline bool Item::isModuleInstance() const
-{
- return m_moduleInstance;
-}
-
-inline Item *Item::outerItem() const
-{
- return m_outerItem;
-}
-
-inline Item *Item::parent() const
-{
- return m_parent;
-}
-
-inline const FileContextPtr Item::file() const
-{
- return m_file;
-}
-
-inline QList<Item *> Item::children() const
-{
- return m_children;
-}
-
-inline const Item::PropertyMap &Item::properties() const
-{
- return m_properties;
-}
-
-inline const Item::PropertyDeclarationMap &Item::propertyDeclarations() const
-{
- return m_propertyDeclarations;
-}
-
-inline void Item::setProperty(const QString &name, const ValuePtr &value)
-{
- m_properties.insert(name, value);
- if (m_propertyObserver)
- m_propertyObserver->onItemPropertyChanged(this);
-}
-
-inline void Item::setPropertyDeclaration(const QString &name,
- const PropertyDeclaration &declaration)
-{
- m_propertyDeclarations.insert(name, declaration);
-}
-
-inline void Item::setTypeName(const QString &name)
-{
- m_typeName = name;
-}
-
-inline void Item::setLocation(const CodeLocation &location)
-{
- m_location = location;
-}
-
-inline void Item::setPrototype(Item *prototype)
-{
- m_prototype = prototype;
-}
-
-inline void Item::setFile(const FileContextPtr &file)
-{
- m_file = file;
-}
-
-inline void Item::setScope(Item *item)
-{
- m_scope = item;
-}
-
-inline void Item::setModuleInstanceFlag(bool b)
-{
- m_moduleInstance = b;
-}
-
-inline void Item::setOuterItem(Item *item)
-{
- m_outerItem = item;
-}
-
-inline void Item::setChildren(const QList<Item *> &children)
-{
- m_children = children;
-}
-
-inline void Item::setParent(Item *item)
-{
- m_parent = item;
-}
-
-inline void Item::addChild(Item *parent, Item *child)
-{
- parent->m_children.append(child);
- child->setParent(parent);
-}
-
-inline const Item::Modules &Item::modules() const
-{
- return m_modules;
-}
-
inline bool operator<(const Item::Module &m1, const Item::Module &m2) { return m1.name < m2.name; }
} // namespace Internal
diff --git a/src/lib/corelib/language/itemdeclaration.h b/src/lib/corelib/language/itemdeclaration.h
index 2876e53e1..960e4ad75 100644
--- a/src/lib/corelib/language/itemdeclaration.h
+++ b/src/lib/corelib/language/itemdeclaration.h
@@ -32,7 +32,9 @@
#define QBS_ITEMDECLARATION_H
#include "propertydeclaration.h"
+
#include <QSet>
+#include <QString>
namespace qbs {
namespace Internal {
diff --git a/src/lib/corelib/language/itemobserver.h b/src/lib/corelib/language/itemobserver.h
index b2c823c9c..dbc4f5767 100644
--- a/src/lib/corelib/language/itemobserver.h
+++ b/src/lib/corelib/language/itemobserver.h
@@ -31,8 +31,6 @@
#ifndef QBS_ITEMOBSERVER_H
#define QBS_ITEMOBSERVER_H
-#include <QString>
-
namespace qbs {
namespace Internal {
diff --git a/src/lib/corelib/language/itemreader.cpp b/src/lib/corelib/language/itemreader.cpp
index f23b45cfd..de3e78eca 100644
--- a/src/lib/corelib/language/itemreader.cpp
+++ b/src/lib/corelib/language/itemreader.cpp
@@ -29,81 +29,19 @@
****************************************************************************/
#include "itemreader.h"
-#include "asttools.h"
-#include "itemreaderastvisitor.h"
-#include <logging/translator.h>
-#include <parser/qmljsengine_p.h>
-#include <parser/qmljslexer_p.h>
-#include <parser/qmljsparser_p.h>
-#include <tools/error.h>
-#include <QExplicitlySharedDataPointer>
-#include <QFile>
-#include <QFileInfo>
-#include <QSharedData>
-#include <QTextStream>
+
+#include "itemreadervisitorstate.h"
namespace qbs {
namespace Internal {
-class ASTCacheValueData : public QSharedData
-{
- Q_DISABLE_COPY(ASTCacheValueData)
-public:
- ASTCacheValueData()
- : ast(0)
- , processing(false)
- {
- }
-
- QString code;
- QbsQmlJS::Engine engine;
- QbsQmlJS::AST::UiProgram *ast;
- bool processing;
-};
-
-class ASTCacheValue
-{
-public:
- ASTCacheValue()
- : d(new ASTCacheValueData)
- {
- }
-
- ASTCacheValue(const ASTCacheValue &other)
- : d(other.d)
- {
- }
-
- void setProcessingFlag(bool b) { d->processing = b; }
- bool isProcessing() const { return d->processing; }
-
- void setCode(const QString &code) { d->code = code; }
- QString code() const { return d->code; }
-
- QbsQmlJS::Engine *engine() const { return &d->engine; }
-
- void setAst(QbsQmlJS::AST::UiProgram *ast) { d->ast = ast; }
- QbsQmlJS::AST::UiProgram *ast() const { return d->ast; }
- bool isValid() const { return d->ast; }
-
-private:
- QExplicitlySharedDataPointer<ASTCacheValueData> d;
-};
-
-class ItemReader::ASTCache : public QHash<QString, ASTCacheValue> {};
-
-
-ItemReader::ItemReader(BuiltinDeclarations *builtins, const Logger &logger)
- : m_pool(0)
- , m_builtins(builtins)
- , m_logger(logger)
- , m_astCache(new ASTCache)
+ItemReader::ItemReader(const Logger &logger) : m_visitorState(new ItemReaderVisitorState(logger))
{
}
ItemReader::~ItemReader()
{
- delete m_astCache;
+ delete m_visitorState;
}
void ItemReader::setSearchPaths(const QStringList &searchPaths)
@@ -135,70 +73,14 @@ QStringList ItemReader::searchPaths() const
return paths;
}
-void ItemReader::cacheDirectoryEntries(const QString &dirPath, const QStringList &entries)
-{
- m_directoryEntries.insert(dirPath, entries);
-}
-
-bool ItemReader::findDirectoryEntries(const QString &dirPath, QStringList *entries) const
-{
- const QHash<QString, QStringList>::ConstIterator it = m_directoryEntries.constFind(dirPath);
- if (it == m_directoryEntries.constEnd())
- return false;
- *entries = it.value();
- return true;
-}
-
Item *ItemReader::readFile(const QString &filePath)
{
- return internalReadFile(filePath).rootItem;
+ return m_visitorState->readFile(filePath, searchPaths(), m_pool);
}
QSet<QString> ItemReader::filesRead() const
{
- return m_filesRead;
-}
-
-ItemReaderResult ItemReader::internalReadFile(const QString &filePath)
-{
- ASTCacheValue &cacheValue = (*m_astCache)[filePath];
- if (cacheValue.isValid()) {
- if (Q_UNLIKELY(cacheValue.isProcessing()))
- throw ErrorInfo(Tr::tr("Loop detected when importing '%1'.").arg(filePath));
- } else {
- QFile file(filePath);
- if (Q_UNLIKELY(!file.open(QFile::ReadOnly)))
- throw ErrorInfo(Tr::tr("Cannot open '%1'.").arg(filePath));
-
- m_filesRead.insert(filePath);
- const QString code = QTextStream(&file).readAll();
- QbsQmlJS::Lexer lexer(cacheValue.engine());
- lexer.setCode(code, 1);
- QbsQmlJS::Parser parser(cacheValue.engine());
-
- file.close();
- if (!parser.parse()) {
- QList<QbsQmlJS::DiagnosticMessage> parserMessages = parser.diagnosticMessages();
- if (Q_UNLIKELY(!parserMessages.isEmpty())) {
- ErrorInfo err;
- foreach (const QbsQmlJS::DiagnosticMessage &msg, parserMessages)
- err.append(msg.message, toCodeLocation(filePath, msg.loc));
- throw err;
- }
- }
-
- cacheValue.setCode(code);
- cacheValue.setAst(parser.ast());
- }
-
- ItemReaderResult result;
- ItemReaderASTVisitor itemReader(this, &result);
- itemReader.setFilePath(QFileInfo(filePath).absoluteFilePath());
- itemReader.setSourceCode(cacheValue.code());
- cacheValue.setProcessingFlag(true);
- cacheValue.ast()->accept(&itemReader);
- cacheValue.setProcessingFlag(false);
- return result;
+ return m_visitorState->filesRead();
}
} // namespace Internal
diff --git a/src/lib/corelib/language/itemreader.h b/src/lib/corelib/language/itemreader.h
index de147ae9b..b77c16b82 100644
--- a/src/lib/corelib/language/itemreader.h
+++ b/src/lib/corelib/language/itemreader.h
@@ -34,7 +34,6 @@
#include "forward_decls.h"
#include <logging/logger.h>
-#include <QHash>
#include <QSet>
#include <QStack>
#include <QStringList>
@@ -42,18 +41,9 @@
namespace qbs {
namespace Internal {
-class BuiltinDeclarations;
class Item;
class ItemPool;
-
-struct ItemReaderResult
-{
- ItemReaderResult()
- : rootItem(0)
- {}
-
- Item *rootItem;
-};
+class ItemReaderVisitorState;
/*
* Reads a qbs file and creates a tree of Item objects.
@@ -66,14 +56,10 @@ struct ItemReaderResult
*/
class ItemReader
{
- friend class ItemReaderASTVisitor;
public:
- ItemReader(BuiltinDeclarations *builtins, const Logger &logger);
+ ItemReader(const Logger &logger);
~ItemReader();
- BuiltinDeclarations *builtins() const { return m_builtins; }
- Logger logger() const { return m_logger; }
-
void setPool(ItemPool *pool) { m_pool = pool; }
void setSearchPaths(const QStringList &searchPaths);
void pushExtraSearchPaths(const QStringList &extraSearchPaths);
@@ -88,22 +74,10 @@ public:
QSet<QString> filesRead() const;
private:
- ItemReaderResult internalReadFile(const QString &filePath);
-
- void cacheDirectoryEntries(const QString &dirPath, const QStringList &entries);
- bool findDirectoryEntries(const QString &dirPath, QStringList *entries) const;
-
- ItemPool *m_pool;
- BuiltinDeclarations *m_builtins;
- Logger m_logger;
+ ItemPool *m_pool = nullptr;
QStringList m_searchPaths;
QStack<QStringList> m_extraSearchPaths;
- QHash<const Item *, QSet<JSSourceValuePtr> > m_conditionalValuesPerScopeItem;
-
- class ASTCache;
- ASTCache *m_astCache;
- QSet<QString> m_filesRead;
- QHash<QString, QStringList> m_directoryEntries;
+ ItemReaderVisitorState * const m_visitorState;
};
} // namespace Internal
diff --git a/src/lib/corelib/language/itemreaderastvisitor.cpp b/src/lib/corelib/language/itemreaderastvisitor.cpp
index ff8f48e6f..712008d96 100644
--- a/src/lib/corelib/language/itemreaderastvisitor.cpp
+++ b/src/lib/corelib/language/itemreaderastvisitor.cpp
@@ -29,10 +29,15 @@
****************************************************************************/
#include "itemreaderastvisitor.h"
+
#include "asttools.h"
#include "builtindeclarations.h"
+#include "filecontext.h"
#include "identifiersearch.h"
-#include "itemreader.h"
+#include "item.h"
+#include "itemreadervisitorstate.h"
+#include "value.h"
+
#include <jsextensions/jsextensions.h>
#include <parser/qmljsast_p.h>
#include <tools/error.h>
@@ -43,20 +48,19 @@
#include <QDirIterator>
#include <QFileInfo>
-#include <QStringList>
using namespace QbsQmlJS;
namespace qbs {
namespace Internal {
-ItemReaderASTVisitor::ItemReaderASTVisitor(ItemReader *reader, ItemReaderResult *result)
- : m_reader(reader)
- , m_readerResult(result)
- , m_languageVersion(readImportVersion(reader->builtins()->languageVersion()))
+ItemReaderASTVisitor::ItemReaderASTVisitor(ItemReaderVisitorState &visitorState,
+ ItemPool *itemPool, Logger logger, const QStringList &searchPaths)
+ : m_visitorState(visitorState)
, m_file(FileContext::create())
- , m_item(0)
- , m_sourceValue(0)
+ , m_itemPool(itemPool)
+ , m_logger(logger)
+ , m_searchPaths(searchPaths)
{
}
@@ -78,7 +82,7 @@ bool ItemReaderASTVisitor::visit(AST::UiProgram *ast)
{
Q_UNUSED(ast);
m_sourceValue.clear();
- m_file->m_searchPaths = m_reader->searchPaths();
+ m_file->setSearchPaths(m_searchPaths);
if (Q_UNLIKELY(!ast->members->member))
throw ErrorInfo(Tr::tr("No root item found in %1.").arg(m_file->filePath()));
@@ -109,7 +113,7 @@ bool ItemReaderASTVisitor::addPrototype(const QString &fileName, const QString &
void ItemReaderASTVisitor::collectPrototypes(const QString &path, const QString &as)
{
QStringList fileNames; // Yes, file *names*.
- if (m_reader->findDirectoryEntries(path, &fileNames)) {
+ if (m_visitorState.findDirectoryEntries(path, &fileNames)) {
foreach (const QString &fileName, fileNames)
addPrototype(fileName, path + QLatin1Char('/') + fileName, as, false);
return;
@@ -122,12 +126,12 @@ void ItemReaderASTVisitor::collectPrototypes(const QString &path, const QString
if (addPrototype(fileName, filePath, as, true))
fileNames << fileName;
}
- m_reader->cacheDirectoryEntries(path, fileNames);
+ m_visitorState.cacheDirectoryEntries(path, fileNames);
}
bool ItemReaderASTVisitor::visit(AST::UiImportList *uiImportList)
{
- foreach (const QString &searchPath, m_reader->searchPaths())
+ foreach (const QString &searchPath, m_searchPaths)
collectPrototypes(searchPath + QLatin1String("/imports"), QString());
const QString path = FileInfo::path(m_file->filePath());
@@ -151,8 +155,8 @@ bool ItemReaderASTVisitor::visit(AST::UiImportList *uiImportList)
if (isBase)
checkImportVersion(import->versionToken);
else if (import->versionToken.length)
- m_reader->logger().printWarning(ErrorInfo(Tr::tr("Superfluous version specification."),
- toCodeLocation(import->versionToken)));
+ m_logger.printWarning(ErrorInfo(Tr::tr("Superfluous version specification."),
+ toCodeLocation(import->versionToken)));
}
QString as;
@@ -169,11 +173,11 @@ bool ItemReaderASTVisitor::visit(AST::UiImportList *uiImportList)
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));
+ if (Q_UNLIKELY(m_file->jsExtensions().contains(extensionName))) {
+ m_logger.printWarning(Tr::tr("Built-in extension '%1' already "
+ "imported.").arg(extensionName));
} else {
- m_file->m_jsExtensions << extensionName;
+ m_file->addJsExtension(extensionName);
}
continue;
}
@@ -234,7 +238,7 @@ bool ItemReaderASTVisitor::visit(AST::UiImportList *uiImportList)
? QLatin1String("qbs/base") : importUri.join(QDir::separator());
bool found = m_typeNameToFile.contains(importUri);
if (!found) {
- foreach (const QString &searchPath, m_reader->searchPaths()) {
+ foreach (const QString &searchPath, m_searchPaths) {
const QFileInfo fi(FileInfo::resolvePath(
FileInfo::resolvePath(searchPath,
QLatin1String("imports")),
@@ -270,7 +274,7 @@ bool ItemReaderASTVisitor::visit(AST::UiImportList *uiImportList)
for (QHash<QString, JsImport>::const_iterator it = jsImports.constBegin();
it != jsImports.constEnd(); ++it)
{
- m_file->m_jsImports += it.value();
+ m_file->addJsImport(it.value());
}
return false;
@@ -280,7 +284,7 @@ bool ItemReaderASTVisitor::visit(AST::UiObjectDefinition *ast)
{
const QString typeName = ast->qualifiedTypeNameId->name.toString();
- Item *item = Item::create(m_reader->m_pool);
+ Item *item = Item::create(m_itemPool);
item->m_file = m_file;
item->m_parent = m_item;
item->m_typeName = typeName;
@@ -293,7 +297,7 @@ bool ItemReaderASTVisitor::visit(AST::UiObjectDefinition *ast)
} else {
// This is the root item.
m_item = item;
- m_readerResult->rootItem = item;
+ m_rootItem = item;
}
if (ast->initializer) {
@@ -302,7 +306,7 @@ bool ItemReaderASTVisitor::visit(AST::UiObjectDefinition *ast)
qSwap(m_item, item);
}
- m_reader->m_builtins->setupItemForBuiltinType(item, m_reader->logger());
+ item->setupForBuiltinType(m_logger);
if (item->typeName() != QLatin1String("Properties")
&& item->typeName() != QLatin1String("SubProject")) {
@@ -313,14 +317,15 @@ bool ItemReaderASTVisitor::visit(AST::UiObjectDefinition *ast)
const QStringList fullTypeName = toStringList(ast->qualifiedTypeNameId);
const QString baseTypeFileName = m_typeNameToFile.value(fullTypeName);
if (!baseTypeFileName.isEmpty()) {
- const ItemReaderResult baseFile = m_reader->internalReadFile(baseTypeFileName);
+ const Item * const rootItem
+ = m_visitorState.readFile(baseTypeFileName, m_searchPaths, m_itemPool);
- inheritItem(item, baseFile.rootItem);
- if (baseFile.rootItem->m_file->m_idScope) {
+ inheritItem(item, rootItem);
+ if (rootItem->m_file->idScope()) {
// Make ids from the derived file visible in the base file.
// ### Do we want to turn off this feature? It's QMLish but kind of strange.
- ensureIdScope(item->m_file);
- baseFile.rootItem->m_file->m_idScope->setPrototype(item->m_file->m_idScope);
+ item->m_file->ensureIdScope(m_itemPool);
+ rootItem->m_file->idScope()->setPrototype(item->m_file->idScope());
}
}
@@ -390,8 +395,8 @@ bool ItemReaderASTVisitor::visit(AST::UiScriptBinding *ast)
if (Q_UNLIKELY(!idExp || idExp->name.isEmpty()))
throw ErrorInfo(Tr::tr("id: must be followed by identifier"));
m_item->m_id = idExp->name.toString();
- ensureIdScope(m_file);
- m_file->m_idScope->m_properties[m_item->m_id] = ItemValue::create(m_item);
+ m_file->ensureIdScope(m_itemPool);
+ m_file->idScope()->m_properties[m_item->m_id] = ItemValue::create(m_item);
return false;
}
@@ -476,7 +481,7 @@ Item *ItemReaderASTVisitor::targetItemForBinding(Item *item,
for (int i = 0; i < c; ++i) {
ValuePtr v = targetItem->m_properties.value(bindingName.at(i));
if (!v) {
- Item *newItem = Item::create(m_reader->m_pool);
+ Item *newItem = Item::create(m_itemPool);
v = ItemValue::create(newItem);
targetItem->m_properties.insert(bindingName.at(i), v);
}
@@ -497,10 +502,11 @@ void ItemReaderASTVisitor::checkImportVersion(const AST::SourceLocation &version
const QString importVersionString = m_file->content().mid(versionToken.offset, versionToken.length);
const Version importVersion = readImportVersion(importVersionString,
toCodeLocation(versionToken));
- if (Q_UNLIKELY(importVersion != m_languageVersion))
+ if (Q_UNLIKELY(importVersion != BuiltinDeclarations::instance().languageVersion()))
throw ErrorInfo(Tr::tr("Incompatible qbs language version %1. This is version %2.").arg(
- importVersionString, m_reader->builtins()->languageVersion()),
- toCodeLocation(versionToken));
+ importVersionString,
+ BuiltinDeclarations::instance().languageVersion().toString()),
+ toCodeLocation(versionToken));
}
void ItemReaderASTVisitor::inheritItem(Item *dst, const Item *src)
@@ -553,14 +559,6 @@ void ItemReaderASTVisitor::inheritItem(Item *dst, const Item *src)
}
}
-void ItemReaderASTVisitor::ensureIdScope(const FileContextPtr &file)
-{
- if (!file->m_idScope) {
- file->m_idScope = Item::create(m_reader->m_pool);
- file->m_idScope->m_typeName = QLatin1String("IdScope");
- }
-}
-
void ItemReaderASTVisitor::setupAlternatives(Item *item)
{
QList<Item *>::iterator it = item->m_children.begin();
diff --git a/src/lib/corelib/language/itemreaderastvisitor.h b/src/lib/corelib/language/itemreaderastvisitor.h
index 5f777f1bf..cf85b852f 100644
--- a/src/lib/corelib/language/itemreaderastvisitor.h
+++ b/src/lib/corelib/language/itemreaderastvisitor.h
@@ -31,24 +31,27 @@
#ifndef QBS_ITEMREADERASTVISITOR_H
#define QBS_ITEMREADERASTVISITOR_H
-#include "item.h"
-#include "filecontext.h"
+#include "forward_decls.h"
+#include <logging/logger.h>
#include <parser/qmljsastvisitor_p.h>
-#include <tools/version.h>
+#include <tools/codelocation.h>
#include <QHash>
+#include <QStringList>
namespace qbs {
namespace Internal {
-
-class ItemReader;
-struct ItemReaderResult;
+class Item;
+class ItemPool;
+class ItemReaderVisitorState;
+class Version;
class ItemReaderASTVisitor : public QbsQmlJS::AST::Visitor
{
public:
- ItemReaderASTVisitor(ItemReader *reader, ItemReaderResult *result);
+ ItemReaderASTVisitor(ItemReaderVisitorState &visitorState,
+ ItemPool *itemPool, Logger logger, const QStringList &searchPaths);
~ItemReaderASTVisitor();
void setFilePath(const QString &filePath);
@@ -61,6 +64,8 @@ public:
bool visit(QbsQmlJS::AST::UiScriptBinding *ast);
bool visit(QbsQmlJS::AST::FunctionDeclaration *ast);
+ Item *rootItem() const { return m_rootItem; }
+
private:
static Version readImportVersion(const QString &str,
const CodeLocation &location = CodeLocation());
@@ -72,7 +77,6 @@ private:
const JSSourceValueConstPtr &value);
void checkImportVersion(const QbsQmlJS::AST::SourceLocation &versionToken) const;
static void inheritItem(Item *dst, const Item *src);
- void ensureIdScope(const FileContextPtr &file);
void setupAlternatives(Item *item);
static void replaceConditionScopes(const JSSourceValuePtr &value, Item *newScope);
void handlePropertiesBlock(Item *item, const Item *block);
@@ -80,12 +84,14 @@ private:
bool addPrototype(const QString &fileName, const QString &filePath, const QString &as,
bool needsCheck);
- ItemReader *m_reader;
- ItemReaderResult *m_readerResult;
- const Version m_languageVersion;
- FileContextPtr m_file;
+ ItemReaderVisitorState &m_visitorState;
+ const FileContextPtr m_file;
+ ItemPool * const m_itemPool;
+ Logger m_logger;
+ const QStringList m_searchPaths;
QHash<QStringList, QString> m_typeNameToFile;
- Item *m_item;
+ Item *m_item = nullptr;
+ Item *m_rootItem = nullptr;
JSSourceValuePtr m_sourceValue;
};
diff --git a/src/lib/corelib/language/itemreadervisitorstate.cpp b/src/lib/corelib/language/itemreadervisitorstate.cpp
new file mode 100644
index 000000000..4eeb7df38
--- /dev/null
+++ b/src/lib/corelib/language/itemreadervisitorstate.cpp
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** 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 The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#include "itemreadervisitorstate.h"
+
+#include "asttools.h"
+#include "itemreaderastvisitor.h"
+
+#include <logging/translator.h>
+#include <parser/qmljsengine_p.h>
+#include <parser/qmljslexer_p.h>
+#include <parser/qmljsparser_p.h>
+#include <tools/error.h>
+
+#include <QExplicitlySharedDataPointer>
+#include <QFile>
+#include <QFileInfo>
+#include <QSharedData>
+#include <QTextStream>
+
+namespace qbs {
+namespace Internal {
+
+class ASTCacheValueData : public QSharedData
+{
+ Q_DISABLE_COPY(ASTCacheValueData)
+public:
+ ASTCacheValueData()
+ : ast(0)
+ , processing(false)
+ {
+ }
+
+ QString code;
+ QbsQmlJS::Engine engine;
+ QbsQmlJS::AST::UiProgram *ast;
+ bool processing;
+};
+
+class ASTCacheValue
+{
+public:
+ ASTCacheValue()
+ : d(new ASTCacheValueData)
+ {
+ }
+
+ ASTCacheValue(const ASTCacheValue &other)
+ : d(other.d)
+ {
+ }
+
+ void setProcessingFlag(bool b) { d->processing = b; }
+ bool isProcessing() const { return d->processing; }
+
+ void setCode(const QString &code) { d->code = code; }
+ QString code() const { return d->code; }
+
+ QbsQmlJS::Engine *engine() const { return &d->engine; }
+
+ void setAst(QbsQmlJS::AST::UiProgram *ast) { d->ast = ast; }
+ QbsQmlJS::AST::UiProgram *ast() const { return d->ast; }
+ bool isValid() const { return d->ast; }
+
+private:
+ QExplicitlySharedDataPointer<ASTCacheValueData> d;
+};
+
+class ItemReaderVisitorState::ASTCache : public QHash<QString, ASTCacheValue> {};
+
+
+ItemReaderVisitorState::ItemReaderVisitorState(Logger logger)
+ : m_logger(logger)
+ , m_astCache(new ASTCache)
+{
+
+}
+
+ItemReaderVisitorState::~ItemReaderVisitorState()
+{
+ delete m_astCache;
+}
+
+Item *ItemReaderVisitorState::readFile(const QString &filePath, const QStringList &searchPaths,
+ ItemPool *itemPool)
+{
+ ASTCacheValue &cacheValue = (*m_astCache)[filePath];
+ if (cacheValue.isValid()) {
+ if (Q_UNLIKELY(cacheValue.isProcessing()))
+ throw ErrorInfo(Tr::tr("Loop detected when importing '%1'.").arg(filePath));
+ } else {
+ QFile file(filePath);
+ if (Q_UNLIKELY(!file.open(QFile::ReadOnly)))
+ throw ErrorInfo(Tr::tr("Cannot open '%1'.").arg(filePath));
+
+ m_filesRead.insert(filePath);
+ const QString code = QTextStream(&file).readAll();
+ QbsQmlJS::Lexer lexer(cacheValue.engine());
+ lexer.setCode(code, 1);
+ QbsQmlJS::Parser parser(cacheValue.engine());
+
+ file.close();
+ if (!parser.parse()) {
+ QList<QbsQmlJS::DiagnosticMessage> parserMessages = parser.diagnosticMessages();
+ if (Q_UNLIKELY(!parserMessages.isEmpty())) {
+ ErrorInfo err;
+ foreach (const QbsQmlJS::DiagnosticMessage &msg, parserMessages)
+ err.append(msg.message, toCodeLocation(filePath, msg.loc));
+ throw err;
+ }
+ }
+
+ cacheValue.setCode(code);
+ cacheValue.setAst(parser.ast());
+ }
+
+ ItemReaderASTVisitor astVisitor(*this, itemPool, m_logger, searchPaths);
+ astVisitor.setFilePath(QFileInfo(filePath).absoluteFilePath());
+ astVisitor.setSourceCode(cacheValue.code());
+ cacheValue.setProcessingFlag(true);
+ cacheValue.ast()->accept(&astVisitor);
+ cacheValue.setProcessingFlag(false);
+ return astVisitor.rootItem();
+}
+
+void ItemReaderVisitorState::cacheDirectoryEntries(const QString &dirPath, const QStringList &entries)
+{
+ m_directoryEntries.insert(dirPath, entries);
+}
+
+bool ItemReaderVisitorState::findDirectoryEntries(const QString &dirPath, QStringList *entries) const
+{
+ const auto it = m_directoryEntries.constFind(dirPath);
+ if (it == m_directoryEntries.constEnd())
+ return false;
+ *entries = it.value();
+ return true;
+}
+
+
+} // namespace Internal
+} // namespace qbs
diff --git a/src/lib/corelib/language/itemreadervisitorstate.h b/src/lib/corelib/language/itemreadervisitorstate.h
new file mode 100644
index 000000000..6f6934f3a
--- /dev/null
+++ b/src/lib/corelib/language/itemreadervisitorstate.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** 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 The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#ifndef QBS_ITEMREADERVISITORSTATE_H
+#define QBS_ITEMREADERVISITORSTATE_H
+
+#include <logging/logger.h>
+
+#include <QSet>
+#include <QStack>
+#include <QStringList>
+
+namespace qbs {
+namespace Internal {
+class Item;
+class ItemPool;
+
+class ItemReaderVisitorState
+{
+public:
+ ItemReaderVisitorState(Logger logger);
+ ~ItemReaderVisitorState();
+
+ QSet<QString> filesRead() const { return m_filesRead; }
+
+ Item *readFile(const QString &filePath, const QStringList &searchPaths, ItemPool *itemPool);
+
+ void cacheDirectoryEntries(const QString &dirPath, const QStringList &entries);
+ bool findDirectoryEntries(const QString &dirPath, QStringList *entries) const;
+
+private:
+ Logger m_logger;
+ QSet<QString> m_filesRead;
+ QHash<QString, QStringList> m_directoryEntries;
+
+ class ASTCache;
+ ASTCache * const m_astCache;
+};
+
+} // namespace Internal
+} // namespace qbs
+
+#endif // Include guard.
diff --git a/src/lib/corelib/language/jsimports.h b/src/lib/corelib/language/jsimports.h
index cb90ae98d..0cbceeea2 100644
--- a/src/lib/corelib/language/jsimports.h
+++ b/src/lib/corelib/language/jsimports.h
@@ -32,8 +32,8 @@
#define QBS_JSIMPORTS_H
#include <tools/codelocation.h>
+
#include <QHash>
-#include <QSet>
#include <QStringList>
namespace qbs {
diff --git a/src/lib/corelib/language/language.cpp b/src/lib/corelib/language/language.cpp
index cde38d86c..18f7024f1 100644
--- a/src/lib/corelib/language/language.cpp
+++ b/src/lib/corelib/language/language.cpp
@@ -31,9 +31,12 @@
#include "language.h"
#include "artifactproperties.h"
+#include "propertymapinternal.h"
#include "resolvedfilecontext.h"
#include "scriptengine.h"
+
#include <buildgraph/artifact.h>
+#include <buildgraph/artifactset.h>
#include <buildgraph/productbuilddata.h>
#include <buildgraph/projectbuilddata.h>
#include <buildgraph/rulegraph.h> // TODO: Move to language?
@@ -43,7 +46,7 @@
#include <tools/buildgraphlocker.h>
#include <tools/hostosinfo.h>
#include <tools/error.h>
-#include <tools/propertyfinder.h>
+#include <tools/fileinfo.h>
#include <tools/persistence.h>
#include <tools/qbsassert.h>
diff --git a/src/lib/corelib/language/language.h b/src/lib/corelib/language/language.h
index f93ef01e9..b86cba33d 100644
--- a/src/lib/corelib/language/language.h
+++ b/src/lib/corelib/language/language.h
@@ -34,22 +34,18 @@
#include "filetags.h"
#include "forward_decls.h"
#include "jsimports.h"
-#include "propertymapinternal.h"
-#include <buildgraph/artifactset.h>
+
#include <buildgraph/forward_decls.h>
#include <tools/codelocation.h>
-#include <tools/fileinfo.h>
+#include <tools/filetime.h>
#include <tools/persistentobject.h>
-#include <tools/settings.h>
#include <tools/weakpointer.h>
-#include <QByteArray>
#include <QDataStream>
#include <QHash>
#include <QMutex>
#include <QProcessEnvironment>
#include <QRegExp>
-#include <QScriptProgram>
#include <QScriptValue>
#include <QScopedPointer>
#include <QSet>
diff --git a/src/lib/corelib/language/language.pri b/src/lib/corelib/language/language.pri
index 7c984176f..68c8139d7 100644
--- a/src/lib/corelib/language/language.pri
+++ b/src/lib/corelib/language/language.pri
@@ -21,6 +21,7 @@ HEADERS += \
$$PWD/itempool.h \
$$PWD/itemreader.h \
$$PWD/itemreaderastvisitor.h \
+ $$PWD/itemreadervisitorstate.h \
$$PWD/jsimports.h \
$$PWD/language.h \
$$PWD/loader.h \
@@ -53,6 +54,7 @@ SOURCES += \
$$PWD/itempool.cpp \
$$PWD/itemreader.cpp \
$$PWD/itemreaderastvisitor.cpp \
+ $$PWD/itemreadervisitorstate.cpp \
$$PWD/language.cpp \
$$PWD/loader.cpp \
$$PWD/moduleloader.cpp \
diff --git a/src/lib/corelib/language/loader.cpp b/src/lib/corelib/language/loader.cpp
index cb15c1ec8..7c2a0bf72 100644
--- a/src/lib/corelib/language/loader.cpp
+++ b/src/lib/corelib/language/loader.cpp
@@ -30,10 +30,11 @@
#include "loader.h"
-#include "builtindeclarations.h"
-#include "item.h"
+#include "language.h"
#include "moduleloader.h"
#include "projectresolver.h"
+#include "scriptengine.h"
+
#include <logging/translator.h>
#include <tools/fileinfo.h>
#include <tools/progressobserver.h>
@@ -41,6 +42,7 @@
#include <tools/setupprojectparameters.h>
#include <QDir>
+#include <QObject>
#include <QTimer>
namespace qbs {
@@ -49,25 +51,13 @@ namespace Internal {
Loader::Loader(ScriptEngine *engine, const Logger &logger)
: m_logger(logger)
, m_progressObserver(0)
- , m_builtins(new BuiltinDeclarations)
- , m_moduleLoader(new ModuleLoader(engine, m_builtins, logger))
- , m_projectResolver(new ProjectResolver(m_moduleLoader, m_builtins, logger))
, m_engine(engine)
{
}
-Loader::~Loader()
-{
- delete m_projectResolver;
- delete m_moduleLoader;
- delete m_builtins;
-}
-
void Loader::setProgressObserver(ProgressObserver *observer)
{
m_progressObserver = observer;
- m_moduleLoader->setProgressObserver(observer);
- m_projectResolver->setProgressObserver(observer);
}
void Loader::setSearchPaths(const QStringList &_searchPaths)
@@ -82,7 +72,7 @@ void Loader::setSearchPaths(const QStringList &_searchPaths)
}
}
- m_moduleLoader->setSearchPaths(searchPaths);
+ m_searchPaths = searchPaths;
}
TopLevelProjectPtr Loader::loadProject(const SetupProjectParameters &parameters)
@@ -91,6 +81,8 @@ TopLevelProjectPtr Loader::loadProject(const SetupProjectParameters &parameters)
m_engine->setEnvironment(parameters.adjustedEnvironment());
m_engine->clearExceptions();
+ m_engine->clearImportsCache();
+ m_engine->clearRequestedProperties();
QTimer cancelationTimer;
@@ -103,13 +95,22 @@ TopLevelProjectPtr Loader::loadProject(const SetupProjectParameters &parameters)
.arg(TopLevelProject::deriveId(parameters.topLevelProfile(),
parameters.finalBuildConfigurationTree())), 1);
cancelationTimer.setSingleShot(false);
- QObject::connect(&cancelationTimer, SIGNAL(timeout()), SLOT(checkForCancelation()));
+ QObject::connect(&cancelationTimer, &QTimer::timeout, [this]() {
+ QBS_ASSERT(m_progressObserver, return);
+ if (m_progressObserver->canceled())
+ m_engine->cancel();
+ });
cancelationTimer.start(1000);
}
const FileTime resolveTime = FileTime::currentTime();
- ModuleLoaderResult loadResult = m_moduleLoader->load(parameters);
- const TopLevelProjectPtr project = m_projectResolver->resolve(loadResult, parameters);
+ ModuleLoader moduleLoader(m_engine, m_logger);
+ moduleLoader.setProgressObserver(m_progressObserver);
+ moduleLoader.setSearchPaths(m_searchPaths);
+ ModuleLoaderResult loadResult = moduleLoader.load(parameters);
+ ProjectResolver resolver(&moduleLoader, m_logger);
+ resolver.setProgressObserver(m_progressObserver);
+ const TopLevelProjectPtr project = resolver.resolve(loadResult, parameters);
project->lastResolveTime = resolveTime;
// E.g. if the top-level project is disabled.
@@ -119,12 +120,5 @@ TopLevelProjectPtr Loader::loadProject(const SetupProjectParameters &parameters)
return project;
}
-void Loader::checkForCancelation()
-{
- QBS_ASSERT(m_progressObserver, return);
- if (m_progressObserver->canceled())
- m_engine->cancel();
-}
-
} // namespace Internal
} // namespace qbs
diff --git a/src/lib/corelib/language/loader.h b/src/lib/corelib/language/loader.h
index 827f9113e..ee2e85c7a 100644
--- a/src/lib/corelib/language/loader.h
+++ b/src/lib/corelib/language/loader.h
@@ -33,41 +33,30 @@
#include "forward_decls.h"
#include <logging/logger.h>
-#include <QObject>
#include <QStringList>
namespace qbs {
class Settings;
class SetupProjectParameters;
namespace Internal {
-class BuiltinDeclarations;
class Logger;
-class ModuleLoader;
class ProgressObserver;
class ScriptEngine;
-class ProjectResolver;
-class Loader : public QObject
+class Loader
{
- Q_OBJECT
public:
Loader(ScriptEngine *engine, const Logger &logger);
- ~Loader();
void setProgressObserver(ProgressObserver *observer);
void setSearchPaths(const QStringList &searchPaths);
TopLevelProjectPtr loadProject(const SetupProjectParameters &parameters);
-private slots:
- void checkForCancelation();
-
private:
Logger m_logger;
ProgressObserver *m_progressObserver;
- BuiltinDeclarations *m_builtins;
- ModuleLoader *m_moduleLoader;
- ProjectResolver *m_projectResolver;
ScriptEngine * const m_engine;
+ QStringList m_searchPaths;
};
} // namespace Internal
diff --git a/src/lib/corelib/language/moduleloader.cpp b/src/lib/corelib/language/moduleloader.cpp
index 77340d179..367e186be 100644
--- a/src/lib/corelib/language/moduleloader.cpp
+++ b/src/lib/corelib/language/moduleloader.cpp
@@ -36,20 +36,20 @@
#include "filecontext.h"
#include "item.h"
#include "itemreader.h"
+#include "qualifiedid.h"
#include "scriptengine.h"
#include "value.h"
+
#include <language/language.h>
#include <language/scriptengine.h>
#include <logging/logger.h>
#include <logging/translator.h>
#include <tools/error.h>
#include <tools/fileinfo.h>
-#include <tools/hostosinfo.h>
#include <tools/preferences.h>
#include <tools/profile.h>
#include <tools/progressobserver.h>
#include <tools/qbsassert.h>
-#include <tools/qttools.h>
#include <tools/scripttools.h>
#include <tools/settings.h>
@@ -65,13 +65,13 @@ class ModuleLoader::ItemModuleList : public QList<Item::Module> {};
const QString moduleSearchSubDir = QLatin1String("modules");
-ModuleLoader::ModuleLoader(ScriptEngine *engine, BuiltinDeclarations *builtins,
+ModuleLoader::ModuleLoader(ScriptEngine *engine,
const Logger &logger)
: m_engine(engine)
, m_pool(0)
, m_logger(logger)
, m_progressObserver(0)
- , m_reader(new ItemReader(builtins, logger))
+ , m_reader(new ItemReader(logger))
, m_evaluator(new Evaluator(engine, logger))
{
}
@@ -425,7 +425,7 @@ QList<Item *> ModuleLoader::multiplexProductItem(ProductContext *dummyContext, I
}
if (i == 0)
continue; // We use the original item for the first profile.
- Item * const cloned = productItem->clone(productItem->pool());
+ Item * const cloned = productItem->clone();
cloned->setProperty(profileKey, VariantValue::create(profileNames.at(i)));
additionalProductItems << cloned;
}
@@ -641,7 +641,7 @@ Item *ModuleLoader::mergeExportItems(ModuleLoader::ProductContext *productContex
}
productContext->item->setChildren(children);
Item::addChild(productContext->item, merged);
- m_reader->builtins()->setupItemForBuiltinType(merged, m_logger);
+ merged->setupForBuiltinType(m_logger);
return merged;
}
@@ -1261,8 +1261,8 @@ void ModuleLoader::instantiateModule(ProductContext *productContext, Item *expor
QBS_CHECK(instanceScope->file());
moduleScope->setFile(instanceScope->file());
moduleScope->setScope(instanceScope);
- copyProperty(QLatin1String("project"), productContext->project->scope, moduleScope);
- copyProperty(QLatin1String("product"), productContext->scope, moduleScope);
+ productContext->project->scope->copyProperty(QLatin1String("project"), moduleScope);
+ productContext->scope->copyProperty(QLatin1String("product"), moduleScope);
if (isProduct) {
exportingProduct = 0;
@@ -1438,12 +1438,13 @@ bool ModuleLoader::checkItemCondition(Item *item)
void ModuleLoader::checkItemTypes(Item *item)
{
if (Q_UNLIKELY(!item->typeName().isEmpty()
- && !m_reader->builtins()->containsType(item->typeName()))) {
+ && !BuiltinDeclarations::instance().containsType(item->typeName()))) {
const QString msg = Tr::tr("Unexpected item type '%1'.");
throw ErrorInfo(msg.arg(item->typeName()), item->location());
}
- const ItemDeclaration decl = m_reader->builtins()->declarationsForType(item->typeName());
+ const ItemDeclaration decl
+ = BuiltinDeclarations::instance().declarationsForType(item->typeName());
foreach (Item *child, item->children()) {
if (child->typeName().isEmpty())
continue;
@@ -1477,8 +1478,8 @@ void ModuleLoader::copyProperties(const Item *sourceProject, Item *targetProject
{
if (!sourceProject)
return;
- const QList<PropertyDeclaration> &builtinProjectProperties
- = m_reader->builtins()->declarationsForType(QLatin1String("Project")).properties();
+ const QList<PropertyDeclaration> &builtinProjectProperties = BuiltinDeclarations::instance()
+ .declarationsForType(QLatin1String("Project")).properties();
QSet<QString> builtinProjectPropertyNames;
foreach (const PropertyDeclaration &p, builtinProjectProperties)
builtinProjectPropertyNames << p.name();
@@ -1496,7 +1497,7 @@ void ModuleLoader::copyProperties(const Item *sourceProject, Item *targetProject
= targetProject->property(it.key()).dynamicCast<const JSSourceValue>();
QBS_ASSERT(v, continue);
if (v->sourceCode() == QLatin1String("undefined"))
- copyProperty(it.key(), sourceProject, targetProject);
+ sourceProject->copyProperty(it.key(), targetProject);
continue;
}
@@ -1507,7 +1508,7 @@ void ModuleLoader::copyProperties(const Item *sourceProject, Item *targetProject
continue; // Ignore stuff the target project already has.
targetProject->setPropertyDeclaration(it.key(), it.value());
- copyProperty(it.key(), sourceProject, targetProject);
+ sourceProject->copyProperty(it.key(), targetProject);
}
}
@@ -1519,7 +1520,7 @@ Item *ModuleLoader::wrapWithProject(Item *item)
prj->setTypeName(QLatin1String("Project"));
prj->setFile(item->file());
prj->setLocation(item->location());
- m_reader->builtins()->setupItemForBuiltinType(prj, m_logger);
+ prj->setupForBuiltinType(m_logger);
return prj;
}
@@ -1535,12 +1536,6 @@ QString ModuleLoader::findExistingModulePath(const QString &searchPath,
return dirPath;
}
-void ModuleLoader::copyProperty(const QString &propertyName, const Item *source,
- Item *destination)
-{
- destination->setProperty(propertyName, source->property(propertyName));
-}
-
void ModuleLoader::setScopeForDescendants(Item *item, Item *scope)
{
foreach (Item *child, item->children()) {
diff --git a/src/lib/corelib/language/moduleloader.h b/src/lib/corelib/language/moduleloader.h
index 27fe83203..6adbc978f 100644
--- a/src/lib/corelib/language/moduleloader.h
+++ b/src/lib/corelib/language/moduleloader.h
@@ -33,7 +33,6 @@
#include "forward_decls.h"
#include "itempool.h"
-#include "qualifiedid.h"
#include <logging/logger.h>
#include <tools/setupprojectparameters.h>
#include <tools/version.h>
@@ -55,11 +54,11 @@ class CodeLocation;
namespace Internal {
-class BuiltinDeclarations;
class Evaluator;
class Item;
class ItemReader;
class ProgressObserver;
+class QualifiedId;
class ScriptEngine;
struct ModuleLoaderResult
@@ -99,7 +98,7 @@ struct ModuleLoaderResult
class ModuleLoader
{
public:
- ModuleLoader(ScriptEngine *engine, BuiltinDeclarations *builtins, const Logger &logger);
+ ModuleLoader(ScriptEngine *engine, const Logger &logger);
~ModuleLoader();
void setProgressObserver(ProgressObserver *progressObserver);
@@ -156,7 +155,9 @@ private:
struct ProductModuleInfo
{
- Item *exportItem = 0;
+ ProductModuleInfo() : exportItem() {}
+
+ Item *exportItem;
QList<ModuleLoaderResult::ProductInfo::Dependency> productDependencies;
};
@@ -224,7 +225,6 @@ private:
Item *wrapWithProject(Item *item);
static QString findExistingModulePath(const QString &searchPath,
const QualifiedId &moduleName);
- static void copyProperty(const QString &propertyName, const Item *source, Item *destination);
static void setScopeForDescendants(Item *item, Item *scope);
void overrideItemProperties(Item *item, const QString &buildConfigKey,
const QVariantMap &buildConfig);
diff --git a/src/lib/corelib/language/modulemerger.cpp b/src/lib/corelib/language/modulemerger.cpp
index 577f9098c..b32361b79 100644
--- a/src/lib/corelib/language/modulemerger.cpp
+++ b/src/lib/corelib/language/modulemerger.cpp
@@ -30,6 +30,8 @@
#include "modulemerger.h"
+#include "value.h"
+
#include <logging/translator.h>
#include <tools/qbsassert.h>
@@ -199,9 +201,15 @@ void ModuleMerger::appendPrototypeValueToNextChain(Item *moduleProto, const QStr
ValuePtr protoValue = moduleProto->property(propertyName);
if (!protoValue)
return;
- ValuePtr cloned = protoValue->clone();
- cloned->setDefiningItem(moduleProto);
- lastInNextChain(sv)->setNext(cloned);
+ Item * const clonedModulePrototype = moduleProto->clone();
+ Item * const scope = Item::create(clonedModulePrototype->pool());
+ scope->setFile(clonedModulePrototype->file());
+ m_mergedModuleItem->scope()->copyProperty(QLatin1String("project"), scope);
+ m_mergedModuleItem->scope()->copyProperty(QLatin1String("product"), scope);
+ clonedModulePrototype->setScope(scope);
+ const ValuePtr clonedValue = protoValue->clone();
+ clonedValue->setDefiningItem(clonedModulePrototype);
+ lastInNextChain(sv)->setNext(clonedValue);
}
ValuePtr ModuleMerger::lastInNextChain(const ValuePtr &v)
diff --git a/src/lib/corelib/language/modulemerger.h b/src/lib/corelib/language/modulemerger.h
index ae13b9143..3b417191b 100644
--- a/src/lib/corelib/language/modulemerger.h
+++ b/src/lib/corelib/language/modulemerger.h
@@ -32,11 +32,12 @@
#define QBS_MODULEMERGER_H
#include "item.h"
+#include "qualifiedid.h"
+
#include <logging/logger.h>
#include <QHash>
#include <QSet>
-#include <QStringList>
namespace qbs {
namespace Internal {
@@ -59,7 +60,7 @@ private:
const Logger &m_logger;
Item * const m_rootItem;
Item *m_mergedModuleItem;
- const QStringList m_moduleName;
+ const QualifiedId m_moduleName;
QHash<ValuePtr, PropertyDeclaration> m_decls;
QSet<const Item *> m_seenInstancesTopDown;
QSet<const Item *> m_seenInstancesBottomUp;
diff --git a/src/lib/corelib/language/projectresolver.cpp b/src/lib/corelib/language/projectresolver.cpp
index 6f80d4db0..5ab191fb6 100644
--- a/src/lib/corelib/language/projectresolver.cpp
+++ b/src/lib/corelib/language/projectresolver.cpp
@@ -31,15 +31,16 @@
#include "projectresolver.h"
#include "artifactproperties.h"
-#include "builtindeclarations.h"
#include "evaluator.h"
#include "filecontext.h"
#include "item.h"
-#include "moduleloader.h"
+#include "language.h"
#include "modulemerger.h"
#include "propertymapinternal.h"
#include "resolvedfilecontext.h"
#include "scriptengine.h"
+#include "value.h"
+
#include <jsextensions/moduleproperties.h>
#include <logging/translator.h>
#include <tools/error.h>
@@ -49,10 +50,8 @@
#include <tools/qbsassert.h>
#include <tools/qttools.h>
-#include <QFileInfo>
#include <QDir>
#include <QQueue>
-#include <QSet>
#include <algorithm>
#include <set>
@@ -68,10 +67,9 @@ static const FileTag unknownFileTag()
return tag;
}
-ProjectResolver::ProjectResolver(ModuleLoader *ldr, const BuiltinDeclarations *builtins,
+ProjectResolver::ProjectResolver(ModuleLoader *ldr,
const Logger &logger)
: m_evaluator(ldr->evaluator())
- , m_builtins(builtins)
, m_logger(logger)
, m_engine(m_evaluator->engine())
, m_progressObserver(0)
@@ -366,7 +364,7 @@ void ProjectResolver::resolveProduct(Item *item, ProjectContext *projectContext)
fakeGroup->setProperty(QLatin1String("excludeFiles"),
item->property(QLatin1String("excludeFiles")));
fakeGroup->setProperty(QLatin1String("overrideTags"), VariantValue::create(false));
- m_builtins->setupItemForBuiltinType(fakeGroup, m_logger);
+ fakeGroup->setupForBuiltinType(m_logger);
subItems.prepend(fakeGroup);
}
diff --git a/src/lib/corelib/language/projectresolver.h b/src/lib/corelib/language/projectresolver.h
index 6787c459a..fc97422de 100644
--- a/src/lib/corelib/language/projectresolver.h
+++ b/src/lib/corelib/language/projectresolver.h
@@ -31,9 +31,7 @@
#ifndef PROJECTRESOLVER_H
#define PROJECTRESOLVER_H
-#include "evaluator.h"
#include "filetags.h"
-#include "language.h"
#include "moduleloader.h"
#include <logging/logger.h>
@@ -45,10 +43,8 @@
namespace qbs {
namespace Internal {
-class BuiltinDeclarations;
class Evaluator;
class Item;
-class ModuleLoader;
class ProgressObserver;
class ScriptEngine;
class QualifiedIdSet;
@@ -56,7 +52,7 @@ class QualifiedIdSet;
class ProjectResolver
{
public:
- ProjectResolver(ModuleLoader *ldr, const BuiltinDeclarations *builtins, const Logger &logger);
+ ProjectResolver(ModuleLoader *ldr, const Logger &logger);
~ProjectResolver();
void setProgressObserver(ProgressObserver *observer);
@@ -153,7 +149,6 @@ private:
const QList<SourceArtifactPtr> &artifacts);
Evaluator *m_evaluator;
- const BuiltinDeclarations *m_builtins;
Logger m_logger;
ScriptEngine *m_engine;
ProgressObserver *m_progressObserver;
diff --git a/src/lib/corelib/language/propertydeclaration.cpp b/src/lib/corelib/language/propertydeclaration.cpp
index c79aed4ab..8d5367ee8 100644
--- a/src/lib/corelib/language/propertydeclaration.cpp
+++ b/src/lib/corelib/language/propertydeclaration.cpp
@@ -32,7 +32,9 @@
#include "deprecationinfo.h"
+#include <QScriptValue>
#include <QSharedData>
+#include <QStringList>
namespace qbs {
namespace Internal {
diff --git a/src/lib/corelib/language/propertydeclaration.h b/src/lib/corelib/language/propertydeclaration.h
index 8071b201a..f0e662a0c 100644
--- a/src/lib/corelib/language/propertydeclaration.h
+++ b/src/lib/corelib/language/propertydeclaration.h
@@ -32,9 +32,12 @@
#define QBS_PROPERTYDECLARATION_H
#include <QSharedDataPointer>
-#include <QString>
-#include <QStringList>
-#include <QScriptValue>
+
+QT_BEGIN_NAMESPACE
+class QScriptValue;
+class QString;
+class QStringList;
+QT_END_NAMESPACE
namespace qbs {
namespace Internal {
diff --git a/src/lib/corelib/language/propertymapinternal.cpp b/src/lib/corelib/language/propertymapinternal.cpp
index 91747cbac..577c7762f 100644
--- a/src/lib/corelib/language/propertymapinternal.cpp
+++ b/src/lib/corelib/language/propertymapinternal.cpp
@@ -80,7 +80,7 @@ static QString toJSLiteral_impl(const QVariantMap &vm, int level = 0)
str += toJSLiteral_impl(it.value().toMap(), level + 1);
str += indent + QLatin1String("}\n");
} else {
- str += indent + it.key() + QLatin1String(": ") + qbs::toJSLiteral(it.value())
+ str += indent + it.key() + QLatin1String(": ") + toJSLiteral(it.value())
+ QLatin1Char('\n');
}
}
diff --git a/src/lib/corelib/language/resolvedfilecontext.h b/src/lib/corelib/language/resolvedfilecontext.h
index b77f69042..b2c9d1741 100644
--- a/src/lib/corelib/language/resolvedfilecontext.h
+++ b/src/lib/corelib/language/resolvedfilecontext.h
@@ -33,7 +33,7 @@
#include "forward_decls.h"
#include "filecontextbase.h"
-#include "jsimports.h"
+
#include <tools/persistentobject.h>
namespace qbs {
diff --git a/src/lib/corelib/language/scriptengine.cpp b/src/lib/corelib/language/scriptengine.cpp
index 5f2d62c96..e0816e712 100644
--- a/src/lib/corelib/language/scriptengine.cpp
+++ b/src/lib/corelib/language/scriptengine.cpp
@@ -32,9 +32,10 @@
#include "evaluatorscriptclass.h"
#include "filecontextbase.h"
-#include "item.h"
+#include "jsimports.h"
#include "propertymapinternal.h"
#include "scriptpropertyobserver.h"
+
#include <buildgraph/artifact.h>
#include <jsextensions/jsextensions.h>
#include <tools/error.h>
@@ -123,23 +124,20 @@ void ScriptEngine::import(const JsImport &jsImport, QScriptValue scope, QScriptV
QBS_ASSERT(targetObject.engine() == this, return);
if (debugJSImports)
- m_logger.qbsDebug() << "[ENGINE] import into " << jsImport.scopeName;
-
- foreach (const QString &filePath, jsImport.filePaths) {
- QScriptValue jsImportValue;
- jsImportValue = m_jsImportCache.value(filePath);
- if (jsImportValue.isValid()) {
- if (debugJSImports)
- m_logger.qbsDebug() << "[ENGINE] " << filePath << " (cache hit)";
- targetObject.setProperty(jsImport.scopeName, jsImportValue);
- } else {
- if (debugJSImports)
- m_logger.qbsDebug() << "[ENGINE] " << filePath << " (cache miss)";
- jsImportValue = importFile(filePath, scope);
- targetObject.setProperty(jsImport.scopeName, jsImportValue);
- m_jsImportCache.insert(filePath, jsImportValue);
- }
+ qDebug() << "[ENGINE] import into " << jsImport.scopeName;
+
+ QScriptValue jsImportValue = m_jsImportCache.value(jsImport);
+ if (jsImportValue.isValid()) {
+ if (debugJSImports)
+ qDebug() << "[ENGINE] " << jsImport.filePaths << " (cache hit)";
+ } else {
+ if (debugJSImports)
+ qDebug() << "[ENGINE] " << jsImport.filePaths << " (cache miss)";
+ foreach (const QString &filePath, jsImport.filePaths)
+ importFile(filePath, scope, &jsImportValue);
+ m_jsImportCache.insert(jsImport, jsImportValue);
}
+ targetObject.setProperty(jsImport.scopeName, jsImportValue);
}
void ScriptEngine::clearImportsCache()
@@ -236,7 +234,8 @@ void ScriptEngine::setEnvironment(const QProcessEnvironment &env)
m_environment = env;
}
-QScriptValue ScriptEngine::importFile(const QString &filePath, const QScriptValue &scope)
+QScriptValue ScriptEngine::importFile(const QString &filePath, const QScriptValue &scope,
+ QScriptValue *targetObject)
{
QFile file(filePath);
if (Q_UNLIKELY(!file.open(QFile::ReadOnly)))
@@ -244,11 +243,13 @@ QScriptValue ScriptEngine::importFile(const QString &filePath, const QScriptValu
const QString sourceCode = QTextStream(&file).readAll();
file.close();
QScriptProgram program(sourceCode, filePath);
- QScriptValue obj = newObject();
+ QScriptValue obj;
+ if (!targetObject)
+ obj = newObject();
m_currentDirPathStack.push(FileInfo::path(filePath));
- importProgram(program, scope, obj);
+ importProgram(program, scope, targetObject ? *targetObject : obj);
m_currentDirPathStack.pop();
- return obj;
+ return targetObject ? *targetObject : obj;
}
void ScriptEngine::importProgram(const QScriptProgram &program, const QScriptValue &scope,
@@ -288,7 +289,7 @@ void ScriptEngine::importProgram(const QScriptProgram &program, const QScriptVal
while (it.hasNext()) {
it.next();
if (debugJSImports)
- m_logger.qbsDebug() << "[ENGINE] Copying property " << it.name();
+ qDebug() << "[ENGINE] Copying property " << it.name();
targetObject.setProperty(it.name(), it.value());
}
}
@@ -303,8 +304,8 @@ void ScriptEngine::importProgram(const QScriptProgram &program, const QScriptVal
continue;
if (debugJSImports) {
- m_logger.qbsDebug() << "[ENGINE] inserting global property "
- << it.name() << " " << it.value().toString();
+ qDebug() << "[ENGINE] inserting global property "
+ << it.name() << " " << it.value().toString();
}
targetObject.setProperty(it.name(), it.value());
@@ -452,14 +453,19 @@ void ScriptEngine::addDirectoryEntriesResult(const QString &path, QDir::Filters
entries);
}
-void ScriptEngine::addFileLastModifiedResult(const QString &filePath, FileTime fileTime)
+void ScriptEngine::addFileLastModifiedResult(const QString &filePath, const FileTime &fileTime)
{
m_fileLastModifiedResult.insert(filePath, fileTime);
}
QSet<QString> ScriptEngine::imports() const
{
- return QSet<QString>::fromList(m_jsImportCache.keys());
+ QSet<QString> filePaths;
+ foreach (const JsImport &jsImport, m_jsImportCache.keys()) {
+ foreach (const QString &filePath, jsImport.filePaths)
+ filePaths << filePath;
+ }
+ return filePaths;
}
QScriptValueList ScriptEngine::argumentList(const QStringList &argumentNames,
diff --git a/src/lib/corelib/language/scriptengine.h b/src/lib/corelib/language/scriptengine.h
index bf2b371d3..2cccc6dc7 100644
--- a/src/lib/corelib/language/scriptengine.h
+++ b/src/lib/corelib/language/scriptengine.h
@@ -32,7 +32,6 @@
#define QBS_SCRIPTENGINE_H
#include "forward_decls.h"
-#include "jsimports.h"
#include "property.h"
#include <logging/logger.h>
#include <tools/filetime.h>
@@ -48,7 +47,7 @@
namespace qbs {
namespace Internal {
class Artifact;
-
+class JsImport;
class ScriptPropertyObserver;
class ScriptEngine : public QScriptEngine
@@ -99,7 +98,7 @@ public:
void addFileExistsResult(const QString &filePath, bool exists);
void addDirectoryEntriesResult(const QString &path, QDir::Filters filters,
const QStringList &entries);
- void addFileLastModifiedResult(const QString &filePath, FileTime fileTime);
+ void addFileLastModifiedResult(const QString &filePath, const FileTime &fileTime);
QHash<QString, QString> canonicalFilePathResults() const { return m_canonicalFilePathResult; }
QHash<QString, bool> fileExistsResults() const { return m_fileExistsResult; }
QHash<QPair<QString, quint32>, QStringList> directoryEntriesResults() const
@@ -133,7 +132,8 @@ private:
void installQbsFunction(const QString &name, FunctionSignature f);
void installImportFunctions();
void uninstallImportFunctions();
- QScriptValue importFile(const QString &filePath, const QScriptValue &scope);
+ QScriptValue importFile(const QString &filePath, const QScriptValue &scope,
+ QScriptValue *targetObject = nullptr);
void importProgram(const QScriptProgram &program, const QScriptValue &scope,
QScriptValue &targetObject);
static QScriptValue js_loadExtension(QScriptContext *context, QScriptEngine *qtengine);
@@ -157,7 +157,7 @@ private:
friend bool operator==(const PropertyCacheKey &lhs, const PropertyCacheKey &rhs);
friend uint qHash(const ScriptEngine::PropertyCacheKey &k, uint seed);
- QHash<QString, QScriptValue> m_jsImportCache;
+ QHash<JsImport, QScriptValue> m_jsImportCache;
bool m_propertyCacheEnabled;
QHash<PropertyCacheKey, QVariant> m_propertyCache;
PropertySet m_propertiesRequestedInScript;
diff --git a/src/lib/corelib/language/scriptpropertyobserver.h b/src/lib/corelib/language/scriptpropertyobserver.h
index 23077d4fb..93cc263a3 100644
--- a/src/lib/corelib/language/scriptpropertyobserver.h
+++ b/src/lib/corelib/language/scriptpropertyobserver.h
@@ -31,7 +31,12 @@
#ifndef QBS_SCRIPTPROPERTYOBSERVER_H
#define QBS_SCRIPTPROPERTYOBSERVER_H
-#include <QScriptValue>
+#include <QtGlobal>
+
+QT_BEGIN_NAMESPACE
+class QScriptValue;
+class QString;
+QT_END_NAMESPACE
namespace qbs {
namespace Internal {
diff --git a/src/lib/corelib/language/testdata/import-collection/imports/Collection/file1.js b/src/lib/corelib/language/testdata/import-collection/imports/Collection/file1.js
new file mode 100644
index 000000000..9f4785b2e
--- /dev/null
+++ b/src/lib/corelib/language/testdata/import-collection/imports/Collection/file1.js
@@ -0,0 +1 @@
+function f1() { return "f1"; }
diff --git a/src/lib/corelib/language/testdata/import-collection/imports/Collection/file2.js b/src/lib/corelib/language/testdata/import-collection/imports/Collection/file2.js
new file mode 100644
index 000000000..887fd6fdb
--- /dev/null
+++ b/src/lib/corelib/language/testdata/import-collection/imports/Collection/file2.js
@@ -0,0 +1 @@
+function f2() { return "f2"; }
diff --git a/src/lib/corelib/language/testdata/import-collection/product.qbs b/src/lib/corelib/language/testdata/import-collection/product.qbs
new file mode 100644
index 000000000..af240ddca
--- /dev/null
+++ b/src/lib/corelib/language/testdata/import-collection/product.qbs
@@ -0,0 +1,6 @@
+import Collection
+
+Product {
+ name: "da product"
+ targetName: Collection.f1() + Collection.f2()
+}
diff --git a/src/lib/corelib/language/testdata/import-collection/project.qbs b/src/lib/corelib/language/testdata/import-collection/project.qbs
new file mode 100644
index 000000000..ee34869b4
--- /dev/null
+++ b/src/lib/corelib/language/testdata/import-collection/project.qbs
@@ -0,0 +1,6 @@
+import qbs
+
+Project {
+ references: ["product.qbs"]
+}
+
diff --git a/src/lib/corelib/language/testdata/moduleproperties.qbs b/src/lib/corelib/language/testdata/moduleproperties.qbs
index 4777b7783..7b782751a 100644
--- a/src/lib/corelib/language/testdata/moduleproperties.qbs
+++ b/src/lib/corelib/language/testdata/moduleproperties.qbs
@@ -23,4 +23,11 @@ Project {
Depends { name: "dummyqt"; submodules: ["gui", "network"] }
Depends { name: "dummy" }
}
+
+ Product {
+ name: "list_property_that_references_product"
+ type: ["blubb"]
+ Depends { name: "dummy" }
+ dummy.listProp: ["x"]
+ }
}
diff --git a/src/lib/corelib/language/testdata/modules/dummy/dummy.qbs b/src/lib/corelib/language/testdata/modules/dummy/dummy.qbs
index a04c7c463..9fdd73459 100644
--- a/src/lib/corelib/language/testdata/modules/dummy/dummy.qbs
+++ b/src/lib/corelib/language/testdata/modules/dummy/dummy.qbs
@@ -11,4 +11,5 @@ DummyBase {
property string upperCaseProductName: productName.toUpperCase()
property string zort: "zort in dummy"
property pathList includePaths
+ property stringList listProp: product.type.contains("blubb") ? ["123"] : ["456"]
}
diff --git a/src/lib/corelib/language/tst_language.cpp b/src/lib/corelib/language/tst_language.cpp
index c73b26665..d07af317a 100644
--- a/src/lib/corelib/language/tst_language.cpp
+++ b/src/lib/corelib/language/tst_language.cpp
@@ -33,18 +33,23 @@
#include "tst_language.h"
#include <language/evaluator.h>
+#include <language/filecontext.h>
#include <language/identifiersearch.h>
#include <language/item.h>
#include <language/itempool.h>
#include <language/language.h>
+#include <language/propertymapinternal.h>
#include <language/scriptengine.h>
+#include <language/value.h>
#include <parser/qmljslexer_p.h>
#include <parser/qmljsparser_p.h>
#include <tools/scripttools.h>
#include <tools/error.h>
+#include <tools/fileinfo.h>
#include <tools/hostosinfo.h>
#include <tools/profile.h>
#include <tools/propertyfinder.h>
+#include <tools/settings.h>
#include <QProcessEnvironment>
@@ -800,6 +805,24 @@ void TestLanguage::idUsage()
QVERIFY(!exceptionCaught);
}
+void TestLanguage::importCollection()
+{
+ bool exceptionCaught = false;
+ try {
+ defaultParameters.setProjectFilePath(testProject("import-collection/project.qbs"));
+ const TopLevelProjectPtr project = loader->loadProject(defaultParameters);
+ QVERIFY(project);
+ QHash<QString, ResolvedProductPtr> products = productsFromProject(project);
+ const ResolvedProductConstPtr product = products.value("da product");
+ QCOMPARE(product->productProperties.value("targetName").toString(), QLatin1String("f1f2"));
+ }
+ catch (const ErrorInfo &e) {
+ exceptionCaught = true;
+ qDebug() << e.toString();
+ }
+ QVERIFY(!exceptionCaught);
+}
+
void TestLanguage::invalidBindingInDisabledItem()
{
bool exceptionCaught = false;
@@ -951,6 +974,9 @@ void TestLanguage::moduleProperties_data()
QTest::newRow("merge_lists_with_prototype_values")
<< "rpaths"
<< (QStringList() << "/opt/qt/lib" << "$ORIGIN");
+ QTest::newRow("list_property_that_references_product")
+ << "listProp"
+ << (QStringList() << "x" << "123");
QTest::newRow("cleanup") << QString() << QStringList();
}
diff --git a/src/lib/corelib/language/tst_language.h b/src/lib/corelib/language/tst_language.h
index a3c2838e3..624f5428b 100644
--- a/src/lib/corelib/language/tst_language.h
+++ b/src/lib/corelib/language/tst_language.h
@@ -70,7 +70,6 @@ private slots:
void buildConfigStringListSyntax();
void builtinFunctionInSearchPathsProperty();
void canonicalArchitecture();
- void rfc1034Identifier();
void conditionalDepends();
void dependencyOnAllProfiles();
void environmentVariable();
@@ -78,14 +77,17 @@ private slots:
void erroneousFiles();
void exports();
void fileContextProperties();
- void getNativeSetting();
+ void fileTags_data();
+ void fileTags();
void groupConditions_data();
void groupConditions();
void groupName();
+ void getNativeSetting();
void homeDirectory();
void identifierSearch_data();
void identifierSearch();
void idUsage();
+ void importCollection();
void invalidBindingInDisabledItem();
void itemPrototype();
void itemScope();
@@ -99,15 +101,14 @@ private slots:
void modules();
void outerInGroup();
void pathProperties();
- void profileValuesAndOverriddenValues();
void productConditions();
void productDirectories();
+ void profileValuesAndOverriddenValues();
void propertiesBlocks_data();
void propertiesBlocks();
void qualifiedId();
void recursiveProductDependencies();
- void fileTags_data();
- void fileTags();
+ void rfc1034Identifier();
void wildcards_data();
void wildcards();
};
diff --git a/src/lib/corelib/language/value.cpp b/src/lib/corelib/language/value.cpp
index 141e1759d..fae97d0da 100644
--- a/src/lib/corelib/language/value.cpp
+++ b/src/lib/corelib/language/value.cpp
@@ -29,6 +29,8 @@
****************************************************************************/
#include "value.h"
+
+#include "filecontext.h"
#include "item.h"
#include <tools/qbsassert.h>
@@ -151,7 +153,7 @@ ItemValue::~ItemValue()
ValuePtr ItemValue::clone() const
{
- Item *clonedItem = m_item ? m_item->clone(m_item->pool()) : 0;
+ Item *clonedItem = m_item ? m_item->clone() : 0;
return ItemValuePtr(new ItemValue(clonedItem));
}
diff --git a/src/lib/corelib/language/value.h b/src/lib/corelib/language/value.h
index 2dcc7ff17..8f17f0be9 100644
--- a/src/lib/corelib/language/value.h
+++ b/src/lib/corelib/language/value.h
@@ -31,14 +31,13 @@
#ifndef QBS_VALUE_H
#define QBS_VALUE_H
-#include "filecontext.h"
-#include "item.h"
+#include "forward_decls.h"
#include <tools/codelocation.h>
#include <QVariant>
namespace qbs {
namespace Internal {
-
+class Item;
class ValueHandler;
class Value
@@ -150,7 +149,6 @@ private:
Item *m_exportScope;
};
-class Item;
class ItemValue : public Value
{
diff --git a/src/lib/corelib/tools/fileinfo.cpp b/src/lib/corelib/tools/fileinfo.cpp
index 178dfba3e..6763ac147 100644
--- a/src/lib/corelib/tools/fileinfo.cpp
+++ b/src/lib/corelib/tools/fileinfo.cpp
@@ -193,6 +193,12 @@ QString FileInfo::resolvePath(const QString &base, const QString &rel)
if (idx >= 0)
r.truncate(idx);
}
+ if (s == QLatin1String("..")) {
+ int idx = r.lastIndexOf(QLatin1Char('/'));
+ if (idx >= 0)
+ r.truncate(idx);
+ return r;
+ }
r.reserve(r.length() + 1 + s.length());
r += QLatin1Char('/');
diff --git a/src/lib/corelib/tools/hostosinfo.h b/src/lib/corelib/tools/hostosinfo.h
index fc27853c4..12571c7e7 100644
--- a/src/lib/corelib/tools/hostosinfo.h
+++ b/src/lib/corelib/tools/hostosinfo.h
@@ -32,9 +32,11 @@
#define QBS_HOSTOSINFO_H
#include "qbs_export.h"
+#include "version.h"
#include <QtGlobal>
#include <QMap>
+#include <QSettings>
#include <QString>
#include <QStringList>
@@ -63,6 +65,25 @@ public:
static inline HostOs hostOs();
+ static inline Version hostOsVersion() {
+ Version v;
+ if (HostOsInfo::isWindowsHost()) {
+ QSettings settings(QString::fromLatin1("HKEY_LOCAL_MACHINE\\Software\\"
+ "Microsoft\\Windows NT\\CurrentVersion"),
+ QSettings::NativeFormat);
+ v = v.fromString(settings.value(QStringLiteral("CurrentVersion")).toString() +
+ QLatin1Char('.') +
+ settings.value(QStringLiteral("CurrentBuildNumber")).toString());
+ Q_ASSERT(v.isValid());
+ } else if (HostOsInfo::isOsxHost()) {
+ QSettings settings(QStringLiteral("/System/Library/CoreServices/SystemVersion.plist"),
+ QSettings::NativeFormat);
+ v = v.fromString(settings.value(QStringLiteral("ProductVersion")).toString());
+ Q_ASSERT(v.isValid());
+ }
+ return v;
+ }
+
static bool isWindowsHost() { return hostOs() == HostOsWindows; }
static bool isLinuxHost() { return hostOs() == HostOsLinux; }
static bool isOsxHost() { return hostOs() == HostOsOsx; }
diff --git a/src/lib/corelib/tools/tst_tools.h b/src/lib/corelib/tools/tst_tools.h
index b984639da..d9e4e8fc2 100644
--- a/src/lib/corelib/tools/tst_tools.h
+++ b/src/lib/corelib/tools/tst_tools.h
@@ -44,11 +44,11 @@ public:
TestTools(Settings *settings);
private slots:
- void testFileInfo();
void fileCaseCheck();
- void testProfiles();
void testBuildConfigMerging();
+ void testFileInfo();
void testProcessNameByPid();
+ void testProfiles();
private:
Settings * const m_settings;