2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2015-01-14 18:07:15 +01:00
|
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
|
|
** Contact: http://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
|
2015-01-14 18:07:15 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms and
|
|
|
|
** conditions see http://www.qt.io/terms-conditions. For further information
|
2014-10-01 13:21:18 +02:00
|
|
|
** use the contact form at http://www.qt.io/contact-us.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
** GNU Lesser General Public License Usage
|
2012-10-02 09:12:39 +02:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
2014-10-01 13:21:18 +02:00
|
|
|
** General Public License version 2.1 or version 3 as published by the Free
|
|
|
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
|
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
|
|
** following information to ensure the GNU Lesser General Public License
|
|
|
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
2012-10-02 09:12:39 +02:00
|
|
|
**
|
2015-01-14 18:07:15 +01:00
|
|
|
** In addition, as a special exception, The Qt Company gives you certain additional
|
|
|
|
** rights. These rights are described in The Qt Company LGPL Exception
|
2010-12-17 16:01:08 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
**
|
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"
|
2015-03-05 08:22:48 +01:00
|
|
|
#include "baseeditordocumentprocessor.h"
|
2013-03-12 12:06:41 +01:00
|
|
|
#include "builtinindexingsupport.h"
|
2014-03-17 08:44:46 -03:00
|
|
|
#include "cppcodemodelinspectordumper.h"
|
2013-09-06 13:14:15 +02:00
|
|
|
#include "cppcodemodelsettings.h"
|
2013-07-11 11:13:07 +02:00
|
|
|
#include "cppfindreferences.h"
|
2012-10-16 16:02:40 +02:00
|
|
|
#include "cppindexingsupport.h"
|
2013-09-04 18:15:08 +02:00
|
|
|
#include "cppmodelmanagersupportinternal.h"
|
2014-09-24 13:42:17 +02:00
|
|
|
#include "cpprefactoringchanges.h"
|
2014-05-16 15:51:04 -04:00
|
|
|
#include "cppsourceprocessor.h"
|
2013-07-11 11:13:07 +02:00
|
|
|
#include "cpptoolsconstants.h"
|
2013-09-06 13:14:15 +02:00
|
|
|
#include "cpptoolsplugin.h"
|
2015-05-12 14:20:32 +02:00
|
|
|
#include "cpptoolsreuse.h"
|
2014-08-19 15:59:29 +02:00
|
|
|
#include "editordocumenthandle.h"
|
2015-10-09 17:42:56 +02:00
|
|
|
#include "symbolfinder.h"
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2014-09-24 13:42:17 +02:00
|
|
|
#include <coreplugin/documentmanager.h>
|
2013-03-27 18:54:03 +01:00
|
|
|
#include <coreplugin/icore.h>
|
|
|
|
#include <coreplugin/progressmanager/progressmanager.h>
|
2015-02-26 13:22:35 +01:00
|
|
|
#include <coreplugin/editormanager/editormanager.h>
|
|
|
|
#include <texteditor/textdocument.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>
|
|
|
|
#include <projectexplorer/session.h>
|
2013-03-27 18:54:03 +01:00
|
|
|
#include <extensionsystem/pluginmanager.h>
|
2015-07-15 17:15:57 +02:00
|
|
|
#include <utils/algorithm.h>
|
2014-11-27 12:40:34 +01:00
|
|
|
#include <utils/fileutils.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>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QMutexLocker>
|
|
|
|
#include <QTextBlock>
|
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-09-05 08:46:38 +02:00
|
|
|
Q_DECLARE_METATYPE(QSet<QString>)
|
|
|
|
|
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;
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
DumpAST(Control *control)
|
|
|
|
: 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', ' ');
|
|
|
|
code.replace(QRegExp("\\s+"), " ");
|
|
|
|
|
|
|
|
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 {
|
|
|
|
namespace Internal {
|
|
|
|
|
|
|
|
static QMutex m_instanceMutex;
|
|
|
|
static CppModelManager *m_instance;
|
|
|
|
|
|
|
|
class CppModelManagerPrivate
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// 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;
|
|
|
|
QMap<ProjectExplorer::Project *, ProjectInfo> m_projectToProjectsInfo;
|
2015-02-04 17:01:07 +02:00
|
|
|
QMap<Utils::FileName, 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;
|
|
|
|
ProjectPart::HeaderPaths m_headerPaths;
|
|
|
|
QByteArray m_definedMacros;
|
|
|
|
|
|
|
|
// 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
|
|
|
|
ModelManagerSupportProvider *m_clangModelManagerSupportProvider;
|
|
|
|
ModelManagerSupport::Ptr m_builtinModelManagerSupport;
|
|
|
|
ModelManagerSupport::Ptr m_activeModelManagerSupport;
|
2014-09-15 00:12:27 +02:00
|
|
|
|
|
|
|
// Indexing
|
|
|
|
CppIndexingSupport *m_indexingSupporter;
|
|
|
|
CppIndexingSupport *m_internalIndexingSupport;
|
|
|
|
bool m_indexerEnabled;
|
|
|
|
|
|
|
|
CppFindReferences *m_findReferences;
|
|
|
|
|
2015-10-09 17:42:56 +02:00
|
|
|
SymbolFinder m_symbolFinder;
|
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
bool m_enableGC;
|
|
|
|
QTimer m_delayedGcTimer;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // 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"
|
|
|
|
"#define __pragma(x)\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>");
|
|
|
|
}
|
|
|
|
|
|
|
|
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()
|
|
|
|
{
|
2013-07-11 11:13:07 +02:00
|
|
|
if (m_instance)
|
|
|
|
return m_instance;
|
|
|
|
|
|
|
|
QMutexLocker locker(&m_instanceMutex);
|
|
|
|
if (!m_instance)
|
|
|
|
m_instance = new CppModelManager;
|
|
|
|
|
|
|
|
return m_instance;
|
2012-10-15 16:38:56 +02:00
|
|
|
}
|
|
|
|
|
2015-11-11 10:47:27 +01:00
|
|
|
void CppModelManager::initializeModelManagerSupports()
|
|
|
|
{
|
|
|
|
d->m_clangModelManagerSupportProvider = nullptr;
|
|
|
|
d->m_builtinModelManagerSupport
|
|
|
|
= ModelManagerSupportProviderInternal().createModelManagerSupport();
|
|
|
|
d->m_activeModelManagerSupport = d->m_builtinModelManagerSupport;
|
|
|
|
}
|
|
|
|
|
2009-01-20 11:52:04 +01:00
|
|
|
CppModelManager::CppModelManager(QObject *parent)
|
2014-09-15 00:12:27 +02:00
|
|
|
: CppModelManagerBase(parent), d(new CppModelManagerPrivate)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_indexingSupporter = 0;
|
|
|
|
d->m_enableGC = true;
|
|
|
|
|
2014-09-05 08:46:38 +02:00
|
|
|
qRegisterMetaType<QSet<QString> >();
|
2014-09-04 14:59:50 +02:00
|
|
|
connect(this, SIGNAL(sourceFilesRefreshed(QSet<QString>)),
|
2014-08-05 11:34:52 +02:00
|
|
|
this, SLOT(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);
|
|
|
|
connect(&d->m_delayedGcTimer, SIGNAL(timeout()), this, SLOT(GC()));
|
2013-07-18 10:57:19 +02:00
|
|
|
|
2013-09-05 11:46:07 +02:00
|
|
|
QObject *sessionManager = ProjectExplorer::SessionManager::instance();
|
|
|
|
connect(sessionManager, SIGNAL(projectAdded(ProjectExplorer::Project*)),
|
2008-12-04 17:07:43 +01:00
|
|
|
this, SLOT(onProjectAdded(ProjectExplorer::Project*)));
|
2013-09-05 11:46:07 +02:00
|
|
|
connect(sessionManager, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)),
|
2012-03-05 22:30:59 +01:00
|
|
|
this, SLOT(onAboutToRemoveProject(ProjectExplorer::Project*)));
|
2013-09-05 11:46:07 +02:00
|
|
|
connect(sessionManager, SIGNAL(aboutToLoadSession(QString)),
|
2013-07-18 10:57:19 +02:00
|
|
|
this, SLOT(onAboutToLoadSession()));
|
2013-09-05 11:46:07 +02:00
|
|
|
connect(sessionManager, SIGNAL(aboutToUnloadSession(QString)),
|
2009-08-13 17:10:53 +02:00
|
|
|
this, SLOT(onAboutToUnloadSession()));
|
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
|
|
|
|
2013-04-19 16:56:12 +02:00
|
|
|
connect(Core::ICore::instance(), SIGNAL(coreAboutToClose()),
|
|
|
|
this, SLOT(onCoreAboutToClose()));
|
|
|
|
|
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-05-08 15:48:17 +02:00
|
|
|
QSharedPointer<CppCodeModelSettings> codeModelSettings
|
|
|
|
= CppToolsPlugin::instance()->codeModelSettings();
|
|
|
|
connect(codeModelSettings.data(), &CppCodeModelSettings::changed,
|
|
|
|
this, &CppModelManager::onCodeModelSettingsChanged);
|
|
|
|
|
2015-11-11 10:47:27 +01:00
|
|
|
initializeModelManagerSupports();
|
2013-09-04 18:15:08 +02:00
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_internalIndexingSupport = new BuiltinIndexingSupport;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
CppModelManager::~CppModelManager()
|
2012-02-20 12:39:08 +01:00
|
|
|
{
|
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;
|
2014-09-15 00:12:27 +02:00
|
|
|
QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(d->m_projectToProjectsInfo);
|
2008-12-02 12:01:29 +01:00
|
|
|
while (it.hasNext()) {
|
|
|
|
it.next();
|
2013-07-11 11:13:07 +02:00
|
|
|
const ProjectInfo pinfo = it.value();
|
2012-11-23 16:29:00 +01:00
|
|
|
foreach (const ProjectPart::Ptr &part, pinfo.projectParts()) {
|
2013-03-04 01:30:46 +04:00
|
|
|
foreach (const ProjectFile &file, part->files)
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-06-25 17:23:19 +02:00
|
|
|
ProjectPart::HeaderPaths CppModelManager::internalHeaderPaths() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2014-06-25 17:23:19 +02:00
|
|
|
ProjectPart::HeaderPaths headerPaths;
|
2014-09-15 00:12:27 +02:00
|
|
|
QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(d->m_projectToProjectsInfo);
|
2008-12-02 12:01:29 +01:00
|
|
|
while (it.hasNext()) {
|
|
|
|
it.next();
|
2013-07-11 11:13:07 +02:00
|
|
|
const ProjectInfo pinfo = it.value();
|
2014-06-25 17:23:19 +02:00
|
|
|
foreach (const ProjectPart::Ptr &part, pinfo.projectParts()) {
|
|
|
|
foreach (const ProjectPart::HeaderPath &path, part->headerPaths) {
|
2014-12-03 14:40:08 +01:00
|
|
|
const ProjectPart::HeaderPath hp(QDir::cleanPath(path.path), path.type);
|
2014-06-25 17:23:19 +02:00
|
|
|
if (!headerPaths.contains(hp))
|
|
|
|
headerPaths += hp;
|
|
|
|
}
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2013-11-27 15:17:51 +01:00
|
|
|
static void addUnique(const QList<QByteArray> &defs, QByteArray *macros, QSet<QByteArray> *alreadyIn)
|
|
|
|
{
|
|
|
|
Q_ASSERT(macros);
|
|
|
|
Q_ASSERT(alreadyIn);
|
|
|
|
|
|
|
|
foreach (const QByteArray &def, defs) {
|
|
|
|
if (def.trimmed().isEmpty())
|
|
|
|
continue;
|
|
|
|
if (!alreadyIn->contains(def)) {
|
|
|
|
macros->append(def);
|
|
|
|
macros->append('\n');
|
|
|
|
alreadyIn->insert(def);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-08 14:48:51 +01:00
|
|
|
QByteArray CppModelManager::internalDefinedMacros() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
QByteArray macros;
|
2012-03-27 15:29:12 +02:00
|
|
|
QSet<QByteArray> alreadyIn;
|
2014-09-15 00:12:27 +02:00
|
|
|
QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(d->m_projectToProjectsInfo);
|
2008-12-02 12:01:29 +01:00
|
|
|
while (it.hasNext()) {
|
|
|
|
it.next();
|
2013-07-11 11:13:07 +02:00
|
|
|
const ProjectInfo pinfo = it.value();
|
2012-03-27 15:29:12 +02:00
|
|
|
foreach (const ProjectPart::Ptr &part, pinfo.projectParts()) {
|
2013-11-27 15:17:51 +01:00
|
|
|
addUnique(part->toolchainDefines.split('\n'), ¯os, &alreadyIn);
|
|
|
|
addUnique(part->projectDefines.split('\n'), ¯os, &alreadyIn);
|
2014-02-05 16:44:35 +01:00
|
|
|
if (!part->projectConfigFile.isEmpty())
|
2014-07-30 17:13:45 +02:00
|
|
|
macros += ProjectPart::readProjectConfigFile(part);
|
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());
|
2015-11-06 16:50:02 +01:00
|
|
|
dumper.dumpMergedEntities(headerPaths(), 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())
|
|
|
|
return 0;
|
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
|
|
|
}
|
|
|
|
|
2015-02-04 17:01:07 +02:00
|
|
|
void CppModelManager::findMacroUsages(const 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
|
|
|
}
|
|
|
|
|
2015-02-04 17:01:07 +02:00
|
|
|
void CppModelManager::renameMacroUsages(const 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
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
QSetIterator<AbstractEditorSupport *> it(d->m_extraEditorSupports);
|
2013-07-11 11:13:07 +02:00
|
|
|
while (it.hasNext()) {
|
|
|
|
AbstractEditorSupport *es = it.next();
|
2013-11-25 15:22:58 +01:00
|
|
|
workingCopy.insert(es->fileName(), es->contents(), es->revision());
|
2009-05-12 13:45:24 +02:00
|
|
|
}
|
|
|
|
|
2013-07-11 11:13:07 +02:00
|
|
|
// Add the project configuration file
|
2013-08-19 16:05:29 +02:00
|
|
|
QByteArray conf = codeModelConfiguration();
|
2008-12-02 12:01:29 +01:00
|
|
|
conf += definedMacros();
|
2013-08-19 15:47:51 +02: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));
|
|
|
|
}
|
|
|
|
|
2015-05-12 14:20:32 +02:00
|
|
|
static QSet<QString> tooBigFilesRemoved(const QSet<QString> &files, int fileSizeLimit)
|
|
|
|
{
|
|
|
|
if (fileSizeLimit == 0)
|
|
|
|
return files;
|
|
|
|
|
|
|
|
QSet<QString> result;
|
|
|
|
QFileInfo fileInfo;
|
|
|
|
|
|
|
|
QSetIterator<QString> i(files);
|
|
|
|
while (i.hasNext()) {
|
|
|
|
const QString filePath = i.next();
|
|
|
|
fileInfo.setFile(filePath);
|
|
|
|
if (skipFileDueToSizeLimit(fileInfo), fileSizeLimit)
|
|
|
|
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>();
|
|
|
|
|
2015-05-12 14:20:32 +02:00
|
|
|
const auto filteredFiles = tooBigFilesRemoved(sourceFiles, fileSizeLimit());
|
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
if (d->m_indexingSupporter)
|
2015-05-12 14:20:32 +02:00
|
|
|
d->m_indexingSupporter->refreshSourceFiles(filteredFiles, mode);
|
|
|
|
return d->m_internalIndexingSupport->refreshSourceFiles(filteredFiles, mode);
|
2012-10-16 16:02:40 +02:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2014-07-30 17:13:45 +02:00
|
|
|
QList<ProjectInfo> CppModelManager::projectInfos() const
|
2008-12-08 10:44:56 +01:00
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
QMutexLocker locker(&d->m_projectMutex);
|
|
|
|
return d->m_projectToProjectsInfo.values();
|
2008-12-08 10:44:56 +01:00
|
|
|
}
|
|
|
|
|
2014-07-30 17:13:45 +02:00
|
|
|
ProjectInfo 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);
|
2014-11-20 12:50:37 +01:00
|
|
|
return d->m_projectToProjectsInfo.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)
|
|
|
|
{
|
|
|
|
if (!projectInfo.isValid())
|
|
|
|
return;
|
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-08 15:48:17 +02:00
|
|
|
void CppModelManager::closeCppEditorDocuments()
|
|
|
|
{
|
|
|
|
QList<Core::IDocument *> cppDocumentsToClose;
|
|
|
|
foreach (CppEditorDocumentHandle *cppDocument, cppEditorDocuments())
|
|
|
|
cppDocumentsToClose << cppDocument->processor()->baseTextDocument();
|
|
|
|
QTC_CHECK(Core::EditorManager::closeDocuments(cppDocumentsToClose));
|
|
|
|
}
|
|
|
|
|
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);
|
2013-07-10 14:46:08 +02:00
|
|
|
QSetIterator<QString> i(filesToRemove);
|
|
|
|
while (i.hasNext())
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_snapshot.remove(i.next());
|
2013-07-10 14:46:08 +02:00
|
|
|
}
|
|
|
|
|
2015-07-15 17:15:57 +02:00
|
|
|
static QSet<QString> projectPartIds(const QSet<ProjectPart::Ptr> &projectParts)
|
2015-05-08 15:48:17 +02:00
|
|
|
{
|
2015-07-15 17:15:57 +02:00
|
|
|
return Utils::transform(projectParts, [](const ProjectPart::Ptr &projectPart) {
|
|
|
|
return projectPart->id();
|
|
|
|
});
|
2015-05-08 15:48:17 +02:00
|
|
|
}
|
|
|
|
|
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()
|
|
|
|
{
|
2015-07-15 17:15:57 +02:00
|
|
|
QSet<QString> removed = projectPartIds(m_old.projectParts().toSet());
|
|
|
|
removed.subtract(projectPartIds(m_new.projectParts().toSet()));
|
|
|
|
return removed.toList();
|
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;
|
|
|
|
QSetIterator<QString> i(commonSourceFiles);
|
|
|
|
while (i.hasNext()) {
|
|
|
|
const QString file = i.next();
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
foreach (const ProjectInfo &projectInfo, d->m_projectToProjectsInfo) {
|
2013-10-04 12:25:26 +02:00
|
|
|
foreach (const ProjectPart::Ptr &projectPart, projectInfo.projectParts()) {
|
2015-07-14 17:30:17 +02:00
|
|
|
d->m_projectPartIdToProjectProjectPart[projectPart->id()] = projectPart;
|
2013-12-02 15:23:13 +01:00
|
|
|
foreach (const ProjectFile &cxxFile, projectPart->files)
|
2014-11-27 12:40:34 +01:00
|
|
|
d->m_fileToProjectParts[Utils::FileName::fromString(cxxFile.path)].append(
|
|
|
|
projectPart);
|
2013-12-02 15:23:13 +01:00
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2014-12-02 12:11:05 +01:00
|
|
|
void CppModelManager::updateCppEditorDocuments() 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);
|
2014-11-24 11:19:41 +01:00
|
|
|
theCppEditorDocument->processor()->run();
|
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
|
|
|
|
= Core::DocumentModel::openedDocuments().toSet();
|
|
|
|
invisibleCppEditorDocuments.subtract(visibleCppEditorDocuments);
|
|
|
|
foreach (Core::IDocument *document, invisibleCppEditorDocuments) {
|
2014-11-24 11:19:41 +01:00
|
|
|
const QString filePath = document->filePath().toString();
|
|
|
|
if (CppEditorDocumentHandle *theCppEditorDocument = cppEditorDocument(filePath))
|
|
|
|
theCppEditorDocument->setNeedsRefresh(true);
|
2014-10-13 14:46:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-10 14:46:08 +02:00
|
|
|
QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectInfo)
|
|
|
|
{
|
|
|
|
if (!newProjectInfo.isValid())
|
2013-07-11 11:13:07 +02:00
|
|
|
return QFuture<void>();
|
2012-02-16 15:09:56 +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;
|
|
|
|
|
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
|
|
|
|
|
|
|
ProjectExplorer::Project *project = newProjectInfo.project().data();
|
2014-09-04 14:59:50 +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
|
2014-09-15 00:12:27 +02:00
|
|
|
ProjectInfo oldProjectInfo = d->m_projectToProjectsInfo.value(project);
|
2013-06-28 11:26:02 +02:00
|
|
|
if (oldProjectInfo.isValid()) {
|
2013-07-10 14:46:08 +02:00
|
|
|
ProjectInfoComparer comparer(oldProjectInfo, 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()) {
|
|
|
|
removeProjectInfoFilesAndIncludesFromSnapshot(oldProjectInfo);
|
|
|
|
filesToReindex.unite(newSourceFiles);
|
|
|
|
|
|
|
|
// The "configuration file" includes all defines and therefore should be updated
|
|
|
|
if (comparer.definesChanged()) {
|
|
|
|
QMutexLocker snapshotLocker(&d->m_snapshotMutex);
|
|
|
|
d->m_snapshot.remove(configurationFileName());
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
emit aboutToRemoveFiles(removedFiles.toList());
|
|
|
|
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
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_projectToProjectsInfo.insert(project, newProjectInfo);
|
2015-07-14 17:30:17 +02:00
|
|
|
recalculateProjectPartMappings();
|
2012-02-16 15:09:56 +01:00
|
|
|
|
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
|
2013-07-10 14:46:08 +02:00
|
|
|
emit projectPartsUpdated(newProjectInfo.project().data());
|
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.
|
2014-12-02 12:11:05 +01:00
|
|
|
updateCppEditorDocuments();
|
2014-10-13 14:46:03 +02:00
|
|
|
|
2013-07-10 14:46:08 +02:00
|
|
|
// Trigger reindexing
|
|
|
|
return updateSourceFiles(filesToReindex, ForcedProgressNotification);
|
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
|
|
|
}
|
|
|
|
|
2014-11-27 12:40:34 +01:00
|
|
|
QList<ProjectPart::Ptr> CppModelManager::projectPart(const Utils::FileName &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(
|
|
|
|
const Utils::FileName &fileName) const
|
2013-08-19 16:05:29 +02:00
|
|
|
{
|
|
|
|
QSet<ProjectPart::Ptr> parts;
|
2014-11-27 12:11:46 +01:00
|
|
|
const Utils::FileNameList 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);
|
|
|
|
foreach (const Utils::FileName &dep, deps) {
|
2014-11-27 12:40:34 +01:00
|
|
|
parts.unite(QSet<ProjectPart::Ptr>::fromList(d->m_fileToProjectParts.value(dep)));
|
2014-10-06 15:18:26 +02:00
|
|
|
}
|
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
|
|
|
{
|
|
|
|
ProjectPart::Ptr part(new ProjectPart);
|
|
|
|
|
2015-11-06 16:50:02 +01:00
|
|
|
part->projectDefines = definedMacros();
|
|
|
|
part->headerPaths = headerPaths();
|
2014-08-21 16:26:06 +02:00
|
|
|
part->languageVersion = ProjectPart::CXX14;
|
2015-11-05 13:57:57 +01:00
|
|
|
|
|
|
|
// Do not activate ObjectiveCExtensions since this will lead to the
|
|
|
|
// "objective-c++" language option for a project-less *.cpp file.
|
2014-08-21 16:26:06 +02:00
|
|
|
part->languageExtensions = ProjectPart::AllExtensions;
|
2015-11-05 13:57:57 +01:00
|
|
|
part->languageExtensions &= ~ProjectPart::ObjectiveCExtensions;
|
|
|
|
|
2013-08-19 18:20:49 +02:00
|
|
|
part->qtVersion = ProjectPart::Qt5;
|
2015-02-15 23:43:26 +02:00
|
|
|
part->updateLanguageFeatures();
|
2013-08-19 18:20:49 +02:00
|
|
|
|
|
|
|
return part;
|
|
|
|
}
|
|
|
|
|
2015-12-01 11:57:08 +01:00
|
|
|
bool CppModelManager::isCppEditor(Core::IEditor *editor)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-06-25 17:37:59 +02:00
|
|
|
return editor->context().contains(ProjectExplorer::Constants::LANG_CXX);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2015-11-11 10:47:27 +01:00
|
|
|
bool CppModelManager::isClangCodeModelAvailable() const
|
2015-08-31 15:41:02 +02:00
|
|
|
{
|
2015-11-11 10:47:27 +01:00
|
|
|
return d->m_clangModelManagerSupportProvider != nullptr;
|
|
|
|
}
|
2015-08-31 15:41:02 +02:00
|
|
|
|
2015-11-11 10:47:27 +01:00
|
|
|
bool CppModelManager::isClangCodeModelActive() const
|
|
|
|
{
|
|
|
|
return isClangCodeModelAvailable()
|
|
|
|
&& 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,
|
|
|
|
const QByteArray &contents)
|
|
|
|
{
|
|
|
|
emit abstractEditorSupportContentsUpdated(filePath, contents);
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2015-07-14 17:30:17 +02:00
|
|
|
static QStringList idsOfAllProjectParts(const ProjectInfo &projectInfo)
|
2015-05-08 15:48:17 +02:00
|
|
|
{
|
|
|
|
QStringList projectPaths;
|
|
|
|
foreach (const ProjectPart::Ptr &part, projectInfo.projectParts())
|
2015-07-14 17:30:17 +02:00
|
|
|
projectPaths << part->id();
|
2015-05-08 15:48:17 +02:00
|
|
|
return projectPaths;
|
|
|
|
}
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
void CppModelManager::onAboutToRemoveProject(ProjectExplorer::Project *project)
|
|
|
|
{
|
2015-07-14 17:30:17 +02:00
|
|
|
QStringList projectPartIds;
|
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;
|
2015-05-08 15:48:17 +02:00
|
|
|
|
|
|
|
// Save paths
|
|
|
|
const ProjectInfo projectInfo = d->m_projectToProjectsInfo.value(project, ProjectInfo());
|
2015-07-14 17:30:17 +02:00
|
|
|
projectPartIds = idsOfAllProjectParts(projectInfo);
|
2015-05-08 15:48:17 +02:00
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_projectToProjectsInfo.remove(project);
|
2015-07-14 17:30:17 +02:00
|
|
|
recalculateProjectPartMappings();
|
2015-05-08 15:48:17 +02:00
|
|
|
}
|
|
|
|
|
2015-07-14 17:30:17 +02:00
|
|
|
if (!projectPartIds.isEmpty())
|
|
|
|
emit projectPartsRemoved(projectPartIds);
|
2008-12-08 10:44:56 +01:00
|
|
|
|
2013-07-18 10:57:19 +02:00
|
|
|
delayedGC();
|
|
|
|
}
|
|
|
|
|
2014-08-05 11:34:52 +02:00
|
|
|
void CppModelManager::onSourceFilesRefreshed() const
|
|
|
|
{
|
|
|
|
if (BuiltinIndexingSupport::isFindErrorsIndexingActive()) {
|
|
|
|
QTimer::singleShot(1, QCoreApplication::instance(), SLOT(quit()));
|
|
|
|
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)) {
|
|
|
|
if (theCppEditorDocument->needsRefresh()) {
|
|
|
|
theCppEditorDocument->setNeedsRefresh(false);
|
|
|
|
theCppEditorDocument->processor()->run();
|
2014-12-02 12:11:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-08 15:48:17 +02:00
|
|
|
void CppModelManager::onCodeModelSettingsChanged()
|
|
|
|
{
|
2015-11-11 10:47:27 +01:00
|
|
|
const bool isClangActive = isClangCodeModelActive();
|
|
|
|
const QSharedPointer<CppCodeModelSettings> settings
|
|
|
|
= CppToolsPlugin::instance()->codeModelSettings();
|
2015-05-08 15:48:17 +02:00
|
|
|
|
2015-11-11 10:47:27 +01:00
|
|
|
ModelManagerSupport::Ptr newCodeModelSupport;
|
2015-05-08 15:48:17 +02:00
|
|
|
|
2015-11-11 10:47:27 +01:00
|
|
|
if (isClangCodeModelAvailable()) {
|
|
|
|
if (!isClangActive && settings->useClangCodeModel())
|
|
|
|
newCodeModelSupport = d->m_clangModelManagerSupportProvider->createModelManagerSupport();
|
|
|
|
else if (isClangActive && !settings->useClangCodeModel())
|
|
|
|
newCodeModelSupport = d->m_builtinModelManagerSupport;
|
|
|
|
}
|
2015-05-08 15:48:17 +02:00
|
|
|
|
2015-11-11 10:47:27 +01:00
|
|
|
if (newCodeModelSupport) {
|
2015-05-08 15:48:17 +02:00
|
|
|
closeCppEditorDocuments();
|
2015-11-11 10:47:27 +01:00
|
|
|
d->m_activeModelManagerSupport = newCodeModelSupport;
|
|
|
|
}
|
2015-05-08 15:48:17 +02: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();
|
|
|
|
}
|
|
|
|
|
2009-08-13 17:10:53 +02:00
|
|
|
void CppModelManager::onAboutToUnloadSession()
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2013-09-03 15:18:37 +02:00
|
|
|
Core::ProgressManager::cancelTasks(CppTools::Constants::TASK_INDEX);
|
2008-12-08 10:44:56 +01:00
|
|
|
do {
|
2014-09-15 00:12:27 +02:00
|
|
|
QMutexLocker locker(&d->m_projectMutex);
|
|
|
|
d->m_projectToProjectsInfo.clear();
|
2015-07-14 17:30:17 +02:00
|
|
|
recalculateProjectPartMappings();
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_dirty = true;
|
2008-12-08 10:44:56 +01:00
|
|
|
} while (0);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2014-09-24 13:42:17 +02:00
|
|
|
void CppModelManager::renameIncludes(const QString &oldFileName, const QString &newFileName)
|
|
|
|
{
|
|
|
|
if (oldFileName.isEmpty() || newFileName.isEmpty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
const QFileInfo oldFileInfo(oldFileName);
|
|
|
|
const QFileInfo newFileInfo(newFileName);
|
|
|
|
|
|
|
|
// We just want to handle renamings so return when the file was actually moved.
|
|
|
|
if (oldFileInfo.absoluteDir() != newFileInfo.absoluteDir())
|
|
|
|
return;
|
|
|
|
|
|
|
|
const TextEditor::RefactoringChanges changes;
|
|
|
|
|
|
|
|
foreach (Snapshot::IncludeLocation loc, snapshot().includeLocationsOfDocument(oldFileName)) {
|
|
|
|
TextEditor::RefactoringFilePtr file = changes.file(loc.first->fileName());
|
2015-10-01 14:54:31 +02:00
|
|
|
const QTextBlock &block = file->document()->findBlockByNumber(loc.second - 1);
|
2014-09-24 13:42:17 +02:00
|
|
|
const int replaceStart = block.text().indexOf(oldFileInfo.fileName());
|
|
|
|
if (replaceStart > -1) {
|
|
|
|
Utils::ChangeSet changeSet;
|
|
|
|
changeSet.replace(block.position() + replaceStart,
|
|
|
|
block.position() + replaceStart + oldFileInfo.fileName().length(),
|
|
|
|
newFileInfo.fileName());
|
|
|
|
file->setChangeSet(changeSet);
|
|
|
|
file->apply();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-19 16:56:12 +02:00
|
|
|
void CppModelManager::onCoreAboutToClose()
|
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
d->m_enableGC = false;
|
2013-04-19 16:56:12 +02:00
|
|
|
}
|
|
|
|
|
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();
|
2014-11-27 12:11:46 +01:00
|
|
|
QSet<Utils::FileName> 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();
|
|
|
|
|
2014-11-27 12:11:46 +01:00
|
|
|
const Utils::FileName fileName = Utils::FileName::fromString(file);
|
|
|
|
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) {
|
2014-11-27 12:11:46 +01:00
|
|
|
const Utils::FileName &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-11-11 10:47:27 +01:00
|
|
|
void CppModelManager::setClangModelManagerSupportProvider(
|
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);
|
2015-11-11 10:47:27 +01:00
|
|
|
QTC_CHECK(d->m_clangModelManagerSupportProvider == nullptr);
|
2015-05-08 15:48:17 +02:00
|
|
|
|
2015-11-11 10:47:27 +01:00
|
|
|
d->m_clangModelManagerSupportProvider = modelManagerSupportProvider;
|
2013-08-30 12:55:06 +02:00
|
|
|
|
2015-11-11 10:47:27 +01:00
|
|
|
onCodeModelSettingsChanged();
|
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
|
|
|
}
|
|
|
|
|
2014-08-19 15:59:29 +02:00
|
|
|
BaseEditorDocumentProcessor *CppModelManager::editorDocumentProcessor(
|
2014-09-22 18:43:31 +02:00
|
|
|
TextEditor::TextDocument *baseTextDocument) const
|
2012-02-07 15:09:08 +01:00
|
|
|
{
|
2015-11-11 10:47:27 +01:00
|
|
|
return d->m_activeModelManagerSupport->editorDocumentProcessor(baseTextDocument);
|
2012-02-20 12:39:08 +01:00
|
|
|
}
|
|
|
|
|
2012-11-23 11:47:39 +01:00
|
|
|
void CppModelManager::setIndexingSupport(CppIndexingSupport *indexingSupport)
|
2012-10-16 16:02:40 +02:00
|
|
|
{
|
2014-10-06 11:26:58 +02:00
|
|
|
if (indexingSupport) {
|
|
|
|
if (dynamic_cast<BuiltinIndexingSupport *>(indexingSupport))
|
|
|
|
d->m_indexingSupporter = 0;
|
|
|
|
else
|
|
|
|
d->m_indexingSupporter = indexingSupport;
|
|
|
|
}
|
2012-11-23 11:47:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
CppIndexingSupport *CppModelManager::indexingSupport()
|
|
|
|
{
|
2014-09-15 00:12:27 +02:00
|
|
|
return d->m_indexingSupporter ? d->m_indexingSupporter : 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
|
|
|
}
|
|
|
|
|
|
|
|
ProjectPart::HeaderPaths CppModelManager::headerPaths()
|
|
|
|
{
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CppModelManager::setHeaderPaths(const ProjectPart::HeaderPaths &headerPaths)
|
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
QByteArray CppModelManager::definedMacros()
|
|
|
|
{
|
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;
|
|
|
|
}
|
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
} // namespace CppTools
|