Commit 5a4cdc11 authored by Fawzi Mohamed's avatar Fawzi Mohamed

qmljs: adding qrc support

Qmljs now keeps a cache of parsed qrc files, and can resolve "qrc:" links.

This breaks the assumption that the name that the qml files has on
the filesystem is the one that qml sees, and that contents of
directories can be found just looking at file whose path starts with the
directory path.

Currently the first file is used when multiple qrc files contain the same
path, but support for strict and weak path resolving is already there.

At the moment only qrc files for projects that call updateQmljsCodeModel
are updated.

ChangeLog: QmljsSupport: Imports using qrc links are resolved.

Task-number: QTCREATORBUG-8953
Change-Id: I695fac2692af2417d49c192c580a1c2e7b4873f4
Reviewed-by: default avatarFawzi Mohamed <fawzi.mohamed@digia.com>
parent 69a9dc3f
......@@ -39,7 +39,8 @@ HEADERS += \
$$PWD/consoleitem.h \
$$PWD/iscriptevaluator.h \
$$PWD/qmljssimplereader.h \
$$PWD/persistenttrie.h
$$PWD/persistenttrie.h \
$$PWD/qmljsqrcparser.h
SOURCES += \
$$PWD/qmljsbind.cpp \
......@@ -69,7 +70,8 @@ SOURCES += \
$$PWD/consolemanagerinterface.cpp \
$$PWD/consoleitem.cpp \
$$PWD/qmljssimplereader.cpp \
$$PWD/persistenttrie.cpp
$$PWD/persistenttrie.cpp \
$$PWD/qmljsqrcparser.cpp
RESOURCES += \
$$PWD/qmljs.qrc
......
DEFINES += QMLJS_BUILD_DIR
QT +=script
QT +=script xml
include(../../qtcreatorlibrary.pri)
include(qmljs-lib.pri)
......@@ -12,7 +12,7 @@ QtcLibrary {
Depends { name: "Utils" }
Depends { name: "LanguageUtils" }
Depends { name: "Qt"; submodules: ["widgets", "script"] }
Depends { name: "Qt"; submodules: ["widgets", "script", "xml"] }
files: [
"jsoncheck.cpp",
......@@ -52,6 +52,8 @@ QtcLibrary {
"qmljsmodelmanagerinterface.h",
"qmljspropertyreader.cpp",
"qmljspropertyreader.h",
"qmljsqrcparser.cpp",
"qmljsqrcparser.h",
"qmljsreformatter.cpp",
"qmljsreformatter.h",
"qmljsrewriter.cpp",
......
......@@ -115,6 +115,22 @@ bool Document::isFullySupportedLanguage(Document::Language language)
return false;
}
bool Document::isQmlLikeOrJsLanguage(Document::Language language)
{
switch (language) {
case QmlLanguage:
case QmlQtQuick1Language:
case QmlQtQuick2Language:
case QmlQbsLanguage:
case QmlProjectLanguage:
case QmlTypeInfoLanguage:
case JavaScriptLanguage:
return true;
default:
return false;
}
}
Document::Document(const QString &fileName, Language language)
: _engine(0)
, _ast(0)
......
......@@ -65,6 +65,7 @@ public:
static bool isQmlLikeLanguage(Language languge);
static bool isFullySupportedLanguage(Language language);
static bool isQmlLikeOrJsLanguage(Language language);
protected:
Document(const QString &fileName, Language language);
......
......@@ -35,6 +35,7 @@
#include "qmljstypedescriptionreader.h"
#include "qmljsvalueowner.h"
#include "qmljscontext.h"
#include "qmljsmodelmanagerinterface.h"
#include "parser/qmljsast_p.h"
#include <utils/qtcassert.h>
......@@ -2107,13 +2108,19 @@ ImportInfo ImportInfo::pathImport(const QString &docPath, const QString &path,
importFileInfo = QFileInfo(docPath + QDir::separator() + path);
info._path = importFileInfo.absoluteFilePath();
if (importFileInfo.isFile())
if (importFileInfo.isFile()) {
info._type = FileImport;
else if (importFileInfo.isDir())
} else if (importFileInfo.isDir()) {
info._type = DirectoryImport;
else
} else if (path.startsWith(QLatin1String("qrc:"))) {
info._path = path;
if (ModelManagerInterface::instance()->filesAtQrcPath(info.path()).isEmpty())
info._type = QrcDirectoryImport;
else
info._type = QrcFileImport;
} else {
info._type = UnknownFileImport;
}
info._version = version;
info._as = as;
info._ast = ast;
......@@ -2192,7 +2199,7 @@ const Value *TypeScope::lookupMember(const QString &name, const Context *context
const ImportInfo &info = i.info;
// JS import has no types
if (info.type() == ImportInfo::FileImport)
if (info.type() == ImportInfo::FileImport || info.type() == ImportInfo::QrcFileImport)
continue;
if (!info.as().isEmpty()) {
......@@ -2222,7 +2229,7 @@ void TypeScope::processMembers(MemberProcessor *processor) const
const ImportInfo &info = i.info;
// JS import has no types
if (info.type() == ImportInfo::FileImport)
if (info.type() == ImportInfo::FileImport || info.type() == ImportInfo::QrcFileImport)
continue;
if (!info.as().isEmpty())
......@@ -2249,7 +2256,7 @@ const Value *JSImportScope::lookupMember(const QString &name, const Context *,
const ImportInfo &info = i.info;
// JS imports are always: import "somefile.js" as Foo
if (info.type() != ImportInfo::FileImport)
if (info.type() != ImportInfo::FileImport && info.type() != ImportInfo::QrcFileImport)
continue;
if (info.as() == name) {
......@@ -2272,7 +2279,7 @@ void JSImportScope::processMembers(MemberProcessor *processor) const
const ObjectValue *import = i.object;
const ImportInfo &info = i.info;
if (info.type() == ImportInfo::FileImport)
if (info.type() == ImportInfo::FileImport || info.type() == ImportInfo::QrcFileImport)
processor->processProperty(info.as(), import);
}
}
......@@ -2329,7 +2336,7 @@ ImportInfo Imports::info(const QString &name, const Context *context) const
continue;
}
if (info.type() == ImportInfo::FileImport) {
if (info.type() == ImportInfo::FileImport || info.type() == ImportInfo::QrcFileImport) {
if (import->className() == firstId)
return info;
} else {
......@@ -2349,7 +2356,7 @@ QString Imports::nameForImportedObject(const ObjectValue *value, const Context *
const ObjectValue *import = i.object;
const ImportInfo &info = i.info;
if (info.type() == ImportInfo::FileImport) {
if (info.type() == ImportInfo::FileImport || info.type() == ImportInfo::QrcFileImport) {
if (import == value)
return import->className();
} else {
......
......@@ -872,6 +872,8 @@ public:
LibraryImport,
FileImport,
DirectoryImport,
QrcFileImport,
QrcDirectoryImport,
UnknownFileImport // refers a file/directory that wasn't found
};
......
......@@ -34,6 +34,7 @@
#include "qmljsbind.h"
#include "qmljsutils.h"
#include "qmljsmodelmanagerinterface.h"
#include <qmljs/qmljsqrcparser.h>
#include <QDir>
#include <QDebug>
......@@ -245,6 +246,8 @@ void LinkPrivate::populateImportedTypes(Imports *imports, Document::Ptr doc)
switch (info.type()) {
case ImportInfo::FileImport:
case ImportInfo::DirectoryImport:
case ImportInfo::QrcFileImport:
case ImportInfo::QrcDirectoryImport:
import = importFileOrDirectory(doc, info);
break;
case ImportInfo::LibraryImport:
......@@ -285,7 +288,7 @@ Import LinkPrivate::importFileOrDirectory(Document::Ptr doc, const ImportInfo &i
import.object = 0;
import.valid = true;
const QString &path = importInfo.path();
QString path = importInfo.path();
if (importInfo.type() == ImportInfo::DirectoryImport
|| importInfo.type() == ImportInfo::ImplicitDirectoryImport) {
......@@ -304,8 +307,36 @@ Import LinkPrivate::importFileOrDirectory(Document::Ptr doc, const ImportInfo &i
Document::Ptr importedDoc = snapshot.document(path);
if (importedDoc)
import.object = importedDoc->bind()->rootObjectValue();
}
} else if (importInfo.type() == ImportInfo::QrcFileImport) {
QLocale locale;
QStringList filePaths = ModelManagerInterface::instance()
->filesAtQrcPath(path, &locale, 0, ModelManagerInterface::ActiveQrcResources);
if (filePaths.isEmpty()) {
filePaths = ModelManagerInterface::instance()->filesAtQrcPath(path);
}
if (!filePaths.isEmpty()) {
Document::Ptr importedDoc = snapshot.document(filePaths.at(0));
if (importedDoc)
import.object = importedDoc->bind()->rootObjectValue();
}
} else if (importInfo.type() == ImportInfo::QrcDirectoryImport){
import.object = new ObjectValue(valueOwner);
importLibrary(doc, path, &import);
QMapIterator<QString,QStringList> iter(ModelManagerInterface::instance()
->filesInQrcPath(path));
while (iter.hasNext()) {
iter.next();
if (Document::isQmlLikeLanguage(Document::guessLanguageFromSuffix(iter.key()))) {
Document::Ptr importedDoc = snapshot.document(iter.value().at(0));
if (importedDoc && importedDoc->bind()->rootObjectValue()) {
const QString targetName = QFileInfo(iter.key()).baseName();
import.object->setMember(targetName, importedDoc->bind()->rootObjectValue());
}
}
}
}
return import;
}
......
......@@ -53,6 +53,11 @@ class QMLJS_EXPORT ModelManagerInterface: public QObject
Q_OBJECT
public:
enum QrcResourceSelector {
ActiveQrcResources,
AllQrcResources
};
class ProjectInfo
{
public:
......@@ -80,6 +85,8 @@ public:
QPointer<ProjectExplorer::Project> project;
QStringList sourceFiles;
QStringList importPaths;
QStringList activeResourceFiles;
QStringList allResourceFiles;
// whether trying to run qmldump makes sense
bool tryQmlDump;
......@@ -142,6 +149,14 @@ public:
bool emitDocumentOnDiskChanged) = 0;
virtual void fileChangedOnDisk(const QString &path) = 0;
virtual void removeFiles(const QStringList &files) = 0;
virtual QStringList filesAtQrcPath(const QString &path, const QLocale *locale = 0,
ProjectExplorer::Project *project = 0,
QrcResourceSelector resources = AllQrcResources) = 0;
virtual QMap<QString,QStringList> filesInQrcPath(const QString &path,
const QLocale *locale = 0,
ProjectExplorer::Project *project = 0,
bool addDirs = false,
QrcResourceSelector resources = AllQrcResources) = 0;
virtual QList<ProjectInfo> projectInfos() const = 0;
virtual ProjectInfo projectInfo(ProjectExplorer::Project *project) const = 0;
......
This diff is collapsed.
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef QMLJSQRCPARSER_H
#define QMLJSQRCPARSER_H
#include "qmljs_global.h"
#include <QMap>
#include <QSharedPointer>
#include <QString>
#include <QStringList>
QT_FORWARD_DECLARE_CLASS(QLocale)
namespace QmlJS {
namespace Internal {
class QrcParserPrivate;
class QrcCachePrivate;
}
class QMLJS_EXPORT QrcParser
{
public:
typedef QSharedPointer<QrcParser> Ptr;
typedef QSharedPointer<const QrcParser> ConstPtr;
~QrcParser();
bool parseFile(const QString &path);
QString firstFileAtPath(const QString &path, const QLocale &locale) const;
void collectFilesAtPath(const QString &path, QStringList *res, const QLocale *locale = 0) const;
bool hasDirAtPath(const QString &path, const QLocale *locale = 0) const;
void collectFilesInPath(const QString &path, QMap<QString,QStringList> *res, bool addDirs = false,
const QLocale *locale = 0) const;
QStringList errorMessages() const;
QStringList languages() const;
bool isValid() const;
static Ptr parseQrcFile(const QString &path);
static QString normalizedQrcFilePath(const QString &path);
static QString normalizedQrcDirectoryPath(const QString &path);
private:
QrcParser();
QrcParser(const QrcParser &);
Internal::QrcParserPrivate *d;
};
class QMLJS_EXPORT QrcCache
{
public:
QrcCache();
~QrcCache();
QrcParser::ConstPtr addPath(const QString &path);
void removePath(const QString &path);
QrcParser::ConstPtr updatePath(const QString &path);
QrcParser::ConstPtr parsedPath(const QString &path);
void clear();
private:
Internal::QrcCachePrivate *d;
};
}
#endif // QMLJSQRCPARSER_H
......@@ -30,6 +30,7 @@
#include "qmljsscopechain.h"
#include "qmljsbind.h"
#include "qmljsevaluate.h"
#include "qmljsmodelmanagerinterface.h"
using namespace QmlJS;
......@@ -310,7 +311,10 @@ void ScopeChain::initializeRootScope()
if (!m_document->bind()->isJsLibrary()) {
foreach (Document::Ptr otherDoc, snapshot) {
foreach (const ImportInfo &import, otherDoc->bind()->imports()) {
if (import.type() == ImportInfo::FileImport && m_document->fileName() == import.path()) {
if ((import.type() == ImportInfo::FileImport && m_document->fileName() == import.path())
|| (import.type() == ImportInfo::QrcFileImport
&& ModelManagerInterface::instance()->filesAtQrcPath(import.path())
.contains(m_document->fileName()))) {
QmlComponentChain *component = new QmlComponentChain(otherDoc);
componentScopes.insert(otherDoc.data(), component);
chain->addInstantiatingComponent(component);
......
......@@ -47,6 +47,7 @@
#include <qmljs/qmljscheck.h>
#include <qmljs/qmljsutils.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qmljs/qmljsqrcparser.h>
#include <QSet>
#include <QDir>
......@@ -362,10 +363,17 @@ public:
} else if (importInfo.isValid() && importInfo.type() == ImportInfo::DirectoryImport) {
QString path = importInfo.path();
QDir dir(m_doc->path());
// should probably try to make it relatve to some import path, not to the document path
QString relativeDir = dir.relativeFilePath(path);
QString name = relativeDir.replace(QLatin1Char('/'), QLatin1Char('.'));
if (!name.isEmpty())
typeName.prepend(name + QLatin1Char('.'));
} else if (importInfo.isValid() && importInfo.type() == ImportInfo::QrcDirectoryImport) {
QString path = QrcParser::normalizedQrcDirectoryPath(importInfo.path());
path = path.mid(1, path.size() - ((path.size() > 1) ? 2 : 1));
const QString name = path.replace(QLatin1Char('/'), QLatin1Char('.'));
if (!name.isEmpty())
typeName.prepend(name + QLatin1Char('.'));
}
}
}
......
......@@ -43,6 +43,7 @@
#include <qmljs/parser/qmljsast_p.h>
#include <qmljs/parser/qmljsastfwd_p.h>
#include <qmljs/qmljsutils.h>
#include <qmljs/qmljsqrcparser.h>
#include <texteditor/itexteditor.h>
#include <texteditor/basetexteditor.h>
#include <texteditor/helpitem.h>
......@@ -134,9 +135,15 @@ static inline QString getModuleName(const ScopeChain &scopeChain, const Document
} else if (importInfo.isValid() && importInfo.type() == ImportInfo::DirectoryImport) {
const QString path = importInfo.path();
const QDir dir(qmlDocument->path());
// should probably try to make it relatve to some import path, not to the document path
QString relativeDir = dir.relativeFilePath(path);
const QString name = relativeDir.replace(QLatin1Char('/'), QLatin1Char('.'));
return name;
} else if (importInfo.isValid() && importInfo.type() == ImportInfo::QrcDirectoryImport) {
QString path = QrcParser::normalizedQrcDirectoryPath(importInfo.path());
path = path.mid(1, path.size() - ((path.size() > 1) ? 2 : 1));
const QString name = path.replace(QLatin1Char('/'), QLatin1Char('.'));
return name;
}
}
return QString();
......
......@@ -58,6 +58,7 @@
#include <QTextStream>
#include <QTimer>
#include <QRegExp>
#include <QtAlgorithms>
#include <QDebug>
......@@ -406,6 +407,114 @@ void ModelManager::removeFiles(const QStringList &files)
}
}
namespace {
bool pInfoLessThanActive(const ModelManager::ProjectInfo &p1, const ModelManager::ProjectInfo &p2)
{
QStringList s1 = p1.activeResourceFiles;
QStringList s2 = p2.activeResourceFiles;
if (s1.size() < s2.size())
return true;
if (s1.size() > s2.size())
return false;
for (int i = 0; i < s1.size(); ++i) {
if (s1.at(i) < s2.at(i))
return true;
else if (s1.at(i) > s2.at(i))
return false;
}
return false;
}
bool pInfoLessThanAll(const ModelManager::ProjectInfo &p1, const ModelManager::ProjectInfo &p2)
{
QStringList s1 = p1.allResourceFiles;
QStringList s2 = p2.allResourceFiles;
if (s1.size() < s2.size())
return true;
if (s1.size() > s2.size())
return false;
for (int i = 0; i < s1.size(); ++i) {
if (s1.at(i) < s2.at(i))
return true;
else if (s1.at(i) > s2.at(i))
return false;
}
return false;
}
}
QStringList ModelManager::filesAtQrcPath(const QString &path, const QLocale *locale,
ProjectExplorer::Project *project,
QrcResourceSelector resources)
{
QString normPath = QrcParser::normalizedQrcFilePath(path);
QList<ProjectInfo> pInfos;
if (project)
pInfos.append(projectInfo(project));
else
pInfos = projectInfos();
QStringList res;
QSet<QString> pathsChecked;
foreach (const ModelManager::ProjectInfo &pInfo, pInfos) {
QStringList qrcFilePaths;
if (resources == ActiveQrcResources)
qrcFilePaths = pInfo.activeResourceFiles;
else
qrcFilePaths = pInfo.allResourceFiles;
foreach (const QString &qrcFilePath, qrcFilePaths) {
if (pathsChecked.contains(qrcFilePath))
continue;
pathsChecked.insert(qrcFilePath);
QrcParser::ConstPtr qrcFile = m_qrcCache.parsedPath(qrcFilePath);
if (qrcFile.isNull())
continue;
qrcFile->collectFilesAtPath(normPath, &res, locale);
}
}
res.sort(); // make the result predictable
return res;
}
QMap<QString, QStringList> ModelManager::filesInQrcPath(const QString &path,
const QLocale *locale,
ProjectExplorer::Project *project,
bool addDirs,
QrcResourceSelector resources)
{
QString normPath = QrcParser::normalizedQrcDirectoryPath(path);
QList<ProjectInfo> pInfos;
if (project) {
pInfos.append(projectInfo(project));
} else {
pInfos = projectInfos();
if (resources == ActiveQrcResources) // make the result predictable
qSort(pInfos.begin(), pInfos.end(), &pInfoLessThanActive);
else
qSort(pInfos.begin(), pInfos.end(), &pInfoLessThanAll);
}
QMap<QString, QStringList> res;
QSet<QString> pathsChecked;
foreach (const ModelManager::ProjectInfo &pInfo, pInfos) {
QStringList qrcFilePaths;
if (resources == ActiveQrcResources)
qrcFilePaths = pInfo.activeResourceFiles;
else
qrcFilePaths = pInfo.allResourceFiles;
foreach (const QString &qrcFilePath, qrcFilePaths) {
if (pathsChecked.contains(qrcFilePath))
continue;
pathsChecked.insert(qrcFilePath);
QrcParser::ConstPtr qrcFile = m_qrcCache.parsedPath(qrcFilePath);
if (qrcFile.isNull())
continue;
qrcFile->collectFilesInPath(normPath, &res, addDirs, locale);
}
}
return res;
}
QList<ModelManager::ProjectInfo> ModelManager::projectInfos() const
{
QMutexLocker locker(&m_mutex);
......@@ -462,6 +571,12 @@ void ModelManager::updateProjectInfo(const ProjectInfo &pinfo)
}
updateSourceFiles(newFiles, false);
// update qrc cache
foreach (const QString &newQrc, pinfo.allResourceFiles)
m_qrcCache.addPath(newQrc);
foreach (const QString &oldQrc, oldInfo.allResourceFiles)
m_qrcCache.removePath(oldQrc);
// dump builtin types if the shipped definitions are probably outdated and the
// Qt version ships qmlplugindump
if (QtSupport::QtVersionNumber(pinfo.qtVersionString) > QtSupport::QtVersionNumber(4, 8, 5))
......@@ -497,6 +612,11 @@ ModelManagerInterface::ProjectInfo ModelManager::projectInfoForPath(QString path
void ModelManager::emitDocumentChangedOnDisk(Document::Ptr doc)
{ emit documentChangedOnDisk(doc); }
void ModelManager::updateQrcFile(const QString &path)
{
m_qrcCache.updatePath(path);
}
void ModelManager::updateDocument(Document::Ptr doc)
{
{
......@@ -560,6 +680,23 @@ static void findNewFileImports(const Document::Ptr &doc, const Snapshot &snapsho
scannedPaths->insert(importName);
}
}
} else if (import.type() == ImportInfo::QrcFileImport) {
QStringList importPaths = ModelManagerInterface::instance()->filesAtQrcPath(importName);
foreach (const QString &importPath, importPaths) {
if (! snapshot.document(importPath))
*importedFiles += importPath;
}
} else if (import.type() == ImportInfo::QrcDirectoryImport) {
QMapIterator<QString,QStringList> dirContents(ModelManagerInterface::instance()->filesInQrcPath(importName));
while (dirContents.hasNext()) {
dirContents.next();
if (Document::isQmlLikeOrJsLanguage(Document::guessLanguageFromSuffix(dirContents.key()))) {
foreach (const QString &filePath, dirContents.value()) {
if (! snapshot.document(filePath))
*importedFiles += filePath;
}
}
}
}
}
}
......@@ -697,8 +834,11 @@ void ModelManager::parse(QFutureInterface<void> &future,
const QString fileName = files.at(i);
Document::Language language = languageOfFile(fileName);
if (language == Document::UnknownLanguage)
if (language == Document::UnknownLanguage) {
if (fileName.endsWith(QLatin1String(".qrc")))
modelManager->updateQrcFile(fileName);
continue;
}
QString contents;
int documentRevision = 0;
......
......@@ -33,6 +33,7 @@
#include "qmljstools_global.h"
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qmljs/qmljsqrcparser.h>
#include <cplusplus/CppDocument.h>
......@@ -41,6 +42,7 @@
#include <QMutex>
QT_FORWARD_DECLARE_CLASS(QTimer)
QT_FORWARD_DECLARE_CLASS(QLocale)
namespace Core {
class MimeType;
......@@ -50,6 +52,10 @@ namespace CPlusPlus {
class CppModelManagerInterface;
}
namespace QmlJS {
class QrcParser;
}
namespace QmlJSTools {
QMLJSTOOLS_EXPORT QmlJS::Document::Language languageOfFile(const QString &fileName);
......@@ -77,6 +83,14 @@ public:
bool emitDocumentOnDiskChanged);
virtual void fileChangedOnDisk(const QString &path);
virtual void removeFiles(const QStringList &files);
virtual QStringList filesAtQrcPath(const QString &path, const QLocale *locale = 0,
ProjectExplorer::Project *project = 0,
QrcResourceSelector resources = AllQrcResources);
virtual QMap<QString,QStringList> filesInQrcPath(const QString &path,
const QLocale *locale = 0,
ProjectExplorer::Project *project = 0,
bool addDirs = false,
QrcResourceSelector resources = AllQrcResources);
virtual QList<ProjectInfo> projectInfos() const;
virtual ProjectInfo projectInfo(ProjectExplorer::Project *project) const;
......@@ -87,6 +101,7 @@ public:
void updateDocument(QmlJS::Document::Ptr doc);
void updateLibraryInfo(const QString &path, const QmlJS::LibraryInfo &info);
void emitDocumentChangedOnDisk(QmlJS::Document::Ptr doc);
void updateQrcFile(const QString &path);
virtual QStringList importPaths() const;
virtual QmlJS::QmlLanguageBundles activeBundles() const;
......@@ -147,6 +162,7 @@ private:
QTimer *m_updateCppQmlTypesTimer;
QHash<QString, QPair<CPlusPlus::Document::Ptr, bool> > m_queuedCppDocuments;
QFuture<void> m_cppQmlTypesUpdater;
QmlJS::QrcCache m_qrcCache;
CppDataHash m_cppDataHash;
mutable QMutex m_cppDataMutex;
......
......@@ -1886,6 +1886,10 @@ void Qt4ProFileNode::applyEvaluate(EvalResult evalResult, bool async)
QLatin1String("OBJECTIVE_HEADERS"), m_projectDir, buildDirectory);
newVarValues[UiDirVar] = QStringList() << uiDirPath(m_readerExact);
newVarValues[MocDirVar] = QStringList() << mocDirPath(m_readerExact);
newVarValues[ResourceVar] = fileListForVar(m_readerExact, m_readerCumulative,
QLatin1String("RESOURCES"), m_projectDir, buildDirectory);
newVarValues[ExactResourceVar] = fileListForVar(m_readerExact, 0,
QLatin1String("RESOURCES"), m_projectDir, buildDirectory);
newVarValues[PkgConfigVar] = m_readerExact->values(QLatin1String("PKGCONFIG"));
newVarValues[PrecompiledHeaderVar] =
m_readerExact->absoluteFileValues(QLatin1String("PRECOMPILED_HEADER"),
......
......@@ -86,6 +86,8 @@ enum Qt4Variable {
CppSourceVar,
ObjCSourceVar,
ObjCHeaderVar,
ResourceVar,
ExactResourceVar,
UiDirVar,
MocDirVar,
PkgConfigVar,
......