1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #pragma once
27
28 #include "qmljs_global.h"
29 #include "qmljsbundle.h"
30 #include "qmljsdocument.h"
31 #include "qmljsqrcparser.h"
32 #include "qmljsdialect.h"
33
34 // #include <cplusplus/CppDocument.h>
35 #include <utils/environment.h>
36
37 #include <QFuture>
38 #include <QHash>
39 #include <QObject>
40 #include <QPointer>
41 #include <QStringList>
42
QT_FORWARD_DECLARE_CLASS(QTimer)43 QT_FORWARD_DECLARE_CLASS(QTimer)
44
45 namespace ProjectExplorer { class Project; }
46
47 namespace QmlJS {
48
49 class Snapshot;
50 class PluginDumper;
51
52 class QMLJS_EXPORT ModelManagerInterface: public QObject
53 {
54 Q_OBJECT
55
56 public:
57 enum QrcResourceSelector {
58 ActiveQrcResources,
59 AllQrcResources
60 };
61
62 class ProjectInfo
63 {
64 public:
ProjectInfo()65 ProjectInfo()
66 : tryQmlDump(false), qmlDumpHasRelocatableFlag(true)
67 { }
68
ProjectInfo(QPointer<ProjectExplorer::Project> project)69 ProjectInfo(QPointer<ProjectExplorer::Project> project)
70 : project(project)
71 , tryQmlDump(false), qmlDumpHasRelocatableFlag(true)
72 { }
73
74 explicit operator bool() const
75 { return ! project.isNull(); }
76
isValid()77 bool isValid() const
78 { return ! project.isNull(); }
79
isNull()80 bool isNull() const
81 { return project.isNull(); }
82
83 public: // attributes
84 QPointer<ProjectExplorer::Project> project;
85 QStringList sourceFiles;
86 PathsAndLanguages importPaths;
87 QStringList activeResourceFiles;
88 QStringList allResourceFiles;
89 QHash<QString, QString> resourceFileContents;
90
91 // whether trying to run qmldump makes sense
92 bool tryQmlDump;
93 bool qmlDumpHasRelocatableFlag;
94 QString qmlDumpPath;
95 ::Utils::Environment qmlDumpEnvironment;
96
97 QString qtImportsPath;
98 QString qtQmlPath;
99 QString qtVersionString;
100 QmlJS::QmlLanguageBundles activeBundle;
101 QmlJS::QmlLanguageBundles extendedBundle;
102 };
103
104 class WorkingCopy
105 {
106 public:
107 typedef QHash<QString, QPair<QString, int> > Table;
108
109 void insert(const QString &fileName, const QString &source, int revision = 0)
110 { _elements.insert(fileName, {source, revision}); }
111
contains(const QString & fileName)112 bool contains(const QString &fileName) const
113 { return _elements.contains(fileName); }
114
source(const QString & fileName)115 QString source(const QString &fileName) const
116 { return _elements.value(fileName).first; }
117
get(const QString & fileName)118 QPair<QString, int> get(const QString &fileName) const
119 { return _elements.value(fileName); }
120
all()121 Table all() const
122 { return _elements; }
123
124 private:
125 Table _elements;
126 };
127
128 class CppData
129 {
130 public:
131 QList<LanguageUtils::FakeMetaObject::ConstPtr> exportedTypes;
132 QHash<QString, QString> contextProperties;
133 };
134
135 typedef QHash<QString, CppData> CppDataHash;
136 typedef QHashIterator<QString, CppData> CppDataHashIterator;
137
138 public:
139 ModelManagerInterface(QObject *parent = 0);
140 ~ModelManagerInterface() override;
141
142 static Dialect guessLanguageOfFile(const QString &fileName);
143 static QStringList globPatternsForLanguages(const QList<Dialect> languages);
144 static ModelManagerInterface *instance();
145 static void writeWarning(const QString &msg);
146 static WorkingCopy workingCopy();
147
148 QmlJS::Snapshot snapshot() const;
149 QmlJS::Snapshot newestSnapshot() const;
150
151 void activateScan();
152 void updateSourceFiles(const QStringList &files,
153 bool emitDocumentOnDiskChanged);
154 void fileChangedOnDisk(const QString &path);
155 void removeFiles(const QStringList &files);
156 QStringList qrcPathsForFile(const QString &file, const QLocale *locale = 0,
157 ProjectExplorer::Project *project = 0,
158 QrcResourceSelector resources = AllQrcResources);
159 QStringList filesAtQrcPath(const QString &path, const QLocale *locale = 0,
160 ProjectExplorer::Project *project = 0,
161 QrcResourceSelector resources = AllQrcResources);
162 QMap<QString,QStringList> filesInQrcPath(const QString &path,
163 const QLocale *locale = 0,
164 ProjectExplorer::Project *project = 0,
165 bool addDirs = false,
166 QrcResourceSelector resources = AllQrcResources);
167
168 QList<ProjectInfo> projectInfos() const;
169 ProjectInfo projectInfo(ProjectExplorer::Project *project,
170 const ModelManagerInterface::ProjectInfo &defaultValue = ProjectInfo()) const;
171 void updateProjectInfo(const ProjectInfo &pinfo, ProjectExplorer::Project *p);
172
173 void updateDocument(QmlJS::Document::Ptr doc);
174 void updateLibraryInfo(const QString &path, const QmlJS::LibraryInfo &info);
175 void emitDocumentChangedOnDisk(QmlJS::Document::Ptr doc);
176 void updateQrcFile(const QString &path);
177 ProjectInfo projectInfoForPath(const QString &path) const;
178 QList<ProjectInfo> allProjectInfosForPath(const QString &path) const;
179 bool isIdle() const ;
180
181 QStringList importPathsNames() const;
182 QmlJS::QmlLanguageBundles activeBundles() const;
183 QmlJS::QmlLanguageBundles extendedBundles() const;
184
185 void loadPluginTypes(const QString &libraryPath, const QString &importPath,
186 const QString &importUri, const QString &importVersion);
187
188 CppDataHash cppData() const;
189 LibraryInfo builtins(const Document::Ptr &doc) const;
190 ViewerContext completeVContext(const ViewerContext &vCtx,
191 const Document::Ptr &doc = Document::Ptr(0)) const;
192 ViewerContext defaultVContext(Dialect language = Dialect::Qml,
193 const Document::Ptr &doc = Document::Ptr(0),
194 bool autoComplete = true) const;
195 void setDefaultVContext(const ViewerContext &vContext);
196 virtual ProjectInfo defaultProjectInfo() const;
197 virtual ProjectInfo defaultProjectInfoForProject(ProjectExplorer::Project *project) const;
198
199
200 // Blocks until all parsing threads are done. Used for testing.
201 void joinAllThreads();
202
203 QmlJS::Document::Ptr ensuredGetDocumentForPath(const QString &filePath);
204 static void importScan(QFutureInterface<void> &future,
205 WorkingCopy workingCopyInternal,
206 PathsAndLanguages paths,
207 ModelManagerInterface *modelManager,
208 bool emitDocChangedOnDisk, bool libOnly = true, bool forceRescan = false);
209
210 virtual void resetCodeModel();
211 void removeProjectInfo(ProjectExplorer::Project *project);
212 // void maybeQueueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc);
213
214 Q_SIGNALS:
215 void documentUpdated(QmlJS::Document::Ptr doc);
216 void documentChangedOnDisk(QmlJS::Document::Ptr doc);
217 void aboutToRemoveFiles(const QStringList &files);
218 void libraryInfoUpdated(const QString &path, const QmlJS::LibraryInfo &info);
219 void projectInfoUpdated(const ProjectInfo &pinfo);
220 void projectPathChanged(const QString &projectPath);
221
222 protected:
223 // Q_INVOKABLE void queueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc, bool scan);
224 Q_INVOKABLE void asyncReset();
225 // virtual void startCppQmlTypeUpdate();
226 QMutex *mutex() const;
227 virtual QHash<QString,Dialect> languageForSuffix() const;
228 virtual void writeMessageInternal(const QString &msg) const;
229 virtual WorkingCopy workingCopyInternal() const;
230 virtual void addTaskInternal(QFuture<void> result, const QString &msg, const char *taskId) const;
231
232 QFuture<void> refreshSourceFiles(const QStringList &sourceFiles,
233 bool emitDocumentOnDiskChanged);
234
235 static void parseLoop(QSet<QString> &scannedPaths, QSet<QString> &newLibraries,
236 WorkingCopy workingCopyInternal, QStringList files, ModelManagerInterface *modelManager,
237 QmlJS::Dialect mainLanguage, bool emitDocChangedOnDisk,
238 std::function<bool (qreal)> reportProgress);
239 static void parse(QFutureInterface<void> &future,
240 WorkingCopy workingCopyInternal,
241 QStringList files,
242 ModelManagerInterface *modelManager,
243 QmlJS::Dialect mainLanguage,
244 bool emitDocChangedOnDisk);
245 // static void updateCppQmlTypes(QFutureInterface<void> &futureInterface,
246 // ModelManagerInterface *qmlModelManager,
247 // CPlusPlus::Snapshot snapshot,
248 // QHash<QString, QPair<CPlusPlus::Document::Ptr, bool> > documents);
249
250 void maybeScan(const PathsAndLanguages &importPaths);
251 void updateImportPaths();
252 void loadQmlTypeDescriptionsInternal(const QString &path);
253 void setDefaultProject(const ProjectInfo &pInfo, ProjectExplorer::Project *p);
254
255 private:
256 void cleanupFutures();
257 void iterateQrcFiles(ProjectExplorer::Project *project,
258 QrcResourceSelector resources,
259 std::function<void(QrcParser::ConstPtr)> callback);
260
261 mutable QMutex m_mutex;
262 QmlJS::Snapshot m_validSnapshot;
263 QmlJS::Snapshot m_newestSnapshot;
264 PathsAndLanguages m_allImportPaths;
265 QStringList m_defaultImportPaths;
266 QmlJS::QmlLanguageBundles m_activeBundles;
267 QmlJS::QmlLanguageBundles m_extendedBundles;
268 QHash<Dialect, QmlJS::ViewerContext> m_defaultVContexts;
269 bool m_shouldScanImports;
270 QSet<QString> m_scannedPaths;
271
272 QTimer *m_updateCppQmlTypesTimer;
273 QTimer *m_asyncResetTimer;
274 // QHash<QString, QPair<CPlusPlus::Document::Ptr, bool> > m_queuedCppDocuments;
275 QFuture<void> m_cppQmlTypesUpdater;
276 QrcCache m_qrcCache;
277 QHash<QString, QString> m_qrcContents;
278
279 CppDataHash m_cppDataHash;
280 // QHash<QString, QList<CPlusPlus::Document::Ptr> > m_cppDeclarationFiles;
281 mutable QMutex m_cppDataMutex;
282
283 // project integration
284 QMap<ProjectExplorer::Project *, ProjectInfo> m_projects;
285 ProjectInfo m_defaultProjectInfo;
286 ProjectExplorer::Project *m_defaultProject;
287 QMultiHash<QString, ProjectExplorer::Project *> m_fileToProject;
288
289 PluginDumper *m_pluginDumper;
290
291 QList<QFuture<void>> m_futures;
292 bool m_indexerEnabled;
293 };
294
295 } // namespace QmlJS
296