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 "cpptools_global.h"
29 
30 #include "cppmodelmanagerinterface.h"
31 #include "refactoringengineinterface.h"
32 #include "projectinfo.h"
33 #include "projectpart.h"
34 #include <projectexplorer/headerpath.h>
35 
36 #include <cplusplus/cppmodelmanagerbase.h>
37 #include <coreplugin/find/ifindfilter.h>
38 #include <coreplugin/locator/ilocatorfilter.h>
39 
40 #include <QFuture>
41 #include <QObject>
42 #include <QStringList>
43 
44 namespace Core {
45 class IDocument;
46 class IEditor;
47 }
48 namespace CPlusPlus { class LookupContext; }
49 namespace ProjectExplorer { class Project; }
50 namespace TextEditor {
51 class BaseHoverHandler;
52 class TextDocument;
53 } // namespace TextEditor
54 
55 namespace CppTools {
56 
57 class AbstractEditorSupport;
58 class AbstractOverviewModel;
59 class BaseEditorDocumentProcessor;
60 class CppCompletionAssistProvider;
61 class CppEditorDocumentHandle;
62 class CppIndexingSupport;
63 class CppLocatorData;
64 class ModelManagerSupportProvider;
65 class FollowSymbolInterface;
66 class SymbolFinder;
67 class WorkingCopy;
68 
69 namespace Internal {
70 class CppSourceProcessor;
71 class CppModelManagerPrivate;
72 class CppToolsPluginPrivate;
73 }
74 
75 namespace Tests {
76 class ModelManagerTestHelper;
77 }
78 
79 enum class RefactoringEngineType : int
80 {
81     BuiltIn = 0,
82     ClangCodeModel = 1,
83     ClangRefactoring = 2
84 };
85 
86 class CPPTOOLS_EXPORT CppModelManager final : public CPlusPlus::CppModelManagerBase,
87         public RefactoringEngineInterface,
88         public CppModelManagerInterface
89 {
90     Q_OBJECT
91 
92 private:
93     friend class Internal::CppToolsPluginPrivate;
94     CppModelManager();
95     ~CppModelManager() override;
96 
97 public:
98     using Document = CPlusPlus::Document;
99 
100     static CppModelManager *instance();
101 
102     void registerJsExtension();
103 
104      // Documented in source file.
105      enum ProgressNotificationMode {
106         ForcedProgressNotification,
107         ReservedProgressNotification
108     };
109 
110     QFuture<void> updateSourceFiles(const QSet<QString> &sourceFiles,
111                                     ProgressNotificationMode mode = ReservedProgressNotification);
112     void updateCppEditorDocuments(bool projectsUpdated = false) const;
113     WorkingCopy workingCopy() const;
114     QByteArray codeModelConfiguration() const;
115     CppLocatorData *locatorData() const;
116 
117     QList<ProjectInfo> projectInfos() const;
118     ProjectInfo projectInfo(ProjectExplorer::Project *project) const;
119     QFuture<void> updateProjectInfo(const ProjectInfo &newProjectInfo,
120                                     const QSet<QString> &additionalFiles = {});
121 
122     /// \return The project part with the given project file
123     ProjectPart::Ptr projectPartForId(const QString &projectPartId) const override;
124     /// \return All project parts that mention the given file name as one of the sources/headers.
125     QList<ProjectPart::Ptr> projectPart(const Utils::FilePath &fileName) const;
projectPart(const QString & fileName)126     QList<ProjectPart::Ptr> projectPart(const QString &fileName) const
127     { return projectPart(Utils::FilePath::fromString(fileName)); }
128     /// This is a fall-back function: find all files that includes the file directly or indirectly,
129     /// and return its \c ProjectPart list for use with this file.
130     QList<ProjectPart::Ptr> projectPartFromDependencies(const Utils::FilePath &fileName) const;
131     /// \return A synthetic \c ProjectPart which consists of all defines/includes/frameworks from
132     ///         all loaded projects.
133     ProjectPart::Ptr fallbackProjectPart();
134 
135     CPlusPlus::Snapshot snapshot() const override;
136     Document::Ptr document(const QString &fileName) const;
137     bool replaceDocument(Document::Ptr newDoc);
138 
139     void emitDocumentUpdated(Document::Ptr doc);
140     void emitAbstractEditorSupportContentsUpdated(const QString &filePath,
141                                                   const QString &sourcePath,
142                                                   const QByteArray &contents);
143     void emitAbstractEditorSupportRemoved(const QString &filePath);
144 
145     static bool isCppEditor(Core::IEditor *editor);
146     static bool supportsOutline(const TextEditor::TextDocument *document);
147     bool isClangCodeModelActive() const;
148 
149     QSet<AbstractEditorSupport*> abstractEditorSupports() const;
150     void addExtraEditorSupport(AbstractEditorSupport *editorSupport);
151     void removeExtraEditorSupport(AbstractEditorSupport *editorSupport);
152 
153     QList<CppEditorDocumentHandle *> cppEditorDocuments() const;
154     CppEditorDocumentHandle *cppEditorDocument(const QString &filePath) const;
155     void registerCppEditorDocument(CppEditorDocumentHandle *cppEditorDocument);
156     void unregisterCppEditorDocument(const QString &filePath);
157 
158     QList<int> references(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context);
159 
160     void startLocalRenaming(const CursorInEditor &data,
161                             CppTools::ProjectPart *projectPart,
162                             RenameCallback &&renameSymbolsCallback) final;
163     void globalRename(const CursorInEditor &data, UsagesCallback &&renameCallback,
164                       const QString &replacement) final;
165     void findUsages(const CppTools::CursorInEditor &data,
166                     UsagesCallback &&showUsagesCallback) const final;
167     void globalFollowSymbol(const CursorInEditor &data,
168                             Utils::ProcessLinkCallback &&processLinkCallback,
169                             const CPlusPlus::Snapshot &snapshot,
170                             const Document::Ptr &documentFromSemanticInfo,
171                             SymbolFinder *symbolFinder,
172                             bool inNextSplit) const final;
173 
174     bool positionRequiresSignal(const QString &filePath, const QByteArray &content,
175                                 int position) const;
176 
177     void renameUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context,
178                       const QString &replacement = QString());
179     void findUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context);
180 
181     void findMacroUsages(const CPlusPlus::Macro &macro);
182     void renameMacroUsages(const CPlusPlus::Macro &macro, const QString &replacement);
183 
184     void finishedRefreshingSourceFiles(const QSet<QString> &files);
185 
186     void activateClangCodeModel(ModelManagerSupportProvider *modelManagerSupportProvider);
187     CppCompletionAssistProvider *completionAssistProvider() const;
188     CppCompletionAssistProvider *functionHintAssistProvider() const;
189     BaseEditorDocumentProcessor *createEditorDocumentProcessor(
190                     TextEditor::TextDocument *baseTextDocument) const;
191     TextEditor::BaseHoverHandler *createHoverHandler() const;
192     FollowSymbolInterface &followSymbolInterface() const;
193     std::unique_ptr<AbstractOverviewModel> createOverviewModel() const;
194 
195     void setIndexingSupport(CppIndexingSupport *indexingSupport);
196     CppIndexingSupport *indexingSupport();
197 
198     QStringList projectFiles();
199 
200     ProjectExplorer::HeaderPaths headerPaths();
201 
202     // Use this *only* for auto tests
203     void setHeaderPaths(const ProjectExplorer::HeaderPaths &headerPaths);
204 
205     ProjectExplorer::Macros definedMacros();
206 
207     void enableGarbageCollector(bool enable);
208 
209     SymbolFinder *symbolFinder();
210 
211     QThreadPool *sharedThreadPool();
212 
213     static QSet<QString> timeStampModifiedFiles(const QList<Document::Ptr> &documentsToCheck);
214 
215     static Internal::CppSourceProcessor *createSourceProcessor();
216     static QString configurationFileName();
217     static QString editorConfigurationFileName();
218 
219     static void addRefactoringEngine(RefactoringEngineType type,
220                                      RefactoringEngineInterface *refactoringEngine);
221     static void removeRefactoringEngine(RefactoringEngineType type);
222     static RefactoringEngineInterface *builtinRefactoringEngine();
223     static FollowSymbolInterface &builtinFollowSymbol();
224 
225     void setLocatorFilter(std::unique_ptr<Core::ILocatorFilter> &&filter);
226     void setClassesFilter(std::unique_ptr<Core::ILocatorFilter> &&filter);
227     void setIncludesFilter(std::unique_ptr<Core::ILocatorFilter> &&filter);
228     void setFunctionsFilter(std::unique_ptr<Core::ILocatorFilter> &&filter);
229     void setSymbolsFindFilter(std::unique_ptr<Core::IFindFilter> &&filter);
230     void setCurrentDocumentFilter(std::unique_ptr<Core::ILocatorFilter> &&filter);
231 
232     Core::ILocatorFilter *locatorFilter() const;
233     Core::ILocatorFilter *classesFilter() const;
234     Core::ILocatorFilter *includesFilter() const;
235     Core::ILocatorFilter *functionsFilter() const;
236     Core::IFindFilter *symbolsFindFilter() const;
237     Core::ILocatorFilter *currentDocumentFilter() const;
238 
239     /*
240      * try to find build system target that depends on the given file - if the file is no header
241      * try to find the corresponding header and use this instead to find the respective target
242      */
243     QSet<QString> dependingInternalTargets(const Utils::FilePath &file) const;
244 
245     QSet<QString> internalTargets(const Utils::FilePath &filePath) const;
246 
247     void renameIncludes(const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath);
248 
249     // for VcsBaseSubmitEditor
250     Q_INVOKABLE QSet<QString> symbolsInFiles(const QSet<Utils::FilePath> &files) const;
251 
252 signals:
253     /// Project data might be locked while this is emitted.
254     void aboutToRemoveFiles(const QStringList &files);
255 
256     void documentUpdated(CPlusPlus::Document::Ptr doc);
257     void sourceFilesRefreshed(const QSet<QString> &files);
258 
259     void projectPartsUpdated(ProjectExplorer::Project *project);
260     void projectPartsRemoved(const QStringList &projectPartIds);
261 
262     void globalSnapshotChanged();
263 
264     void gcFinished(); // Needed for tests.
265 
266     void abstractEditorSupportContentsUpdated(const QString &filePath,
267                                               const QString &sourcePath,
268                                               const QByteArray &contents);
269     void abstractEditorSupportRemoved(const QString &filePath);
270 
271 public slots:
272     void updateModifiedSourceFiles();
273     void GC();
274 
275 private:
276     // This should be executed in the GUI thread.
277     friend class Tests::ModelManagerTestHelper;
278     void onAboutToLoadSession();
279     void onProjectAdded(ProjectExplorer::Project *project);
280     void onAboutToRemoveProject(ProjectExplorer::Project *project);
281     void onActiveProjectChanged(ProjectExplorer::Project *project);
282     void onSourceFilesRefreshed() const;
283     void onCurrentEditorChanged(Core::IEditor *editor);
284     void onCoreAboutToClose();
285     void setupFallbackProjectPart();
286 
287     void initializeBuiltinModelManagerSupport();
288     void delayedGC();
289     void recalculateProjectPartMappings();
290     void watchForCanceledProjectIndexer(const QFuture<void> &future,
291                                         ProjectExplorer::Project *project);
292 
293     void replaceSnapshot(const CPlusPlus::Snapshot &newSnapshot);
294     void removeFilesFromSnapshot(const QSet<QString> &removedFiles);
295     void removeProjectInfoFilesAndIncludesFromSnapshot(const ProjectInfo &projectInfo);
296 
297     WorkingCopy buildWorkingCopyList();
298 
299     void ensureUpdated();
300     QStringList internalProjectFiles() const;
301     ProjectExplorer::HeaderPaths internalHeaderPaths() const;
302     ProjectExplorer::Macros internalDefinedMacros() const;
303 
304     void dumpModelManagerConfiguration(const QString &logFileId);
305     void initCppTools();
306 
307 private:
308     Internal::CppModelManagerPrivate *d;
309 };
310 
311 } // namespace CppTools
312