2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** 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
|
2016-01-15 14:57:40 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** GNU General Public License Usage
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2010-12-17 16:01:08 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2008-12-02 15:08:31 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "cppmodelmanager.h"
|
2013-03-27 18:54:03 +01:00
|
|
|
|
2013-07-11 11:13:07 +02:00
|
|
|
#include "abstracteditorsupport.h"
|
2018-02-02 13:01:07 +01:00
|
|
|
#include "abstractoverviewmodel.h"
|
2015-03-05 08:22:48 +01:00
|
|
|
#include "baseeditordocumentprocessor.h"
|
2013-03-12 12:06:41 +01:00
|
|
|
#include "builtinindexingsupport.h"
|
2017-09-29 14:41:09 +02:00
|
|
|
#include "cppclassesfilter.h"
|
2014-03-17 08:44:46 -03:00
|
|
|
#include "cppcodemodelinspectordumper.h"
|
2017-09-29 14:41:09 +02:00
|
|
|
#include "cppcurrentdocumentfilter.h"
|
2013-07-11 11:13:07 +02:00
|
|
|
#include "cppfindreferences.h"
|
2017-09-29 14:41:09 +02:00
|
|
|
#include "cppfunctionsfilter.h"
|
|
|
|
#include "cppincludesfilter.h"
|
2012-10-16 16:02:40 +02:00
|
|
|
#include "cppindexingsupport.h"
|
2017-09-29 14:41:09 +02:00
|
|
|
#include "cpplocatordata.h"
|
|
|
|
#include "cpplocatorfilter.h"
|
2018-10-18 09:21:35 +02:00
|
|
|
#include "cppbuiltinmodelmanagersupport.h"
|
2014-09-24 13:42:17 +02:00
|
|
|
#include "cpprefactoringchanges.h"
|
2017-09-18 11:29:55 +02:00
|
|
|
#include "cpprefactoringengine.h"
|
2014-05-16 15:51:04 -04:00
|
|
|
#include "cppsourceprocessor.h"
|
2021-01-15 16:55:26 +01:00
|
|
|
#include "cpptoolsjsextension.h"
|
2013-09-06 13:14:15 +02:00
|
|
|
#include "cpptoolsplugin.h"
|
2018-02-07 13:18:48 +01:00
|
|
|
#include "cpptoolsconstants.h"
|
2015-05-12 14:20:32 +02:00
|
|
|
#include "cpptoolsreuse.h"
|
2014-08-19 15:59:29 +02:00
|
|
|
#include "editordocumenthandle.h"
|
2018-02-07 13:18:48 +01:00
|
|
|
#include "stringtable.h"
|
2015-10-09 17:42:56 +02:00
|
|
|
#include "symbolfinder.h"
|
2017-09-29 14:41:09 +02:00
|
|
|
#include "symbolsfindfilter.h"
|
2017-08-03 16:43:38 +02:00
|
|
|
#include "followsymbolinterface.h"
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2014-09-24 13:42:17 +02:00
|
|
|
#include <coreplugin/documentmanager.h>
|
2019-08-13 15:42:03 +02:00
|
|
|
#include <coreplugin/editormanager/editormanager.h>
|
2013-03-27 18:54:03 +01:00
|
|
|
#include <coreplugin/icore.h>
|
2021-01-15 16:55:26 +01:00
|
|
|
#include <coreplugin/jsexpander.h>
|
2013-03-27 18:54:03 +01:00
|
|
|
#include <coreplugin/progressmanager/progressmanager.h>
|
2019-08-13 15:42:03 +02:00
|
|
|
#include <coreplugin/vcsmanager.h>
|
2020-08-25 14:32:56 +02:00
|
|
|
#include <cplusplus/ASTPath.h>
|
|
|
|
#include <cplusplus/TypeOfExpression.h>
|
2019-08-13 15:42:03 +02:00
|
|
|
#include <extensionsystem/pluginmanager.h>
|
2021-05-06 12:56:21 +02:00
|
|
|
#include <projectexplorer/kitinformation.h>
|
|
|
|
#include <projectexplorer/kitmanager.h>
|
2015-03-05 08:22:48 +01:00
|
|
|
#include <projectexplorer/project.h>
|
2012-09-07 10:51:50 +02:00
|
|
|
#include <projectexplorer/projectexplorer.h>
|
2017-02-07 15:00:38 +01:00
|
|
|
#include <projectexplorer/projectmacro.h>
|
2012-09-07 10:51:50 +02:00
|
|
|
#include <projectexplorer/session.h>
|
2019-08-13 15:42:03 +02:00
|
|
|
#include <texteditor/textdocument.h>
|
2014-11-27 12:40:34 +01:00
|
|
|
#include <utils/fileutils.h>
|
2019-06-19 12:46:17 +02:00
|
|
|
#include <utils/hostosinfo.h>
|
2008-12-09 15:25:01 +01:00
|
|
|
#include <utils/qtcassert.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QCoreApplication>
|
|
|
|
#include <QDebug>
|
2015-03-05 08:22:48 +01:00
|
|
|
#include <QDir>
|
2016-04-25 13:17:20 +02:00
|
|
|
#include <QFutureWatcher>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QMutexLocker>
|
|
|
|
#include <QTextBlock>
|
2016-02-17 23:27:41 +02:00
|
|
|
#include <QThreadPool>
|
2013-07-11 11:13:07 +02:00
|
|
|
#include <QTimer>
|
2010-04-26 14:02:09 +02:00
|
|
|
|
2013-04-23 15:04:36 +02:00
|
|
|
#if defined(QTCREATOR_WITH_DUMP_AST) && defined(Q_CC_GNU)
|
|
|
|
#define WITH_AST_DUMP
|
2009-02-18 16:01:28 +01:00
|
|
|
#include <iostream>
|
|
|
|
#include <sstream>
|
2013-04-23 15:04:36 +02:00
|
|
|
#endif
|
2008-12-09 15:25:01 +01:00
|
|
|
|
2014-03-06 14:42:01 -03:00
|
|
|
static const bool DumpProjectInfo = qgetenv("QTC_DUMP_PROJECT_INFO") == "1";
|
|
|
|
|
2008-12-08 11:08:48 +01:00
|
|
|
using namespace CppTools;
|
|
|
|
using namespace CppTools::Internal;
|
2008-12-02 12:01:29 +01:00
|
|
|
using namespace CPlusPlus;
|
2021-05-06 12:56:21 +02:00
|
|
|
using namespace ProjectExplorer;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-07-11 11:13:07 +02:00
|
|
|
#ifdef QTCREATOR_WITH_DUMP_AST
|
2009-02-18 16:01:28 +01:00
|
|
|
|
|
|
|
#include <cxxabi.h>
|
|
|
|
|
|
|
|
class DumpAST: protected ASTVisitor
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
int depth;
|
|
|
|
|
2019-01-14 01:40:53 +01:00
|
|
|
explicit DumpAST(Control *control)
|
2009-02-18 16:01:28 +01:00
|
|
|
: ASTVisitor(control), depth(0)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
void operator()(AST *ast)
|
|
|
|
{ accept(ast); }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual bool preVisit(AST *ast)
|
|
|
|
{
|
|
|
|
std::ostringstream s;
|
|
|
|
PrettyPrinter pp(control(), s);
|
|
|
|
pp(ast);
|
|
|
|
QString code = QString::fromStdString(s.str());
|
|
|
|
code.replace('\n', ' ');
|
2020-07-13 12:05:22 +02:00
|
|
|
code.replace(QRegularExpression("\\s+"), " ");
|
2009-02-18 16:01:28 +01:00
|
|
|
|
|
|
|
const char *name = abi::__cxa_demangle(typeid(*ast).name(), 0, 0, 0) + 11;
|
|
|
|
|
|
|
|
QByteArray ind(depth, ' ');
|
|
|
|
ind += name;
|
|
|
|
|
|
|
|
printf("%-40s %s\n", ind.constData(), qPrintable(code));
|
|
|
|
++depth;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void postVisit(AST *)
|
|
|
|
{ --depth; }
|
|
|
|
};
|
|
|
|
|
2009-03-05 09:46:54 +01:00
|
|
|
#endif // QTCREATOR_WITH_DUMP_AST
|
2009-02-18 16:01:28 +01:00
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
namespace CppTools {
|
2017-09-25 16:41:17 +02:00
|
|
|
|
|
|
|
using REType = RefactoringEngineType;
|
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
namespace Internal {
|
|
|
|
|
|
|
|
static CppModelManager *m_instance;
|
|
|
|
|
2021-08-19 12:30:11 +02:00
|
|
|
class ProjectData
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ProjectInfo::Ptr projectInfo;
|
|
|
|
QFutureWatcher<void> *indexer = nullptr;
|
|
|
|
bool fullyIndexed = false;
|
|
|
|
};
|
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
class CppModelManagerPrivate
|
|
|
|
{
|
|
|
|
public:
|
2021-08-19 12:30:11 +02:00
|
|
|
void setupWatcher(const QFuture<void> &future, ProjectExplorer::Project *project,
|
|
|
|
ProjectData *projectData, CppModelManager *q);
|
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
// Snapshot
|
|
|
|
mutable QMutex m_snapshotMutex;
|
2015-02-04 17:01:07 +02:00
|
|
|
Snapshot m_snapshot;
|
2014-09-15 00:12:27 +02:00
|
|
|
|
|
|
|
// Project integration
|
|
|
|
mutable QMutex m_projectMutex;
|
2021-08-19 12:30:11 +02:00
|
|
|
QHash<ProjectExplorer::Project *, ProjectData> m_projectData;
|
2019-05-28 13:49:26 +02:00
|
|
|
QMap<Utils::FilePath, QList<ProjectPart::Ptr> > m_fileToProjectParts;
|
2015-07-14 17:30:17 +02:00
|
|
|
QMap<QString, ProjectPart::Ptr> m_projectPartIdToProjectProjectPart;
|
2014-09-15 00:12:27 +02:00
|
|
|
// The members below are cached/(re)calculated from the projects and/or their project parts
|
|
|
|
bool m_dirty;
|
|
|
|
QStringList m_projectFiles;
|
2018-09-03 16:10:43 +02:00
|
|
|
ProjectExplorer::HeaderPaths m_headerPaths;
|
2017-02-07 15:00:38 +01:00
|
|
|
ProjectExplorer::Macros m_definedMacros;
|
2014-09-15 00:12:27 +02:00
|
|
|
|
|
|
|
// Editor integration
|
2014-11-24 11:19:41 +01:00
|
|
|
mutable QMutex m_cppEditorDocumentsMutex;
|
|
|
|
QMap<QString, CppEditorDocumentHandle *> m_cppEditorDocuments;
|
2014-09-15 00:12:27 +02:00
|
|
|
QSet<AbstractEditorSupport *> m_extraEditorSupports;
|
|
|
|
|
2015-11-11 10:47:27 +01:00
|
|
|
// Model Manager Supports for e.g. completion and highlighting
|
|
|
|
ModelManagerSupport::Ptr m_builtinModelManagerSupport;
|
|
|
|
ModelManagerSupport::Ptr m_activeModelManagerSupport;
|
2014-09-15 00:12:27 +02:00
|
|
|
|
|
|
|
// Indexing
|
|
|
|
CppIndexingSupport *m_internalIndexingSupport;
|
|
|
|
bool m_indexerEnabled;
|
|
|
|
|
2021-07-16 16:35:11 +02:00
|
|
|
QMutex m_fallbackProjectPartMutex;
|
|
|
|
ProjectPart::Ptr m_fallbackProjectPart;
|
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
CppFindReferences *m_findReferences;
|
|
|
|
|
2015-10-09 17:42:56 +02:00
|
|
|
SymbolFinder m_symbolFinder;
|
2016-02-17 23:27:41 +02:00
|
|
|
QThreadPool m_threadPool;
|
2015-10-09 17:42:56 +02:00
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
bool m_enableGC;
|
|
|
|
QTimer m_delayedGcTimer;
|
2016-08-04 15:26:53 +02:00
|
|
|
|
|
|
|
// Refactoring
|
2017-09-25 16:41:17 +02:00
|
|
|
using REHash = QMap<REType, RefactoringEngineInterface *>;
|
2017-09-26 16:00:30 +02:00
|
|
|
REHash m_refactoringEngines;
|
2017-09-29 14:41:09 +02:00
|
|
|
|
|
|
|
CppLocatorData m_locatorData;
|
|
|
|
std::unique_ptr<Core::ILocatorFilter> m_locatorFilter;
|
|
|
|
std::unique_ptr<Core::ILocatorFilter> m_classesFilter;
|
|
|
|
std::unique_ptr<Core::ILocatorFilter> m_includesFilter;
|
|
|
|
std::unique_ptr<Core::ILocatorFilter> m_functionsFilter;
|
|
|
|
std::unique_ptr<Core::IFindFilter> m_symbolsFindFilter;
|
|
|
|
std::unique_ptr<Core::ILocatorFilter> m_currentDocumentFilter;
|
2014-09-15 00:12:27 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace Internal
|
|
|
|
|
|
|
|
const char pp_configuration[] =
|
2008-12-02 12:01:29 +01:00
|
|
|
"# 1 \"<configuration>\"\n"
|
2013-05-27 11:37:50 +02:00
|
|
|
"#define Q_CREATOR_RUN 1\n"
|
2008-12-02 12:01:29 +01:00
|
|
|
"#define __cplusplus 1\n"
|
|
|
|
"#define __extension__\n"
|
|
|
|
"#define __context__\n"
|
|
|
|
"#define __range__\n"
|
|
|
|
"#define restrict\n"
|
|
|
|
"#define __restrict\n"
|
2009-07-17 10:54:08 +02:00
|
|
|
"#define __restrict__\n"
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2009-02-23 09:53:26 +01:00
|
|
|
"#define __complex__\n"
|
|
|
|
"#define __imag__\n"
|
|
|
|
"#define __real__\n"
|
|
|
|
|
2009-06-18 17:48:55 +02:00
|
|
|
"#define __builtin_va_arg(a,b) ((b)0)\n"
|
|
|
|
|
2015-02-27 14:43:25 +01:00
|
|
|
"#define _Pragma(x)\n" // C99 _Pragma operator
|
|
|
|
|
2015-12-02 10:17:08 +01:00
|
|
|
"#define __func__ \"\"\n"
|
|
|
|
|
|
|
|
// ### add macros for gcc
|
|
|
|
"#define __PRETTY_FUNCTION__ \"\"\n"
|
|
|
|
"#define __FUNCTION__ \"\"\n"
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
// ### add macros for win32
|
|
|
|
"#define __cdecl\n"
|
2009-12-10 16:20:34 +01:00
|
|
|
"#define __stdcall\n"
|
2014-06-11 08:05:08 +03:00
|
|
|
"#define __thiscall\n"
|
2008-12-02 12:01:29 +01:00
|
|
|
"#define QT_WA(x) x\n"
|
|
|
|
"#define CALLBACK\n"
|
|
|
|
"#define STDMETHODCALLTYPE\n"
|
|
|
|
"#define __RPC_FAR\n"
|
|
|
|
"#define __declspec(a)\n"
|
2011-09-06 16:45:47 +02:00
|
|
|
"#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method\n"
|
|
|
|
"#define __try try\n"
|
|
|
|
"#define __except catch\n"
|
2011-09-08 11:30:48 +02:00
|
|
|
"#define __finally\n"
|
|
|
|
"#define __inline inline\n"
|
2015-02-27 14:43:25 +01:00
|
|
|
"#define __forceinline inline\n"
|
2017-03-15 12:10:02 +01:00
|
|
|
"#define __pragma(x)\n"
|
|
|
|
"#define __w64\n"
|
|
|
|
"#define __int64 long long\n"
|
|
|
|
"#define __int32 long\n"
|
|
|
|
"#define __int16 short\n"
|
|
|
|
"#define __int8 char\n"
|
|
|
|
"#define __ptr32\n"
|
|
|
|
"#define __ptr64\n";
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2014-09-04 14:59:50 +02:00
|
|
|
QSet<QString> CppModelManager::timeStampModifiedFiles(const QList<Document::Ptr> &documentsToCheck)
|
2009-11-05 12:34:02 +01:00
|
|
|
{
|
2014-09-04 14:59:50 +02:00
|
|
|
QSet<QString> sourceFiles;
|
2009-11-05 12:34:02 +01:00
|
|
|
|
2013-07-10 14:46:08 +02:00
|
|
|
foreach (const Document::Ptr doc, documentsToCheck) {
|
2009-11-05 12:34:02 +01:00
|
|
|
const QDateTime lastModified = doc->lastModified();
|
|
|
|
|
2013-07-24 11:59:39 +02:00
|
|
|
if (!lastModified.isNull()) {
|
2009-11-05 12:34:02 +01:00
|
|
|
QFileInfo fileInfo(doc->fileName());
|
|
|
|
|
|
|
|
if (fileInfo.exists() && fileInfo.lastModified() != lastModified)
|
2014-09-04 14:59:50 +02:00
|
|
|
sourceFiles.insert(doc->fileName());
|
2009-11-05 12:34:02 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-10 14:46:08 +02:00
|
|
|
return sourceFiles;
|
|
|
|
}
|
|
|
|
|
2014-06-06 14:41:19 +02:00
|
|
|
/*!
|
|
|
|
* \brief createSourceProcessor Create a new source processor, which will signal the
|
|
|
|
* model manager when a document has been processed.
|
|
|
|
*
|
|
|
|
* Indexed file is truncated version of fully parsed document: copy of source
|
|
|
|
* code and full AST will be dropped when indexing is done.
|
|
|
|
*
|
|
|
|
* \return a new source processor object, which the caller needs to delete when finished.
|
|
|
|
*/
|
|
|
|
CppSourceProcessor *CppModelManager::createSourceProcessor()
|
|
|
|
{
|
|
|
|
CppModelManager *that = instance();
|
2014-06-25 09:29:33 +03:00
|
|
|
return new CppSourceProcessor(that->snapshot(), [that](const Document::Ptr &doc) {
|
2015-01-19 13:14:45 +01:00
|
|
|
const Document::Ptr previousDocument = that->document(doc->fileName());
|
|
|
|
const unsigned newRevision = previousDocument.isNull()
|
|
|
|
? 1U
|
|
|
|
: previousDocument->revision() + 1;
|
|
|
|
doc->setRevision(newRevision);
|
2014-06-06 14:41:19 +02:00
|
|
|
that->emitDocumentUpdated(doc);
|
|
|
|
doc->releaseSourceAndAST();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
QString CppModelManager::editorConfigurationFileName()
|
|
|
|
{
|
|
|
|
return QLatin1String("<per-editor-defines>");
|
|
|
|
}
|
|
|
|
|
2021-05-19 11:22:50 +02:00
|
|
|
static RefactoringEngineInterface *getRefactoringEngine(CppModelManagerPrivate::REHash &engines)
|
2017-09-25 16:41:17 +02:00
|
|
|
{
|
2017-09-26 16:00:30 +02:00
|
|
|
QTC_ASSERT(!engines.empty(), return nullptr;);
|
2017-09-25 16:41:17 +02:00
|
|
|
RefactoringEngineInterface *currentEngine = engines[REType::BuiltIn];
|
2021-05-19 11:22:50 +02:00
|
|
|
if (engines.find(REType::ClangCodeModel) != engines.end()) {
|
2017-09-25 16:41:17 +02:00
|
|
|
currentEngine = engines[REType::ClangCodeModel];
|
|
|
|
} else if (engines.find(REType::ClangRefactoring) != engines.end()) {
|
|
|
|
RefactoringEngineInterface *engine = engines[REType::ClangRefactoring];
|
|
|
|
if (engine->isRefactoringEngineAvailable())
|
|
|
|
currentEngine = engine;
|
|
|
|
}
|
|
|
|
return currentEngine;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CppModelManager::startLocalRenaming(const CursorInEditor &data,
|
|
|
|
CppTools::ProjectPart *projectPart,
|
|
|
|
RenameCallback &&renameSymbolsCallback)
|
|
|
|
{
|
2021-05-19 11:22:50 +02:00
|
|
|
RefactoringEngineInterface *engine = getRefactoringEngine(d->m_refactoringEngines);
|
2017-09-26 16:00:30 +02:00
|
|
|
QTC_ASSERT(engine, return;);
|
2017-09-25 16:41:17 +02:00
|
|
|
engine->startLocalRenaming(data, projectPart, std::move(renameSymbolsCallback));
|
|
|
|
}
|
|
|
|
|
2017-09-25 10:51:39 +02:00
|
|
|
void CppModelManager::globalRename(const CursorInEditor &data, UsagesCallback &&renameCallback,
|
|
|
|
const QString &replacement)
|
2017-09-25 16:41:17 +02:00
|
|
|
{
|
2021-05-19 11:22:50 +02:00
|
|
|
RefactoringEngineInterface *engine = getRefactoringEngine(d->m_refactoringEngines);
|
2017-09-26 16:00:30 +02:00
|
|
|
QTC_ASSERT(engine, return;);
|
2017-09-25 10:51:39 +02:00
|
|
|
engine->globalRename(data, std::move(renameCallback), replacement);
|
2017-09-25 16:41:17 +02:00
|
|
|
}
|
2017-09-26 16:00:30 +02:00
|
|
|
|
2017-09-19 15:38:20 +02:00
|
|
|
void CppModelManager::findUsages(const CppTools::CursorInEditor &data,
|
|
|
|
UsagesCallback &&showUsagesCallback) const
|
|
|
|
{
|
2021-05-19 11:22:50 +02:00
|
|
|
RefactoringEngineInterface *engine = getRefactoringEngine(d->m_refactoringEngines);
|
2017-09-26 16:00:30 +02:00
|
|
|
QTC_ASSERT(engine, return;);
|
2017-09-19 15:38:20 +02:00
|
|
|
engine->findUsages(data, std::move(showUsagesCallback));
|
|
|
|
}
|
|
|
|
|
2018-02-21 11:58:16 +01:00
|
|
|
void CppModelManager::globalFollowSymbol(
|
2017-10-05 09:54:21 +02:00
|
|
|
const CursorInEditor &data,
|
2018-02-21 11:58:16 +01:00
|
|
|
Utils::ProcessLinkCallback &&processLinkCallback,
|
2017-10-05 09:54:21 +02:00
|
|
|
const CPlusPlus::Snapshot &snapshot,
|
|
|
|
const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
|
|
|
|
SymbolFinder *symbolFinder,
|
|
|
|
bool inNextSplit) const
|
|
|
|
{
|
2021-05-19 11:22:50 +02:00
|
|
|
RefactoringEngineInterface *engine = getRefactoringEngine(d->m_refactoringEngines);
|
2018-02-21 11:58:16 +01:00
|
|
|
QTC_ASSERT(engine, return;);
|
|
|
|
engine->globalFollowSymbol(data, std::move(processLinkCallback), snapshot, documentFromSemanticInfo,
|
|
|
|
symbolFinder, inNextSplit);
|
2017-10-05 09:54:21 +02:00
|
|
|
}
|
|
|
|
|
2020-08-25 14:32:56 +02:00
|
|
|
bool CppModelManager::positionRequiresSignal(const QString &filePath, const QByteArray &content,
|
|
|
|
int position) const
|
|
|
|
{
|
|
|
|
if (content.isEmpty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Insert a dummy prefix if we don't have a real one. Otherwise the AST path will not contain
|
|
|
|
// anything after the CallAST.
|
|
|
|
QByteArray fixedContent = content;
|
|
|
|
if (position > 2 && content.mid(position - 2, 2) == "::")
|
|
|
|
fixedContent.insert(position, 'x');
|
|
|
|
|
|
|
|
const Snapshot snapshot = this->snapshot();
|
2021-08-10 16:19:02 +02:00
|
|
|
const Document::Ptr document = snapshot.preprocessedDocument(fixedContent,
|
|
|
|
Utils::FilePath::fromString(filePath));
|
2020-08-25 14:32:56 +02:00
|
|
|
document->check();
|
|
|
|
QTextDocument textDocument(QString::fromUtf8(fixedContent));
|
|
|
|
QTextCursor cursor(&textDocument);
|
|
|
|
cursor.setPosition(position);
|
|
|
|
|
|
|
|
// Are we at the second argument of a function call?
|
|
|
|
const QList<AST *> path = ASTPath(document)(cursor);
|
|
|
|
if (path.isEmpty() || !path.last()->asSimpleName())
|
|
|
|
return false;
|
|
|
|
const CallAST *callAst = nullptr;
|
|
|
|
for (auto it = path.crbegin(); it != path.crend(); ++it) {
|
|
|
|
if ((callAst = (*it)->asCall()))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!callAst)
|
|
|
|
return false;
|
|
|
|
if (!callAst->expression_list || !callAst->expression_list->next)
|
|
|
|
return false;
|
|
|
|
const ExpressionAST * const secondArg = callAst->expression_list->next->value;
|
|
|
|
if (secondArg->firstToken() > path.last()->firstToken()
|
|
|
|
|| secondArg->lastToken() < path.last()->lastToken()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Is the function called "connect" or "disconnect"?
|
|
|
|
if (!callAst->base_expression)
|
|
|
|
return false;
|
|
|
|
Scope *scope = document->globalNamespace();
|
|
|
|
for (auto it = path.crbegin(); it != path.crend(); ++it) {
|
|
|
|
if (const CompoundStatementAST * const stmtAst = (*it)->asCompoundStatement()) {
|
|
|
|
scope = stmtAst->symbol;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const NameAST *nameAst = nullptr;
|
|
|
|
const LookupContext context(document, snapshot);
|
|
|
|
if (const IdExpressionAST * const idAst = callAst->base_expression->asIdExpression()) {
|
|
|
|
nameAst = idAst->name;
|
|
|
|
} else if (const MemberAccessAST * const ast = callAst->base_expression->asMemberAccess()) {
|
|
|
|
nameAst = ast->member_name;
|
|
|
|
TypeOfExpression exprType;
|
|
|
|
exprType.setExpandTemplates(true);
|
|
|
|
exprType.init(document, snapshot);
|
|
|
|
const QList<LookupItem> typeMatches = exprType(ast->base_expression, document, scope);
|
|
|
|
if (typeMatches.isEmpty())
|
|
|
|
return false;
|
|
|
|
const std::function<const NamedType *(const FullySpecifiedType &)> getNamedType
|
|
|
|
= [&getNamedType](const FullySpecifiedType &type ) -> const NamedType * {
|
|
|
|
Type * const t = type.type();
|
|
|
|
if (const auto namedType = t->asNamedType())
|
|
|
|
return namedType;
|
|
|
|
if (const auto pointerType = t->asPointerType())
|
|
|
|
return getNamedType(pointerType->elementType());
|
|
|
|
if (const auto refType = t->asReferenceType())
|
|
|
|
return getNamedType(refType->elementType());
|
|
|
|
return nullptr;
|
|
|
|
};
|
|
|
|
const NamedType *namedType = getNamedType(typeMatches.first().type());
|
|
|
|
if (!namedType && typeMatches.first().declaration())
|
|
|
|
namedType = getNamedType(typeMatches.first().declaration()->type());
|
|
|
|
if (!namedType)
|
|
|
|
return false;
|
|
|
|
const ClassOrNamespace * const result = context.lookupType(namedType->name(), scope);
|
|
|
|
if (!result)
|
|
|
|
return false;
|
|
|
|
scope = result->rootClass();
|
|
|
|
if (!scope)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!nameAst || !nameAst->name)
|
|
|
|
return false;
|
|
|
|
const Identifier * const id = nameAst->name->identifier();
|
|
|
|
if (!id)
|
|
|
|
return false;
|
|
|
|
const QString funcName = QString::fromUtf8(id->chars(), id->size());
|
|
|
|
if (funcName != "connect" && funcName != "disconnect")
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Is the function a member function of QObject?
|
|
|
|
const QList<LookupItem> matches = context.lookup(nameAst->name, scope);
|
|
|
|
for (const LookupItem &match : matches) {
|
|
|
|
if (!match.scope())
|
|
|
|
continue;
|
|
|
|
const Class *klass = match.scope()->asClass();
|
|
|
|
if (!klass || !klass->name())
|
|
|
|
continue;
|
|
|
|
const Identifier * const classId = klass->name()->identifier();
|
|
|
|
if (classId && QString::fromUtf8(classId->chars(), classId->size()) == "QObject")
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-09-25 16:41:17 +02:00
|
|
|
void CppModelManager::addRefactoringEngine(RefactoringEngineType type,
|
|
|
|
RefactoringEngineInterface *refactoringEngine)
|
2016-08-04 15:26:53 +02:00
|
|
|
{
|
2017-09-25 16:41:17 +02:00
|
|
|
instance()->d->m_refactoringEngines[type] = refactoringEngine;
|
2016-08-04 15:26:53 +02:00
|
|
|
}
|
|
|
|
|
2017-09-25 16:41:17 +02:00
|
|
|
void CppModelManager::removeRefactoringEngine(RefactoringEngineType type)
|
2016-08-04 15:26:53 +02:00
|
|
|
{
|
2017-09-25 16:41:17 +02:00
|
|
|
instance()->d->m_refactoringEngines.remove(type);
|
2016-08-04 15:26:53 +02:00
|
|
|
}
|
|
|
|
|
2021-02-23 13:51:41 +01:00
|
|
|
RefactoringEngineInterface *CppModelManager::builtinRefactoringEngine()
|
|
|
|
{
|
|
|
|
return instance()->d->m_refactoringEngines.value(RefactoringEngineType::BuiltIn);
|
|
|
|
}
|
|
|
|
|
2021-05-31 15:57:44 +02:00
|
|
|
FollowSymbolInterface &CppModelManager::builtinFollowSymbol()
|
|
|
|
{
|
|
|
|
return instance()->d->m_builtinModelManagerSupport->followSymbolInterface();
|
|
|
|
}
|
|
|
|
|
2017-09-29 14:41:09 +02:00
|
|
|
template<class FilterClass>
|
|
|
|
static void setFilter(std::unique_ptr<FilterClass> &filter,
|
|
|
|
std::unique_ptr<FilterClass> &&newFilter)
|
|
|
|
{
|
2018-03-08 12:43:33 +01:00
|
|
|
QTC_ASSERT(newFilter, return;);
|
2017-09-29 14:41:09 +02:00
|
|
|
filter = std::move(newFilter);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CppModelManager::setLocatorFilter(std::unique_ptr<Core::ILocatorFilter> &&filter)
|
|
|
|
{
|
|
|
|
setFilter(d->m_locatorFilter, std::move(filter));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CppModelManager::setClassesFilter(std::unique_ptr<Core::ILocatorFilter> &&filter)
|
|
|
|
{
|
|
|
|
setFilter(d->m_classesFilter, std::move(filter));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CppModelManager::setIncludesFilter(std::unique_ptr<Core::ILocatorFilter> &&filter)
|
|
|
|
{
|
|
|
|
setFilter(d->m_includesFilter, std::move(filter));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CppModelManager::setFunctionsFilter(std::unique_ptr<Core::ILocatorFilter> &&filter)
|
|
|
|
{
|
|
|
|
setFilter(d->m_functionsFilter, std::move(filter));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CppModelManager::setSymbolsFindFilter(std::unique_ptr<Core::IFindFilter> &&filter)
|
|
|
|
{
|
|
|
|
setFilter(d->m_symbolsFindFilter, std::move(filter));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CppModelManager::setCurrentDocumentFilter(std::unique_ptr<Core::ILocatorFilter> &&filter)
|
|
|
|
{
|
|
|
|
setFilter(d->m_currentDocumentFilter, std::move(filter));
|
|
|
|
}
|
|
|
|
|
2018-06-27 12:58:35 +02:00
|
|
|
Core::ILocatorFilter *CppModelManager::locatorFilter() const
|
|
|
|
{
|
|
|
|
return d->m_locatorFilter.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
Core::ILocatorFilter *CppModelManager::classesFilter() const
|
|
|
|
{
|
|
|
|
return d->m_classesFilter.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
Core::ILocatorFilter *CppModelManager::includesFilter() const
|
|
|
|
{
|
|
|
|
return d->m_includesFilter.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
Core::ILocatorFilter *CppModelManager::functionsFilter() const
|
|
|
|
{
|
|
|
|
return d->m_functionsFilter.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
Core::IFindFilter *CppModelManager::symbolsFindFilter() const
|
|
|
|
{
|
|
|
|
return d->m_symbolsFindFilter.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
Core::ILocatorFilter *CppModelManager::currentDocumentFilter() const
|
|
|
|
{
|
|
|
|
return d->m_currentDocumentFilter.get();
|
|
|
|
}
|
|
|
|
|
2017-09-18 10:19:27 +02:00
|
|
|
FollowSymbolInterface &CppModelManager::followSymbolInterface() const
|
2017-08-03 16:43:38 +02:00
|
|
|
{
|
|
|
|
return d->m_activeModelManagerSupport->followSymbolInterface();
|
|
|
|
}
|
|
|
|
|
2018-02-02 13:01:07 +01:00
|
|
|
std::unique_ptr<AbstractOverviewModel> CppModelManager::createOverviewModel() const
|
|
|
|
{
|
|
|
|
return d->m_activeModelManagerSupport->createOverviewModel();
|
|
|
|
}
|
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
QString CppModelManager::configurationFileName()
|
|
|
|
{
|
2015-10-09 13:33:27 +02:00
|
|
|
return Preprocessor::configurationFileName();
|
2014-09-15 00:12:27 +02:00
|
|
|
}
|
|
|
|
|
2013-07-10 14:46:08 +02:00
|
|
|
void CppModelManager::updateModifiedSourceFiles()
|
|
|
|
{
|
|
|
|
const Snapshot snapshot = this->snapshot();
|
|
|
|
QList<Document::Ptr> documentsToCheck;
|
|
|
|
foreach (const Document::Ptr document, snapshot)
|
|
|
|
documentsToCheck << document;
|
|
|
|
|
2014-09-04 14:59:50 +02:00
|
|
|
updateSourceFiles(timeStampModifiedFiles(documentsToCheck));
|
2009-11-05 12:34:02 +01:00
|
|
|
}
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
/*!
|
|
|
|
\class CppTools::CppModelManager
|
2013-07-11 11:13:07 +02:00
|
|
|
\brief The CppModelManager keeps tracks of the source files the code model is aware of.
|
|
|
|
|
|
|
|
The CppModelManager manages the source files in a Snapshot object.
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-07-11 11:13:07 +02:00
|
|
|
The snapshot is updated in case e.g.
|
|
|
|
* New files are opened/edited (Editor integration)
|
|
|
|
* A project manager pushes updated project information (Project integration)
|
|
|
|
* Files are garbage collected
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
|
|
|
|
2012-10-15 16:38:56 +02:00
|
|
|
CppModelManager *CppModelManager::instance()
|
|
|
|
{
|
2017-09-29 14:41:09 +02:00
|
|
|
QTC_ASSERT(m_instance, return nullptr;);
|
|
|
|
return m_instance;
|
|
|
|
}
|
2013-07-11 11:13:07 +02:00
|
|
|
|
2021-01-15 16:55:26 +01:00
|
|
|
void CppModelManager::registerJsExtension()
|
|
|
|
{
|
|
|
|
Core::JsExpander::registerGlobalObject("Cpp", [this] {
|
|
|
|
return new CppToolsJsExtension(&d->m_locatorData);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-02-07 13:18:48 +01:00
|
|
|
void CppModelManager::initCppTools()
|
2017-09-29 14:41:09 +02:00
|
|
|
{
|
|
|
|
// Objects
|
|
|
|
connect(Core::VcsManager::instance(), &Core::VcsManager::repositoryChanged,
|
|
|
|
this, &CppModelManager::updateModifiedSourceFiles);
|
|
|
|
connect(Core::DocumentManager::instance(), &Core::DocumentManager::filesChangedInternally,
|
2021-06-22 08:57:36 +02:00
|
|
|
[this](const Utils::FilePaths &filePaths) {
|
|
|
|
updateSourceFiles(Utils::transform<QSet>(filePaths, &Utils::FilePath::toString));
|
2017-09-29 14:41:09 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
connect(this, &CppModelManager::documentUpdated,
|
|
|
|
&d->m_locatorData, &CppLocatorData::onDocumentUpdated);
|
|
|
|
|
|
|
|
connect(this, &CppModelManager::aboutToRemoveFiles,
|
|
|
|
&d->m_locatorData, &CppLocatorData::onAboutToRemoveFiles);
|
|
|
|
|
|
|
|
// Set up builtin filters
|
|
|
|
setLocatorFilter(std::make_unique<CppLocatorFilter>(&d->m_locatorData));
|
|
|
|
setClassesFilter(std::make_unique<CppClassesFilter>(&d->m_locatorData));
|
|
|
|
setIncludesFilter(std::make_unique<CppIncludesFilter>());
|
|
|
|
setFunctionsFilter(std::make_unique<CppFunctionsFilter>(&d->m_locatorData));
|
|
|
|
setSymbolsFindFilter(std::make_unique<SymbolsFindFilter>(this));
|
|
|
|
setCurrentDocumentFilter(
|
2018-02-07 13:18:48 +01:00
|
|
|
std::make_unique<Internal::CppCurrentDocumentFilter>(this));
|
2012-10-15 16:38:56 +02:00
|
|
|
}
|
|
|
|
|
2015-12-15 18:09:45 +01:00
|
|
|
void CppModelManager::initializeBuiltinModelManagerSupport()
|
2015-11-11 10:47:27 +01:00
|
|
|
{
|
|
|
|
d->m_builtinModelManagerSupport
|
2018-10-18 09:21:35 +02:00
|
|
|
= BuiltinModelManagerSupportProvider().createModelManagerSupport();
|
2015-11-11 10:47:27 +01:00
|
|
|
d->m_activeModelManagerSupport = d->m_builtinModelManagerSupport;
|
2017-09-26 16:00:30 +02:00
|
|
|
d->m_refactoringEngines[RefactoringEngineType::BuiltIn] =
|
|
|
|
&d->m_activeModelManagerSupport->refactoringEngineInterface();
|
2015-11-11 10:47:27 +01:00
|
|
|
}
|
|
|
|
|
2017-09-29 14:41:09 +02:00
|
|
|
CppModelManager::CppModelManager()
|
2018-08-29 15:58:13 +02:00
|
|
|
: CppModelManagerBase(nullptr)
|
|
|
|
, d(new CppModelManagerPrivate)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2020-02-04 17:23:27 +01:00
|
|
|
m_instance = this;
|
|
|
|
|
2019-08-13 15:42:03 +02:00
|
|
|
// Used for weak dependency in VcsBaseSubmitEditor
|
|
|
|
setObjectName("CppModelManager");
|
|
|
|
ExtensionSystem::PluginManager::addObject(this);
|
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_enableGC = true;
|
|
|
|
|
2019-06-19 12:46:17 +02:00
|
|
|
// Visual C++ has 1MiB, macOSX has 512KiB
|
|
|
|
if (Utils::HostOsInfo::isWindowsHost() || Utils::HostOsInfo::isMacHost())
|
|
|
|
d->m_threadPool.setStackSize(2 * 1024 * 1024);
|
|
|
|
|
2014-09-05 08:46:38 +02:00
|
|
|
qRegisterMetaType<QSet<QString> >();
|
2016-03-12 22:53:45 +02:00
|
|
|
connect(this, &CppModelManager::sourceFilesRefreshed,
|
|
|
|
this, &CppModelManager::onSourceFilesRefreshed);
|
2013-10-10 10:26:39 +02:00
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_findReferences = new CppFindReferences(this);
|
|
|
|
d->m_indexerEnabled = qgetenv("QTC_NO_CODE_INDEXER") != "1";
|
2009-03-11 12:00:07 +01:00
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_dirty = true;
|
2008-12-04 17:07:43 +01:00
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_delayedGcTimer.setObjectName(QLatin1String("CppModelManager::m_delayedGcTimer"));
|
|
|
|
d->m_delayedGcTimer.setSingleShot(true);
|
2016-03-12 22:53:45 +02:00
|
|
|
connect(&d->m_delayedGcTimer, &QTimer::timeout, this, &CppModelManager::GC);
|
2013-07-18 10:57:19 +02:00
|
|
|
|
2016-03-12 22:53:45 +02:00
|
|
|
auto sessionManager = ProjectExplorer::SessionManager::instance();
|
|
|
|
connect(sessionManager, &ProjectExplorer::SessionManager::projectAdded,
|
|
|
|
this, &CppModelManager::onProjectAdded);
|
|
|
|
connect(sessionManager, &ProjectExplorer::SessionManager::aboutToRemoveProject,
|
|
|
|
this, &CppModelManager::onAboutToRemoveProject);
|
|
|
|
connect(sessionManager, &ProjectExplorer::SessionManager::aboutToLoadSession,
|
|
|
|
this, &CppModelManager::onAboutToLoadSession);
|
2016-12-15 11:21:44 +01:00
|
|
|
connect(sessionManager, &ProjectExplorer::SessionManager::startupProjectChanged,
|
|
|
|
this, &CppModelManager::onActiveProjectChanged);
|
2014-12-02 12:11:05 +01:00
|
|
|
|
|
|
|
connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged,
|
|
|
|
this, &CppModelManager::onCurrentEditorChanged);
|
|
|
|
|
2014-09-24 13:42:17 +02:00
|
|
|
connect(Core::DocumentManager::instance(), &Core::DocumentManager::allDocumentsRenamed,
|
|
|
|
this, &CppModelManager::renameIncludes);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-12 22:53:45 +02:00
|
|
|
connect(Core::ICore::instance(), &Core::ICore::coreAboutToClose,
|
|
|
|
this, &CppModelManager::onCoreAboutToClose);
|
2013-04-19 16:56:12 +02:00
|
|
|
|
2021-07-16 16:35:11 +02:00
|
|
|
connect(KitManager::instance(), &KitManager::kitsChanged, this,
|
|
|
|
&CppModelManager::setupFallbackProjectPart);
|
|
|
|
setupFallbackProjectPart();
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
qRegisterMetaType<CPlusPlus::Document::Ptr>("CPlusPlus::Document::Ptr");
|
2015-02-04 17:01:07 +02:00
|
|
|
qRegisterMetaType<QList<Document::DiagnosticMessage>>(
|
2014-09-15 11:13:36 +02:00
|
|
|
"QList<CPlusPlus::Document::DiagnosticMessage>");
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-12-15 18:09:45 +01:00
|
|
|
initializeBuiltinModelManagerSupport();
|
2013-09-04 18:15:08 +02:00
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_internalIndexingSupport = new BuiltinIndexingSupport;
|
2020-02-04 17:23:27 +01:00
|
|
|
|
|
|
|
initCppTools();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
CppModelManager::~CppModelManager()
|
2012-02-20 12:39:08 +01:00
|
|
|
{
|
2019-08-13 15:42:03 +02:00
|
|
|
ExtensionSystem::PluginManager::removeObject(this);
|
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
delete d->m_internalIndexingSupport;
|
2014-09-22 12:48:06 +02:00
|
|
|
delete d;
|
2012-02-20 12:39:08 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2008-12-12 10:07:58 +01:00
|
|
|
Snapshot CppModelManager::snapshot() const
|
2009-03-04 09:38:01 +01:00
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
QMutexLocker locker(&d->m_snapshotMutex);
|
|
|
|
return d->m_snapshot;
|
2009-03-04 09:38:01 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-02-19 12:48:42 +01:00
|
|
|
Document::Ptr CppModelManager::document(const QString &fileName) const
|
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
QMutexLocker locker(&d->m_snapshotMutex);
|
|
|
|
return d->m_snapshot.document(fileName);
|
2013-02-19 12:48:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Replace the document in the snapshot.
|
|
|
|
///
|
|
|
|
/// \returns true if successful, false if the new document is out-dated.
|
|
|
|
bool CppModelManager::replaceDocument(Document::Ptr newDoc)
|
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
QMutexLocker locker(&d->m_snapshotMutex);
|
2013-02-19 12:48:42 +01:00
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
Document::Ptr previous = d->m_snapshot.document(newDoc->fileName());
|
2013-02-19 12:48:42 +01:00
|
|
|
if (previous && (newDoc->revision() != 0 && newDoc->revision() < previous->revision()))
|
|
|
|
// the new document is outdated
|
|
|
|
return false;
|
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_snapshot.insert(newDoc);
|
2013-02-19 12:48:42 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-11-06 16:50:02 +01:00
|
|
|
/// Make sure that m_projectMutex is locked when calling this.
|
2008-12-08 10:44:56 +01:00
|
|
|
void CppModelManager::ensureUpdated()
|
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
if (!d->m_dirty)
|
2008-12-08 10:44:56 +01:00
|
|
|
return;
|
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_projectFiles = internalProjectFiles();
|
|
|
|
d->m_headerPaths = internalHeaderPaths();
|
|
|
|
d->m_definedMacros = internalDefinedMacros();
|
|
|
|
d->m_dirty = false;
|
2008-12-08 10:44:56 +01:00
|
|
|
}
|
|
|
|
|
2008-12-08 14:48:51 +01:00
|
|
|
QStringList CppModelManager::internalProjectFiles() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
QStringList files;
|
2021-08-19 12:30:11 +02:00
|
|
|
for (const ProjectData &projectData : qAsConst(d->m_projectData)) {
|
|
|
|
for (const ProjectPart::Ptr &part : projectData.projectInfo->projectParts()) {
|
|
|
|
for (const ProjectFile &file : part->files)
|
2013-03-04 01:30:46 +04:00
|
|
|
files += file.path;
|
2012-11-23 16:29:00 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2008-12-08 14:48:51 +01:00
|
|
|
files.removeDuplicates();
|
2008-12-02 12:01:29 +01:00
|
|
|
return files;
|
|
|
|
}
|
|
|
|
|
2018-09-03 16:10:43 +02:00
|
|
|
ProjectExplorer::HeaderPaths CppModelManager::internalHeaderPaths() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2018-09-03 16:10:43 +02:00
|
|
|
ProjectExplorer::HeaderPaths headerPaths;
|
2021-08-19 12:30:11 +02:00
|
|
|
for (const ProjectData &projectData: qAsConst(d->m_projectData)) {
|
|
|
|
for (const ProjectPart::Ptr &part : projectData.projectInfo->projectParts()) {
|
|
|
|
for (const ProjectExplorer::HeaderPath &path : part->headerPaths) {
|
2018-09-03 16:10:43 +02:00
|
|
|
ProjectExplorer::HeaderPath hp(QDir::cleanPath(path.path), path.type);
|
2014-06-25 17:23:19 +02:00
|
|
|
if (!headerPaths.contains(hp))
|
2018-09-03 16:10:43 +02:00
|
|
|
headerPaths.push_back(std::move(hp));
|
2014-06-25 17:23:19 +02:00
|
|
|
}
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2014-06-25 17:23:19 +02:00
|
|
|
return headerPaths;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:00:38 +01:00
|
|
|
static void addUnique(const ProjectExplorer::Macros &newMacros,
|
|
|
|
ProjectExplorer::Macros ¯os,
|
|
|
|
QSet<ProjectExplorer::Macro> &alreadyIn)
|
2013-11-27 15:17:51 +01:00
|
|
|
{
|
2017-02-07 15:00:38 +01:00
|
|
|
for (const ProjectExplorer::Macro ¯o : newMacros) {
|
|
|
|
if (!alreadyIn.contains(macro)) {
|
|
|
|
macros += macro;
|
|
|
|
alreadyIn.insert(macro);
|
2013-11-27 15:17:51 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-07 15:00:38 +01:00
|
|
|
ProjectExplorer::Macros CppModelManager::internalDefinedMacros() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2017-02-07 15:00:38 +01:00
|
|
|
ProjectExplorer::Macros macros;
|
|
|
|
QSet<ProjectExplorer::Macro> alreadyIn;
|
2021-08-19 12:30:11 +02:00
|
|
|
for (const ProjectData &projectData : qAsConst(d->m_projectData)) {
|
|
|
|
for (const ProjectPart::Ptr &part : projectData.projectInfo->projectParts()) {
|
2017-02-07 15:00:38 +01:00
|
|
|
addUnique(part->toolChainMacros, macros, alreadyIn);
|
|
|
|
addUnique(part->projectMacros, macros, alreadyIn);
|
2012-03-27 15:29:12 +02:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
return macros;
|
|
|
|
}
|
|
|
|
|
2014-03-17 08:44:46 -03:00
|
|
|
/// This function will acquire mutexes!
|
2014-03-17 09:45:07 -03:00
|
|
|
void CppModelManager::dumpModelManagerConfiguration(const QString &logFileId)
|
2012-11-06 10:48:16 +01:00
|
|
|
{
|
2014-03-17 08:44:46 -03:00
|
|
|
const Snapshot globalSnapshot = snapshot();
|
|
|
|
const QString globalSnapshotTitle
|
|
|
|
= QString::fromLatin1("Global/Indexing Snapshot (%1 Documents)").arg(globalSnapshot.size());
|
|
|
|
|
2014-03-17 09:45:07 -03:00
|
|
|
CppCodeModelInspector::Dumper dumper(globalSnapshot, logFileId);
|
2014-03-17 08:44:46 -03:00
|
|
|
dumper.dumpProjectInfos(projectInfos());
|
|
|
|
dumper.dumpSnapshot(globalSnapshot, globalSnapshotTitle, /*isGlobalSnapshot=*/ true);
|
|
|
|
dumper.dumpWorkingCopy(workingCopy());
|
2017-02-07 15:00:38 +01:00
|
|
|
dumper.dumpMergedEntities(headerPaths(),
|
|
|
|
ProjectExplorer:: Macro::toByteArray(definedMacros()));
|
2012-11-06 10:48:16 +01:00
|
|
|
}
|
|
|
|
|
2015-05-08 15:48:17 +02:00
|
|
|
QSet<AbstractEditorSupport *> CppModelManager::abstractEditorSupports() const
|
|
|
|
{
|
|
|
|
return d->m_extraEditorSupports;
|
|
|
|
}
|
|
|
|
|
2013-07-11 11:13:07 +02:00
|
|
|
void CppModelManager::addExtraEditorSupport(AbstractEditorSupport *editorSupport)
|
2009-05-12 13:45:24 +02:00
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_extraEditorSupports.insert(editorSupport);
|
2009-05-12 13:45:24 +02:00
|
|
|
}
|
|
|
|
|
2013-07-11 11:13:07 +02:00
|
|
|
void CppModelManager::removeExtraEditorSupport(AbstractEditorSupport *editorSupport)
|
2009-05-12 13:45:24 +02:00
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_extraEditorSupports.remove(editorSupport);
|
2009-05-12 13:45:24 +02:00
|
|
|
}
|
|
|
|
|
2014-11-24 11:19:41 +01:00
|
|
|
CppEditorDocumentHandle *CppModelManager::cppEditorDocument(const QString &filePath) const
|
2013-04-17 10:58:20 +02:00
|
|
|
{
|
2014-12-03 12:11:48 +01:00
|
|
|
if (filePath.isEmpty())
|
2019-01-14 01:40:53 +01:00
|
|
|
return nullptr;
|
2013-04-17 10:58:20 +02:00
|
|
|
|
2014-11-24 11:19:41 +01:00
|
|
|
QMutexLocker locker(&d->m_cppEditorDocumentsMutex);
|
|
|
|
return d->m_cppEditorDocuments.value(filePath, 0);
|
2013-04-17 10:58:20 +02:00
|
|
|
}
|
|
|
|
|
2014-11-24 11:19:41 +01:00
|
|
|
void CppModelManager::registerCppEditorDocument(CppEditorDocumentHandle *editorDocument)
|
2013-07-11 11:13:07 +02:00
|
|
|
{
|
2014-08-19 15:59:29 +02:00
|
|
|
QTC_ASSERT(editorDocument, return);
|
|
|
|
const QString filePath = editorDocument->filePath();
|
|
|
|
QTC_ASSERT(!filePath.isEmpty(), return);
|
2013-07-11 11:13:07 +02:00
|
|
|
|
2014-11-24 11:19:41 +01:00
|
|
|
QMutexLocker locker(&d->m_cppEditorDocumentsMutex);
|
|
|
|
QTC_ASSERT(d->m_cppEditorDocuments.value(filePath, 0) == 0, return);
|
|
|
|
d->m_cppEditorDocuments.insert(filePath, editorDocument);
|
2014-08-19 15:59:29 +02:00
|
|
|
}
|
2013-07-11 11:13:07 +02:00
|
|
|
|
2014-11-24 11:19:41 +01:00
|
|
|
void CppModelManager::unregisterCppEditorDocument(const QString &filePath)
|
2014-08-19 15:59:29 +02:00
|
|
|
{
|
|
|
|
QTC_ASSERT(!filePath.isEmpty(), return);
|
2013-07-11 11:13:07 +02:00
|
|
|
|
2014-08-19 15:59:29 +02:00
|
|
|
static short closedCppDocuments = 0;
|
|
|
|
int openCppDocuments = 0;
|
2013-07-11 11:13:07 +02:00
|
|
|
|
2014-08-19 15:59:29 +02:00
|
|
|
{
|
2014-11-24 11:19:41 +01:00
|
|
|
QMutexLocker locker(&d->m_cppEditorDocumentsMutex);
|
|
|
|
QTC_ASSERT(d->m_cppEditorDocuments.value(filePath, 0), return);
|
|
|
|
QTC_CHECK(d->m_cppEditorDocuments.remove(filePath) == 1);
|
|
|
|
openCppDocuments = d->m_cppEditorDocuments.size();
|
2013-07-11 11:13:07 +02:00
|
|
|
}
|
|
|
|
|
2014-08-19 15:59:29 +02:00
|
|
|
++closedCppDocuments;
|
|
|
|
if (openCppDocuments == 0 || closedCppDocuments == 5) {
|
|
|
|
closedCppDocuments = 0;
|
2013-07-18 10:57:19 +02:00
|
|
|
delayedGC();
|
2013-07-11 11:13:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-04 17:01:07 +02:00
|
|
|
QList<int> CppModelManager::references(Symbol *symbol, const LookupContext &context)
|
2009-09-30 13:25:40 +02:00
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
return d->m_findReferences->references(symbol, context);
|
2009-09-30 13:25:40 +02:00
|
|
|
}
|
|
|
|
|
2015-02-04 17:01:07 +02:00
|
|
|
void CppModelManager::findUsages(Symbol *symbol, const LookupContext &context)
|
2009-08-07 13:02:36 +02:00
|
|
|
{
|
2009-09-24 16:51:40 +02:00
|
|
|
if (symbol->identifier())
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_findReferences->findUsages(symbol, context);
|
2009-10-05 15:17:25 +02:00
|
|
|
}
|
|
|
|
|
2015-02-04 17:01:07 +02:00
|
|
|
void CppModelManager::renameUsages(Symbol *symbol,
|
|
|
|
const LookupContext &context,
|
2010-07-20 11:02:37 +02:00
|
|
|
const QString &replacement)
|
2009-10-05 15:17:25 +02:00
|
|
|
{
|
|
|
|
if (symbol->identifier())
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_findReferences->renameUsages(symbol, context, replacement);
|
2009-08-07 13:02:36 +02:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:00:38 +01:00
|
|
|
void CppModelManager::findMacroUsages(const CPlusPlus::Macro ¯o)
|
2009-12-21 14:54:10 +01:00
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_findReferences->findMacroUses(macro);
|
2009-12-21 14:54:10 +01:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:00:38 +01:00
|
|
|
void CppModelManager::renameMacroUsages(const CPlusPlus::Macro ¯o, const QString &replacement)
|
2012-03-17 13:26:27 +01:00
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_findReferences->renameMacroUses(macro, replacement);
|
2012-03-17 13:26:27 +01:00
|
|
|
}
|
|
|
|
|
2015-02-04 17:01:07 +02:00
|
|
|
void CppModelManager::replaceSnapshot(const Snapshot &newSnapshot)
|
2013-02-19 12:48:42 +01:00
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
QMutexLocker snapshotLocker(&d->m_snapshotMutex);
|
|
|
|
d->m_snapshot = newSnapshot;
|
2013-02-19 12:48:42 +01:00
|
|
|
}
|
|
|
|
|
2014-07-30 16:29:02 +02:00
|
|
|
WorkingCopy CppModelManager::buildWorkingCopyList()
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2009-12-15 15:16:46 +01:00
|
|
|
WorkingCopy workingCopy;
|
2014-03-20 17:03:27 -03:00
|
|
|
|
2014-11-24 11:19:41 +01:00
|
|
|
foreach (const CppEditorDocumentHandle *cppEditorDocument, cppEditorDocuments()) {
|
|
|
|
workingCopy.insert(cppEditorDocument->filePath(),
|
|
|
|
cppEditorDocument->contents(),
|
|
|
|
cppEditorDocument->revision());
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2019-07-24 13:43:54 +02:00
|
|
|
for (AbstractEditorSupport *es : qAsConst(d->m_extraEditorSupports))
|
2013-11-25 15:22:58 +01:00
|
|
|
workingCopy.insert(es->fileName(), es->contents(), es->revision());
|
2009-05-12 13:45:24 +02:00
|
|
|
|
2017-02-27 11:34:30 +01:00
|
|
|
// Add the project configuration file
|
|
|
|
QByteArray conf = codeModelConfiguration();
|
2017-02-07 15:00:38 +01:00
|
|
|
conf += ProjectExplorer::Macro::toByteArray(definedMacros());
|
2017-02-27 11:34:30 +01:00
|
|
|
workingCopy.insert(configurationFileName(), conf);
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
return workingCopy;
|
|
|
|
}
|
|
|
|
|
2014-07-30 16:29:02 +02:00
|
|
|
WorkingCopy CppModelManager::workingCopy() const
|
2009-10-12 10:38:00 +02:00
|
|
|
{
|
|
|
|
return const_cast<CppModelManager *>(this)->buildWorkingCopyList();
|
|
|
|
}
|
|
|
|
|
2013-08-19 16:05:29 +02:00
|
|
|
QByteArray CppModelManager::codeModelConfiguration() const
|
|
|
|
{
|
|
|
|
return QByteArray::fromRawData(pp_configuration, qstrlen(pp_configuration));
|
|
|
|
}
|
|
|
|
|
2021-02-23 13:51:41 +01:00
|
|
|
CppLocatorData *CppModelManager::locatorData() const
|
|
|
|
{
|
|
|
|
return &d->m_locatorData;
|
|
|
|
}
|
|
|
|
|
2016-08-16 13:37:49 +02:00
|
|
|
static QSet<QString> tooBigFilesRemoved(const QSet<QString> &files, int fileSizeLimitInMb)
|
2015-05-12 14:20:32 +02:00
|
|
|
{
|
2016-08-16 13:37:49 +02:00
|
|
|
if (fileSizeLimitInMb <= 0)
|
2015-05-12 14:20:32 +02:00
|
|
|
return files;
|
|
|
|
|
|
|
|
QSet<QString> result;
|
|
|
|
QFileInfo fileInfo;
|
|
|
|
|
2019-07-24 13:43:54 +02:00
|
|
|
for (const QString &filePath : files) {
|
2015-05-12 14:20:32 +02:00
|
|
|
fileInfo.setFile(filePath);
|
2016-08-16 13:37:49 +02:00
|
|
|
if (fileSizeExceedsLimit(fileInfo, fileSizeLimitInMb))
|
2015-05-12 14:20:32 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
result << filePath;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2014-09-04 14:59:50 +02:00
|
|
|
QFuture<void> CppModelManager::updateSourceFiles(const QSet<QString> &sourceFiles,
|
2013-06-21 08:42:27 +02:00
|
|
|
ProgressNotificationMode mode)
|
2012-10-16 16:02:40 +02:00
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
if (sourceFiles.isEmpty() || !d->m_indexerEnabled)
|
2012-10-16 16:02:40 +02:00
|
|
|
return QFuture<void>();
|
|
|
|
|
2016-08-16 13:37:49 +02:00
|
|
|
const QSet<QString> filteredFiles = tooBigFilesRemoved(sourceFiles, indexerFileSizeLimitInMb());
|
2015-05-12 14:20:32 +02:00
|
|
|
|
2020-11-10 17:55:54 +01:00
|
|
|
return d->m_internalIndexingSupport->refreshSourceFiles(filteredFiles, mode);
|
2012-10-16 16:02:40 +02:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2021-05-07 16:10:07 +02:00
|
|
|
QList<ProjectInfo::Ptr> CppModelManager::projectInfos() const
|
2008-12-08 10:44:56 +01:00
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
QMutexLocker locker(&d->m_projectMutex);
|
2021-08-19 12:30:11 +02:00
|
|
|
return Utils::transform<QList<ProjectInfo::Ptr>>(d->m_projectData,
|
|
|
|
[](const ProjectData &d) { return d.projectInfo; });
|
2008-12-08 10:44:56 +01:00
|
|
|
}
|
|
|
|
|
2021-05-07 16:10:07 +02:00
|
|
|
ProjectInfo::Ptr CppModelManager::projectInfo(ProjectExplorer::Project *project) const
|
2008-12-08 10:44:56 +01:00
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
QMutexLocker locker(&d->m_projectMutex);
|
2021-08-19 12:30:11 +02:00
|
|
|
return d->m_projectData.value(project).projectInfo;
|
2008-12-08 10:44:56 +01:00
|
|
|
}
|
|
|
|
|
2013-07-10 14:46:08 +02:00
|
|
|
/// \brief Remove all files and their includes (recursively) of given ProjectInfo from the snapshot.
|
|
|
|
void CppModelManager::removeProjectInfoFilesAndIncludesFromSnapshot(const ProjectInfo &projectInfo)
|
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
QMutexLocker snapshotLocker(&d->m_snapshotMutex);
|
2013-07-10 14:46:08 +02:00
|
|
|
foreach (const ProjectPart::Ptr &projectPart, projectInfo.projectParts()) {
|
|
|
|
foreach (const ProjectFile &cxxFile, projectPart->files) {
|
2014-09-15 00:12:27 +02:00
|
|
|
foreach (const QString &fileName, d->m_snapshot.allIncludesForDocument(cxxFile.path))
|
|
|
|
d->m_snapshot.remove(fileName);
|
|
|
|
d->m_snapshot.remove(cxxFile.path);
|
2013-07-10 14:46:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-24 11:19:41 +01:00
|
|
|
QList<CppEditorDocumentHandle *> CppModelManager::cppEditorDocuments() const
|
2014-03-20 17:03:27 -03:00
|
|
|
{
|
2014-11-24 11:19:41 +01:00
|
|
|
QMutexLocker locker(&d->m_cppEditorDocumentsMutex);
|
|
|
|
return d->m_cppEditorDocuments.values();
|
2014-03-20 17:03:27 -03:00
|
|
|
}
|
|
|
|
|
2013-07-10 14:46:08 +02:00
|
|
|
/// \brief Remove all given files from the snapshot.
|
|
|
|
void CppModelManager::removeFilesFromSnapshot(const QSet<QString> &filesToRemove)
|
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
QMutexLocker snapshotLocker(&d->m_snapshotMutex);
|
2019-07-24 13:43:54 +02:00
|
|
|
for (const QString &file : filesToRemove)
|
|
|
|
d->m_snapshot.remove(file);
|
2013-07-10 14:46:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
class ProjectInfoComparer
|
2008-12-08 10:44:56 +01:00
|
|
|
{
|
2013-07-10 14:46:08 +02:00
|
|
|
public:
|
2014-07-30 17:13:45 +02:00
|
|
|
ProjectInfoComparer(const ProjectInfo &oldProjectInfo,
|
|
|
|
const ProjectInfo &newProjectInfo)
|
2013-07-10 14:46:08 +02:00
|
|
|
: m_old(oldProjectInfo)
|
2014-09-04 14:59:50 +02:00
|
|
|
, m_oldSourceFiles(oldProjectInfo.sourceFiles())
|
2013-07-10 14:46:08 +02:00
|
|
|
, m_new(newProjectInfo)
|
2014-09-04 14:59:50 +02:00
|
|
|
, m_newSourceFiles(newProjectInfo.sourceFiles())
|
2013-07-10 14:46:08 +02:00
|
|
|
{}
|
|
|
|
|
2014-10-28 12:29:23 +01:00
|
|
|
bool definesChanged() const { return m_new.definesChanged(m_old); }
|
|
|
|
bool configurationChanged() const { return m_new.configurationChanged(m_old); }
|
|
|
|
bool configurationOrFilesChanged() const { return m_new.configurationOrFilesChanged(m_old); }
|
2013-07-10 14:46:08 +02:00
|
|
|
|
|
|
|
QSet<QString> addedFiles() const
|
|
|
|
{
|
|
|
|
QSet<QString> addedFilesSet = m_newSourceFiles;
|
|
|
|
addedFilesSet.subtract(m_oldSourceFiles);
|
|
|
|
return addedFilesSet;
|
|
|
|
}
|
|
|
|
|
|
|
|
QSet<QString> removedFiles() const
|
|
|
|
{
|
|
|
|
QSet<QString> removedFilesSet = m_oldSourceFiles;
|
|
|
|
removedFilesSet.subtract(m_newSourceFiles);
|
|
|
|
return removedFilesSet;
|
|
|
|
}
|
|
|
|
|
2015-05-08 15:48:17 +02:00
|
|
|
QStringList removedProjectParts()
|
|
|
|
{
|
2016-12-05 16:30:29 +01:00
|
|
|
QSet<QString> removed = projectPartIds(m_old.projectParts());
|
|
|
|
removed.subtract(projectPartIds(m_new.projectParts()));
|
2019-07-03 18:34:30 +02:00
|
|
|
return Utils::toList(removed);
|
2015-05-08 15:48:17 +02:00
|
|
|
}
|
|
|
|
|
2013-07-10 14:46:08 +02:00
|
|
|
/// Returns a list of common files that have a changed timestamp.
|
|
|
|
QSet<QString> timeStampModifiedFiles(const Snapshot &snapshot) const
|
|
|
|
{
|
|
|
|
QSet<QString> commonSourceFiles = m_newSourceFiles;
|
|
|
|
commonSourceFiles.intersect(m_oldSourceFiles);
|
|
|
|
|
|
|
|
QList<Document::Ptr> documentsToCheck;
|
2019-07-24 13:43:54 +02:00
|
|
|
for (const QString &file : commonSourceFiles) {
|
2013-07-10 14:46:08 +02:00
|
|
|
if (Document::Ptr document = snapshot.document(file))
|
|
|
|
documentsToCheck << document;
|
|
|
|
}
|
|
|
|
|
2014-09-04 14:59:50 +02:00
|
|
|
return CppModelManager::timeStampModifiedFiles(documentsToCheck);
|
2013-07-10 14:46:08 +02:00
|
|
|
}
|
|
|
|
|
2016-12-05 16:30:29 +01:00
|
|
|
private:
|
|
|
|
static QSet<QString> projectPartIds(const QVector<ProjectPart::Ptr> &projectParts)
|
|
|
|
{
|
|
|
|
QSet<QString> ids;
|
|
|
|
|
|
|
|
foreach (const ProjectPart::Ptr &projectPart, projectParts)
|
|
|
|
ids.insert(projectPart->id());
|
|
|
|
|
|
|
|
return ids;
|
|
|
|
}
|
|
|
|
|
2013-07-10 14:46:08 +02:00
|
|
|
private:
|
2014-07-30 17:13:45 +02:00
|
|
|
const ProjectInfo &m_old;
|
2013-07-10 14:46:08 +02:00
|
|
|
const QSet<QString> m_oldSourceFiles;
|
|
|
|
|
2014-07-30 17:13:45 +02:00
|
|
|
const ProjectInfo &m_new;
|
2013-07-10 14:46:08 +02:00
|
|
|
const QSet<QString> m_newSourceFiles;
|
|
|
|
};
|
|
|
|
|
2013-10-04 12:25:26 +02:00
|
|
|
/// Make sure that m_projectMutex is locked when calling this.
|
2015-07-14 17:30:17 +02:00
|
|
|
void CppModelManager::recalculateProjectPartMappings()
|
2013-10-04 12:25:26 +02:00
|
|
|
{
|
2015-07-14 17:30:17 +02:00
|
|
|
d->m_projectPartIdToProjectProjectPart.clear();
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_fileToProjectParts.clear();
|
2021-08-19 12:30:11 +02:00
|
|
|
for (const ProjectData &projectData : qAsConst(d->m_projectData)) {
|
|
|
|
for (const ProjectPart::Ptr &projectPart : projectData.projectInfo->projectParts()) {
|
2015-07-14 17:30:17 +02:00
|
|
|
d->m_projectPartIdToProjectProjectPart[projectPart->id()] = projectPart;
|
2021-08-19 12:30:11 +02:00
|
|
|
for (const ProjectFile &cxxFile : projectPart->files)
|
2019-05-28 13:49:26 +02:00
|
|
|
d->m_fileToProjectParts[Utils::FilePath::fromString(cxxFile.path)].append(
|
2014-11-27 12:40:34 +01:00
|
|
|
projectPart);
|
2013-10-04 12:25:26 +02:00
|
|
|
}
|
|
|
|
}
|
2015-10-08 13:32:36 +02:00
|
|
|
|
|
|
|
d->m_symbolFinder.clearCache();
|
2013-10-04 12:25:26 +02:00
|
|
|
}
|
|
|
|
|
2021-08-19 12:30:11 +02:00
|
|
|
void CppModelManagerPrivate::setupWatcher(const QFuture<void> &future,
|
|
|
|
ProjectExplorer::Project *project,
|
|
|
|
ProjectData *projectData, CppModelManager *q)
|
2016-04-25 13:17:20 +02:00
|
|
|
{
|
2021-08-19 12:30:11 +02:00
|
|
|
projectData->indexer = new QFutureWatcher<void>(q);
|
|
|
|
const auto handleFinished = [this, project, watcher = projectData->indexer, q] {
|
|
|
|
if (const auto it = m_projectData.find(project);
|
|
|
|
it != m_projectData.end() && it->indexer == watcher) {
|
|
|
|
it->indexer = nullptr;
|
|
|
|
it->fullyIndexed = !watcher->isCanceled();
|
|
|
|
}
|
|
|
|
watcher->disconnect(q);
|
2020-11-10 17:55:54 +01:00
|
|
|
watcher->deleteLater();
|
2021-08-19 12:30:11 +02:00
|
|
|
};
|
|
|
|
q->connect(projectData->indexer, &QFutureWatcher<void>::canceled, q, handleFinished);
|
|
|
|
q->connect(projectData->indexer, &QFutureWatcher<void>::finished, q, handleFinished);
|
|
|
|
projectData->indexer->setFuture(future);
|
2016-04-25 13:17:20 +02:00
|
|
|
}
|
|
|
|
|
2017-01-19 15:46:40 +01:00
|
|
|
void CppModelManager::updateCppEditorDocuments(bool projectsUpdated) const
|
2014-10-13 14:46:03 +02:00
|
|
|
{
|
2014-12-02 12:11:05 +01:00
|
|
|
// Refresh visible documents
|
|
|
|
QSet<Core::IDocument *> visibleCppEditorDocuments;
|
2014-10-13 14:46:03 +02:00
|
|
|
foreach (Core::IEditor *editor, Core::EditorManager::visibleEditors()) {
|
2014-12-02 12:11:05 +01:00
|
|
|
if (Core::IDocument *document = editor->document()) {
|
2014-11-24 11:19:41 +01:00
|
|
|
const QString filePath = document->filePath().toString();
|
|
|
|
if (CppEditorDocumentHandle *theCppEditorDocument = cppEditorDocument(filePath)) {
|
2014-12-02 12:11:05 +01:00
|
|
|
visibleCppEditorDocuments.insert(document);
|
2017-01-19 15:46:40 +01:00
|
|
|
theCppEditorDocument->processor()->run(projectsUpdated);
|
2014-12-02 12:11:05 +01:00
|
|
|
}
|
2014-10-13 14:46:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-02 12:11:05 +01:00
|
|
|
// Mark invisible documents dirty
|
|
|
|
QSet<Core::IDocument *> invisibleCppEditorDocuments
|
2019-07-03 18:34:30 +02:00
|
|
|
= Utils::toSet(Core::DocumentModel::openedDocuments());
|
2014-12-02 12:11:05 +01:00
|
|
|
invisibleCppEditorDocuments.subtract(visibleCppEditorDocuments);
|
|
|
|
foreach (Core::IDocument *document, invisibleCppEditorDocuments) {
|
2014-11-24 11:19:41 +01:00
|
|
|
const QString filePath = document->filePath().toString();
|
2016-12-15 11:21:44 +01:00
|
|
|
if (CppEditorDocumentHandle *theCppEditorDocument = cppEditorDocument(filePath)) {
|
2017-01-19 15:46:40 +01:00
|
|
|
const CppEditorDocumentHandle::RefreshReason refreshReason = projectsUpdated
|
|
|
|
? CppEditorDocumentHandle::ProjectUpdate
|
|
|
|
: CppEditorDocumentHandle::Other;
|
2016-12-15 11:21:44 +01:00
|
|
|
theCppEditorDocument->setRefreshReason(refreshReason);
|
|
|
|
}
|
2014-10-13 14:46:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-07 16:10:07 +02:00
|
|
|
QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo::Ptr &newProjectInfo,
|
2021-06-29 15:26:23 +02:00
|
|
|
const QSet<QString> &additionalFiles)
|
2013-07-10 14:46:08 +02:00
|
|
|
{
|
2021-05-07 16:10:07 +02:00
|
|
|
if (!newProjectInfo)
|
|
|
|
return {};
|
2016-12-06 13:07:00 +01:00
|
|
|
|
2014-09-04 14:59:50 +02:00
|
|
|
QSet<QString> filesToReindex;
|
2015-10-13 16:54:59 +02:00
|
|
|
QStringList removedProjectParts;
|
2013-07-10 14:46:08 +02:00
|
|
|
bool filesRemoved = false;
|
2021-05-07 16:10:07 +02:00
|
|
|
|
|
|
|
ProjectExplorer::Project * const project = projectForProjectInfo(*newProjectInfo);
|
|
|
|
if (!project)
|
|
|
|
return {};
|
2013-07-10 14:46:08 +02:00
|
|
|
|
2021-08-19 12:30:11 +02:00
|
|
|
ProjectData *projectData = nullptr;
|
2013-07-11 11:13:07 +02:00
|
|
|
{ // Only hold the mutex for a limited scope, so the dumping afterwards does not deadlock.
|
2014-09-15 00:12:27 +02:00
|
|
|
QMutexLocker projectLocker(&d->m_projectMutex);
|
2013-07-10 14:46:08 +02:00
|
|
|
|
2021-05-07 16:10:07 +02:00
|
|
|
const QSet<QString> newSourceFiles = newProjectInfo->sourceFiles();
|
2008-12-08 10:44:56 +01:00
|
|
|
|
2013-07-10 14:46:08 +02:00
|
|
|
// Check if we can avoid a full reindexing
|
2021-08-19 12:30:11 +02:00
|
|
|
const auto it = d->m_projectData.find(project);
|
|
|
|
if (it != d->m_projectData.end() && it->projectInfo && it->fullyIndexed) {
|
|
|
|
ProjectInfoComparer comparer(*it->projectInfo, *newProjectInfo);
|
2014-10-28 12:29:23 +01:00
|
|
|
|
2015-04-02 11:13:49 +02:00
|
|
|
if (comparer.configurationOrFilesChanged()) {
|
|
|
|
d->m_dirty = true;
|
|
|
|
|
|
|
|
// If the project configuration changed, do a full reindexing
|
|
|
|
if (comparer.configurationChanged()) {
|
2021-08-19 12:30:11 +02:00
|
|
|
removeProjectInfoFilesAndIncludesFromSnapshot(*it->projectInfo);
|
2015-04-02 11:13:49 +02:00
|
|
|
filesToReindex.unite(newSourceFiles);
|
|
|
|
|
2017-02-27 11:34:30 +01:00
|
|
|
// The "configuration file" includes all defines and therefore should be updated
|
|
|
|
if (comparer.definesChanged()) {
|
|
|
|
QMutexLocker snapshotLocker(&d->m_snapshotMutex);
|
|
|
|
d->m_snapshot.remove(configurationFileName());
|
|
|
|
}
|
|
|
|
|
2015-04-02 11:13:49 +02:00
|
|
|
// Otherwise check for added and modified files
|
|
|
|
} else {
|
|
|
|
const QSet<QString> addedFiles = comparer.addedFiles();
|
|
|
|
filesToReindex.unite(addedFiles);
|
|
|
|
|
|
|
|
const QSet<QString> modifiedFiles = comparer.timeStampModifiedFiles(snapshot());
|
|
|
|
filesToReindex.unite(modifiedFiles);
|
2013-06-28 11:26:02 +02:00
|
|
|
}
|
2013-07-10 14:46:08 +02:00
|
|
|
|
2015-04-02 11:13:49 +02:00
|
|
|
// Announce and purge the removed files from the snapshot
|
|
|
|
const QSet<QString> removedFiles = comparer.removedFiles();
|
|
|
|
if (!removedFiles.isEmpty()) {
|
|
|
|
filesRemoved = true;
|
2019-07-03 18:34:30 +02:00
|
|
|
emit aboutToRemoveFiles(Utils::toList(removedFiles));
|
2015-04-02 11:13:49 +02:00
|
|
|
removeFilesFromSnapshot(removedFiles);
|
|
|
|
}
|
2013-07-10 14:46:08 +02:00
|
|
|
}
|
|
|
|
|
2015-10-13 16:54:59 +02:00
|
|
|
removedProjectParts = comparer.removedProjectParts();
|
2015-05-08 15:48:17 +02:00
|
|
|
|
2013-07-10 14:46:08 +02:00
|
|
|
// A new project was opened/created, do a full indexing
|
|
|
|
} else {
|
2015-04-02 11:13:49 +02:00
|
|
|
d->m_dirty = true;
|
2014-09-04 14:59:50 +02:00
|
|
|
filesToReindex.unite(newSourceFiles);
|
2013-06-28 11:26:02 +02:00
|
|
|
}
|
|
|
|
|
2013-07-10 14:46:08 +02:00
|
|
|
// Update Project/ProjectInfo and File/ProjectPart table
|
2021-08-19 12:30:11 +02:00
|
|
|
if (it != d->m_projectData.end()) {
|
|
|
|
if (it->indexer)
|
|
|
|
it->indexer->cancel();
|
|
|
|
it->projectInfo = newProjectInfo;
|
|
|
|
it->fullyIndexed = false;
|
|
|
|
}
|
|
|
|
projectData = it == d->m_projectData.end()
|
|
|
|
? &(d->m_projectData[project] = ProjectData{newProjectInfo, nullptr, false})
|
|
|
|
: &(*it);
|
2015-07-14 17:30:17 +02:00
|
|
|
recalculateProjectPartMappings();
|
2013-07-10 14:46:08 +02:00
|
|
|
} // Mutex scope
|
|
|
|
|
|
|
|
// If requested, dump everything we got
|
2014-03-06 14:42:01 -03:00
|
|
|
if (DumpProjectInfo)
|
2014-03-17 09:45:07 -03:00
|
|
|
dumpModelManagerConfiguration(QLatin1String("updateProjectInfo"));
|
2013-01-01 10:34:42 +01:00
|
|
|
|
2013-07-10 14:46:08 +02:00
|
|
|
// Remove files from snapshot that are not reachable any more
|
|
|
|
if (filesRemoved)
|
|
|
|
GC();
|
|
|
|
|
2015-10-13 16:54:59 +02:00
|
|
|
// Announce removed project parts
|
|
|
|
if (!removedProjectParts.isEmpty())
|
|
|
|
emit projectPartsRemoved(removedProjectParts);
|
|
|
|
|
2015-05-08 15:48:17 +02:00
|
|
|
// Announce added project parts
|
2021-05-07 16:10:07 +02:00
|
|
|
emit projectPartsUpdated(project);
|
2013-07-16 12:08:39 +02:00
|
|
|
|
2014-10-13 14:46:03 +02:00
|
|
|
// Ideally, we would update all the editor documents that depend on the 'filesToReindex'.
|
|
|
|
// However, on e.g. a session restore first the editor documents are created and then the
|
|
|
|
// project updates come in. That is, there are no reasonable dependency tables based on
|
|
|
|
// resolved includes that we could rely on.
|
2017-01-19 15:46:40 +01:00
|
|
|
updateCppEditorDocuments(/*projectsUpdated = */ true);
|
2014-10-13 14:46:03 +02:00
|
|
|
|
2021-06-29 15:26:23 +02:00
|
|
|
filesToReindex.unite(additionalFiles);
|
2013-07-10 14:46:08 +02:00
|
|
|
// Trigger reindexing
|
2020-11-10 17:55:54 +01:00
|
|
|
const QFuture<void> indexingFuture = updateSourceFiles(filesToReindex,
|
2017-02-06 16:59:53 +01:00
|
|
|
ForcedProgressNotification);
|
2021-08-19 12:30:11 +02:00
|
|
|
|
|
|
|
// It's safe to do this here, as only the UI thread writes to the map and no other thread
|
|
|
|
// uses the indexer value.
|
|
|
|
// FIXME: Use a read/write lock instead of a mutex.
|
|
|
|
d->setupWatcher(indexingFuture, project, projectData, this);
|
|
|
|
|
2017-02-06 16:59:53 +01:00
|
|
|
return indexingFuture;
|
2012-02-16 15:09:56 +01:00
|
|
|
}
|
|
|
|
|
2015-07-14 17:30:17 +02:00
|
|
|
ProjectPart::Ptr CppModelManager::projectPartForId(const QString &projectPartId) const
|
2013-12-02 15:23:13 +01:00
|
|
|
{
|
2015-07-14 17:30:17 +02:00
|
|
|
return d->m_projectPartIdToProjectProjectPart.value(projectPartId);
|
2013-12-02 15:23:13 +01:00
|
|
|
}
|
|
|
|
|
2019-05-28 13:49:26 +02:00
|
|
|
QList<ProjectPart::Ptr> CppModelManager::projectPart(const Utils::FilePath &fileName) const
|
2012-02-16 15:09:56 +01:00
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
QMutexLocker locker(&d->m_projectMutex);
|
|
|
|
return d->m_fileToProjectParts.value(fileName);
|
2013-08-19 16:05:29 +02:00
|
|
|
}
|
2012-02-16 15:09:56 +01:00
|
|
|
|
2014-11-27 12:40:34 +01:00
|
|
|
QList<ProjectPart::Ptr> CppModelManager::projectPartFromDependencies(
|
2019-05-28 13:49:26 +02:00
|
|
|
const Utils::FilePath &fileName) const
|
2013-08-19 16:05:29 +02:00
|
|
|
{
|
|
|
|
QSet<ProjectPart::Ptr> parts;
|
2019-12-17 14:07:53 +01:00
|
|
|
const Utils::FilePaths deps = snapshot().filesDependingOn(fileName);
|
2014-10-06 15:18:26 +02:00
|
|
|
|
2014-11-27 12:11:46 +01:00
|
|
|
QMutexLocker locker(&d->m_projectMutex);
|
2019-07-03 18:34:30 +02:00
|
|
|
for (const Utils::FilePath &dep : deps)
|
|
|
|
parts.unite(Utils::toSet(d->m_fileToProjectParts.value(dep)));
|
2012-02-16 15:09:56 +01:00
|
|
|
|
2013-08-19 16:05:29 +02:00
|
|
|
return parts.values();
|
2008-12-08 10:44:56 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-11-06 16:50:02 +01:00
|
|
|
ProjectPart::Ptr CppModelManager::fallbackProjectPart()
|
2013-08-19 18:20:49 +02:00
|
|
|
{
|
2021-07-16 16:35:11 +02:00
|
|
|
QMutexLocker locker(&d->m_fallbackProjectPartMutex);
|
|
|
|
return d->m_fallbackProjectPart;
|
2013-08-19 18:20:49 +02:00
|
|
|
}
|
|
|
|
|
2015-12-01 11:57:08 +01:00
|
|
|
bool CppModelManager::isCppEditor(Core::IEditor *editor)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2017-01-30 14:59:10 +01:00
|
|
|
return editor->context().contains(ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2021-06-08 14:28:25 +02:00
|
|
|
bool CppModelManager::supportsOutline(const TextEditor::TextDocument *document)
|
|
|
|
{
|
|
|
|
return instance()->d->m_activeModelManagerSupport->supportsOutline(document);
|
|
|
|
}
|
|
|
|
|
2015-11-11 10:47:27 +01:00
|
|
|
bool CppModelManager::isClangCodeModelActive() const
|
|
|
|
{
|
2015-12-15 18:09:45 +01:00
|
|
|
return d->m_activeModelManagerSupport != d->m_builtinModelManagerSupport;
|
2015-08-31 15:41:02 +02:00
|
|
|
}
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
void CppModelManager::emitDocumentUpdated(Document::Ptr doc)
|
|
|
|
{
|
2013-02-19 12:48:42 +01:00
|
|
|
if (replaceDocument(doc))
|
2013-04-17 10:58:20 +02:00
|
|
|
emit documentUpdated(doc);
|
2009-02-10 22:56:04 +01:00
|
|
|
}
|
|
|
|
|
2015-05-18 09:35:29 +02:00
|
|
|
void CppModelManager::emitAbstractEditorSupportContentsUpdated(const QString &filePath,
|
2019-01-23 13:14:50 +01:00
|
|
|
const QString &sourcePath,
|
2015-05-18 09:35:29 +02:00
|
|
|
const QByteArray &contents)
|
|
|
|
{
|
2019-01-23 13:14:50 +01:00
|
|
|
emit abstractEditorSupportContentsUpdated(filePath, sourcePath, contents);
|
2015-05-18 09:35:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CppModelManager::emitAbstractEditorSupportRemoved(const QString &filePath)
|
|
|
|
{
|
|
|
|
emit abstractEditorSupportRemoved(filePath);
|
|
|
|
}
|
|
|
|
|
2008-12-04 17:07:43 +01:00
|
|
|
void CppModelManager::onProjectAdded(ProjectExplorer::Project *)
|
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
QMutexLocker locker(&d->m_projectMutex);
|
|
|
|
d->m_dirty = true;
|
2008-12-04 17:07:43 +01:00
|
|
|
}
|
|
|
|
|
2013-07-18 10:57:19 +02:00
|
|
|
void CppModelManager::delayedGC()
|
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
if (d->m_enableGC)
|
|
|
|
d->m_delayedGcTimer.start(500);
|
2013-07-18 10:57:19 +02:00
|
|
|
}
|
|
|
|
|
2016-06-22 11:15:19 +02:00
|
|
|
static QStringList removedProjectParts(const QStringList &before, const QStringList &after)
|
2015-05-08 15:48:17 +02:00
|
|
|
{
|
2019-07-03 18:34:30 +02:00
|
|
|
QSet<QString> b = Utils::toSet(before);
|
|
|
|
b.subtract(Utils::toSet(after));
|
2016-06-22 11:15:19 +02:00
|
|
|
|
2019-07-03 18:34:30 +02:00
|
|
|
return Utils::toList(b);
|
2015-05-08 15:48:17 +02:00
|
|
|
}
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
void CppModelManager::onAboutToRemoveProject(ProjectExplorer::Project *project)
|
|
|
|
{
|
2016-06-22 11:15:19 +02:00
|
|
|
QStringList idsOfRemovedProjectParts;
|
2015-05-08 15:48:17 +02:00
|
|
|
|
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
QMutexLocker locker(&d->m_projectMutex);
|
|
|
|
d->m_dirty = true;
|
2016-06-22 11:15:19 +02:00
|
|
|
const QStringList projectPartsIdsBefore = d->m_projectPartIdToProjectProjectPart.keys();
|
2015-05-08 15:48:17 +02:00
|
|
|
|
2021-08-19 12:30:11 +02:00
|
|
|
d->m_projectData.remove(project);
|
2015-07-14 17:30:17 +02:00
|
|
|
recalculateProjectPartMappings();
|
2016-06-22 11:15:19 +02:00
|
|
|
|
|
|
|
const QStringList projectPartsIdsAfter = d->m_projectPartIdToProjectProjectPart.keys();
|
|
|
|
idsOfRemovedProjectParts = removedProjectParts(projectPartsIdsBefore, projectPartsIdsAfter);
|
2015-05-08 15:48:17 +02:00
|
|
|
}
|
|
|
|
|
2016-06-22 11:15:19 +02:00
|
|
|
if (!idsOfRemovedProjectParts.isEmpty())
|
|
|
|
emit projectPartsRemoved(idsOfRemovedProjectParts);
|
2008-12-08 10:44:56 +01:00
|
|
|
|
2013-07-18 10:57:19 +02:00
|
|
|
delayedGC();
|
|
|
|
}
|
|
|
|
|
2017-01-19 15:46:40 +01:00
|
|
|
void CppModelManager::onActiveProjectChanged(ProjectExplorer::Project *project)
|
2016-12-15 11:21:44 +01:00
|
|
|
{
|
2017-01-19 15:46:40 +01:00
|
|
|
if (!project)
|
|
|
|
return; // Last project closed.
|
|
|
|
|
|
|
|
{
|
|
|
|
QMutexLocker locker(&d->m_projectMutex);
|
2021-08-19 12:30:11 +02:00
|
|
|
if (!d->m_projectData.contains(project))
|
2017-01-19 15:46:40 +01:00
|
|
|
return; // Not yet known to us.
|
|
|
|
}
|
|
|
|
|
|
|
|
updateCppEditorDocuments();
|
2016-12-15 11:21:44 +01:00
|
|
|
}
|
|
|
|
|
2014-08-05 11:34:52 +02:00
|
|
|
void CppModelManager::onSourceFilesRefreshed() const
|
|
|
|
{
|
|
|
|
if (BuiltinIndexingSupport::isFindErrorsIndexingActive()) {
|
2016-03-12 22:53:45 +02:00
|
|
|
QTimer::singleShot(1, QCoreApplication::instance(), &QCoreApplication::quit);
|
2014-08-05 11:34:52 +02:00
|
|
|
qDebug("FindErrorsIndexing: Done, requesting Qt Creator to quit.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-02 12:11:05 +01:00
|
|
|
void CppModelManager::onCurrentEditorChanged(Core::IEditor *editor)
|
|
|
|
{
|
|
|
|
if (!editor || !editor->document())
|
|
|
|
return;
|
|
|
|
|
2014-11-24 11:19:41 +01:00
|
|
|
const QString filePath = editor->document()->filePath().toString();
|
|
|
|
if (CppEditorDocumentHandle *theCppEditorDocument = cppEditorDocument(filePath)) {
|
2016-12-15 11:21:44 +01:00
|
|
|
const CppEditorDocumentHandle::RefreshReason refreshReason
|
|
|
|
= theCppEditorDocument->refreshReason();
|
|
|
|
if (refreshReason != CppEditorDocumentHandle::None) {
|
2017-01-19 15:46:40 +01:00
|
|
|
const bool projectsChanged = refreshReason == CppEditorDocumentHandle::ProjectUpdate;
|
2016-12-15 11:21:44 +01:00
|
|
|
theCppEditorDocument->setRefreshReason(CppEditorDocumentHandle::None);
|
2017-01-19 15:46:40 +01:00
|
|
|
theCppEditorDocument->processor()->run(projectsChanged);
|
2014-12-02 12:11:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-18 10:57:19 +02:00
|
|
|
void CppModelManager::onAboutToLoadSession()
|
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
if (d->m_delayedGcTimer.isActive())
|
|
|
|
d->m_delayedGcTimer.stop();
|
2008-12-02 12:01:29 +01:00
|
|
|
GC();
|
|
|
|
}
|
|
|
|
|
2021-05-26 15:50:03 +02:00
|
|
|
QSet<QString> CppModelManager::dependingInternalTargets(const Utils::FilePath &file) const
|
2021-01-01 19:19:43 +01:00
|
|
|
{
|
|
|
|
QSet<QString> result;
|
|
|
|
const Snapshot snapshot = this->snapshot();
|
|
|
|
QTC_ASSERT(snapshot.contains(file), return result);
|
|
|
|
bool wasHeader;
|
|
|
|
const QString correspondingFile
|
2021-05-26 15:50:03 +02:00
|
|
|
= correspondingHeaderOrSource(file.toString(), &wasHeader, CacheUsage::ReadOnly);
|
2021-01-01 19:19:43 +01:00
|
|
|
const Utils::FilePaths dependingFiles = snapshot.filesDependingOn(
|
2021-05-26 15:50:03 +02:00
|
|
|
wasHeader ? file : Utils::FilePath::fromString(correspondingFile));
|
2021-01-01 19:19:43 +01:00
|
|
|
for (const Utils::FilePath &fn : qAsConst(dependingFiles)) {
|
|
|
|
for (const ProjectPart::Ptr &part : projectPart(fn))
|
|
|
|
result.insert(part->buildSystemTarget);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-05-26 15:50:03 +02:00
|
|
|
QSet<QString> CppModelManager::internalTargets(const Utils::FilePath &filePath) const
|
2021-01-01 19:19:43 +01:00
|
|
|
{
|
|
|
|
const QList<ProjectPart::Ptr> projectParts = projectPart(filePath);
|
|
|
|
// if we have no project parts it's most likely a header with declarations only and CMake based
|
|
|
|
if (projectParts.isEmpty())
|
|
|
|
return dependingInternalTargets(filePath);
|
|
|
|
QSet<QString> targets;
|
|
|
|
for (const ProjectPart::Ptr &part : projectParts) {
|
|
|
|
targets.insert(part->buildSystemTarget);
|
|
|
|
if (part->buildTargetType != ProjectExplorer::BuildTargetType::Executable)
|
|
|
|
targets.unite(dependingInternalTargets(filePath));
|
|
|
|
}
|
|
|
|
return targets;
|
|
|
|
}
|
|
|
|
|
2021-06-11 14:34:34 +02:00
|
|
|
void CppModelManager::renameIncludes(const Utils::FilePath &oldFilePath,
|
|
|
|
const Utils::FilePath &newFilePath)
|
2014-09-24 13:42:17 +02:00
|
|
|
{
|
2021-06-11 14:34:34 +02:00
|
|
|
if (oldFilePath.isEmpty() || newFilePath.isEmpty())
|
2014-09-24 13:42:17 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
// We just want to handle renamings so return when the file was actually moved.
|
2021-06-11 14:34:34 +02:00
|
|
|
if (oldFilePath.absolutePath() != newFilePath.absolutePath())
|
2014-09-24 13:42:17 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
const TextEditor::RefactoringChanges changes;
|
|
|
|
|
2021-06-11 14:34:34 +02:00
|
|
|
foreach (Snapshot::IncludeLocation loc,
|
|
|
|
snapshot().includeLocationsOfDocument(oldFilePath.toString())) {
|
2021-05-28 12:02:36 +02:00
|
|
|
TextEditor::RefactoringFilePtr file = changes.file(
|
|
|
|
Utils::FilePath::fromString(loc.first->fileName()));
|
2015-10-01 14:54:31 +02:00
|
|
|
const QTextBlock &block = file->document()->findBlockByNumber(loc.second - 1);
|
2021-06-11 14:34:34 +02:00
|
|
|
const int replaceStart = block.text().indexOf(oldFilePath.fileName());
|
2014-09-24 13:42:17 +02:00
|
|
|
if (replaceStart > -1) {
|
|
|
|
Utils::ChangeSet changeSet;
|
|
|
|
changeSet.replace(block.position() + replaceStart,
|
2021-06-11 14:34:34 +02:00
|
|
|
block.position() + replaceStart + oldFilePath.fileName().length(),
|
|
|
|
newFilePath.fileName());
|
2014-09-24 13:42:17 +02:00
|
|
|
file->setChangeSet(changeSet);
|
|
|
|
file->apply();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-13 15:42:03 +02:00
|
|
|
// Return the class name which function belongs to
|
|
|
|
static const char *belongingClassName(const Function *function)
|
|
|
|
{
|
|
|
|
if (!function)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if (auto funcName = function->name()) {
|
|
|
|
if (auto qualifiedNameId = funcName->asQualifiedNameId()) {
|
|
|
|
if (const Name *funcBaseName = qualifiedNameId->base()) {
|
|
|
|
if (auto identifier = funcBaseName->identifier())
|
|
|
|
return identifier->chars();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
QSet<QString> CppModelManager::symbolsInFiles(const QSet<Utils::FilePath> &files) const
|
|
|
|
{
|
|
|
|
QSet<QString> uniqueSymbols;
|
|
|
|
const Snapshot cppSnapShot = snapshot();
|
|
|
|
|
|
|
|
// Iterate over the files and get interesting symbols
|
|
|
|
for (const Utils::FilePath &file : files) {
|
|
|
|
// Add symbols from the C++ code model
|
|
|
|
const CPlusPlus::Document::Ptr doc = cppSnapShot.document(file);
|
|
|
|
if (!doc.isNull() && doc->control()) {
|
|
|
|
const CPlusPlus::Control *ctrl = doc->control();
|
|
|
|
CPlusPlus::Symbol **symPtr = ctrl->firstSymbol(); // Read-only
|
|
|
|
while (symPtr != ctrl->lastSymbol()) {
|
|
|
|
const CPlusPlus::Symbol *sym = *symPtr;
|
|
|
|
|
|
|
|
const CPlusPlus::Identifier *symId = sym->identifier();
|
|
|
|
// Add any class, function or namespace identifiers
|
|
|
|
if ((sym->isClass() || sym->isFunction() || sym->isNamespace()) && symId
|
|
|
|
&& symId->chars()) {
|
|
|
|
uniqueSymbols.insert(QString::fromUtf8(symId->chars()));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle specific case : get "Foo" in "void Foo::function() {}"
|
|
|
|
if (sym->isFunction() && !sym->asFunction()->isDeclaration()) {
|
|
|
|
const char *className = belongingClassName(sym->asFunction());
|
|
|
|
if (className)
|
|
|
|
uniqueSymbols.insert(QString::fromUtf8(className));
|
|
|
|
}
|
|
|
|
|
|
|
|
++symPtr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return uniqueSymbols;
|
|
|
|
}
|
|
|
|
|
2013-04-19 16:56:12 +02:00
|
|
|
void CppModelManager::onCoreAboutToClose()
|
|
|
|
{
|
2016-02-10 15:33:38 +01:00
|
|
|
Core::ProgressManager::cancelTasks(CppTools::Constants::TASK_INDEX);
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_enableGC = false;
|
2013-04-19 16:56:12 +02:00
|
|
|
}
|
|
|
|
|
2021-07-16 16:35:11 +02:00
|
|
|
void CppModelManager::setupFallbackProjectPart()
|
|
|
|
{
|
2021-05-07 16:10:07 +02:00
|
|
|
ToolChainInfo tcInfo;
|
|
|
|
RawProjectPart rpp;
|
|
|
|
rpp.setMacros(definedMacros());
|
|
|
|
rpp.setHeaderPaths(headerPaths());
|
|
|
|
rpp.setQtVersion(Utils::QtVersion::Qt5);
|
2021-07-16 16:35:11 +02:00
|
|
|
|
|
|
|
// Do not activate ObjectiveCExtensions since this will lead to the
|
|
|
|
// "objective-c++" language option for a project-less *.cpp file.
|
2021-05-07 16:10:07 +02:00
|
|
|
Utils::LanguageExtensions langExtensions = Utils::LanguageExtension::All;
|
|
|
|
langExtensions &= ~Utils::LanguageExtensions(Utils::LanguageExtension::ObjectiveC);
|
2021-07-16 16:35:11 +02:00
|
|
|
|
|
|
|
// TODO: Use different fallback toolchain for different kinds of files?
|
|
|
|
const Kit * const defaultKit = KitManager::isLoaded() ? KitManager::defaultKit() : nullptr;
|
|
|
|
const ToolChain * const defaultTc = defaultKit
|
|
|
|
? ToolChainKitAspect::cxxToolChain(defaultKit) : nullptr;
|
|
|
|
if (defaultKit && defaultTc) {
|
|
|
|
Utils::FilePath sysroot = SysRootKitAspect::sysRoot(defaultKit);
|
|
|
|
if (sysroot.isEmpty())
|
|
|
|
sysroot = Utils::FilePath::fromString(defaultTc->sysRoot());
|
|
|
|
Utils::Environment env = defaultKit->buildEnvironment();
|
2021-05-07 16:10:07 +02:00
|
|
|
tcInfo = ToolChainInfo(defaultTc, sysroot.toString(), env);
|
|
|
|
const auto macroInspectionWrapper = [runner = tcInfo.macroInspectionRunner](
|
|
|
|
const QStringList &flags) {
|
|
|
|
ToolChain::MacroInspectionReport report = runner(flags);
|
|
|
|
report.languageVersion = Utils::LanguageVersion::LatestCxx;
|
|
|
|
return report;
|
|
|
|
};
|
|
|
|
tcInfo.macroInspectionRunner = macroInspectionWrapper;
|
2021-07-16 16:35:11 +02:00
|
|
|
}
|
|
|
|
|
2021-05-07 16:10:07 +02:00
|
|
|
const auto part = ProjectPart::create({}, rpp, {}, {}, {}, langExtensions, {}, tcInfo);
|
2021-07-16 16:35:11 +02:00
|
|
|
QMutexLocker locker(&d->m_fallbackProjectPartMutex);
|
|
|
|
d->m_fallbackProjectPart = part;
|
|
|
|
}
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
void CppModelManager::GC()
|
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
if (!d->m_enableGC)
|
2013-04-19 16:56:12 +02:00
|
|
|
return;
|
|
|
|
|
2014-10-21 10:52:03 +02:00
|
|
|
// Collect files of opened editors and editor supports (e.g. ui code model)
|
2013-07-17 13:50:38 +02:00
|
|
|
QStringList filesInEditorSupports;
|
2014-11-24 11:19:41 +01:00
|
|
|
foreach (const CppEditorDocumentHandle *editorDocument, cppEditorDocuments())
|
|
|
|
filesInEditorSupports << editorDocument->filePath();
|
2013-07-17 13:50:38 +02:00
|
|
|
|
2015-05-08 15:48:17 +02:00
|
|
|
foreach (AbstractEditorSupport *abstractEditorSupport, abstractEditorSupports())
|
2013-07-17 13:50:38 +02:00
|
|
|
filesInEditorSupports << abstractEditorSupport->fileName();
|
|
|
|
|
|
|
|
Snapshot currentSnapshot = snapshot();
|
2019-05-28 13:49:26 +02:00
|
|
|
QSet<Utils::FilePath> reachableFiles;
|
2013-07-17 13:50:38 +02:00
|
|
|
// The configuration file is part of the project files, which is just fine.
|
|
|
|
// If single files are open, without any project, then there is no need to
|
|
|
|
// keep the configuration file around.
|
|
|
|
QStringList todo = filesInEditorSupports + projectFiles();
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-07-11 11:13:07 +02:00
|
|
|
// Collect all files that are reachable from the project files
|
2013-07-24 11:59:39 +02:00
|
|
|
while (!todo.isEmpty()) {
|
2013-07-11 11:13:07 +02:00
|
|
|
const QString file = todo.last();
|
2008-12-02 12:01:29 +01:00
|
|
|
todo.removeLast();
|
|
|
|
|
2019-05-28 13:49:26 +02:00
|
|
|
const Utils::FilePath fileName = Utils::FilePath::fromString(file);
|
2014-11-27 12:11:46 +01:00
|
|
|
if (reachableFiles.contains(fileName))
|
2008-12-02 12:01:29 +01:00
|
|
|
continue;
|
2014-11-27 12:11:46 +01:00
|
|
|
reachableFiles.insert(fileName);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-07-11 11:13:07 +02:00
|
|
|
if (Document::Ptr doc = currentSnapshot.document(file))
|
2008-12-02 12:01:29 +01:00
|
|
|
todo += doc->includedFiles();
|
|
|
|
}
|
|
|
|
|
2013-07-11 11:13:07 +02:00
|
|
|
// Find out the files in the current snapshot that are not reachable from the project files
|
|
|
|
QStringList notReachableFiles;
|
2009-12-07 10:54:27 +01:00
|
|
|
Snapshot newSnapshot;
|
|
|
|
for (Snapshot::const_iterator it = currentSnapshot.begin(); it != currentSnapshot.end(); ++it) {
|
2019-05-28 13:49:26 +02:00
|
|
|
const Utils::FilePath &fileName = it.key();
|
2009-12-07 10:54:27 +01:00
|
|
|
|
2013-07-11 11:13:07 +02:00
|
|
|
if (reachableFiles.contains(fileName))
|
2009-12-07 10:54:27 +01:00
|
|
|
newSnapshot.insert(it.value());
|
|
|
|
else
|
2014-11-27 12:11:46 +01:00
|
|
|
notReachableFiles.append(fileName.toString());
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2013-07-11 11:13:07 +02:00
|
|
|
// Announce removing files and replace the snapshot
|
|
|
|
emit aboutToRemoveFiles(notReachableFiles);
|
2013-02-19 12:48:42 +01:00
|
|
|
replaceSnapshot(newSnapshot);
|
2013-07-18 10:57:19 +02:00
|
|
|
emit gcFinished();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2010-12-03 13:49:35 +01:00
|
|
|
|
2014-09-04 14:59:50 +02:00
|
|
|
void CppModelManager::finishedRefreshingSourceFiles(const QSet<QString> &files)
|
2011-07-05 10:46:46 +02:00
|
|
|
{
|
|
|
|
emit sourceFilesRefreshed(files);
|
|
|
|
}
|
|
|
|
|
2015-12-15 18:09:45 +01:00
|
|
|
void CppModelManager::activateClangCodeModel(
|
2015-05-08 15:48:17 +02:00
|
|
|
ModelManagerSupportProvider *modelManagerSupportProvider)
|
2013-08-30 12:55:06 +02:00
|
|
|
{
|
2015-05-08 15:48:17 +02:00
|
|
|
QTC_ASSERT(modelManagerSupportProvider, return);
|
2013-08-30 12:55:06 +02:00
|
|
|
|
2015-12-15 18:09:45 +01:00
|
|
|
d->m_activeModelManagerSupport = modelManagerSupportProvider->createModelManagerSupport();
|
2017-09-26 16:00:30 +02:00
|
|
|
d->m_refactoringEngines[RefactoringEngineType::ClangCodeModel] =
|
|
|
|
&d->m_activeModelManagerSupport->refactoringEngineInterface();
|
2013-08-30 12:55:06 +02:00
|
|
|
}
|
|
|
|
|
2015-11-11 10:47:27 +01:00
|
|
|
CppCompletionAssistProvider *CppModelManager::completionAssistProvider() const
|
2012-02-20 12:39:08 +01:00
|
|
|
{
|
2015-11-11 10:47:27 +01:00
|
|
|
return d->m_activeModelManagerSupport->completionAssistProvider();
|
2012-02-20 12:39:08 +01:00
|
|
|
}
|
|
|
|
|
2020-07-31 16:50:03 +02:00
|
|
|
CppCompletionAssistProvider *CppModelManager::functionHintAssistProvider() const
|
|
|
|
{
|
|
|
|
return d->m_activeModelManagerSupport->functionHintAssistProvider();
|
|
|
|
}
|
|
|
|
|
2018-01-11 17:06:26 +01:00
|
|
|
TextEditor::BaseHoverHandler *CppModelManager::createHoverHandler() const
|
|
|
|
{
|
|
|
|
return d->m_activeModelManagerSupport->createHoverHandler();
|
|
|
|
}
|
|
|
|
|
2018-01-11 16:46:45 +01:00
|
|
|
BaseEditorDocumentProcessor *CppModelManager::createEditorDocumentProcessor(
|
2018-01-11 17:06:26 +01:00
|
|
|
TextEditor::TextDocument *baseTextDocument) const
|
2012-02-07 15:09:08 +01:00
|
|
|
{
|
2018-01-11 16:46:45 +01:00
|
|
|
return d->m_activeModelManagerSupport->createEditorDocumentProcessor(baseTextDocument);
|
2012-02-20 12:39:08 +01:00
|
|
|
}
|
|
|
|
|
2012-11-23 11:47:39 +01:00
|
|
|
CppIndexingSupport *CppModelManager::indexingSupport()
|
|
|
|
{
|
2021-08-19 17:46:33 +02:00
|
|
|
return d->m_internalIndexingSupport;
|
2012-10-16 16:02:40 +02:00
|
|
|
}
|
|
|
|
|
2014-09-05 10:57:58 +03:00
|
|
|
QStringList CppModelManager::projectFiles()
|
|
|
|
{
|
2015-11-06 16:50:02 +01:00
|
|
|
QMutexLocker locker(&d->m_projectMutex);
|
2014-09-05 10:57:58 +03:00
|
|
|
ensureUpdated();
|
2015-11-06 16:50:02 +01:00
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
return d->m_projectFiles;
|
2014-09-05 10:57:58 +03:00
|
|
|
}
|
|
|
|
|
2018-09-03 16:10:43 +02:00
|
|
|
ProjectExplorer::HeaderPaths CppModelManager::headerPaths()
|
2014-09-05 10:57:58 +03:00
|
|
|
{
|
2015-11-06 16:50:02 +01:00
|
|
|
QMutexLocker locker(&d->m_projectMutex);
|
2014-09-05 10:57:58 +03:00
|
|
|
ensureUpdated();
|
2015-11-06 16:50:02 +01:00
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
return d->m_headerPaths;
|
|
|
|
}
|
|
|
|
|
2018-09-03 16:10:43 +02:00
|
|
|
void CppModelManager::setHeaderPaths(const ProjectExplorer::HeaderPaths &headerPaths)
|
2014-09-15 00:12:27 +02:00
|
|
|
{
|
2015-11-06 16:50:02 +01:00
|
|
|
QMutexLocker locker(&d->m_projectMutex);
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_headerPaths = headerPaths;
|
2014-09-05 10:57:58 +03:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:00:38 +01:00
|
|
|
ProjectExplorer::Macros CppModelManager::definedMacros()
|
2014-09-05 10:57:58 +03:00
|
|
|
{
|
2015-11-06 16:50:02 +01:00
|
|
|
QMutexLocker locker(&d->m_projectMutex);
|
2014-09-05 10:57:58 +03:00
|
|
|
ensureUpdated();
|
2015-11-06 16:50:02 +01:00
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
return d->m_definedMacros;
|
2014-09-05 10:57:58 +03:00
|
|
|
}
|
|
|
|
|
2013-12-17 13:54:52 +01:00
|
|
|
void CppModelManager::enableGarbageCollector(bool enable)
|
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_delayedGcTimer.stop();
|
|
|
|
d->m_enableGC = enable;
|
2013-12-17 13:54:52 +01:00
|
|
|
}
|
2014-09-15 00:12:27 +02:00
|
|
|
|
2015-10-09 17:42:56 +02:00
|
|
|
SymbolFinder *CppModelManager::symbolFinder()
|
|
|
|
{
|
|
|
|
return &d->m_symbolFinder;
|
|
|
|
}
|
|
|
|
|
2016-02-17 23:27:41 +02:00
|
|
|
QThreadPool *CppModelManager::sharedThreadPool()
|
|
|
|
{
|
|
|
|
return &d->m_threadPool;
|
|
|
|
}
|
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
} // namespace CppTools
|