summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libs/cplusplus/cplusplus-lib.pri6
-rw-r--r--src/libs/cplusplus/cplusplus.qbs1
-rw-r--r--src/libs/cplusplus/cppmodelmanagerbase.cpp76
-rw-r--r--src/libs/cplusplus/cppmodelmanagerbase.h62
-rw-r--r--src/libs/qmljs/qmljs-lib.pri4
-rw-r--r--src/libs/qmljs/qmljs.qbs3
-rw-r--r--src/libs/qmljs/qmljs_dependencies.pri3
-rw-r--r--src/libs/qmljs/qmljsconstants.h6
-rw-r--r--src/libs/qmljs/qmljsfindexportedcpptypes.cpp (renamed from src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp)37
-rw-r--r--src/libs/qmljs/qmljsfindexportedcpptypes.h (renamed from src/plugins/qmljstools/qmljsfindexportedcpptypes.h)13
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.cpp1140
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.h167
-rw-r--r--src/libs/qmljs/qmljsplugindumper.cpp (renamed from src/plugins/qmljstools/qmljsplugindumper.cpp)27
-rw-r--r--src/libs/qmljs/qmljsplugindumper.h (renamed from src/plugins/qmljstools/qmljsplugindumper.h)12
-rw-r--r--src/plugins/cpptools/cppmodelmanager.cpp5
-rw-r--r--src/plugins/cpptools/cppmodelmanager.h2
-rw-r--r--src/plugins/cpptools/cppmodelmanagerinterface.cpp16
-rw-r--r--src/plugins/cpptools/cppmodelmanagerinterface.h6
-rw-r--r--src/plugins/qbsprojectmanager/qbsproject.cpp2
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeproject.cpp2
-rw-r--r--src/plugins/qmljstools/qmljsmodelmanager.cpp1079
-rw-r--r--src/plugins/qmljstools/qmljsmodelmanager.h126
-rw-r--r--src/plugins/qmljstools/qmljstools.pro4
-rw-r--r--src/plugins/qmljstools/qmljstools.qbs4
-rw-r--r--src/plugins/qmljstools/qmljstoolsconstants.h3
-rw-r--r--src/plugins/qmljstools/qmljstoolsplugin.cpp4
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.cpp2
-rw-r--r--src/plugins/qtsupport/qmldumptool.cpp2
28 files changed, 1505 insertions, 1309 deletions
diff --git a/src/libs/cplusplus/cplusplus-lib.pri b/src/libs/cplusplus/cplusplus-lib.pri
index bd77b940bf..7d2a3c9aca 100644
--- a/src/libs/cplusplus/cplusplus-lib.pri
+++ b/src/libs/cplusplus/cplusplus-lib.pri
@@ -57,7 +57,8 @@ HEADERS += \
$$PWD/pp-scanner.h \
$$PWD/findcdbbreakpoint.h \
$$PWD/PPToken.h \
- $$PWD/Dumpers.h
+ $$PWD/Dumpers.h \
+ $$PWD/cppmodelmanagerbase.h
SOURCES += \
$$PWD/SimpleLexer.cpp \
@@ -85,6 +86,7 @@ SOURCES += \
$$PWD/pp-scanner.cpp \
$$PWD/findcdbbreakpoint.cpp \
$$PWD/PPToken.cpp \
- $$PWD/Dumpers.cpp
+ $$PWD/Dumpers.cpp \
+ $$PWD/cppmodelmanagerbase.cpp
RESOURCES += $$PWD/cplusplus.qrc
diff --git a/src/libs/cplusplus/cplusplus.qbs b/src/libs/cplusplus/cplusplus.qbs
index 2331804a55..09dfe63cec 100644
--- a/src/libs/cplusplus/cplusplus.qbs
+++ b/src/libs/cplusplus/cplusplus.qbs
@@ -94,6 +94,7 @@ QtcLibrary {
"BackwardsScanner.cpp", "BackwardsScanner.h",
"CppDocument.cpp", "CppDocument.h",
"CppRewriter.cpp", "CppRewriter.h",
+ "cppmodelmanagerbase.cpp", "cppmodelmanagerbase.h",
"DependencyTable.cpp", "DependencyTable.h",
"DeprecatedGenTemplateInstance.cpp", "DeprecatedGenTemplateInstance.h",
"ExpressionUnderCursor.cpp", "ExpressionUnderCursor.h",
diff --git a/src/libs/cplusplus/cppmodelmanagerbase.cpp b/src/libs/cplusplus/cppmodelmanagerbase.cpp
new file mode 100644
index 0000000000..6ad44b5bc4
--- /dev/null
+++ b/src/libs/cplusplus/cppmodelmanagerbase.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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.
+**
+****************************************************************************/
+
+#include "cppmodelmanagerbase.h"
+
+namespace CPlusPlus {
+
+static CppModelManagerBase *g_instance = 0;
+
+CppModelManagerBase::CppModelManagerBase(QObject *parent)
+ : QObject(parent)
+{
+ Q_ASSERT(!g_instance);
+ g_instance = this;
+}
+
+CppModelManagerBase::~CppModelManagerBase()
+{
+ Q_ASSERT(g_instance == this);
+ g_instance = 0;
+}
+
+CppModelManagerBase *CppModelManagerBase::instance()
+{
+ return g_instance;
+}
+
+bool CppModelManagerBase::trySetExtraDiagnostics(const QString &fileName, const QString &kind,
+ const QList<CPlusPlus::Document::DiagnosticMessage> &diagnostics)
+{
+ if (CppModelManagerBase *mm = instance())
+ return mm->setExtraDiagnostics(fileName, kind, diagnostics);
+ return false;
+}
+
+bool CppModelManagerBase::setExtraDiagnostics(const QString &fileName, const QString &kind,
+ const QList<CPlusPlus::Document::DiagnosticMessage> &diagnostics)
+{
+ Q_UNUSED(fileName);
+ Q_UNUSED(kind);
+ Q_UNUSED(diagnostics);
+ return false;
+}
+
+CPlusPlus::Snapshot CppModelManagerBase::snapshot() const
+{
+ return CPlusPlus::Snapshot();
+}
+
+} // namespace CPlusPlus
diff --git a/src/libs/cplusplus/cppmodelmanagerbase.h b/src/libs/cplusplus/cppmodelmanagerbase.h
new file mode 100644
index 0000000000..f76c80a3ed
--- /dev/null
+++ b/src/libs/cplusplus/cppmodelmanagerbase.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 CPPMODELMANAGERBASE_H
+#define CPPMODELMANAGERBASE_H
+
+#include <cplusplus/CppDocument.h>
+
+#include <QObject>
+#include <QList>
+
+QT_BEGIN_NAMESPACE
+class QString;
+QT_END_NAMESPACE
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT CppModelManagerBase : public QObject
+{
+ Q_OBJECT
+public:
+ CppModelManagerBase(QObject *parent = 0);
+ ~CppModelManagerBase();
+
+ static CppModelManagerBase *instance();
+ static bool trySetExtraDiagnostics(const QString &fileName, const QString &kind,
+ const QList<Document::DiagnosticMessage> &diagnostics);
+
+ virtual bool setExtraDiagnostics(const QString &fileName, const QString &kind,
+ const QList<Document::DiagnosticMessage> &diagnostics);
+ virtual CPlusPlus::Snapshot snapshot() const;
+};
+
+} // namespace CPlusPlus
+
+#endif // CPPMODELMANAGERBASE_H
diff --git a/src/libs/qmljs/qmljs-lib.pri b/src/libs/qmljs/qmljs-lib.pri
index 6324d83e32..47c4a9ecf6 100644
--- a/src/libs/qmljs/qmljs-lib.pri
+++ b/src/libs/qmljs/qmljs-lib.pri
@@ -11,6 +11,7 @@ HEADERS += \
$$PWD/qmljsbind.h \
$$PWD/qmljsbundle.h \
$$PWD/qmljsevaluate.h \
+ $$PWD/qmljsfindexportedcpptypes.h \
$$PWD/qmljsdocument.h \
$$PWD/qmljsscanner.h \
$$PWD/qmljsinterpreter.h \
@@ -25,6 +26,7 @@ HEADERS += \
$$PWD/qmljsrewriter.h \
$$PWD/qmljsicons.h \
$$PWD/qmljsdelta.h \
+ $$PWD/qmljsplugindumper.h \
$$PWD/qmljstypedescriptionreader.h \
$$PWD/qmljsscopeastpath.h \
$$PWD/qmljsvalueowner.h \
@@ -47,6 +49,7 @@ SOURCES += \
$$PWD/qmljsbind.cpp \
$$PWD/qmljsbundle.cpp \
$$PWD/qmljsevaluate.cpp \
+ $$PWD/qmljsfindexportedcpptypes.cpp \
$$PWD/qmljsdocument.cpp \
$$PWD/qmljsscanner.cpp \
$$PWD/qmljsinterpreter.cpp \
@@ -60,6 +63,7 @@ SOURCES += \
$$PWD/qmljsrewriter.cpp \
$$PWD/qmljsicons.cpp \
$$PWD/qmljsdelta.cpp \
+ $$PWD/qmljsplugindumper.cpp \
$$PWD/qmljstypedescriptionreader.cpp \
$$PWD/qmljsscopeastpath.cpp \
$$PWD/qmljsvalueowner.cpp \
diff --git a/src/libs/qmljs/qmljs.qbs b/src/libs/qmljs/qmljs.qbs
index 94968cf313..0016128545 100644
--- a/src/libs/qmljs/qmljs.qbs
+++ b/src/libs/qmljs/qmljs.qbs
@@ -11,6 +11,7 @@ QtcLibrary {
Depends { name: "Utils" }
Depends { name: "LanguageUtils" }
+ Depends { name: "CPlusPlus" }
Depends { name: "Qt"; submodules: ["widgets", "script", "xml"] }
Group {
@@ -33,6 +34,7 @@ QtcLibrary {
"qmljsdelta.cpp", "qmljsdelta.h",
"qmljsdocument.cpp", "qmljsdocument.h",
"qmljsevaluate.cpp", "qmljsevaluate.h",
+ "qmljsfindexportedcpptypes.cpp", "qmljsfindexportedcpptypes.h",
"qmljsicons.cpp", "qmljsicons.h",
"qmljsicontextpane.h",
"qmljsimportdependencies.cpp", "qmljsimportdependencies.h",
@@ -41,6 +43,7 @@ QtcLibrary {
"qmljslineinfo.cpp", "qmljslineinfo.h",
"qmljslink.cpp", "qmljslink.h",
"qmljsmodelmanagerinterface.cpp", "qmljsmodelmanagerinterface.h",
+ "qmljsplugindumper.cpp", "qmljsplugindumper.h",
"qmljspropertyreader.cpp", "qmljspropertyreader.h",
"qmljsqrcparser.cpp", "qmljsqrcparser.h",
"qmljsreformatter.cpp", "qmljsreformatter.h",
diff --git a/src/libs/qmljs/qmljs_dependencies.pri b/src/libs/qmljs/qmljs_dependencies.pri
index e1d1204148..3686f2e628 100644
--- a/src/libs/qmljs/qmljs_dependencies.pri
+++ b/src/libs/qmljs/qmljs_dependencies.pri
@@ -1,4 +1,5 @@
QTC_LIB_NAME = QmlJS
QTC_LIB_DEPENDS += \
utils \
- languageutils
+ languageutils \
+ cplusplus
diff --git a/src/libs/qmljs/qmljsconstants.h b/src/libs/qmljs/qmljsconstants.h
index 3ddb014754..377f282ea4 100644
--- a/src/libs/qmljs/qmljsconstants.h
+++ b/src/libs/qmljs/qmljsconstants.h
@@ -80,5 +80,11 @@ enum Enum
};
}
+namespace Constants {
+
+const char TASK_INDEX[] = "QmlJSEditor.TaskIndex";
+const char TASK_IMPORT_SCAN[] = "QmlJSEditor.TaskImportScan";
+
+} // namespace Constants
} // namespace QmlJS
#endif // QMLJSCONSTANTS_H
diff --git a/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp b/src/libs/qmljs/qmljsfindexportedcpptypes.cpp
index 4b9f819fd7..7034ea64b9 100644
--- a/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp
+++ b/src/libs/qmljs/qmljsfindexportedcpptypes.cpp
@@ -30,13 +30,16 @@
#include "qmljsfindexportedcpptypes.h"
#include <qmljs/qmljsinterpreter.h>
+#include <qmljs/qmljsdocument.h>
#include <cplusplus/Overview.h>
#include <cplusplus/TypeOfExpression.h>
-#include <cpptools/cppmodelmanagerinterface.h>
+#include <cplusplus/cppmodelmanagerbase.h>
+#include <cplusplus/CppDocument.h>
#include <QDebug>
+#include <QList>
-using namespace QmlJSTools;
+//using namespace QmlJS;
namespace {
using namespace CPlusPlus;
@@ -66,7 +69,7 @@ class FindExportsVisitor : protected ASTVisitor
ASTMatcher _matcher;
ASTPatternBuilder _builder;
Overview _overview;
- QList<Document::DiagnosticMessage> _messages;
+ QList<CPlusPlus::Document::DiagnosticMessage> _messages;
public:
FindExportsVisitor(CPlusPlus::Document::Ptr doc)
@@ -82,7 +85,7 @@ public:
accept(translationUnit()->ast());
}
- QList<Document::DiagnosticMessage> messages() const
+ QList<CPlusPlus::Document::DiagnosticMessage> messages() const
{
return _messages;
}
@@ -181,7 +184,7 @@ protected:
Document::DiagnosticMessage::Warning,
_doc->fileName(),
line, column,
- FindExportedCppTypes::tr(
+ QmlJS::FindExportedCppTypes::tr(
"The type will only be available in Qt Creator's QML editors when the type name is a string literal"));
return false;
}
@@ -239,7 +242,7 @@ protected:
Document::DiagnosticMessage::Warning,
_doc->fileName(),
line, column,
- FindExportedCppTypes::tr(
+ QmlJS::FindExportedCppTypes::tr(
"The module URI cannot be determined by static analysis. The type will be available\n"
"globally in the QML editor. You can add a \"// @uri My.Module.Uri\" annotation to let\n"
"Qt Creator know about a likely URI."));
@@ -370,7 +373,7 @@ protected:
Document::DiagnosticMessage::Warning,
_doc->fileName(),
line, column,
- FindExportedCppTypes::tr(
+ QmlJS::FindExportedCppTypes::tr(
"must be a string literal to be available in the QML editor"));
return false;
}
@@ -389,7 +392,7 @@ protected:
}
private:
- QString stringOf(AST *ast)
+ QString stringOf(CPlusPlus::AST *ast)
{
return stringOf(ast->firstToken(), ast->lastToken() - 1);
}
@@ -681,6 +684,8 @@ static void buildContextProperties(
} // anonymous namespace
+namespace QmlJS {
+
FindExportedCppTypes::FindExportedCppTypes(const CPlusPlus::Snapshot &snapshot)
: m_snapshot(snapshot)
{
@@ -699,11 +704,9 @@ void FindExportedCppTypes::operator()(const CPlusPlus::Document::Ptr &document)
FindExportsVisitor finder(document);
finder();
- if (CppTools::CppModelManagerInterface *cppModelManager = CppTools::CppModelManagerInterface::instance()) {
- static const QString kindKey = QLatin1String("QmlJSTools.ExportedQmlTypesDiagnostic");
- cppModelManager->setExtraDiagnostics(document->fileName(), kindKey,
- finder.messages());
- }
+ static const QString kindKey = QLatin1String("QmlJSTools.ExportedQmlTypesDiagnostic");
+ CppModelManagerBase::trySetExtraDiagnostics(document->fileName(), kindKey,
+ finder.messages());
// if nothing was found, done
const QList<ContextProperty> contextPropertyDescriptions = finder.contextProperties();
@@ -712,8 +715,8 @@ void FindExportedCppTypes::operator()(const CPlusPlus::Document::Ptr &document)
return;
// context properties need lookup inside function scope, and thus require a full check
- Document::Ptr localDoc = document;
- if (document->checkMode() != Document::FullCheck && !contextPropertyDescriptions.isEmpty()) {
+ CPlusPlus::Document::Ptr localDoc = document;
+ if (document->checkMode() != CPlusPlus::Document::FullCheck && !contextPropertyDescriptions.isEmpty()) {
localDoc = m_snapshot.documentFromSource(document->utf8Source(), document->fileName());
localDoc->check();
}
@@ -749,7 +752,7 @@ QHash<QString, QString> FindExportedCppTypes::contextProperties() const
return m_contextProperties;
}
-bool FindExportedCppTypes::maybeExportsTypes(const Document::Ptr &document)
+bool FindExportedCppTypes::maybeExportsTypes(const CPlusPlus::Document::Ptr &document)
{
if (!document->control())
return false;
@@ -770,3 +773,5 @@ bool FindExportedCppTypes::maybeExportsTypes(const Document::Ptr &document)
}
return false;
}
+
+} // namespace QmlJS
diff --git a/src/plugins/qmljstools/qmljsfindexportedcpptypes.h b/src/libs/qmljs/qmljsfindexportedcpptypes.h
index 90884d66d2..ca6508c39a 100644
--- a/src/plugins/qmljstools/qmljsfindexportedcpptypes.h
+++ b/src/libs/qmljs/qmljsfindexportedcpptypes.h
@@ -27,18 +27,19 @@
**
****************************************************************************/
-#ifndef QMLJSTOOLS_QMLJSFINDEXPORTEDCPPTYPES_H
-#define QMLJSTOOLS_QMLJSFINDEXPORTEDCPPTYPES_H
+#ifndef QMLJS_QMLJSFINDEXPORTEDCPPTYPES_H
+#define QMLJS_QMLJSFINDEXPORTEDCPPTYPES_H
+#include "qmljs_global.h"
#include <cplusplus/CppDocument.h>
#include <languageutils/fakemetaobject.h>
#include <QCoreApplication>
#include <QHash>
-namespace QmlJSTools {
+namespace QmlJS {
-class FindExportedCppTypes
+class QMLJS_EXPORT FindExportedCppTypes
{
Q_DECLARE_TR_FUNCTIONS(QmlJSTools::FindExportedCppTypes)
public:
@@ -58,6 +59,6 @@ private:
QHash<QString, QString> m_contextProperties;
};
-} // namespace QmlJSTools
+} // namespace QmlJS
-#endif // QMLJSTOOLS_QMLJSFINDEXPORTEDCPPTYPES_H
+#endif // QMLJS_QMLJSFINDEXPORTEDCPPTYPES_H
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
index ec70d6bf65..d9aa6aa118 100644
--- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
+++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
@@ -27,11 +27,33 @@
**
****************************************************************************/
+#include "qmljsbind.h"
+#include "qmljsconstants.h"
+#include "qmljsfindexportedcpptypes.h"
+#include "qmljsinterpreter.h"
#include "qmljsmodelmanagerinterface.h"
+#include "qmljsplugindumper.h"
+#include "qmljstypedescriptionreader.h"
+#include <cplusplus/cppmodelmanagerbase.h>
+#include <utils/function.h>
+#include <utils/hostosinfo.h>
+
+#include <QDebug>
+#include <QDir>
+#include <QFile>
#include <QFileInfo>
+#include <QMetaObject>
+#include <QRegExp>
+#include <QTextDocument>
+#include <QTextStream>
+#include <QTimer>
+#include <QtAlgorithms>
+#include <utils/runextensions.h>
+
+#include <stdio.h>
-using namespace QmlJS;
+namespace QmlJS {
/*!
\class QmlJS::ModelManagerInterface
@@ -54,9 +76,45 @@ using namespace QmlJS;
static ModelManagerInterface *g_instance = 0;
+static QStringList environmentImportPaths()
+{
+ QStringList paths;
+
+ QByteArray envImportPath = qgetenv("QML_IMPORT_PATH");
+
+ foreach (const QString &path, QString::fromLatin1(envImportPath)
+ .split(Utils::HostOsInfo::pathListSeparator(), QString::SkipEmptyParts)) {
+ QString canonicalPath = QDir(path).canonicalPath();
+ if (!canonicalPath.isEmpty() && !paths.contains(canonicalPath))
+ paths.append(canonicalPath);
+ }
+
+ return paths;
+}
+
ModelManagerInterface::ModelManagerInterface(QObject *parent)
- : QObject(parent)
+ : QObject(parent),
+ m_shouldScanImports(false),
+ m_pluginDumper(new PluginDumper(this))
{
+ m_synchronizer.setCancelOnWait(true);
+
+ m_updateCppQmlTypesTimer = new QTimer(this);
+ m_updateCppQmlTypesTimer->setInterval(1000);
+ m_updateCppQmlTypesTimer->setSingleShot(true);
+ connect(m_updateCppQmlTypesTimer, SIGNAL(timeout()), SLOT(startCppQmlTypeUpdate()));
+
+ m_asyncResetTimer = new QTimer(this);
+ m_asyncResetTimer->setInterval(15000);
+ m_asyncResetTimer->setSingleShot(true);
+ connect(m_asyncResetTimer, SIGNAL(timeout()), SLOT(resetCodeModel()));
+
+ qRegisterMetaType<QmlJS::Document::Ptr>("QmlJS::Document::Ptr");
+ qRegisterMetaType<QmlJS::LibraryInfo>("QmlJS::LibraryInfo");
+
+ m_defaultImportPaths << environmentImportPaths();
+ updateImportPaths();
+
Q_ASSERT(! g_instance);
g_instance = this;
}
@@ -113,8 +171,1086 @@ ModelManagerInterface *ModelManagerInterface::instance()
return g_instance;
}
+void ModelManagerInterface::writeWarning(const QString &msg)
+{
+ if (ModelManagerInterface *i = instance())
+ i->writeMessageInternal(msg);
+ else
+ qDebug() << msg;
+}
+
+ModelManagerInterface::WorkingCopy ModelManagerInterface::workingCopy()
+{
+ if (ModelManagerInterface *i = instance())
+ return i->workingCopyInternal();
+ return WorkingCopy();
+}
+
QHash<QString, Language::Enum> ModelManagerInterface::languageForSuffix() const
{
return defaultLanguageMapping();
}
+void ModelManagerInterface::writeMessageInternal(const QString &msg) const
+{
+ qDebug() << msg;
+}
+
+ModelManagerInterface::WorkingCopy ModelManagerInterface::workingCopyInternal() const
+{
+ ModelManagerInterface::WorkingCopy res;
+ return res;
+}
+
+void ModelManagerInterface::addTaskInternal(QFuture<void> result, const QString &msg,
+ const char *taskId) const
+{
+ Q_UNUSED(result);
+ qDebug() << "started " << taskId << " " << msg;
+}
+
+void ModelManagerInterface::loadQmlTypeDescriptionsInternal(const QString &resourcePath)
+{
+ const QDir typeFileDir(resourcePath + QLatin1String("/qml-type-descriptions"));
+ const QStringList qmlTypesExtensions = QStringList() << QLatin1String("*.qmltypes");
+ QFileInfoList qmlTypesFiles = typeFileDir.entryInfoList(
+ qmlTypesExtensions,
+ QDir::Files,
+ QDir::Name);
+
+ QStringList errors;
+ QStringList warnings;
+
+ // filter out the actual Qt builtins
+ for (int i = 0; i < qmlTypesFiles.size(); ++i) {
+ if (qmlTypesFiles.at(i).baseName() == QLatin1String("builtins")) {
+ QFileInfoList list;
+ list.append(qmlTypesFiles.at(i));
+ CppQmlTypesLoader::defaultQtObjects =
+ CppQmlTypesLoader::loadQmlTypes(list, &errors, &warnings);
+ qmlTypesFiles.removeAt(i);
+ break;
+ }
+ }
+
+ // load the fallbacks for libraries
+ CppQmlTypesLoader::defaultLibraryObjects.unite(
+ CppQmlTypesLoader::loadQmlTypes(qmlTypesFiles, &errors, &warnings));
+
+ foreach (const QString &error, errors)
+ writeMessageInternal(error);
+ foreach (const QString &warning, warnings)
+ writeMessageInternal(warning);
+}
+
+
+
+Snapshot ModelManagerInterface::snapshot() const
+{
+ QMutexLocker locker(&m_mutex);
+ return _validSnapshot;
+}
+
+Snapshot ModelManagerInterface::newestSnapshot() const
+{
+ QMutexLocker locker(&m_mutex);
+ return _newestSnapshot;
+}
+
+void ModelManagerInterface::updateSourceFiles(const QStringList &files,
+ bool emitDocumentOnDiskChanged)
+{
+ refreshSourceFiles(files, emitDocumentOnDiskChanged);
+}
+
+QFuture<void> ModelManagerInterface::refreshSourceFiles(const QStringList &sourceFiles,
+ bool emitDocumentOnDiskChanged)
+{
+ if (sourceFiles.isEmpty())
+ return QFuture<void>();
+
+ QFuture<void> result = QtConcurrent::run(&ModelManagerInterface::parse,
+ workingCopyInternal(), sourceFiles,
+ this, Language::Qml,
+ emitDocumentOnDiskChanged);
+
+ if (m_synchronizer.futures().size() > 10) {
+ QList<QFuture<void> > futures = m_synchronizer.futures();
+
+ m_synchronizer.clearFutures();
+
+ foreach (const QFuture<void> &future, futures) {
+ if (! (future.isFinished() || future.isCanceled()))
+ m_synchronizer.addFuture(future);
+ }
+ }
+
+ m_synchronizer.addFuture(result);
+
+ if (sourceFiles.count() > 1)
+ addTaskInternal(result, tr("Indexing"), Constants::TASK_INDEX);
+
+ if (sourceFiles.count() > 1 && !m_shouldScanImports) {
+ bool scan = false;
+ {
+ QMutexLocker l(&m_mutex);
+ if (!m_shouldScanImports) {
+ m_shouldScanImports = true;
+ scan = true;
+ }
+ }
+ if (scan)
+ updateImportPaths();
+ }
+
+ return result;
+}
+
+
+void ModelManagerInterface::fileChangedOnDisk(const QString &path)
+{
+ QtConcurrent::run(&ModelManagerInterface::parse,
+ workingCopyInternal(), QStringList() << path,
+ this, Language::Unknown, true);
+}
+
+void ModelManagerInterface::removeFiles(const QStringList &files)
+{
+ emit aboutToRemoveFiles(files);
+
+ QMutexLocker locker(&m_mutex);
+
+ foreach (const QString &file, files) {
+ _validSnapshot.remove(file);
+ _newestSnapshot.remove(file);
+ }
+}
+
+namespace {
+bool pInfoLessThanActive(const ModelManagerInterface::ProjectInfo &p1, const ModelManagerInterface::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 ModelManagerInterface::ProjectInfo &p1, const ModelManagerInterface::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 ModelManagerInterface::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 ModelManagerInterface::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> ModelManagerInterface::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 ModelManagerInterface::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<ModelManagerInterface::ProjectInfo> ModelManagerInterface::projectInfos() const
+{
+ QMutexLocker locker(&m_mutex);
+
+ return m_projects.values();
+}
+
+ModelManagerInterface::ProjectInfo ModelManagerInterface::projectInfo(ProjectExplorer::Project *project) const
+{
+ QMutexLocker locker(&m_mutex);
+
+ return m_projects.value(project, ProjectInfo());
+}
+
+void ModelManagerInterface::updateProjectInfo(const ProjectInfo &pinfo, ProjectExplorer::Project *p)
+{
+ if (! pinfo.isValid() || !p)
+ return;
+
+ Snapshot snapshot;
+ ProjectInfo oldInfo;
+ {
+ QMutexLocker locker(&m_mutex);
+ oldInfo = m_projects.value(p);
+ m_projects.insert(p, pinfo);
+ snapshot = _validSnapshot;
+ }
+
+ if (oldInfo.qmlDumpPath != pinfo.qmlDumpPath
+ || oldInfo.qmlDumpEnvironment != pinfo.qmlDumpEnvironment) {
+ m_pluginDumper->scheduleRedumpPlugins();
+ m_pluginDumper->scheduleMaybeRedumpBuiltins(pinfo);
+ }
+
+
+ updateImportPaths();
+
+ // remove files that are no longer in the project and have been deleted
+ QStringList deletedFiles;
+ foreach (const QString &oldFile, oldInfo.sourceFiles) {
+ if (snapshot.document(oldFile)
+ && !pinfo.sourceFiles.contains(oldFile)
+ && !QFile::exists(oldFile)) {
+ deletedFiles += oldFile;
+ }
+ }
+ removeFiles(deletedFiles);
+ foreach (const QString &oldFile, deletedFiles)
+ m_fileToProject.remove(oldFile, p);
+
+ // parse any files not yet in the snapshot
+ QStringList newFiles;
+ foreach (const QString &file, pinfo.sourceFiles) {
+ if (!snapshot.document(file))
+ newFiles += file;
+ }
+ updateSourceFiles(newFiles, false);
+ foreach (const QString &newFile, deletedFiles)
+ m_fileToProject.insert(newFile, p);
+
+ // update qrc cache
+ foreach (const QString &newQrc, pinfo.allResourceFiles)
+ m_qrcCache.addPath(newQrc);
+ foreach (const QString &oldQrc, oldInfo.allResourceFiles)
+ m_qrcCache.removePath(oldQrc);
+
+ int majorVersion, minorVersion, patchVersion;
+ // dump builtin types if the shipped definitions are probably outdated and the
+ // Qt version ships qmlplugindump
+ if (::sscanf(pinfo.qtVersionString.toLatin1().constData(), "%d.%d.%d",
+ &majorVersion, &minorVersion, &patchVersion) != 3)
+ majorVersion = minorVersion = patchVersion = -1;
+
+ if (majorVersion > 4 || (majorVersion == 4 && (minorVersion > 8 || (majorVersion == 8
+ && patchVersion >= 5)))) {
+ m_pluginDumper->loadBuiltinTypes(pinfo);
+ }
+
+ emit projectInfoUpdated(pinfo);
+}
+
+
+void ModelManagerInterface::removeProjectInfo(ProjectExplorer::Project *project)
+{
+ ProjectInfo info;
+ info.sourceFiles.clear();
+ // update with an empty project info to clear data
+ updateProjectInfo(info, project);
+
+ {
+ QMutexLocker locker(&m_mutex);
+ m_projects.remove(project);
+ }
+}
+
+ModelManagerInterface::ProjectInfo ModelManagerInterface::projectInfoForPath(QString path)
+{
+ QMutexLocker locker(&m_mutex);
+
+ foreach (const ProjectInfo &p, m_projects)
+ if (p.sourceFiles.contains(path))
+ return p;
+ return ProjectInfo();
+}
+
+void ModelManagerInterface::emitDocumentChangedOnDisk(Document::Ptr doc)
+{ emit documentChangedOnDisk(doc); }
+
+void ModelManagerInterface::updateQrcFile(const QString &path)
+{
+ m_qrcCache.updatePath(path);
+}
+
+void ModelManagerInterface::updateDocument(Document::Ptr doc)
+{
+ {
+ QMutexLocker locker(&m_mutex);
+ _validSnapshot.insert(doc);
+ _newestSnapshot.insert(doc, true);
+ }
+ emit documentUpdated(doc);
+}
+
+void ModelManagerInterface::updateLibraryInfo(const QString &path, const LibraryInfo &info)
+{
+ if (!info.pluginTypeInfoError().isEmpty())
+ qDebug() << "Dumping errors for " << path << ":" << info.pluginTypeInfoError();
+
+ {
+ QMutexLocker locker(&m_mutex);
+ _validSnapshot.insertLibraryInfo(path, info);
+ _newestSnapshot.insertLibraryInfo(path, info);
+ }
+ // only emit if we got new useful information
+ if (info.isValid())
+ emit libraryInfoUpdated(path, info);
+}
+
+static QStringList filesInDirectoryForLanguages(const QString &path, QList<Language::Enum> languages)
+{
+ const QStringList pattern = ModelManagerInterface::globPatternsForLanguages(languages);
+ QStringList files;
+
+ const QDir dir(path);
+ foreach (const QFileInfo &fi, dir.entryInfoList(pattern, QDir::Files))
+ files += fi.absoluteFilePath();
+
+ return files;
+}
+
+static void findNewImplicitImports(const Document::Ptr &doc, const Snapshot &snapshot,
+ QStringList *importedFiles, QSet<QString> *scannedPaths)
+{
+ // scan files that could be implicitly imported
+ // it's important we also do this for JS files, otherwise the isEmpty check will fail
+ if (snapshot.documentsInDirectory(doc->path()).isEmpty()) {
+ if (! scannedPaths->contains(doc->path())) {
+ *importedFiles += filesInDirectoryForLanguages(doc->path(),
+ Document::companionLanguages(doc->language()));
+ scannedPaths->insert(doc->path());
+ }
+ }
+}
+
+static void findNewFileImports(const Document::Ptr &doc, const Snapshot &snapshot,
+ QStringList *importedFiles, QSet<QString> *scannedPaths)
+{
+ // scan files and directories that are explicitly imported
+ foreach (const ImportInfo &import, doc->bind()->imports()) {
+ const QString &importName = import.path();
+ if (import.type() == ImportType::File) {
+ if (! snapshot.document(importName))
+ *importedFiles += importName;
+ } else if (import.type() == ImportType::Directory) {
+ if (snapshot.documentsInDirectory(importName).isEmpty()) {
+ if (! scannedPaths->contains(importName)) {
+ *importedFiles += filesInDirectoryForLanguages(importName,
+ Document::companionLanguages(doc->language()));
+ scannedPaths->insert(importName);
+ }
+ }
+ } else if (import.type() == ImportType::QrcFile) {
+ QStringList importPaths = ModelManagerInterface::instance()->filesAtQrcPath(importName);
+ foreach (const QString &importPath, importPaths) {
+ if (! snapshot.document(importPath))
+ *importedFiles += importPath;
+ }
+ } else if (import.type() == ImportType::QrcDirectory) {
+ QMapIterator<QString,QStringList> dirContents(ModelManagerInterface::instance()->filesInQrcPath(importName));
+ while (dirContents.hasNext()) {
+ dirContents.next();
+ if (Document::isQmlLikeOrJsLanguage(ModelManagerInterface::guessLanguageOfFile(dirContents.key()))) {
+ foreach (const QString &filePath, dirContents.value()) {
+ if (! snapshot.document(filePath))
+ *importedFiles += filePath;
+ }
+ }
+ }
+ }
+ }
+}
+
+static bool findNewQmlLibraryInPath(const QString &path,
+ const Snapshot &snapshot,
+ ModelManagerInterface *modelManager,
+ QStringList *importedFiles,
+ QSet<QString> *scannedPaths,
+ QSet<QString> *newLibraries,
+ bool ignoreMissing)
+{
+ // if we know there is a library, done
+ const LibraryInfo &existingInfo = snapshot.libraryInfo(path);
+ if (existingInfo.isValid())
+ return true;
+ if (newLibraries->contains(path))
+ return true;
+ // if we looked at the path before, done
+ if (existingInfo.wasScanned())
+ return false;
+
+ const QDir dir(path);
+ QFile qmldirFile(dir.filePath(QLatin1String("qmldir")));
+ if (!qmldirFile.exists()) {
+ if (!ignoreMissing) {
+ LibraryInfo libraryInfo(LibraryInfo::NotFound);
+ modelManager->updateLibraryInfo(path, libraryInfo);
+ }
+ return false;
+ }
+
+ if (Utils::HostOsInfo::isWindowsHost()) {
+ // QTCREATORBUG-3402 - be case sensitive even here?
+ }
+
+ // found a new library!
+ qmldirFile.open(QFile::ReadOnly);
+ QString qmldirData = QString::fromUtf8(qmldirFile.readAll());
+
+ QmlDirParser qmldirParser;
+ qmldirParser.parse(qmldirData);
+
+ const QString libraryPath = QFileInfo(qmldirFile).absolutePath();
+ newLibraries->insert(libraryPath);
+ modelManager->updateLibraryInfo(libraryPath, LibraryInfo(qmldirParser));
+
+ // scan the qml files in the library
+ foreach (const QmlDirParser::Component &component, qmldirParser.components()) {
+ if (! component.fileName.isEmpty()) {
+ const QFileInfo componentFileInfo(dir.filePath(component.fileName));
+ const QString path = QDir::cleanPath(componentFileInfo.absolutePath());
+ if (! scannedPaths->contains(path)) {
+ *importedFiles += filesInDirectoryForLanguages(path,
+ Document::companionLanguages(Language::Unknown));
+ scannedPaths->insert(path);
+ }
+ }
+ }
+
+ return true;
+}
+
+static void findNewQmlLibrary(
+ const QString &path,
+ const LanguageUtils::ComponentVersion &version,
+ const Snapshot &snapshot,
+ ModelManagerInterface *modelManager,
+ QStringList *importedFiles,
+ QSet<QString> *scannedPaths,
+ QSet<QString> *newLibraries)
+{
+ QString libraryPath = QString::fromLatin1("%1.%2.%3").arg(
+ path,
+ QString::number(version.majorVersion()),
+ QString::number(version.minorVersion()));
+ findNewQmlLibraryInPath(
+ libraryPath, snapshot, modelManager,
+ importedFiles, scannedPaths, newLibraries, false);
+
+ libraryPath = QString::fromLatin1("%1.%2").arg(
+ path,
+ QString::number(version.majorVersion()));
+ findNewQmlLibraryInPath(
+ libraryPath, snapshot, modelManager,
+ importedFiles, scannedPaths, newLibraries, false);
+
+ findNewQmlLibraryInPath(
+ path, snapshot, modelManager,
+ importedFiles, scannedPaths, newLibraries, false);
+}
+
+static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snapshot,
+ ModelManagerInterface *modelManager,
+ QStringList *importedFiles, QSet<QString> *scannedPaths, QSet<QString> *newLibraries)
+{
+ // scan current dir
+ findNewQmlLibraryInPath(doc->path(), snapshot, modelManager,
+ importedFiles, scannedPaths, newLibraries, false);
+
+ // scan dir and lib imports
+ const QStringList importPaths = modelManager->importPaths();
+ foreach (const ImportInfo &import, doc->bind()->imports()) {
+ if (import.type() == ImportType::Directory) {
+ const QString targetPath = import.path();
+ findNewQmlLibraryInPath(targetPath, snapshot, modelManager,
+ importedFiles, scannedPaths, newLibraries, false);
+ }
+
+ if (import.type() == ImportType::Library) {
+ if (!import.version().isValid())
+ continue;
+ foreach (const QString &importPath, importPaths) {
+ const QString targetPath = QDir(importPath).filePath(import.path());
+ findNewQmlLibrary(targetPath, import.version(), snapshot, modelManager,
+ importedFiles, scannedPaths, newLibraries);
+ }
+ }
+ }
+}
+
+void ModelManagerInterface::parseLoop(QSet<QString> &scannedPaths,
+ QSet<QString> &newLibraries,
+ WorkingCopy workingCopy,
+ QStringList files,
+ ModelManagerInterface *modelManager,
+ Language::Enum mainLanguage,
+ bool emitDocChangedOnDisk,
+ Utils::function<bool(qreal)> reportProgress)
+{
+ for (int i = 0; i < files.size(); ++i) {
+ if (!reportProgress(qreal(i) / files.size()))
+ return;
+
+ const QString fileName = files.at(i);
+
+ Language::Enum language = guessLanguageOfFile(fileName);
+ if (language == Language::Unknown) {
+ if (fileName.endsWith(QLatin1String(".qrc")))
+ modelManager->updateQrcFile(fileName);
+ continue;
+ }
+ if (language == Language::Qml
+ && (mainLanguage == Language::QmlQtQuick1 || Language::QmlQtQuick2))
+ language = mainLanguage;
+ QString contents;
+ int documentRevision = 0;
+
+ if (workingCopy.contains(fileName)) {
+ QPair<QString, int> entry = workingCopy.get(fileName);
+ contents = entry.first;
+ documentRevision = entry.second;
+ } else {
+ QFile inFile(fileName);
+
+ if (inFile.open(QIODevice::ReadOnly)) {
+ QTextStream ins(&inFile);
+ contents = ins.readAll();
+ inFile.close();
+ }
+ }
+
+ Document::MutablePtr doc = Document::create(fileName, language);
+ doc->setEditorRevision(documentRevision);
+ doc->setSource(contents);
+ doc->parse();
+
+ // update snapshot. requires synchronization, but significantly reduces amount of file
+ // system queries for library imports because queries are cached in libraryInfo
+ const Snapshot snapshot = modelManager->snapshot();
+
+ // get list of referenced files not yet in snapshot or in directories already scanned
+ QStringList importedFiles;
+ findNewImplicitImports(doc, snapshot, &importedFiles, &scannedPaths);
+ findNewFileImports(doc, snapshot, &importedFiles, &scannedPaths);
+ findNewLibraryImports(doc, snapshot, modelManager, &importedFiles, &scannedPaths, &newLibraries);
+
+ // add new files to parse list
+ foreach (const QString &file, importedFiles) {
+ if (! files.contains(file))
+ files.append(file);
+ }
+
+ modelManager->updateDocument(doc);
+ if (emitDocChangedOnDisk)
+ modelManager->emitDocumentChangedOnDisk(doc);
+ }
+}
+
+class FutureReporter
+{
+public:
+ FutureReporter(QFutureInterface<void> &future, int multiplier = 100, int base = 0)
+ :future(future), multiplier(multiplier), base(base)
+ { }
+ bool operator()(qreal val)
+ {
+ if (future.isCanceled())
+ return false;
+ future.setProgressValue(int(base + multiplier * val));
+ return true;
+ }
+private:
+ QFutureInterface<void> &future;
+ int multiplier;
+ int base;
+};
+
+void ModelManagerInterface::parse(QFutureInterface<void> &future,
+ WorkingCopy workingCopy,
+ QStringList files,
+ ModelManagerInterface *modelManager,
+ Language::Enum mainLanguage,
+ bool emitDocChangedOnDisk)
+{
+ FutureReporter reporter(future);
+ future.setProgressRange(0, 100);
+
+ // paths we have scanned for files and added to the files list
+ QSet<QString> scannedPaths;
+ // libraries we've found while scanning imports
+ QSet<QString> newLibraries;
+ parseLoop(scannedPaths, newLibraries, workingCopy, files, modelManager, mainLanguage,
+ emitDocChangedOnDisk, reporter);
+ future.setProgressValue(100);
+}
+
+struct ScanItem {
+ QString path;
+ int depth;
+ ScanItem(QString path = QString(), int depth = 0)
+ : path(path), depth(depth)
+ { }
+};
+
+void ModelManagerInterface::importScan(QFutureInterface<void> &future,
+ ModelManagerInterface::WorkingCopy workingCopy,
+ QStringList paths, ModelManagerInterface *modelManager,
+ Language::Enum language,
+ bool emitDocChangedOnDisk)
+{
+ // paths we have scanned for files and added to the files list
+ QSet<QString> scannedPaths = modelManager->m_scannedPaths;
+ // libraries we've found while scanning imports
+ QSet<QString> newLibraries;
+
+ QVector<ScanItem> pathsToScan;
+ pathsToScan.reserve(paths.size());
+ {
+ QMutexLocker l(&modelManager->m_mutex);
+ foreach (const QString &path, paths) {
+ QString cPath = QDir::cleanPath(path);
+ if (modelManager->m_scannedPaths.contains(cPath))
+ continue;
+ pathsToScan.append(ScanItem(cPath));
+ modelManager->m_scannedPaths.insert(cPath);
+ }
+ }
+ const int maxScanDepth = 5;
+ int progressRange = pathsToScan.size() * (1 << (2 + maxScanDepth));
+ int totalWork(progressRange), workDone(0);
+ future.setProgressRange(0, progressRange); // update max length while iterating?
+ const bool libOnly = true; // FIXME remove when tested more
+ const Snapshot snapshot = modelManager->snapshot();
+ while (!pathsToScan.isEmpty() && !future.isCanceled()) {
+ ScanItem toScan = pathsToScan.last();
+ pathsToScan.pop_back();
+ int pathBudget = (maxScanDepth + 2 - toScan.depth);
+ if (!scannedPaths.contains(toScan.path)) {
+ QStringList importedFiles;
+ if (!findNewQmlLibraryInPath(toScan.path, snapshot, modelManager, &importedFiles,
+ &scannedPaths, &newLibraries, true)
+ && !libOnly && snapshot.documentsInDirectory(toScan.path).isEmpty())
+ importedFiles += filesInDirectoryForLanguages(toScan.path,
+ Document::companionLanguages(language));
+ workDone += 1;
+ future.setProgressValue(progressRange * workDone / totalWork);
+ if (!importedFiles.isEmpty()) {
+ FutureReporter reporter(future, progressRange * pathBudget / (4 * totalWork),
+ progressRange * workDone / totalWork);
+ parseLoop(scannedPaths, newLibraries, workingCopy, importedFiles, modelManager,
+ language, emitDocChangedOnDisk, reporter); // run in parallel??
+ importedFiles.clear();
+ }
+ workDone += pathBudget / 4 - 1;
+ future.setProgressValue(progressRange * workDone / totalWork);
+ } else {
+ workDone += pathBudget / 4;
+ }
+ // always descend tree, as we might have just scanned with a smaller depth
+ if (toScan.depth < maxScanDepth) {
+ QDir dir(toScan.path);
+ QStringList subDirs(dir.entryList(QDir::Dirs));
+ workDone += 1;
+ totalWork += pathBudget / 2 * subDirs.size() - pathBudget * 3 / 4 + 1;
+ foreach (const QString path, subDirs)
+ pathsToScan.append(ScanItem(dir.absoluteFilePath(path), toScan.depth + 1));
+ } else {
+ workDone += pathBudget *3 / 4;
+ }
+ future.setProgressValue(progressRange * workDone / totalWork);
+ }
+ future.setProgressValue(progressRange);
+ if (future.isCanceled()) {
+ // assume no work has been done
+ QMutexLocker l(&modelManager->m_mutex);
+ foreach (const QString &path, paths)
+ modelManager->m_scannedPaths.remove(path);
+ }
+}
+
+QStringList ModelManagerInterface::importPaths() const
+{
+ QMutexLocker l(&m_mutex);
+ return m_allImportPaths;
+}
+
+QmlLanguageBundles ModelManagerInterface::activeBundles() const
+{
+ QMutexLocker l(&m_mutex);
+ return m_activeBundles;
+}
+
+QmlLanguageBundles ModelManagerInterface::extendedBundles() const
+{
+ QMutexLocker l(&m_mutex);
+ return m_extendedBundles;
+}
+
+void ModelManagerInterface::updateImportPaths()
+{
+ QStringList allImportPaths;
+ QmlLanguageBundles activeBundles;
+ QmlLanguageBundles extendedBundles;
+ QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects);
+ while (it.hasNext()) {
+ it.next();
+ foreach (const QString &path, it.value().importPaths) {
+ const QString canonicalPath = QFileInfo(path).canonicalFilePath();
+ if (!canonicalPath.isEmpty())
+ allImportPaths += canonicalPath;
+ }
+ }
+ it.toFront();
+ while (it.hasNext()) {
+ it.next();
+ activeBundles.mergeLanguageBundles(it.value().activeBundle);
+ foreach (Language::Enum l, it.value().activeBundle.languages()) {
+ foreach (const QString &path, it.value().activeBundle.bundleForLanguage(l)
+ .searchPaths().stringList()) {
+ const QString canonicalPath = QFileInfo(path).canonicalFilePath();
+ if (!canonicalPath.isEmpty())
+ allImportPaths += canonicalPath;
+ }
+ }
+ }
+ it.toFront();
+ while (it.hasNext()) {
+ it.next();
+ extendedBundles.mergeLanguageBundles(it.value().extendedBundle);
+ foreach (Language::Enum l, it.value().extendedBundle.languages()) {
+ foreach (const QString &path, it.value().extendedBundle.bundleForLanguage(l)
+ .searchPaths().stringList()) {
+ const QString canonicalPath = QFileInfo(path).canonicalFilePath();
+ if (!canonicalPath.isEmpty())
+ allImportPaths += canonicalPath;
+ }
+ }
+ }
+ allImportPaths += m_defaultImportPaths;
+ allImportPaths.removeDuplicates();
+
+ {
+ QMutexLocker l(&m_mutex);
+ m_allImportPaths = allImportPaths;
+ m_activeBundles = activeBundles;
+ m_extendedBundles = extendedBundles;
+ }
+
+
+ // check if any file in the snapshot imports something new in the new paths
+ Snapshot snapshot = _validSnapshot;
+ QStringList importedFiles;
+ QSet<QString> scannedPaths;
+ QSet<QString> newLibraries;
+ foreach (const Document::Ptr &doc, snapshot)
+ findNewLibraryImports(doc, snapshot, this, &importedFiles, &scannedPaths, &newLibraries);
+
+ updateSourceFiles(importedFiles, true);
+
+ if (!m_shouldScanImports)
+ return;
+ QStringList pathToScan;
+ {
+ QMutexLocker l(&m_mutex);
+ foreach (QString importPath, allImportPaths)
+ if (!m_scannedPaths.contains(importPath)) {
+ pathToScan.append(importPath);
+ }
+ }
+
+ if (pathToScan.count() > 1) {
+ QFuture<void> result = QtConcurrent::run(&ModelManagerInterface::importScan,
+ workingCopyInternal(), pathToScan,
+ this, Language::Qml,
+ true);
+
+ if (m_synchronizer.futures().size() > 10) {
+ QList<QFuture<void> > futures = m_synchronizer.futures();
+
+ m_synchronizer.clearFutures();
+
+ foreach (const QFuture<void> &future, futures) {
+ if (! (future.isFinished() || future.isCanceled()))
+ m_synchronizer.addFuture(future);
+ }
+ }
+
+ m_synchronizer.addFuture(result);
+
+ addTaskInternal(result, tr("Qml import scan"), Constants::TASK_IMPORT_SCAN);
+ }
+}
+
+ModelManagerInterface::ProjectInfo ModelManagerInterface::defaultProjectInfo() const
+{
+ if (m_projects.isEmpty())
+ return ProjectInfo();
+ return m_projects.begin().value();
+}
+
+void ModelManagerInterface::loadPluginTypes(const QString &libraryPath, const QString &importPath,
+ const QString &importUri, const QString &importVersion)
+{
+ m_pluginDumper->loadPluginTypes(libraryPath, importPath, importUri, importVersion);
+}
+
+// is called *inside a c++ parsing thread*, to allow hanging on to source and ast
+void ModelManagerInterface::maybeQueueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc)
+{
+ // avoid scanning documents without source code available
+ doc->keepSourceAndAST();
+ if (doc->utf8Source().isEmpty()) {
+ doc->releaseSourceAndAST();
+ return;
+ }
+
+ // keep source and AST alive if we want to scan for register calls
+ const bool scan = FindExportedCppTypes::maybeExportsTypes(doc);
+ if (!scan)
+ doc->releaseSourceAndAST();
+
+ // delegate actual queuing to the gui thread
+ QMetaObject::invokeMethod(this, "queueCppQmlTypeUpdate",
+ Q_ARG(CPlusPlus::Document::Ptr, doc), Q_ARG(bool, scan));
+}
+
+void ModelManagerInterface::queueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc, bool scan)
+{
+ QPair<CPlusPlus::Document::Ptr, bool> prev = m_queuedCppDocuments.value(doc->fileName());
+ if (prev.first && prev.second)
+ prev.first->releaseSourceAndAST();
+ m_queuedCppDocuments.insert(doc->fileName(), qMakePair(doc, scan));
+ m_updateCppQmlTypesTimer->start();
+}
+
+void ModelManagerInterface::startCppQmlTypeUpdate()
+{
+ // if a future is still running, delay
+ if (m_cppQmlTypesUpdater.isRunning()) {
+ m_updateCppQmlTypesTimer->start();
+ return;
+ }
+
+ CPlusPlus::CppModelManagerBase *cppModelManager =
+ CPlusPlus::CppModelManagerBase::instance();
+ if (!cppModelManager)
+ return;
+
+ m_cppQmlTypesUpdater = QtConcurrent::run(
+ &ModelManagerInterface::updateCppQmlTypes,
+ this, cppModelManager->snapshot(), m_queuedCppDocuments);
+ m_queuedCppDocuments.clear();
+}
+
+void ModelManagerInterface::asyncReset()
+{
+ m_asyncResetTimer->start();
+}
+
+void ModelManagerInterface::updateCppQmlTypes(QFutureInterface<void> &interface,
+ ModelManagerInterface *qmlModelManager,
+ CPlusPlus::Snapshot snapshot,
+ QHash<QString, QPair<CPlusPlus::Document::Ptr, bool> > documents)
+{
+ CppDataHash newData = qmlModelManager->cppData();
+
+ FindExportedCppTypes finder(snapshot);
+
+ bool hasNewInfo = false;
+ typedef QPair<CPlusPlus::Document::Ptr, bool> DocScanPair;
+ foreach (const DocScanPair &pair, documents) {
+ if (interface.isCanceled())
+ return;
+
+ CPlusPlus::Document::Ptr doc = pair.first;
+ const bool scan = pair.second;
+ const QString fileName = doc->fileName();
+ if (!scan) {
+ hasNewInfo = hasNewInfo || newData.remove(fileName) > 0;
+ continue;
+ }
+
+ finder(doc);
+
+ QList<LanguageUtils::FakeMetaObject::ConstPtr> exported = finder.exportedTypes();
+ QHash<QString, QString> contextProperties = finder.contextProperties();
+ if (exported.isEmpty() && contextProperties.isEmpty()) {
+ hasNewInfo = hasNewInfo || newData.remove(fileName) > 0;
+ } else {
+ CppData &data = newData[fileName];
+ // currently we have no simple way to compare, so we assume the worse
+ hasNewInfo = true;
+ data.exportedTypes = exported;
+ data.contextProperties = contextProperties;
+ }
+
+ doc->releaseSourceAndAST();
+ }
+
+ QMutexLocker locker(&qmlModelManager->m_cppDataMutex);
+ qmlModelManager->m_cppDataHash = newData;
+ if (hasNewInfo)
+ // one could get away with re-linking the cpp types...
+ QMetaObject::invokeMethod(qmlModelManager, "asyncReset");
+}
+
+ModelManagerInterface::CppDataHash ModelManagerInterface::cppData() const
+{
+ QMutexLocker locker(&m_cppDataMutex);
+ return m_cppDataHash;
+}
+
+LibraryInfo ModelManagerInterface::builtins(const Document::Ptr &doc) const
+{
+ QList<ProjectExplorer::Project *> projects = m_fileToProject.values(doc->fileName());
+
+ ProjectExplorer::Project *project = 0;
+ foreach (ProjectExplorer::Project *p, projects) {
+ if (p) {
+ project = p;
+ break;
+ }
+ }
+
+ if (!project)
+ return LibraryInfo();
+
+ QMutexLocker locker(&m_mutex);
+ ProjectInfo info = m_projects.value(project);
+ if (!info.isValid())
+ return LibraryInfo();
+
+ return _validSnapshot.libraryInfo(info.qtImportsPath);
+}
+
+ViewerContext ModelManagerInterface::completeVContext(const ViewerContext &vCtx,
+ const Document::Ptr &doc) const
+{
+ Q_UNUSED(doc);
+ ViewerContext res = vCtx;
+ switch (res.flags) {
+ case ViewerContext::Complete:
+ break;
+ case ViewerContext::AddQtPath:
+ case ViewerContext::AddAllPaths:
+ res.paths << importPaths();
+ }
+ res.flags = ViewerContext::Complete;
+ return res;
+}
+
+ViewerContext ModelManagerInterface::defaultVContext(bool autoComplete, const Document::Ptr &doc) const
+{
+ if (autoComplete)
+ return completeVContext(m_vContext, doc);
+ else
+ return m_vContext;
+}
+
+void ModelManagerInterface::setDefaultVContext(const ViewerContext &vContext)
+{
+ m_vContext = vContext;
+}
+
+void ModelManagerInterface::joinAllThreads()
+{
+ foreach (QFuture<void> future, m_synchronizer.futures())
+ future.waitForFinished();
+}
+
+void ModelManagerInterface::resetCodeModel()
+{
+ QStringList documents;
+
+ {
+ QMutexLocker locker(&m_mutex);
+
+ // find all documents currently in the code model
+ foreach (Document::Ptr doc, _validSnapshot)
+ documents.append(doc->fileName());
+
+ // reset the snapshot
+ _validSnapshot = Snapshot();
+ _newestSnapshot = Snapshot();
+ }
+
+ // start a reparse thread
+ updateSourceFiles(documents, false);
+}
+
+} // namespace QmlJS
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h
index 7d225f33a6..88463d36ca 100644
--- a/src/libs/qmljs/qmljsmodelmanagerinterface.h
+++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h
@@ -31,21 +31,31 @@
#define QMLJSMODELMANAGERINTERFACE_H
#include "qmljs_global.h"
-#include "qmljsdocument.h"
#include "qmljsbundle.h"
#include "qmljsconstants.h"
+#include "qmljsdocument.h"
+#include "qmljsqrcparser.h"
#include "qmljsviewercontext.h"
+
+#include <cplusplus/CppDocument.h>
#include <utils/environment.h>
+#include <QFuture>
+#include <QFutureSynchronizer>
+#include <QHash>
+#include <QMultiHash>
#include <QObject>
-#include <QStringList>
#include <QPointer>
+#include <QStringList>
+#include <QStringList>
+#include <QTimer>
namespace ProjectExplorer { class Project; }
namespace QmlJS {
class Snapshot;
+class PluginDumper;
class QMLJS_EXPORT ModelManagerInterface: public QObject
{
@@ -140,61 +150,130 @@ public:
static Language::Enum guessLanguageOfFile(const QString &fileName);
static QStringList globPatternsForLanguages(const QList<Language::Enum> languages);
static ModelManagerInterface *instance();
-
- virtual WorkingCopy workingCopy() const = 0;
-
- virtual QmlJS::Snapshot snapshot() const = 0;
- virtual QmlJS::Snapshot newestSnapshot() const = 0;
-
- virtual void updateSourceFiles(const QStringList &files,
- 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;
- virtual void updateProjectInfo(const ProjectInfo &pinfo) = 0;
- Q_SLOT virtual void removeProjectInfo(ProjectExplorer::Project *project) = 0;
- virtual ProjectInfo projectInfoForPath(QString path) = 0;
-
- virtual QStringList importPaths() const = 0;
- virtual QmlJS::QmlLanguageBundles activeBundles() const = 0;
- virtual QmlJS::QmlLanguageBundles extendedBundles() const = 0;
-
- virtual void loadPluginTypes(const QString &libraryPath, const QString &importPath,
- const QString &importUri, const QString &importVersion) = 0;
-
- virtual CppDataHash cppData() const = 0;
-
- virtual LibraryInfo builtins(const Document::Ptr &doc) const = 0;
-
+ static void writeWarning(const QString &msg);
+ static WorkingCopy workingCopy();
+
+ QmlJS::Snapshot snapshot() const;
+ QmlJS::Snapshot newestSnapshot() const;
+
+ void updateSourceFiles(const QStringList &files,
+ bool emitDocumentOnDiskChanged);
+ void fileChangedOnDisk(const QString &path);
+ void removeFiles(const QStringList &files);
+ QStringList filesAtQrcPath(const QString &path, const QLocale *locale = 0,
+ ProjectExplorer::Project *project = 0,
+ QrcResourceSelector resources = AllQrcResources);
+ QMap<QString,QStringList> filesInQrcPath(const QString &path,
+ const QLocale *locale = 0,
+ ProjectExplorer::Project *project = 0,
+ bool addDirs = false,
+ QrcResourceSelector resources = AllQrcResources);
+
+ QList<ProjectInfo> projectInfos() const;
+ ProjectInfo projectInfo(ProjectExplorer::Project *project) const;
+ void updateProjectInfo(const ProjectInfo &pinfo, ProjectExplorer::Project *p);
+
+ 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);
+ ProjectInfo projectInfoForPath(QString path);
+
+ QStringList importPaths() const;
+ QmlJS::QmlLanguageBundles activeBundles() const;
+ QmlJS::QmlLanguageBundles extendedBundles() const;
+
+ void loadPluginTypes(const QString &libraryPath, const QString &importPath,
+ const QString &importUri, const QString &importVersion);
+
+ CppDataHash cppData() const;
+ LibraryInfo builtins(const Document::Ptr &doc) const;
virtual ViewerContext completeVContext(const ViewerContext &vCtx,
- const Document::Ptr &doc = Document::Ptr(0)) const = 0;
+ const Document::Ptr &doc = Document::Ptr(0)) const;
virtual ViewerContext defaultVContext(bool autoComplete = true,
- const Document::Ptr &doc = Document::Ptr(0)) const = 0;
- virtual void setDefaultVContext(const ViewerContext &vContext) = 0;
+ const Document::Ptr &doc = Document::Ptr(0)) const;
+ virtual void setDefaultVContext(const ViewerContext &vContext);
// Blocks until all parsing threads are done. Used for testing.
- virtual void joinAllThreads() = 0;
-public slots:
- virtual void resetCodeModel() = 0;
+ void joinAllThreads();
+ virtual ModelManagerInterface::ProjectInfo defaultProjectInfo() const;
+
+public slots:
+ virtual void resetCodeModel();
+ void removeProjectInfo(ProjectExplorer::Project *project);
signals:
void documentUpdated(QmlJS::Document::Ptr doc);
void documentChangedOnDisk(QmlJS::Document::Ptr doc);
void aboutToRemoveFiles(const QStringList &files);
void libraryInfoUpdated(const QString &path, const QmlJS::LibraryInfo &info);
void projectInfoUpdated(const ProjectInfo &pinfo);
+ void projectPathChanged(const QString &projectPath);
+protected slots:
+ void maybeQueueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc);
+ void queueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc, bool scan);
+ void asyncReset();
+ virtual void startCppQmlTypeUpdate();
protected:
virtual QHash<QString,Language::Enum> languageForSuffix() const;
+ virtual void writeMessageInternal(const QString &msg) const;
+ virtual WorkingCopy workingCopyInternal() const;
+ virtual void addTaskInternal(QFuture<void> result, const QString &msg, const char *taskId) const;
+
+ QFuture<void> refreshSourceFiles(const QStringList &sourceFiles,
+ bool emitDocumentOnDiskChanged);
+
+ static void parseLoop(QSet<QString> &scannedPaths, QSet<QString> &newLibraries,
+ WorkingCopy workingCopyInternal, QStringList files, ModelManagerInterface *modelManager,
+ QmlJS::Language::Enum mainLanguage, bool emitDocChangedOnDisk,
+ Utils::function<bool (qreal)> reportProgress);
+ static void parse(QFutureInterface<void> &future,
+ WorkingCopy workingCopyInternal,
+ QStringList files,
+ ModelManagerInterface *modelManager,
+ QmlJS::Language::Enum mainLanguage,
+ bool emitDocChangedOnDisk);
+ static void importScan(QFutureInterface<void> &future,
+ WorkingCopy workingCopyInternal,
+ QStringList paths,
+ ModelManagerInterface *modelManager,
+ QmlJS::Language::Enum mainLanguage,
+ bool emitDocChangedOnDisk);
+ static void updateCppQmlTypes(QFutureInterface<void> &interface,
+ ModelManagerInterface *qmlModelManager,
+ CPlusPlus::Snapshot snapshot,
+ QHash<QString, QPair<CPlusPlus::Document::Ptr, bool> > documents);
+
+ void updateImportPaths();
+ void loadQmlTypeDescriptionsInternal(const QString &path);
+
+ mutable QMutex m_mutex;
+ QmlJS::Snapshot _validSnapshot;
+ QmlJS::Snapshot _newestSnapshot;
+ QStringList m_allImportPaths;
+ QStringList m_defaultImportPaths;
+ QmlJS::QmlLanguageBundles m_activeBundles;
+ QmlJS::QmlLanguageBundles m_extendedBundles;
+ QmlJS::ViewerContext m_vContext;
+ bool m_shouldScanImports;
+ QSet<QString> m_scannedPaths;
+
+ QTimer *m_updateCppQmlTypesTimer;
+ QTimer *m_asyncResetTimer;
+ QHash<QString, QPair<CPlusPlus::Document::Ptr, bool> > m_queuedCppDocuments;
+ QFuture<void> m_cppQmlTypesUpdater;
+ QrcCache m_qrcCache;
+
+ CppDataHash m_cppDataHash;
+ mutable QMutex m_cppDataMutex;
+
+ // project integration
+ QMap<ProjectExplorer::Project *, ProjectInfo> m_projects;
+ QMultiHash<QString, ProjectExplorer::Project *> m_fileToProject;
+
+ PluginDumper *m_pluginDumper;
+
+ QFutureSynchronizer<void> m_synchronizer;
};
} // namespace QmlJS
diff --git a/src/plugins/qmljstools/qmljsplugindumper.cpp b/src/libs/qmljs/qmljsplugindumper.cpp
index cf99d00637..12df8f5d00 100644
--- a/src/plugins/qmljstools/qmljsplugindumper.cpp
+++ b/src/libs/qmljs/qmljsplugindumper.cpp
@@ -28,11 +28,11 @@
****************************************************************************/
#include "qmljsplugindumper.h"
-#include "qmljsmodelmanager.h"
+#include "qmljsmodelmanagerinterface.h"
#include <qmljs/qmljsinterpreter.h>
-#include <projectexplorer/session.h>
-#include <coreplugin/messagemanager.h>
+//#include <projectexplorer/session.h>
+//#include <coreplugin/messagemanager.h>
#include <utils/filesystemwatcher.h>
#include <utils/fileutils.h>
@@ -40,10 +40,8 @@
using namespace LanguageUtils;
using namespace QmlJS;
-using namespace QmlJSTools;
-using namespace QmlJSTools::Internal;
-PluginDumper::PluginDumper(ModelManager *modelManager)
+PluginDumper::PluginDumper(ModelManagerInterface *modelManager)
: QObject(modelManager)
, m_modelManager(modelManager)
, m_pluginWatcher(0)
@@ -256,10 +254,9 @@ static QString qmldumpFailedMessage(const QString &libraryPath, const QString &e
static void printParseWarnings(const QString &libraryPath, const QString &warning)
{
- Core::MessageManager::write(
+ ModelManagerInterface::writeWarning(
PluginDumper::tr("Warnings while parsing qmltypes information of %1:\n"
- "%2").arg(libraryPath, warning),
- Core::MessageManager::Flash);
+ "%2").arg(libraryPath, warning));
}
static QString qmlPluginDumpErrorMessage(QProcess *process)
@@ -317,8 +314,7 @@ void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
if (exitCode != 0) {
const QString errorMessages = qmlPluginDumpErrorMessage(process);
- Core::MessageManager::write(qmldumpErrorMessage(libraryPath, errorMessages),
- Core::MessageManager::Flash);
+ ModelManagerInterface::writeWarning(qmldumpErrorMessage(libraryPath, errorMessages));
libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpError, qmldumpFailedMessage(libraryPath, errorMessages));
}
@@ -360,8 +356,7 @@ void PluginDumper::qmlPluginTypeDumpError(QProcess::ProcessError)
return;
const QString errorMessages = qmlPluginDumpErrorMessage(process);
- Core::MessageManager::write(qmldumpErrorMessage(libraryPath, errorMessages),
- Core::MessageManager::Flash);
+ ModelManagerInterface::writeWarning(qmldumpErrorMessage(libraryPath, errorMessages));
if (!libraryPath.isEmpty()) {
const Snapshot snapshot = m_modelManager->snapshot();
LibraryInfo libraryInfo = snapshot.libraryInfo(libraryPath);
@@ -442,11 +437,7 @@ void PluginDumper::dump(const Plugin &plugin)
return;
}
- ProjectExplorer::Project *activeProject = ProjectExplorer::SessionManager::startupProject();
- if (!activeProject)
- return;
-
- ModelManagerInterface::ProjectInfo info = m_modelManager->projectInfo(activeProject);
+ ModelManagerInterface::ProjectInfo info = m_modelManager->defaultProjectInfo();
if (!info.tryQmlDump || info.qmlDumpPath.isEmpty()) {
const Snapshot snapshot = m_modelManager->snapshot();
diff --git a/src/plugins/qmljstools/qmljsplugindumper.h b/src/libs/qmljs/qmljsplugindumper.h
index a1567b7ab3..8c4a95c42e 100644
--- a/src/plugins/qmljstools/qmljsplugindumper.h
+++ b/src/libs/qmljs/qmljsplugindumper.h
@@ -42,16 +42,13 @@ QT_END_NAMESPACE
namespace Utils { class FileSystemWatcher; }
-namespace QmlJSTools {
-namespace Internal {
-
-class ModelManager;
+namespace QmlJS {
class PluginDumper : public QObject
{
Q_OBJECT
public:
- explicit PluginDumper(ModelManager *modelManager);
+ explicit PluginDumper(ModelManagerInterface *modelManager);
public:
void loadBuiltinTypes(const QmlJS::ModelManagerInterface::ProjectInfo &info);
@@ -94,7 +91,7 @@ private:
private:
Utils::FileSystemWatcher *pluginWatcher();
- ModelManager *m_modelManager;
+ ModelManagerInterface *m_modelManager;
Utils::FileSystemWatcher *m_pluginWatcher;
QHash<QProcess *, QString> m_runningQmldumps;
QList<Plugin> m_plugins;
@@ -102,7 +99,6 @@ private:
QHash<QString, QmlJS::ModelManagerInterface::ProjectInfo> m_qtToInfo;
};
-} // namespace Internal
-} // namespace QmlJSTools
+} // namespace QmlJS
#endif // QMLJSPLUGINDUMPER_H
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index f4a5329b33..5a0e96a369 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -999,7 +999,7 @@ void CppModelManager::enableGarbageCollector(bool enable)
m_enableGC = enable;
}
-void CppModelManager::setExtraDiagnostics(const QString &fileName,
+bool CppModelManager::setExtraDiagnostics(const QString &fileName,
const QString &kind,
const QList<Document::DiagnosticMessage> &diagnostics)
{
@@ -1013,9 +1013,10 @@ void CppModelManager::setExtraDiagnostics(const QString &fileName,
foreach (CppEditorSupport *editorSupport, cppEditorSupports) {
if (editorSupport->fileName() == fileName) {
editorSupport->setExtraDiagnostics(kind, diagnostics);
- break;
+ return true;
}
}
+ return false;
}
void CppModelManager::setIfdefedOutBlocks(const QString &fileName,
diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h
index 96a5796a2d..b7b192c530 100644
--- a/src/plugins/cpptools/cppmodelmanager.h
+++ b/src/plugins/cpptools/cppmodelmanager.h
@@ -107,7 +107,7 @@ public:
virtual void findMacroUsages(const CPlusPlus::Macro &macro);
virtual void renameMacroUsages(const CPlusPlus::Macro &macro, const QString &replacement);
- virtual void setExtraDiagnostics(const QString &fileName, const QString &key,
+ virtual bool setExtraDiagnostics(const QString &fileName, const QString &key,
const QList<Document::DiagnosticMessage> &diagnostics);
virtual void setIfdefedOutBlocks(const QString &fileName,
const QList<TextEditor::BlockRange> &ifdeffedOutBlocks);
diff --git a/src/plugins/cpptools/cppmodelmanagerinterface.cpp b/src/plugins/cpptools/cppmodelmanagerinterface.cpp
index e755783bef..0f65f16225 100644
--- a/src/plugins/cpptools/cppmodelmanagerinterface.cpp
+++ b/src/plugins/cpptools/cppmodelmanagerinterface.cpp
@@ -164,8 +164,6 @@ void ProjectPart::evaluateToolchain(const ToolChain *tc,
toolchainDefines = tc->predefinedMacros(cxxflags);
}
-static CppModelManagerInterface *g_instance = 0;
-
const QString CppModelManagerInterface::configurationFileName()
{ return CPlusPlus::Preprocessor::configurationFileName; }
@@ -175,21 +173,15 @@ const QString CppModelManagerInterface::editorConfigurationFileName()
}
CppModelManagerInterface::CppModelManagerInterface(QObject *parent)
- : QObject(parent)
-{
- Q_ASSERT(!g_instance);
- g_instance = this;
-}
+ : CPlusPlus::CppModelManagerBase(parent)
+{ }
CppModelManagerInterface::~CppModelManagerInterface()
-{
- Q_ASSERT(g_instance == this);
- g_instance = 0;
-}
+{ }
CppModelManagerInterface *CppModelManagerInterface::instance()
{
- return g_instance;
+ return qobject_cast<CppModelManagerInterface *>(CPlusPlus::CppModelManagerBase::instance());
}
void CppModelManagerInterface::ProjectInfo::clearProjectParts()
diff --git a/src/plugins/cpptools/cppmodelmanagerinterface.h b/src/plugins/cpptools/cppmodelmanagerinterface.h
index 84cca908b7..188367c68a 100644
--- a/src/plugins/cpptools/cppmodelmanagerinterface.h
+++ b/src/plugins/cpptools/cppmodelmanagerinterface.h
@@ -35,6 +35,7 @@
#include "cppprojectfile.h"
#include <cplusplus/CppDocument.h>
+#include <cplusplus/cppmodelmanagerbase.h>
#include <projectexplorer/toolchain.h>
#include <QFuture>
@@ -118,7 +119,7 @@ public:
ProjectExplorer::ToolChain::WarningFlags cxxWarningFlags;
};
-class CPPTOOLS_EXPORT CppModelManagerInterface : public QObject
+class CPPTOOLS_EXPORT CppModelManagerInterface : public CPlusPlus::CppModelManagerBase
{
Q_OBJECT
@@ -228,7 +229,6 @@ public:
virtual WorkingCopy workingCopy() const = 0;
virtual QByteArray codeModelConfiguration() const = 0;
- virtual CPlusPlus::Snapshot snapshot() const = 0;
virtual QList<ProjectInfo> projectInfos() const = 0;
virtual ProjectInfo projectInfo(ProjectExplorer::Project *project) const = 0;
@@ -255,8 +255,6 @@ public:
virtual void renameMacroUsages(const CPlusPlus::Macro &macro, const QString &replacement = QString()) = 0;
virtual void findMacroUsages(const CPlusPlus::Macro &macro) = 0;
- virtual void setExtraDiagnostics(const QString &fileName, const QString &kind,
- const QList<CPlusPlus::Document::DiagnosticMessage> &diagnostics) = 0;
virtual void setIfdefedOutBlocks(const QString &fileName,
const QList<TextEditor::BlockRange> &ifdeffedOutBlocks) = 0;
diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp
index 87f5fa205d..8a4e111278 100644
--- a/src/plugins/qbsprojectmanager/qbsproject.cpp
+++ b/src/plugins/qbsprojectmanager/qbsproject.cpp
@@ -671,7 +671,7 @@ void QbsProject::updateQmlJsCodeModel(const qbs::ProjectData &prj)
QmlJSTools::defaultProjectInfoForProject(this);
setProjectLanguage(ProjectExplorer::Constants::LANG_QMLJS, !projectInfo.sourceFiles.isEmpty());
- modelManager->updateProjectInfo(projectInfo);
+ modelManager->updateProjectInfo(projectInfo, this);
}
void QbsProject::updateApplicationTargets(const qbs::ProjectData &projectData)
diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp
index 6358d335ba..ec55f9f7c4 100644
--- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp
@@ -634,7 +634,7 @@ void QmakeProject::updateQmlJSCodeModel()
setProjectLanguage(ProjectExplorer::Constants::LANG_QMLJS, !projectInfo.sourceFiles.isEmpty());
- modelManager->updateProjectInfo(projectInfo);
+ modelManager->updateProjectInfo(projectInfo, this);
}
///*!
diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp
index edc1e633a7..61a16bcc9a 100644
--- a/src/plugins/qmljstools/qmljsmodelmanager.cpp
+++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp
@@ -29,28 +29,28 @@
#include "qmljsmodelmanager.h"
#include "qmljstoolsconstants.h"
-#include "qmljsplugindumper.h"
-#include "qmljsfindexportedcpptypes.h"
#include "qmljssemanticinfo.h"
#include "qmljsbundleprovider.h"
#include <coreplugin/icore.h>
-#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/messagemanager.h>
+#include <coreplugin/progressmanager/progressmanager.h>
#include <cpptools/cppmodelmanagerinterface.h>
-#include <qmljs/qmljsbind.h>
-#include <texteditor/basetextdocument.h>
+#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
-#include <qtsupport/qtkitinformation.h>
+#include <qmljs/qmljsbind.h>
+#include <qmljs/qmljsfindexportedcpptypes.h>
+#include <qmljs/qmljsplugindumper.h>
#include <qtsupport/qmldumptool.h>
+#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtsupportconstants.h>
-#include <utils/hostosinfo.h>
+#include <texteditor/basetextdocument.h>
#include <utils/function.h>
-#include <extensionsystem/pluginmanager.h>
+#include <utils/hostosinfo.h>
#include <QDir>
#include <QFile>
@@ -170,8 +170,6 @@ void QmlJSTools::setupProjectInfoQmlBundles(ModelManagerInterface::ProjectInfo &
}
}
-static QStringList environmentImportPaths();
-
QHash<QString,QmlJS::Language::Enum> ModelManager::languageForSuffix() const
{
QHash<QString,QmlJS::Language::Enum> res = ModelManagerInterface::languageForSuffix();
@@ -197,30 +195,10 @@ QHash<QString,QmlJS::Language::Enum> ModelManager::languageForSuffix() const
}
ModelManager::ModelManager(QObject *parent):
- ModelManagerInterface(parent),
- m_shouldScanImports(false),
- m_pluginDumper(new PluginDumper(this))
+ ModelManagerInterface(parent)
{
- m_synchronizer.setCancelOnWait(true);
-
- m_updateCppQmlTypesTimer = new QTimer(this);
- m_updateCppQmlTypesTimer->setInterval(1000);
- m_updateCppQmlTypesTimer->setSingleShot(true);
- connect(m_updateCppQmlTypesTimer, SIGNAL(timeout()), SLOT(startCppQmlTypeUpdate()));
-
- m_asyncResetTimer = new QTimer(this);
- m_asyncResetTimer->setInterval(15000);
- m_asyncResetTimer->setSingleShot(true);
- connect(m_asyncResetTimer, SIGNAL(timeout()), SLOT(resetCodeModel()));
-
- qRegisterMetaType<QmlJS::Document::Ptr>("QmlJS::Document::Ptr");
- qRegisterMetaType<QmlJS::LibraryInfo>("QmlJS::LibraryInfo");
qRegisterMetaType<QmlJSTools::SemanticInfo>("QmlJSTools::SemanticInfo");
-
- loadQmlTypeDescriptions();
-
- m_defaultImportPaths << environmentImportPaths();
- updateImportPaths();
+ loadDefaultQmlTypeDescriptions();
}
ModelManager::~ModelManager()
@@ -244,49 +222,20 @@ void ModelManager::delayedInitialization()
this, SLOT(removeProjectInfo(ProjectExplorer::Project*)));
}
-void ModelManager::loadQmlTypeDescriptions()
+void ModelManager::loadDefaultQmlTypeDescriptions()
{
if (ICore::instance()) {
- loadQmlTypeDescriptions(ICore::resourcePath());
- loadQmlTypeDescriptions(ICore::userResourcePath());
+ loadQmlTypeDescriptionsInternal(ICore::resourcePath());
+ loadQmlTypeDescriptionsInternal(ICore::userResourcePath());
}
}
-void ModelManager::loadQmlTypeDescriptions(const QString &resourcePath)
+void ModelManager::writeMessageInternal(const QString &msg) const
{
- const QDir typeFileDir(resourcePath + QLatin1String("/qml-type-descriptions"));
- const QStringList qmlTypesExtensions = QStringList() << QLatin1String("*.qmltypes");
- QFileInfoList qmlTypesFiles = typeFileDir.entryInfoList(
- qmlTypesExtensions,
- QDir::Files,
- QDir::Name);
-
- QStringList errors;
- QStringList warnings;
-
- // filter out the actual Qt builtins
- for (int i = 0; i < qmlTypesFiles.size(); ++i) {
- if (qmlTypesFiles.at(i).baseName() == QLatin1String("builtins")) {
- QFileInfoList list;
- list.append(qmlTypesFiles.at(i));
- CppQmlTypesLoader::defaultQtObjects =
- CppQmlTypesLoader::loadQmlTypes(list, &errors, &warnings);
- qmlTypesFiles.removeAt(i);
- break;
- }
- }
-
- // load the fallbacks for libraries
- CppQmlTypesLoader::defaultLibraryObjects.unite(
- CppQmlTypesLoader::loadQmlTypes(qmlTypesFiles, &errors, &warnings));
-
- foreach (const QString &error, errors)
- MessageManager::write(error, MessageManager::Flash);
- foreach (const QString &warning, warnings)
- MessageManager::write(warning, MessageManager::Flash);
+ MessageManager::write(msg, MessageManager::Flash);
}
-ModelManagerInterface::WorkingCopy ModelManager::workingCopy() const
+ModelManagerInterface::WorkingCopy ModelManager::workingCopyInternal() const
{
WorkingCopy workingCopy;
DocumentModel *documentModel = EditorManager::documentModel();
@@ -302,691 +251,13 @@ ModelManagerInterface::WorkingCopy ModelManager::workingCopy() const
return workingCopy;
}
-Snapshot ModelManager::snapshot() const
-{
- QMutexLocker locker(&m_mutex);
- return _validSnapshot;
-}
-
-Snapshot ModelManager::newestSnapshot() const
-{
- QMutexLocker locker(&m_mutex);
- return _newestSnapshot;
-}
-
-void ModelManager::updateSourceFiles(const QStringList &files,
- bool emitDocumentOnDiskChanged)
-{
- refreshSourceFiles(files, emitDocumentOnDiskChanged);
-}
-
-QFuture<void> ModelManager::refreshSourceFiles(const QStringList &sourceFiles,
- bool emitDocumentOnDiskChanged)
-{
- if (sourceFiles.isEmpty())
- return QFuture<void>();
-
- QFuture<void> result = QtConcurrent::run(&ModelManager::parse,
- workingCopy(), sourceFiles,
- this, Language::Qml,
- emitDocumentOnDiskChanged);
-
- if (m_synchronizer.futures().size() > 10) {
- QList<QFuture<void> > futures = m_synchronizer.futures();
-
- m_synchronizer.clearFutures();
-
- foreach (const QFuture<void> &future, futures) {
- if (! (future.isFinished() || future.isCanceled()))
- m_synchronizer.addFuture(future);
- }
- }
-
- m_synchronizer.addFuture(result);
-
- if (sourceFiles.count() > 1)
- ProgressManager::addTask(result, tr("Indexing"), Constants::TASK_INDEX);
-
- if (sourceFiles.count() > 1 && !m_shouldScanImports) {
- bool scan = false;
- {
- QMutexLocker l(&m_mutex);
- if (!m_shouldScanImports) {
- m_shouldScanImports = true;
- scan = true;
- }
- }
- if (scan)
- updateImportPaths();
- }
-
-
- return result;
-}
-
-void ModelManager::fileChangedOnDisk(const QString &path)
-{
- QtConcurrent::run(&ModelManager::parse,
- workingCopy(), QStringList() << path,
- this, Language::Unknown, true);
-}
-
-void ModelManager::removeFiles(const QStringList &files)
-{
- emit aboutToRemoveFiles(files);
-
- QMutexLocker locker(&m_mutex);
-
- foreach (const QString &file, files) {
- _validSnapshot.remove(file);
- _newestSnapshot.remove(file);
- }
-}
-
-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)
+ModelManagerInterface::ProjectInfo ModelManager::defaultProjectInfo() const
{
- 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);
-
- return m_projects.values();
-}
-
-ModelManager::ProjectInfo ModelManager::projectInfo(ProjectExplorer::Project *project) const
-{
- QMutexLocker locker(&m_mutex);
-
- return m_projects.value(project, ProjectInfo(project));
-}
-
-void ModelManager::updateProjectInfo(const ProjectInfo &pinfo)
-{
- if (! pinfo.isValid())
- return;
-
- Snapshot snapshot;
- ProjectInfo oldInfo;
- {
- QMutexLocker locker(&m_mutex);
- oldInfo = m_projects.value(pinfo.project);
- m_projects.insert(pinfo.project, pinfo);
- snapshot = _validSnapshot;
- }
-
- if (oldInfo.qmlDumpPath != pinfo.qmlDumpPath
- || oldInfo.qmlDumpEnvironment != pinfo.qmlDumpEnvironment) {
- m_pluginDumper->scheduleRedumpPlugins();
- m_pluginDumper->scheduleMaybeRedumpBuiltins(pinfo);
- }
-
-
- updateImportPaths();
-
- // remove files that are no longer in the project and have been deleted
- QStringList deletedFiles;
- foreach (const QString &oldFile, oldInfo.sourceFiles) {
- if (snapshot.document(oldFile)
- && !pinfo.sourceFiles.contains(oldFile)
- && !QFile::exists(oldFile)) {
- deletedFiles += oldFile;
- }
- }
- removeFiles(deletedFiles);
-
- // parse any files not yet in the snapshot
- QStringList newFiles;
- foreach (const QString &file, pinfo.sourceFiles) {
- if (!snapshot.document(file))
- newFiles += file;
- }
- 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))
- m_pluginDumper->loadBuiltinTypes(pinfo);
-
- emit projectInfoUpdated(pinfo);
-}
-
-
-void ModelManager::removeProjectInfo(ProjectExplorer::Project *project)
-{
- ProjectInfo info(project);
- info.sourceFiles.clear();
- // update with an empty project info to clear data
- updateProjectInfo(info);
-
- {
- QMutexLocker locker(&m_mutex);
- m_projects.remove(project);
- }
-}
+ ProjectExplorer::Project *activeProject = ProjectExplorer::SessionManager::startupProject();
+ if (!activeProject)
+ return ModelManagerInterface::ProjectInfo();
-ModelManagerInterface::ProjectInfo ModelManager::projectInfoForPath(QString path)
-{
- QMutexLocker locker(&m_mutex);
-
- foreach (const ProjectInfo &p, m_projects)
- if (p.sourceFiles.contains(path))
- return p;
- return ProjectInfo();
-}
-
-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)
-{
- {
- QMutexLocker locker(&m_mutex);
- _validSnapshot.insert(doc);
- _newestSnapshot.insert(doc, true);
- }
- emit documentUpdated(doc);
-}
-
-void ModelManager::updateLibraryInfo(const QString &path, const LibraryInfo &info)
-{
- if (!info.pluginTypeInfoError().isEmpty())
- qDebug() << "Dumping errors for " << path << ":" << info.pluginTypeInfoError();
-
- {
- QMutexLocker locker(&m_mutex);
- _validSnapshot.insertLibraryInfo(path, info);
- _newestSnapshot.insertLibraryInfo(path, info);
- }
- // only emit if we got new useful information
- if (info.isValid())
- emit libraryInfoUpdated(path, info);
-}
-
-static QStringList filesInDirectoryForLanguages(const QString &path, QList<Language::Enum> languages)
-{
- const QStringList pattern = ModelManagerInterface::globPatternsForLanguages(languages);
- QStringList files;
-
- const QDir dir(path);
- foreach (const QFileInfo &fi, dir.entryInfoList(pattern, QDir::Files))
- files += fi.absoluteFilePath();
-
- return files;
-}
-
-static void findNewImplicitImports(const Document::Ptr &doc, const Snapshot &snapshot,
- QStringList *importedFiles, QSet<QString> *scannedPaths)
-{
- // scan files that could be implicitly imported
- // it's important we also do this for JS files, otherwise the isEmpty check will fail
- if (snapshot.documentsInDirectory(doc->path()).isEmpty()) {
- if (! scannedPaths->contains(doc->path())) {
- *importedFiles += filesInDirectoryForLanguages(doc->path(),
- Document::companionLanguages(doc->language()));
- scannedPaths->insert(doc->path());
- }
- }
-}
-
-static void findNewFileImports(const Document::Ptr &doc, const Snapshot &snapshot,
- QStringList *importedFiles, QSet<QString> *scannedPaths)
-{
- // scan files and directories that are explicitly imported
- foreach (const ImportInfo &import, doc->bind()->imports()) {
- const QString &importName = import.path();
- if (import.type() == ImportType::File) {
- if (! snapshot.document(importName))
- *importedFiles += importName;
- } else if (import.type() == ImportType::Directory) {
- if (snapshot.documentsInDirectory(importName).isEmpty()) {
- if (! scannedPaths->contains(importName)) {
- *importedFiles += filesInDirectoryForLanguages(importName,
- Document::companionLanguages(doc->language()));
- scannedPaths->insert(importName);
- }
- }
- } else if (import.type() == ImportType::QrcFile) {
- QStringList importPaths = ModelManagerInterface::instance()->filesAtQrcPath(importName);
- foreach (const QString &importPath, importPaths) {
- if (! snapshot.document(importPath))
- *importedFiles += importPath;
- }
- } else if (import.type() == ImportType::QrcDirectory) {
- QMapIterator<QString,QStringList> dirContents(ModelManagerInterface::instance()->filesInQrcPath(importName));
- while (dirContents.hasNext()) {
- dirContents.next();
- if (Document::isQmlLikeOrJsLanguage(ModelManagerInterface::guessLanguageOfFile(dirContents.key()))) {
- foreach (const QString &filePath, dirContents.value()) {
- if (! snapshot.document(filePath))
- *importedFiles += filePath;
- }
- }
- }
- }
- }
-}
-
-static bool findNewQmlLibraryInPath(const QString &path,
- const Snapshot &snapshot,
- ModelManager *modelManager,
- QStringList *importedFiles,
- QSet<QString> *scannedPaths,
- QSet<QString> *newLibraries,
- bool ignoreMissing)
-{
- // if we know there is a library, done
- const LibraryInfo &existingInfo = snapshot.libraryInfo(path);
- if (existingInfo.isValid())
- return true;
- if (newLibraries->contains(path))
- return true;
- // if we looked at the path before, done
- if (existingInfo.wasScanned())
- return false;
-
- const QDir dir(path);
- QFile qmldirFile(dir.filePath(QLatin1String("qmldir")));
- if (!qmldirFile.exists()) {
- if (!ignoreMissing) {
- LibraryInfo libraryInfo(LibraryInfo::NotFound);
- modelManager->updateLibraryInfo(path, libraryInfo);
- }
- return false;
- }
-
- if (Utils::HostOsInfo::isWindowsHost()) {
- // QTCREATORBUG-3402 - be case sensitive even here?
- }
-
- // found a new library!
- qmldirFile.open(QFile::ReadOnly);
- QString qmldirData = QString::fromUtf8(qmldirFile.readAll());
-
- QmlDirParser qmldirParser;
- qmldirParser.parse(qmldirData);
-
- const QString libraryPath = QFileInfo(qmldirFile).absolutePath();
- newLibraries->insert(libraryPath);
- modelManager->updateLibraryInfo(libraryPath, LibraryInfo(qmldirParser));
-
- // scan the qml files in the library
- foreach (const QmlDirParser::Component &component, qmldirParser.components()) {
- if (! component.fileName.isEmpty()) {
- const QFileInfo componentFileInfo(dir.filePath(component.fileName));
- const QString path = QDir::cleanPath(componentFileInfo.absolutePath());
- if (! scannedPaths->contains(path)) {
- *importedFiles += filesInDirectoryForLanguages(path,
- Document::companionLanguages(Language::Unknown));
- scannedPaths->insert(path);
- }
- }
- }
-
- return true;
-}
-
-static void findNewQmlLibrary(
- const QString &path,
- const LanguageUtils::ComponentVersion &version,
- const Snapshot &snapshot,
- ModelManager *modelManager,
- QStringList *importedFiles,
- QSet<QString> *scannedPaths,
- QSet<QString> *newLibraries)
-{
- QString libraryPath = QString::fromLatin1("%1.%2.%3").arg(
- path,
- QString::number(version.majorVersion()),
- QString::number(version.minorVersion()));
- findNewQmlLibraryInPath(
- libraryPath, snapshot, modelManager,
- importedFiles, scannedPaths, newLibraries, false);
-
- libraryPath = QString::fromLatin1("%1.%2").arg(
- path,
- QString::number(version.majorVersion()));
- findNewQmlLibraryInPath(
- libraryPath, snapshot, modelManager,
- importedFiles, scannedPaths, newLibraries, false);
-
- findNewQmlLibraryInPath(
- path, snapshot, modelManager,
- importedFiles, scannedPaths, newLibraries, false);
-}
-
-static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snapshot,
- ModelManager *modelManager,
- QStringList *importedFiles, QSet<QString> *scannedPaths, QSet<QString> *newLibraries)
-{
- // scan current dir
- findNewQmlLibraryInPath(doc->path(), snapshot, modelManager,
- importedFiles, scannedPaths, newLibraries, false);
-
- // scan dir and lib imports
- const QStringList importPaths = modelManager->importPaths();
- foreach (const ImportInfo &import, doc->bind()->imports()) {
- if (import.type() == ImportType::Directory) {
- const QString targetPath = import.path();
- findNewQmlLibraryInPath(targetPath, snapshot, modelManager,
- importedFiles, scannedPaths, newLibraries, false);
- }
-
- if (import.type() == ImportType::Library) {
- if (!import.version().isValid())
- continue;
- foreach (const QString &importPath, importPaths) {
- const QString targetPath = QDir(importPath).filePath(import.path());
- findNewQmlLibrary(targetPath, import.version(), snapshot, modelManager,
- importedFiles, scannedPaths, newLibraries);
- }
- }
- }
-}
-
-void ModelManager::parseLoop(QSet<QString> &scannedPaths,
- QSet<QString> &newLibraries,
- WorkingCopy workingCopy,
- QStringList files,
- ModelManager *modelManager,
- Language::Enum mainLanguage,
- bool emitDocChangedOnDisk,
- Utils::function<bool(qreal)> reportProgress)
-{
- for (int i = 0; i < files.size(); ++i) {
- if (!reportProgress(qreal(i) / files.size()))
- return;
-
- const QString fileName = files.at(i);
-
- Language::Enum language = guessLanguageOfFile(fileName);
- if (language == Language::Unknown) {
- if (fileName.endsWith(QLatin1String(".qrc")))
- modelManager->updateQrcFile(fileName);
- continue;
- }
- if (language == Language::Qml
- && (mainLanguage == Language::QmlQtQuick1 || Language::QmlQtQuick2))
- language = mainLanguage;
- QString contents;
- int documentRevision = 0;
-
- if (workingCopy.contains(fileName)) {
- QPair<QString, int> entry = workingCopy.get(fileName);
- contents = entry.first;
- documentRevision = entry.second;
- } else {
- QFile inFile(fileName);
-
- if (inFile.open(QIODevice::ReadOnly)) {
- QTextStream ins(&inFile);
- contents = ins.readAll();
- inFile.close();
- }
- }
-
- Document::MutablePtr doc = Document::create(fileName, language);
- doc->setEditorRevision(documentRevision);
- doc->setSource(contents);
- doc->parse();
-
- // update snapshot. requires synchronization, but significantly reduces amount of file
- // system queries for library imports because queries are cached in libraryInfo
- const Snapshot snapshot = modelManager->snapshot();
-
- // get list of referenced files not yet in snapshot or in directories already scanned
- QStringList importedFiles;
- findNewImplicitImports(doc, snapshot, &importedFiles, &scannedPaths);
- findNewFileImports(doc, snapshot, &importedFiles, &scannedPaths);
- findNewLibraryImports(doc, snapshot, modelManager, &importedFiles, &scannedPaths, &newLibraries);
-
- // add new files to parse list
- foreach (const QString &file, importedFiles) {
- if (! files.contains(file))
- files.append(file);
- }
-
- modelManager->updateDocument(doc);
- if (emitDocChangedOnDisk)
- modelManager->emitDocumentChangedOnDisk(doc);
- }
-}
-
-class FutureReporter
-{
-public:
- FutureReporter(QFutureInterface<void> &future, int multiplier = 100, int base = 0)
- :future(future), multiplier(multiplier), base(base)
- { }
- bool operator()(qreal val)
- {
- if (future.isCanceled())
- return false;
- future.setProgressValue(int(base + multiplier * val));
- return true;
- }
-private:
- QFutureInterface<void> &future;
- int multiplier;
- int base;
-};
-
-void ModelManager::parse(QFutureInterface<void> &future,
- WorkingCopy workingCopy,
- QStringList files,
- ModelManager *modelManager,
- Language::Enum mainLanguage,
- bool emitDocChangedOnDisk)
-{
- FutureReporter reporter(future);
- future.setProgressRange(0, 100);
-
- // paths we have scanned for files and added to the files list
- QSet<QString> scannedPaths;
- // libraries we've found while scanning imports
- QSet<QString> newLibraries;
- parseLoop(scannedPaths, newLibraries, workingCopy, files, modelManager, mainLanguage,
- emitDocChangedOnDisk, reporter);
- future.setProgressValue(100);
-}
-
-struct ScanItem {
- QString path;
- int depth;
- ScanItem(QString path = QString(), int depth = 0)
- : path(path), depth(depth)
- { }
-};
-
-void ModelManager::importScan(QFutureInterface<void> &future,
- ModelManagerInterface::WorkingCopy workingCopy,
- QStringList paths, ModelManager *modelManager,
- Language::Enum language,
- bool emitDocChangedOnDisk)
-{
- // paths we have scanned for files and added to the files list
- QSet<QString> scannedPaths = modelManager->m_scannedPaths;
- // libraries we've found while scanning imports
- QSet<QString> newLibraries;
-
- QVector<ScanItem> pathsToScan;
- pathsToScan.reserve(paths.size());
- {
- QMutexLocker l(&modelManager->m_mutex);
- foreach (const QString &path, paths) {
- QString cPath = QDir::cleanPath(path);
- if (modelManager->m_scannedPaths.contains(cPath))
- continue;
- pathsToScan.append(ScanItem(cPath));
- modelManager->m_scannedPaths.insert(cPath);
- }
- }
- const int maxScanDepth = 5;
- int progressRange = pathsToScan.size() * (1 << (2 + maxScanDepth));
- int totalWork(progressRange), workDone(0);
- future.setProgressRange(0, progressRange); // update max length while iterating?
- const bool libOnly = true; // FIXME remove when tested more
- const Snapshot snapshot = modelManager->snapshot();
- while (!pathsToScan.isEmpty() && !future.isCanceled()) {
- ScanItem toScan = pathsToScan.last();
- pathsToScan.pop_back();
- int pathBudget = (maxScanDepth + 2 - toScan.depth);
- if (!scannedPaths.contains(toScan.path)) {
- QStringList importedFiles;
- if (!findNewQmlLibraryInPath(toScan.path, snapshot, modelManager, &importedFiles,
- &scannedPaths, &newLibraries, true)
- && !libOnly && snapshot.documentsInDirectory(toScan.path).isEmpty())
- importedFiles += filesInDirectoryForLanguages(toScan.path,
- Document::companionLanguages(language));
- workDone += 1;
- future.setProgressValue(progressRange * workDone / totalWork);
- if (!importedFiles.isEmpty()) {
- FutureReporter reporter(future, progressRange * pathBudget / (4 * totalWork),
- progressRange * workDone / totalWork);
- parseLoop(scannedPaths, newLibraries, workingCopy, importedFiles, modelManager,
- language, emitDocChangedOnDisk, reporter); // run in parallel??
- importedFiles.clear();
- }
- workDone += pathBudget / 4 - 1;
- future.setProgressValue(progressRange * workDone / totalWork);
- } else {
- workDone += pathBudget / 4;
- }
- // always descend tree, as we might have just scanned with a smaller depth
- if (toScan.depth < maxScanDepth) {
- QDir dir(toScan.path);
- QStringList subDirs(dir.entryList(QDir::Dirs));
- workDone += 1;
- totalWork += pathBudget / 2 * subDirs.size() - pathBudget * 3 / 4 + 1;
- foreach (const QString path, subDirs)
- pathsToScan.append(ScanItem(dir.absoluteFilePath(path), toScan.depth + 1));
- } else {
- workDone += pathBudget *3 / 4;
- }
- future.setProgressValue(progressRange * workDone / totalWork);
- }
- future.setProgressValue(progressRange);
- if (future.isCanceled()) {
- // assume no work has been done
- QMutexLocker l(&modelManager->m_mutex);
- foreach (const QString &path, paths)
- modelManager->m_scannedPaths.remove(path);
- }
+ return projectInfo(activeProject);
}
// Check whether fileMimeType is the same or extends knownMimeType
@@ -1006,312 +277,8 @@ bool ModelManager::matchesMimeType(const MimeType &fileMimeType, const MimeType
return false;
}
-QStringList ModelManager::importPaths() const
-{
- QMutexLocker l(&m_mutex);
- return m_allImportPaths;
-}
-
-QmlLanguageBundles ModelManager::activeBundles() const
-{
- QMutexLocker l(&m_mutex);
- return m_activeBundles;
-}
-
-QmlLanguageBundles ModelManager::extendedBundles() const
+void ModelManager::addTaskInternal(QFuture<void> result, const QString &msg, const char *taskId) const
{
- QMutexLocker l(&m_mutex);
- return m_extendedBundles;
+ ProgressManager::addTask(result, msg, taskId);
}
-static QStringList environmentImportPaths()
-{
- QStringList paths;
-
- QByteArray envImportPath = qgetenv("QML_IMPORT_PATH");
-
- foreach (const QString &path, QString::fromLatin1(envImportPath)
- .split(Utils::HostOsInfo::pathListSeparator(), QString::SkipEmptyParts)) {
- QString canonicalPath = QDir(path).canonicalPath();
- if (!canonicalPath.isEmpty() && !paths.contains(canonicalPath))
- paths.append(canonicalPath);
- }
-
- return paths;
-}
-
-void ModelManager::updateImportPaths()
-{
- QStringList allImportPaths;
- QmlLanguageBundles activeBundles;
- QmlLanguageBundles extendedBundles;
- QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects);
- while (it.hasNext()) {
- it.next();
- foreach (const QString &path, it.value().importPaths) {
- const QString canonicalPath = QFileInfo(path).canonicalFilePath();
- if (!canonicalPath.isEmpty())
- allImportPaths += canonicalPath;
- }
- }
- it.toFront();
- while (it.hasNext()) {
- it.next();
- activeBundles.mergeLanguageBundles(it.value().activeBundle);
- foreach (Language::Enum l, it.value().activeBundle.languages()) {
- foreach (const QString &path, it.value().activeBundle.bundleForLanguage(l)
- .searchPaths().stringList()) {
- const QString canonicalPath = QFileInfo(path).canonicalFilePath();
- if (!canonicalPath.isEmpty())
- allImportPaths += canonicalPath;
- }
- }
- }
- it.toFront();
- while (it.hasNext()) {
- it.next();
- extendedBundles.mergeLanguageBundles(it.value().extendedBundle);
- foreach (Language::Enum l, it.value().extendedBundle.languages()) {
- foreach (const QString &path, it.value().extendedBundle.bundleForLanguage(l)
- .searchPaths().stringList()) {
- const QString canonicalPath = QFileInfo(path).canonicalFilePath();
- if (!canonicalPath.isEmpty())
- allImportPaths += canonicalPath;
- }
- }
- }
- allImportPaths += m_defaultImportPaths;
- allImportPaths.removeDuplicates();
-
- {
- QMutexLocker l(&m_mutex);
- m_allImportPaths = allImportPaths;
- m_activeBundles = activeBundles;
- m_extendedBundles = extendedBundles;
- }
-
-
- // check if any file in the snapshot imports something new in the new paths
- Snapshot snapshot = _validSnapshot;
- QStringList importedFiles;
- QSet<QString> scannedPaths;
- QSet<QString> newLibraries;
- foreach (const Document::Ptr &doc, snapshot)
- findNewLibraryImports(doc, snapshot, this, &importedFiles, &scannedPaths, &newLibraries);
-
- updateSourceFiles(importedFiles, true);
-
- if (!m_shouldScanImports)
- return;
- QStringList pathToScan;
- {
- QMutexLocker l(&m_mutex);
- foreach (QString importPath, allImportPaths)
- if (!m_scannedPaths.contains(importPath)) {
- pathToScan.append(importPath);
- }
- }
-
- if (pathToScan.count() > 1) {
- QFuture<void> result = QtConcurrent::run(&ModelManager::importScan,
- workingCopy(), pathToScan,
- this, Language::Qml,
- true);
-
- if (m_synchronizer.futures().size() > 10) {
- QList<QFuture<void> > futures = m_synchronizer.futures();
-
- m_synchronizer.clearFutures();
-
- foreach (const QFuture<void> &future, futures) {
- if (! (future.isFinished() || future.isCanceled()))
- m_synchronizer.addFuture(future);
- }
- }
-
- m_synchronizer.addFuture(result);
-
- ProgressManager::addTask(result, tr("Qml import scan"), Constants::TASK_IMPORT_SCAN);
- }
-}
-
-void ModelManager::loadPluginTypes(const QString &libraryPath, const QString &importPath,
- const QString &importUri, const QString &importVersion)
-{
- m_pluginDumper->loadPluginTypes(libraryPath, importPath, importUri, importVersion);
-}
-
-// is called *inside a c++ parsing thread*, to allow hanging on to source and ast
-void ModelManager::maybeQueueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc)
-{
- // avoid scanning documents without source code available
- doc->keepSourceAndAST();
- if (doc->utf8Source().isEmpty()) {
- doc->releaseSourceAndAST();
- return;
- }
-
- // keep source and AST alive if we want to scan for register calls
- const bool scan = FindExportedCppTypes::maybeExportsTypes(doc);
- if (!scan)
- doc->releaseSourceAndAST();
-
- // delegate actual queuing to the gui thread
- QMetaObject::invokeMethod(this, "queueCppQmlTypeUpdate",
- Q_ARG(CPlusPlus::Document::Ptr, doc), Q_ARG(bool, scan));
-}
-
-void ModelManager::queueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc, bool scan)
-{
- QPair<CPlusPlus::Document::Ptr, bool> prev = m_queuedCppDocuments.value(doc->fileName());
- if (prev.first && prev.second)
- prev.first->releaseSourceAndAST();
- m_queuedCppDocuments.insert(doc->fileName(), qMakePair(doc, scan));
- m_updateCppQmlTypesTimer->start();
-}
-
-void ModelManager::startCppQmlTypeUpdate()
-{
- // if a future is still running, delay
- if (m_cppQmlTypesUpdater.isRunning()) {
- m_updateCppQmlTypesTimer->start();
- return;
- }
-
- CppTools::CppModelManagerInterface *cppModelManager =
- CppTools::CppModelManagerInterface::instance();
- if (!cppModelManager)
- return;
-
- m_cppQmlTypesUpdater = QtConcurrent::run(
- &ModelManager::updateCppQmlTypes,
- this, cppModelManager->snapshot(), m_queuedCppDocuments);
- m_queuedCppDocuments.clear();
-}
-
-void ModelManager::asyncReset()
-{
- m_asyncResetTimer->start();
-}
-
-void ModelManager::updateCppQmlTypes(QFutureInterface<void> &interface,
- ModelManager *qmlModelManager,
- CPlusPlus::Snapshot snapshot,
- QHash<QString, QPair<CPlusPlus::Document::Ptr, bool> > documents)
-{
- CppDataHash newData = qmlModelManager->cppData();
-
- FindExportedCppTypes finder(snapshot);
-
- bool hasNewInfo = false;
- typedef QPair<CPlusPlus::Document::Ptr, bool> DocScanPair;
- foreach (const DocScanPair &pair, documents) {
- if (interface.isCanceled())
- return;
-
- CPlusPlus::Document::Ptr doc = pair.first;
- const bool scan = pair.second;
- const QString fileName = doc->fileName();
- if (!scan) {
- hasNewInfo = hasNewInfo || newData.remove(fileName) > 0;
- continue;
- }
-
- finder(doc);
-
- QList<LanguageUtils::FakeMetaObject::ConstPtr> exported = finder.exportedTypes();
- QHash<QString, QString> contextProperties = finder.contextProperties();
- if (exported.isEmpty() && contextProperties.isEmpty()) {
- hasNewInfo = hasNewInfo || newData.remove(fileName) > 0;
- } else {
- CppData &data = newData[fileName];
- // currently we have no simple way to compare, so we assume the worse
- hasNewInfo = true;
- data.exportedTypes = exported;
- data.contextProperties = contextProperties;
- }
-
- doc->releaseSourceAndAST();
- }
-
- QMutexLocker locker(&qmlModelManager->m_cppDataMutex);
- qmlModelManager->m_cppDataHash = newData;
- if (hasNewInfo)
- // one could get away with re-linking the cpp types...
- QMetaObject::invokeMethod(qmlModelManager, "asyncReset");
-}
-
-ModelManager::CppDataHash ModelManager::cppData() const
-{
- QMutexLocker locker(&m_cppDataMutex);
- return m_cppDataHash;
-}
-
-LibraryInfo ModelManager::builtins(const Document::Ptr &doc) const
-{
- ProjectExplorer::Project *project = ProjectExplorer::SessionManager::projectForFile(doc->fileName());
- if (!project)
- return LibraryInfo();
-
- QMutexLocker locker(&m_mutex);
- ProjectInfo info = m_projects.value(project);
- if (!info.isValid())
- return LibraryInfo();
-
- return _validSnapshot.libraryInfo(info.qtImportsPath);
-}
-
-ViewerContext ModelManager::completeVContext(const ViewerContext &vCtx,
- const Document::Ptr &doc) const
-{
- Q_UNUSED(doc);
- ViewerContext res = vCtx;
- switch (res.flags) {
- case ViewerContext::Complete:
- break;
- case ViewerContext::AddQtPath:
- case ViewerContext::AddAllPaths:
- res.paths << importPaths();
- }
- res.flags = ViewerContext::Complete;
- return res;
-}
-
-ViewerContext ModelManager::defaultVContext(bool autoComplete, const Document::Ptr &doc) const
-{
- if (autoComplete)
- return completeVContext(m_vContext, doc);
- else
- return m_vContext;
-}
-
-void ModelManager::setDefaultVContext(const ViewerContext &vContext)
-{
- m_vContext = vContext;
-}
-
-void ModelManager::joinAllThreads()
-{
- foreach (QFuture<void> future, m_synchronizer.futures())
- future.waitForFinished();
-}
-
-void ModelManager::resetCodeModel()
-{
- QStringList documents;
-
- {
- QMutexLocker locker(&m_mutex);
-
- // find all documents currently in the code model
- foreach (Document::Ptr doc, _validSnapshot)
- documents.append(doc->fileName());
-
- // reset the snapshot
- _validSnapshot = Snapshot();
- _newestSnapshot = Snapshot();
- }
-
- // start a reparse thread
- updateSourceFiles(documents, false);
-}
diff --git a/src/plugins/qmljstools/qmljsmodelmanager.h b/src/plugins/qmljstools/qmljsmodelmanager.h
index ac60ea106c..2b8233a66f 100644
--- a/src/plugins/qmljstools/qmljsmodelmanager.h
+++ b/src/plugins/qmljstools/qmljsmodelmanager.h
@@ -67,129 +67,15 @@ public:
~ModelManager();
void delayedInitialization();
-
- WorkingCopy workingCopy() const QTC_OVERRIDE;
- QmlJS::Snapshot snapshot() const QTC_OVERRIDE;
- QmlJS::Snapshot newestSnapshot() const QTC_OVERRIDE;
-
- void updateSourceFiles(const QStringList &files,
- bool emitDocumentOnDiskChanged) QTC_OVERRIDE;
- void fileChangedOnDisk(const QString &path) QTC_OVERRIDE;
- void removeFiles(const QStringList &files) QTC_OVERRIDE;
- QStringList filesAtQrcPath(const QString &path, const QLocale *locale = 0,
- ProjectExplorer::Project *project = 0,
- QrcResourceSelector resources = AllQrcResources) QTC_OVERRIDE;
- QMap<QString,QStringList> filesInQrcPath(const QString &path,
- const QLocale *locale = 0,
- ProjectExplorer::Project *project = 0,
- bool addDirs = false,
- QrcResourceSelector resources = AllQrcResources) QTC_OVERRIDE;
-
- QList<ProjectInfo> projectInfos() const QTC_OVERRIDE;
- ProjectInfo projectInfo(ProjectExplorer::Project *project) const QTC_OVERRIDE;
- void updateProjectInfo(const ProjectInfo &pinfo) QTC_OVERRIDE;
- Q_SLOT virtual void removeProjectInfo(ProjectExplorer::Project *project);
- virtual ProjectInfo projectInfoForPath(QString path);
-
- 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);
-
- QStringList importPaths() const QTC_OVERRIDE;
- QmlJS::QmlLanguageBundles activeBundles() const QTC_OVERRIDE;
- QmlJS::QmlLanguageBundles extendedBundles() const QTC_OVERRIDE;
-
- void loadPluginTypes(const QString &libraryPath, const QString &importPath,
- const QString &importUri, const QString &importVersion) QTC_OVERRIDE;
-
- CppDataHash cppData() const QTC_OVERRIDE;
-
- QmlJS::LibraryInfo builtins(const QmlJS::Document::Ptr &doc) const QTC_OVERRIDE;
-
- QmlJS::ViewerContext completeVContext(
- const QmlJS::ViewerContext &vCtx,
- const QmlJS::Document::Ptr &doc = QmlJS::Document::Ptr(0)) const QTC_OVERRIDE;
- QmlJS::ViewerContext defaultVContext(
- bool autoComplete = true,
- const QmlJS::Document::Ptr &doc = QmlJS::Document::Ptr(0)) const QTC_OVERRIDE;
- void setDefaultVContext(const QmlJS::ViewerContext &vContext) QTC_OVERRIDE;
-
- void joinAllThreads() QTC_OVERRIDE;
-
-public slots:
- void resetCodeModel() QTC_OVERRIDE;
-
-Q_SIGNALS:
- void projectPathChanged(const QString &projectPath);
-
protected:
- QFuture<void> refreshSourceFiles(const QStringList &sourceFiles,
- bool emitDocumentOnDiskChanged);
-
- static void parseLoop(QSet<QString> &scannedPaths, QSet<QString> &newLibraries,
- WorkingCopy workingCopy, QStringList files, ModelManager *modelManager,
- QmlJS::Language::Enum mainLanguage, bool emitDocChangedOnDisk,
- Utils::function<bool (qreal)> reportProgress);
- static void parse(QFutureInterface<void> &future,
- WorkingCopy workingCopy,
- QStringList files,
- ModelManager *modelManager,
- QmlJS::Language::Enum mainLanguage,
- bool emitDocChangedOnDisk);
- static void importScan(QFutureInterface<void> &future,
- WorkingCopy workingCopy,
- QStringList paths,
- ModelManager *modelManager,
- QmlJS::Language::Enum mainLanguage,
- bool emitDocChangedOnDisk);
-
- void loadQmlTypeDescriptions();
- void loadQmlTypeDescriptions(const QString &path);
-
- void updateImportPaths();
-
-private slots:
- void maybeQueueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc);
- void queueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc, bool scan);
- void startCppQmlTypeUpdate();
- void asyncReset();
-
+ QHash<QString, QmlJS::Language::Enum> languageForSuffix() const QTC_OVERRIDE;
+ void writeMessageInternal(const QString &msg) const QTC_OVERRIDE;
+ ModelManagerInterface::ProjectInfo defaultProjectInfo() const QTC_OVERRIDE;
+ WorkingCopy workingCopyInternal() const QTC_OVERRIDE;
+ void addTaskInternal(QFuture<void> result, const QString &msg, const char *taskId) const QTC_OVERRIDE;
private:
+ void loadDefaultQmlTypeDescriptions();
static bool matchesMimeType(const Core::MimeType &fileMimeType, const Core::MimeType &knownMimeType);
- static void updateCppQmlTypes(QFutureInterface<void> &interface,
- ModelManager *qmlModelManager,
- CPlusPlus::Snapshot snapshot,
- QHash<QString, QPair<CPlusPlus::Document::Ptr, bool> > documents);
-
- mutable QMutex m_mutex;
- QmlJS::Snapshot _validSnapshot;
- QmlJS::Snapshot _newestSnapshot;
- QStringList m_allImportPaths;
- QStringList m_defaultImportPaths;
- QmlJS::QmlLanguageBundles m_activeBundles;
- QmlJS::QmlLanguageBundles m_extendedBundles;
- QmlJS::ViewerContext m_vContext;
- bool m_shouldScanImports;
- QSet<QString> m_scannedPaths;
-
- QTimer *m_updateCppQmlTypesTimer;
- QTimer *m_asyncResetTimer;
- QHash<QString, QPair<CPlusPlus::Document::Ptr, bool> > m_queuedCppDocuments;
- QFuture<void> m_cppQmlTypesUpdater;
- QmlJS::QrcCache m_qrcCache;
-
- CppDataHash m_cppDataHash;
- mutable QMutex m_cppDataMutex;
-
- // project integration
- QMap<ProjectExplorer::Project *, ProjectInfo> m_projects;
-
- PluginDumper *m_pluginDumper;
-
- QFutureSynchronizer<void> m_synchronizer;
-
- QHash<QString, QmlJS::Language::Enum> languageForSuffix() const QTC_OVERRIDE;
};
} // namespace Internal
diff --git a/src/plugins/qmljstools/qmljstools.pro b/src/plugins/qmljstools/qmljstools.pro
index c3fdd89e7d..d0a6409055 100644
--- a/src/plugins/qmljstools/qmljstools.pro
+++ b/src/plugins/qmljstools/qmljstools.pro
@@ -15,12 +15,10 @@ HEADERS += \
$$PWD/qmljsmodelmanager.h \
$$PWD/qmljsqtstylecodeformatter.h \
$$PWD/qmljsrefactoringchanges.h \
- $$PWD/qmljsplugindumper.h \
$$PWD/qmljsfunctionfilter.h \
$$PWD/qmljslocatordata.h \
$$PWD/qmljsindenter.h \
$$PWD/qmljscodestylesettingspage.h \
- $$PWD/qmljsfindexportedcpptypes.h \
$$PWD/qmljssemanticinfo.h \
$$PWD/qmljstools_global.h \
$$PWD/qmlconsolemanager.h \
@@ -41,12 +39,10 @@ SOURCES += \
$$PWD/qmljsmodelmanager.cpp \
$$PWD/qmljsqtstylecodeformatter.cpp \
$$PWD/qmljsrefactoringchanges.cpp \
- $$PWD/qmljsplugindumper.cpp \
$$PWD/qmljsfunctionfilter.cpp \
$$PWD/qmljslocatordata.cpp \
$$PWD/qmljsindenter.cpp \
$$PWD/qmljscodestylesettingspage.cpp \
- $$PWD/qmljsfindexportedcpptypes.cpp \
$$PWD/qmljssemanticinfo.cpp \
$$PWD/qmlconsolemanager.cpp \
$$PWD/qmlconsoleitemmodel.cpp \
diff --git a/src/plugins/qmljstools/qmljstools.qbs b/src/plugins/qmljstools/qmljstools.qbs
index 714528ac3d..6fab90b4af 100644
--- a/src/plugins/qmljstools/qmljstools.qbs
+++ b/src/plugins/qmljstools/qmljstools.qbs
@@ -27,8 +27,6 @@ QtcPlugin {
"qmljscodestylesettingspage.cpp",
"qmljscodestylesettingspage.h",
"qmljscodestylesettingspage.ui",
- "qmljsfindexportedcpptypes.cpp",
- "qmljsfindexportedcpptypes.h",
"qmljsfunctionfilter.cpp",
"qmljsfunctionfilter.h",
"qmljsindenter.cpp",
@@ -39,8 +37,6 @@ QtcPlugin {
"qmljsmodelmanager.cpp",
"qmljsmodelmanager.h",
"qmljsmodelmanager.h",
- "qmljsplugindumper.cpp",
- "qmljsplugindumper.h",
"qmljsqtstylecodeformatter.cpp",
"qmljsqtstylecodeformatter.h",
"qmljsrefactoringchanges.cpp",
diff --git a/src/plugins/qmljstools/qmljstoolsconstants.h b/src/plugins/qmljstools/qmljstoolsconstants.h
index 0803cf4988..b68acf1d63 100644
--- a/src/plugins/qmljstools/qmljstoolsconstants.h
+++ b/src/plugins/qmljstools/qmljstoolsconstants.h
@@ -42,9 +42,6 @@ const char QMLTYPES_MIMETYPE[] = "application/x-qt.meta-info+qml";
const char JS_MIMETYPE[] = "application/javascript";
const char JSON_MIMETYPE[] = "application/json";
-const char TASK_INDEX[] = "QmlJSEditor.TaskIndex";
-const char TASK_IMPORT_SCAN[] = "QmlJSEditor.TaskImportScan";
-
const char QML_JS_CODE_STYLE_SETTINGS_ID[] = "A.Code Style";
const char QML_JS_CODE_STYLE_SETTINGS_NAME[] = QT_TRANSLATE_NOOP("QmlJSTools", "Code Style");
diff --git a/src/plugins/qmljstools/qmljstoolsplugin.cpp b/src/plugins/qmljstools/qmljstoolsplugin.cpp
index 4e02e5b36c..199cacd334 100644
--- a/src/plugins/qmljstools/qmljstoolsplugin.cpp
+++ b/src/plugins/qmljstools/qmljstoolsplugin.cpp
@@ -132,13 +132,13 @@ ExtensionSystem::IPlugin::ShutdownFlag QmlJSToolsPlugin::aboutToShutdown()
void QmlJSToolsPlugin::onTaskStarted(Core::Id type)
{
- if (type == QmlJSTools::Constants::TASK_INDEX)
+ if (type == QmlJS::Constants::TASK_INDEX)
m_resetCodeModelAction->setEnabled(false);
}
void QmlJSToolsPlugin::onAllTasksFinished(Core::Id type)
{
- if (type == QmlJSTools::Constants::TASK_INDEX)
+ if (type == QmlJS::Constants::TASK_INDEX)
m_resetCodeModelAction->setEnabled(true);
}
diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp
index 76a07ce9de..03e732513a 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.cpp
+++ b/src/plugins/qmlprojectmanager/qmlproject.cpp
@@ -247,7 +247,7 @@ void QmlProject::refresh(RefreshOptions options)
QmlJSTools::defaultProjectInfoForProject(this);
projectInfo.importPaths = customImportPaths();
- m_modelManager->updateProjectInfo(projectInfo);
+ m_modelManager->updateProjectInfo(projectInfo, this);
}
QStringList QmlProject::convertToAbsoluteFiles(const QStringList &paths) const
diff --git a/src/plugins/qtsupport/qmldumptool.cpp b/src/plugins/qtsupport/qmldumptool.cpp
index af5d9c2759..c2a3e318f9 100644
--- a/src/plugins/qtsupport/qmldumptool.cpp
+++ b/src/plugins/qtsupport/qmldumptool.cpp
@@ -134,7 +134,7 @@ private slots:
projectInfo.qmlDumpPath = version->qmlDumpTool(!update.preferDebug);
projectInfo.qmlDumpEnvironment = version->qmlToolsEnvironment();
projectInfo.qmlDumpHasRelocatableFlag = version->hasQmlDumpWithRelocatableFlag();
- modelManager->updateProjectInfo(projectInfo);
+ modelManager->updateProjectInfo(projectInfo, update.project);
}
// clean up