forked from qt-creator/qt-creator
CppIndexingSupport: Flatten class hierarchy
Don't make CppIndexingSupport a pure virtual class as there is only one subclass. Change-Id: I9f216a2f1f5d04f601d07b9507a4e9cf27ff7c46 Reviewed-by: Christian Kandeler <christian.kandeler@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
@@ -10,7 +10,6 @@ add_qtc_plugin(CppEditor
|
||||
builtincursorinfo.cpp builtincursorinfo.h
|
||||
builtineditordocumentparser.cpp builtineditordocumentparser.h
|
||||
builtineditordocumentprocessor.cpp builtineditordocumentprocessor.h
|
||||
builtinindexingsupport.cpp builtinindexingsupport.h
|
||||
clangdiagnosticconfig.cpp clangdiagnosticconfig.h
|
||||
clangdiagnosticconfigsmodel.cpp clangdiagnosticconfigsmodel.h
|
||||
clangdiagnosticconfigsselectionwidget.cpp clangdiagnosticconfigsselectionwidget.h
|
||||
|
@@ -1,361 +0,0 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "builtinindexingsupport.h"
|
||||
|
||||
#include "builtineditordocumentparser.h"
|
||||
#include "cppchecksymbols.h"
|
||||
#include "cppeditorconstants.h"
|
||||
#include "cppmodelmanager.h"
|
||||
#include "cppprojectfile.h"
|
||||
#include "cppsourceprocessor.h"
|
||||
#include "cpptoolsreuse.h"
|
||||
#include "searchsymbols.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/find/searchresultwindow.h>
|
||||
#include <coreplugin/progressmanager/progressmanager.h>
|
||||
|
||||
#include <cplusplus/LookupContext.h>
|
||||
#include <utils/environment.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/runextensions.h>
|
||||
#include <utils/stringutils.h>
|
||||
#include <utils/temporarydirectory.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QElapsedTimer>
|
||||
#include <QLoggingCategory>
|
||||
#include <QRegularExpression>
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
namespace CppEditor::Internal {
|
||||
|
||||
static Q_LOGGING_CATEGORY(indexerLog, "qtc.cppeditor.indexer", QtWarningMsg)
|
||||
|
||||
namespace {
|
||||
|
||||
class ParseParams
|
||||
{
|
||||
public:
|
||||
ProjectExplorer::HeaderPaths headerPaths;
|
||||
WorkingCopy workingCopy;
|
||||
QSet<QString> sourceFiles;
|
||||
int indexerFileSizeLimitInMb = -1;
|
||||
};
|
||||
|
||||
class WriteTaskFileForDiagnostics
|
||||
{
|
||||
Q_DISABLE_COPY(WriteTaskFileForDiagnostics)
|
||||
|
||||
public:
|
||||
WriteTaskFileForDiagnostics()
|
||||
{
|
||||
const QString fileName = Utils::TemporaryDirectory::masterDirectoryPath()
|
||||
+ "/qtc_findErrorsIndexing.diagnostics."
|
||||
+ QDateTime::currentDateTime().toString("yyMMdd_HHmm") + ".tasks";
|
||||
|
||||
m_file.setFileName(fileName);
|
||||
Q_ASSERT(m_file.open(QIODevice::WriteOnly | QIODevice::Text));
|
||||
m_out.setDevice(&m_file);
|
||||
|
||||
qDebug("FindErrorsIndexing: Task file for diagnostics is \"%s\".",
|
||||
qPrintable(m_file.fileName()));
|
||||
}
|
||||
|
||||
~WriteTaskFileForDiagnostics()
|
||||
{
|
||||
qDebug("FindErrorsIndexing: %d diagnostic messages written to \"%s\".",
|
||||
m_processedDiagnostics, qPrintable(m_file.fileName()));
|
||||
}
|
||||
|
||||
void process(const CPlusPlus::Document::Ptr document)
|
||||
{
|
||||
using namespace CPlusPlus;
|
||||
const QString fileName = document->filePath().toString();
|
||||
|
||||
const QList<Document::DiagnosticMessage> messages = document->diagnosticMessages();
|
||||
for (const Document::DiagnosticMessage &message : messages) {
|
||||
++m_processedDiagnostics;
|
||||
|
||||
QString type;
|
||||
switch (message.level()) {
|
||||
case Document::DiagnosticMessage::Warning:
|
||||
type = QLatin1String("warn"); break;
|
||||
case Document::DiagnosticMessage::Error:
|
||||
case Document::DiagnosticMessage::Fatal:
|
||||
type = QLatin1String("err"); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// format: file\tline\ttype\tdescription
|
||||
m_out << fileName << "\t"
|
||||
<< message.line() << "\t"
|
||||
<< type << "\t"
|
||||
<< message.text() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QFile m_file;
|
||||
QTextStream m_out;
|
||||
int m_processedDiagnostics = 0;
|
||||
};
|
||||
|
||||
void classifyFiles(const QSet<QString> &files, QStringList *headers, QStringList *sources)
|
||||
{
|
||||
for (const QString &file : files) {
|
||||
if (ProjectFile::isSource(ProjectFile::classify(file)))
|
||||
sources->append(file);
|
||||
else
|
||||
headers->append(file);
|
||||
}
|
||||
}
|
||||
|
||||
void indexFindErrors(QFutureInterface<void> &indexingFuture,
|
||||
const ParseParams params)
|
||||
{
|
||||
QStringList sources, headers;
|
||||
classifyFiles(params.sourceFiles, &headers, &sources);
|
||||
sources.sort();
|
||||
headers.sort();
|
||||
QStringList files = sources + headers;
|
||||
|
||||
WriteTaskFileForDiagnostics taskFileWriter;
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
|
||||
for (int i = 0, end = files.size(); i < end ; ++i) {
|
||||
if (indexingFuture.isCanceled())
|
||||
break;
|
||||
|
||||
const QString file = files.at(i);
|
||||
qDebug("FindErrorsIndexing: \"%s\"", qPrintable(file));
|
||||
|
||||
// Parse the file as precisely as possible
|
||||
BuiltinEditorDocumentParser parser(FilePath::fromString(file));
|
||||
parser.setReleaseSourceAndAST(false);
|
||||
parser.update({CppModelManager::instance()->workingCopy(), nullptr,
|
||||
Utils::Language::Cxx, false});
|
||||
CPlusPlus::Document::Ptr document = parser.document();
|
||||
QTC_ASSERT(document, return);
|
||||
|
||||
// Write diagnostic messages
|
||||
taskFileWriter.process(document);
|
||||
|
||||
// Look up symbols
|
||||
CPlusPlus::LookupContext context(document, parser.snapshot());
|
||||
CheckSymbols::go(document, context, QList<CheckSymbols::Result>()).waitForFinished();
|
||||
|
||||
document->releaseSourceAndAST();
|
||||
|
||||
indexingFuture.setProgressValue(i + 1);
|
||||
}
|
||||
|
||||
const QString elapsedTime = Utils::formatElapsedTime(timer.elapsed());
|
||||
qDebug("FindErrorsIndexing: %s", qPrintable(elapsedTime));
|
||||
}
|
||||
|
||||
void index(QFutureInterface<void> &indexingFuture,
|
||||
const ParseParams params)
|
||||
{
|
||||
QScopedPointer<CppSourceProcessor> sourceProcessor(CppModelManager::createSourceProcessor());
|
||||
sourceProcessor->setFileSizeLimitInMb(params.indexerFileSizeLimitInMb);
|
||||
sourceProcessor->setHeaderPaths(params.headerPaths);
|
||||
sourceProcessor->setWorkingCopy(params.workingCopy);
|
||||
|
||||
QStringList sources;
|
||||
QStringList headers;
|
||||
classifyFiles(params.sourceFiles, &headers, &sources);
|
||||
|
||||
for (const QString &file : std::as_const(params.sourceFiles))
|
||||
sourceProcessor->removeFromCache(FilePath::fromString(file));
|
||||
|
||||
const int sourceCount = sources.size();
|
||||
QStringList files = sources + headers;
|
||||
|
||||
sourceProcessor->setTodo(Utils::toSet(files));
|
||||
|
||||
const FilePath &conf = CppModelManager::configurationFileName();
|
||||
bool processingHeaders = false;
|
||||
|
||||
CppModelManager *cmm = CppModelManager::instance();
|
||||
const ProjectExplorer::HeaderPaths fallbackHeaderPaths = cmm->headerPaths();
|
||||
const CPlusPlus::LanguageFeatures defaultFeatures =
|
||||
CPlusPlus::LanguageFeatures::defaultFeatures();
|
||||
|
||||
qCDebug(indexerLog) << "About to index" << files.size() << "files.";
|
||||
for (int i = 0; i < files.size(); ++i) {
|
||||
if (indexingFuture.isCanceled())
|
||||
break;
|
||||
|
||||
const QString fileName = files.at(i);
|
||||
const QList<ProjectPart::ConstPtr> parts = cmm->projectPart(fileName);
|
||||
const CPlusPlus::LanguageFeatures languageFeatures = parts.isEmpty()
|
||||
? defaultFeatures
|
||||
: parts.first()->languageFeatures;
|
||||
sourceProcessor->setLanguageFeatures(languageFeatures);
|
||||
|
||||
const bool isSourceFile = i < sourceCount;
|
||||
if (isSourceFile) {
|
||||
sourceProcessor->run(conf);
|
||||
} else if (!processingHeaders) {
|
||||
sourceProcessor->run(conf);
|
||||
|
||||
processingHeaders = true;
|
||||
}
|
||||
|
||||
qCDebug(indexerLog) << " Indexing" << i + 1 << "of" << files.size() << ":" << fileName;
|
||||
ProjectExplorer::HeaderPaths headerPaths = parts.isEmpty()
|
||||
? fallbackHeaderPaths
|
||||
: parts.first()->headerPaths;
|
||||
sourceProcessor->setHeaderPaths(headerPaths);
|
||||
sourceProcessor->run(FilePath::fromString(fileName));
|
||||
|
||||
indexingFuture.setProgressValue(files.size() - sourceProcessor->todo().size());
|
||||
|
||||
if (isSourceFile)
|
||||
sourceProcessor->resetEnvironment();
|
||||
}
|
||||
qCDebug(indexerLog) << "Indexing finished.";
|
||||
}
|
||||
|
||||
void parse(QFutureInterface<void> &indexingFuture, const ParseParams params)
|
||||
{
|
||||
const QSet<QString> &files = params.sourceFiles;
|
||||
if (files.isEmpty())
|
||||
return;
|
||||
|
||||
indexingFuture.setProgressRange(0, files.size());
|
||||
|
||||
if (BuiltinIndexingSupport::isFindErrorsIndexingActive())
|
||||
indexFindErrors(indexingFuture, params);
|
||||
else
|
||||
index(indexingFuture, params);
|
||||
|
||||
indexingFuture.setProgressValue(files.size());
|
||||
CppModelManager::instance()->finishedRefreshingSourceFiles(files);
|
||||
}
|
||||
|
||||
class BuiltinSymbolSearcher: public SymbolSearcher
|
||||
{
|
||||
public:
|
||||
BuiltinSymbolSearcher(const CPlusPlus::Snapshot &snapshot,
|
||||
const Parameters ¶meters, const QSet<QString> &fileNames)
|
||||
: m_snapshot(snapshot)
|
||||
, m_parameters(parameters)
|
||||
, m_fileNames(fileNames)
|
||||
{}
|
||||
|
||||
~BuiltinSymbolSearcher() override = default;
|
||||
|
||||
void runSearch(QFutureInterface<Core::SearchResultItem> &future) override
|
||||
{
|
||||
future.setProgressRange(0, m_snapshot.size());
|
||||
future.setProgressValue(0);
|
||||
int progress = 0;
|
||||
|
||||
SearchSymbols search;
|
||||
search.setSymbolsToSearchFor(m_parameters.types);
|
||||
CPlusPlus::Snapshot::const_iterator it = m_snapshot.begin();
|
||||
|
||||
QString findString = (m_parameters.flags & Core::FindRegularExpression
|
||||
? m_parameters.text : QRegularExpression::escape(m_parameters.text));
|
||||
if (m_parameters.flags & Core::FindWholeWords)
|
||||
findString = QString::fromLatin1("\\b%1\\b").arg(findString);
|
||||
QRegularExpression matcher(findString, (m_parameters.flags & Core::FindCaseSensitively
|
||||
? QRegularExpression::NoPatternOption
|
||||
: QRegularExpression::CaseInsensitiveOption));
|
||||
matcher.optimize();
|
||||
while (it != m_snapshot.end()) {
|
||||
if (future.isPaused())
|
||||
future.waitForResume();
|
||||
if (future.isCanceled())
|
||||
break;
|
||||
if (m_fileNames.isEmpty() || m_fileNames.contains(it.value()->filePath().path())) {
|
||||
QVector<Core::SearchResultItem> resultItems;
|
||||
auto filter = [&](const IndexItem::Ptr &info) -> IndexItem::VisitorResult {
|
||||
if (matcher.match(info->symbolName()).hasMatch()) {
|
||||
QString text = info->symbolName();
|
||||
QString scope = info->symbolScope();
|
||||
if (info->type() == IndexItem::Function) {
|
||||
QString name;
|
||||
info->unqualifiedNameAndScope(info->symbolName(), &name, &scope);
|
||||
text = name + info->symbolType();
|
||||
} else if (info->type() == IndexItem::Declaration){
|
||||
text = info->representDeclaration();
|
||||
}
|
||||
|
||||
Core::SearchResultItem item;
|
||||
item.setPath(scope.split(QLatin1String("::"), Qt::SkipEmptyParts));
|
||||
item.setLineText(text);
|
||||
item.setIcon(info->icon());
|
||||
item.setUserData(QVariant::fromValue(info));
|
||||
resultItems << item;
|
||||
}
|
||||
|
||||
return IndexItem::Recurse;
|
||||
};
|
||||
search(it.value())->visitAllChildren(filter);
|
||||
if (!resultItems.isEmpty())
|
||||
future.reportResults(resultItems);
|
||||
}
|
||||
++it;
|
||||
++progress;
|
||||
future.setProgressValue(progress);
|
||||
}
|
||||
if (future.isPaused())
|
||||
future.waitForResume();
|
||||
}
|
||||
|
||||
private:
|
||||
const CPlusPlus::Snapshot m_snapshot;
|
||||
const Parameters m_parameters;
|
||||
const QSet<QString> m_fileNames;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
BuiltinIndexingSupport::BuiltinIndexingSupport()
|
||||
{
|
||||
m_synchronizer.setCancelOnWait(true);
|
||||
}
|
||||
|
||||
BuiltinIndexingSupport::~BuiltinIndexingSupport() = default;
|
||||
|
||||
QFuture<void> BuiltinIndexingSupport::refreshSourceFiles(
|
||||
const QSet<QString> &sourceFiles, CppModelManager::ProgressNotificationMode mode)
|
||||
{
|
||||
CppModelManager *mgr = CppModelManager::instance();
|
||||
|
||||
ParseParams params;
|
||||
params.indexerFileSizeLimitInMb = indexerFileSizeLimitInMb();
|
||||
params.headerPaths = mgr->headerPaths();
|
||||
params.workingCopy = mgr->workingCopy();
|
||||
params.sourceFiles = sourceFiles;
|
||||
|
||||
QFuture<void> result = Utils::runAsync(mgr->sharedThreadPool(), parse, params);
|
||||
m_synchronizer.addFuture(result);
|
||||
|
||||
if (mode == CppModelManager::ForcedProgressNotification || sourceFiles.count() > 1) {
|
||||
Core::ProgressManager::addTask(result, QCoreApplication::translate("CppEditor::Internal::BuiltinIndexingSupport", "Parsing C/C++ Files"),
|
||||
CppEditor::Constants::TASK_INDEX);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SymbolSearcher *BuiltinIndexingSupport::createSymbolSearcher(
|
||||
const SymbolSearcher::Parameters ¶meters, const QSet<QString> &fileNames)
|
||||
{
|
||||
return new BuiltinSymbolSearcher(CppModelManager::instance()->snapshot(), parameters, fileNames);
|
||||
}
|
||||
|
||||
bool BuiltinIndexingSupport::isFindErrorsIndexingActive()
|
||||
{
|
||||
return Utils::qtcEnvironmentVariable("QTC_FIND_ERRORS_INDEXING") == "1";
|
||||
}
|
||||
|
||||
} // namespace CppEditor::Internal
|
@@ -1,30 +0,0 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cppindexingsupport.h"
|
||||
#include "cppmodelmanager.h"
|
||||
|
||||
#include <utils/futuresynchronizer.h>
|
||||
|
||||
namespace CppEditor::Internal {
|
||||
|
||||
class BuiltinIndexingSupport: public CppIndexingSupport {
|
||||
public:
|
||||
BuiltinIndexingSupport();
|
||||
~BuiltinIndexingSupport() override;
|
||||
|
||||
QFuture<void> refreshSourceFiles(const QSet<QString> &sourceFiles,
|
||||
CppModelManager::ProgressNotificationMode mode) override;
|
||||
SymbolSearcher *createSymbolSearcher(const SymbolSearcher::Parameters ¶meters,
|
||||
const QSet<QString> &fileNames) override;
|
||||
|
||||
public:
|
||||
static bool isFindErrorsIndexingActive();
|
||||
|
||||
private:
|
||||
Utils::FutureSynchronizer m_synchronizer;
|
||||
};
|
||||
|
||||
} // namespace CppEditor::Internal
|
@@ -39,8 +39,6 @@ QtcPlugin {
|
||||
"builtineditordocumentparser.h",
|
||||
"builtineditordocumentprocessor.cpp",
|
||||
"builtineditordocumentprocessor.h",
|
||||
"builtinindexingsupport.cpp",
|
||||
"builtinindexingsupport.h",
|
||||
"clangdiagnosticconfig.cpp",
|
||||
"clangdiagnosticconfig.h",
|
||||
"clangdiagnosticconfigsmodel.cpp",
|
||||
|
@@ -3,9 +3,29 @@
|
||||
|
||||
#include "cppindexingsupport.h"
|
||||
|
||||
#include "builtineditordocumentparser.h"
|
||||
#include "cppchecksymbols.h"
|
||||
#include "cppeditorconstants.h"
|
||||
#include "cppsourceprocessor.h"
|
||||
#include "searchsymbols.h"
|
||||
|
||||
#include <coreplugin/find/searchresultitem.h>
|
||||
#include <coreplugin/progressmanager/progressmanager.h>
|
||||
|
||||
#include <cplusplus/LookupContext.h>
|
||||
|
||||
#include <utils/filepath.h>
|
||||
#include <utils/runextensions.h>
|
||||
#include <utils/stringutils.h>
|
||||
#include <utils/temporarydirectory.h>
|
||||
|
||||
#include <QLoggingCategory>
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
namespace CppEditor {
|
||||
|
||||
CppIndexingSupport::~CppIndexingSupport() = default;
|
||||
static Q_LOGGING_CATEGORY(indexerLog, "qtc.cppeditor.indexer", QtWarningMsg)
|
||||
|
||||
SymbolSearcher::SymbolSearcher(QObject *parent)
|
||||
: QObject(parent)
|
||||
@@ -14,4 +34,329 @@ SymbolSearcher::SymbolSearcher(QObject *parent)
|
||||
|
||||
SymbolSearcher::~SymbolSearcher() = default;
|
||||
|
||||
namespace {
|
||||
|
||||
class ParseParams
|
||||
{
|
||||
public:
|
||||
ProjectExplorer::HeaderPaths headerPaths;
|
||||
WorkingCopy workingCopy;
|
||||
QSet<QString> sourceFiles;
|
||||
int indexerFileSizeLimitInMb = -1;
|
||||
};
|
||||
|
||||
class WriteTaskFileForDiagnostics
|
||||
{
|
||||
Q_DISABLE_COPY(WriteTaskFileForDiagnostics)
|
||||
|
||||
public:
|
||||
WriteTaskFileForDiagnostics()
|
||||
{
|
||||
const QString fileName = Utils::TemporaryDirectory::masterDirectoryPath()
|
||||
+ "/qtc_findErrorsIndexing.diagnostics."
|
||||
+ QDateTime::currentDateTime().toString("yyMMdd_HHmm") + ".tasks";
|
||||
|
||||
m_file.setFileName(fileName);
|
||||
Q_ASSERT(m_file.open(QIODevice::WriteOnly | QIODevice::Text));
|
||||
m_out.setDevice(&m_file);
|
||||
|
||||
qDebug("FindErrorsIndexing: Task file for diagnostics is \"%s\".",
|
||||
qPrintable(m_file.fileName()));
|
||||
}
|
||||
|
||||
~WriteTaskFileForDiagnostics()
|
||||
{
|
||||
qDebug("FindErrorsIndexing: %d diagnostic messages written to \"%s\".",
|
||||
m_processedDiagnostics, qPrintable(m_file.fileName()));
|
||||
}
|
||||
|
||||
void process(const CPlusPlus::Document::Ptr document)
|
||||
{
|
||||
using namespace CPlusPlus;
|
||||
const QString fileName = document->filePath().toString();
|
||||
|
||||
const QList<Document::DiagnosticMessage> messages = document->diagnosticMessages();
|
||||
for (const Document::DiagnosticMessage &message : messages) {
|
||||
++m_processedDiagnostics;
|
||||
|
||||
QString type;
|
||||
switch (message.level()) {
|
||||
case Document::DiagnosticMessage::Warning:
|
||||
type = QLatin1String("warn"); break;
|
||||
case Document::DiagnosticMessage::Error:
|
||||
case Document::DiagnosticMessage::Fatal:
|
||||
type = QLatin1String("err"); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// format: file\tline\ttype\tdescription
|
||||
m_out << fileName << "\t"
|
||||
<< message.line() << "\t"
|
||||
<< type << "\t"
|
||||
<< message.text() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QFile m_file;
|
||||
QTextStream m_out;
|
||||
int m_processedDiagnostics = 0;
|
||||
};
|
||||
|
||||
void classifyFiles(const QSet<QString> &files, QStringList *headers, QStringList *sources)
|
||||
{
|
||||
for (const QString &file : files) {
|
||||
if (ProjectFile::isSource(ProjectFile::classify(file)))
|
||||
sources->append(file);
|
||||
else
|
||||
headers->append(file);
|
||||
}
|
||||
}
|
||||
|
||||
void indexFindErrors(QFutureInterface<void> &indexingFuture,
|
||||
const ParseParams params)
|
||||
{
|
||||
QStringList sources, headers;
|
||||
classifyFiles(params.sourceFiles, &headers, &sources);
|
||||
sources.sort();
|
||||
headers.sort();
|
||||
QStringList files = sources + headers;
|
||||
|
||||
WriteTaskFileForDiagnostics taskFileWriter;
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
|
||||
for (int i = 0, end = files.size(); i < end ; ++i) {
|
||||
if (indexingFuture.isCanceled())
|
||||
break;
|
||||
|
||||
const QString file = files.at(i);
|
||||
qDebug("FindErrorsIndexing: \"%s\"", qPrintable(file));
|
||||
|
||||
// Parse the file as precisely as possible
|
||||
BuiltinEditorDocumentParser parser(FilePath::fromString(file));
|
||||
parser.setReleaseSourceAndAST(false);
|
||||
parser.update({CppModelManager::instance()->workingCopy(), nullptr,
|
||||
Utils::Language::Cxx, false});
|
||||
CPlusPlus::Document::Ptr document = parser.document();
|
||||
QTC_ASSERT(document, return);
|
||||
|
||||
// Write diagnostic messages
|
||||
taskFileWriter.process(document);
|
||||
|
||||
// Look up symbols
|
||||
CPlusPlus::LookupContext context(document, parser.snapshot());
|
||||
CheckSymbols::go(document, context, QList<CheckSymbols::Result>()).waitForFinished();
|
||||
|
||||
document->releaseSourceAndAST();
|
||||
|
||||
indexingFuture.setProgressValue(i + 1);
|
||||
}
|
||||
|
||||
const QString elapsedTime = Utils::formatElapsedTime(timer.elapsed());
|
||||
qDebug("FindErrorsIndexing: %s", qPrintable(elapsedTime));
|
||||
}
|
||||
|
||||
void index(QFutureInterface<void> &indexingFuture,
|
||||
const ParseParams params)
|
||||
{
|
||||
QScopedPointer<Internal::CppSourceProcessor> sourceProcessor(CppModelManager::createSourceProcessor());
|
||||
sourceProcessor->setFileSizeLimitInMb(params.indexerFileSizeLimitInMb);
|
||||
sourceProcessor->setHeaderPaths(params.headerPaths);
|
||||
sourceProcessor->setWorkingCopy(params.workingCopy);
|
||||
|
||||
QStringList sources;
|
||||
QStringList headers;
|
||||
classifyFiles(params.sourceFiles, &headers, &sources);
|
||||
|
||||
for (const QString &file : std::as_const(params.sourceFiles))
|
||||
sourceProcessor->removeFromCache(FilePath::fromString(file));
|
||||
|
||||
const int sourceCount = sources.size();
|
||||
QStringList files = sources + headers;
|
||||
|
||||
sourceProcessor->setTodo(Utils::toSet(files));
|
||||
|
||||
const FilePath &conf = CppModelManager::configurationFileName();
|
||||
bool processingHeaders = false;
|
||||
|
||||
CppModelManager *cmm = CppModelManager::instance();
|
||||
const ProjectExplorer::HeaderPaths fallbackHeaderPaths = cmm->headerPaths();
|
||||
const CPlusPlus::LanguageFeatures defaultFeatures =
|
||||
CPlusPlus::LanguageFeatures::defaultFeatures();
|
||||
|
||||
qCDebug(indexerLog) << "About to index" << files.size() << "files.";
|
||||
for (int i = 0; i < files.size(); ++i) {
|
||||
if (indexingFuture.isCanceled())
|
||||
break;
|
||||
|
||||
const QString fileName = files.at(i);
|
||||
const QList<ProjectPart::ConstPtr> parts = cmm->projectPart(fileName);
|
||||
const CPlusPlus::LanguageFeatures languageFeatures = parts.isEmpty()
|
||||
? defaultFeatures
|
||||
: parts.first()->languageFeatures;
|
||||
sourceProcessor->setLanguageFeatures(languageFeatures);
|
||||
|
||||
const bool isSourceFile = i < sourceCount;
|
||||
if (isSourceFile) {
|
||||
sourceProcessor->run(conf);
|
||||
} else if (!processingHeaders) {
|
||||
sourceProcessor->run(conf);
|
||||
|
||||
processingHeaders = true;
|
||||
}
|
||||
|
||||
qCDebug(indexerLog) << " Indexing" << i + 1 << "of" << files.size() << ":" << fileName;
|
||||
ProjectExplorer::HeaderPaths headerPaths = parts.isEmpty()
|
||||
? fallbackHeaderPaths
|
||||
: parts.first()->headerPaths;
|
||||
sourceProcessor->setHeaderPaths(headerPaths);
|
||||
sourceProcessor->run(FilePath::fromString(fileName));
|
||||
|
||||
indexingFuture.setProgressValue(files.size() - sourceProcessor->todo().size());
|
||||
|
||||
if (isSourceFile)
|
||||
sourceProcessor->resetEnvironment();
|
||||
}
|
||||
qCDebug(indexerLog) << "Indexing finished.";
|
||||
}
|
||||
|
||||
void parse(QFutureInterface<void> &indexingFuture, const ParseParams params)
|
||||
{
|
||||
const QSet<QString> &files = params.sourceFiles;
|
||||
if (files.isEmpty())
|
||||
return;
|
||||
|
||||
indexingFuture.setProgressRange(0, files.size());
|
||||
|
||||
if (CppIndexingSupport::isFindErrorsIndexingActive())
|
||||
indexFindErrors(indexingFuture, params);
|
||||
else
|
||||
index(indexingFuture, params);
|
||||
|
||||
indexingFuture.setProgressValue(files.size());
|
||||
CppModelManager::instance()->finishedRefreshingSourceFiles(files);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
class BuiltinSymbolSearcher: public SymbolSearcher
|
||||
{
|
||||
public:
|
||||
BuiltinSymbolSearcher(const CPlusPlus::Snapshot &snapshot,
|
||||
const Parameters ¶meters, const QSet<QString> &fileNames)
|
||||
: m_snapshot(snapshot)
|
||||
, m_parameters(parameters)
|
||||
, m_fileNames(fileNames)
|
||||
{}
|
||||
|
||||
~BuiltinSymbolSearcher() override = default;
|
||||
|
||||
void runSearch(QFutureInterface<Core::SearchResultItem> &future) override
|
||||
{
|
||||
future.setProgressRange(0, m_snapshot.size());
|
||||
future.setProgressValue(0);
|
||||
int progress = 0;
|
||||
|
||||
SearchSymbols search;
|
||||
search.setSymbolsToSearchFor(m_parameters.types);
|
||||
CPlusPlus::Snapshot::const_iterator it = m_snapshot.begin();
|
||||
|
||||
QString findString = (m_parameters.flags & Core::FindRegularExpression
|
||||
? m_parameters.text : QRegularExpression::escape(m_parameters.text));
|
||||
if (m_parameters.flags & Core::FindWholeWords)
|
||||
findString = QString::fromLatin1("\\b%1\\b").arg(findString);
|
||||
QRegularExpression matcher(findString, (m_parameters.flags & Core::FindCaseSensitively
|
||||
? QRegularExpression::NoPatternOption
|
||||
: QRegularExpression::CaseInsensitiveOption));
|
||||
matcher.optimize();
|
||||
while (it != m_snapshot.end()) {
|
||||
if (future.isPaused())
|
||||
future.waitForResume();
|
||||
if (future.isCanceled())
|
||||
break;
|
||||
if (m_fileNames.isEmpty() || m_fileNames.contains(it.value()->filePath().path())) {
|
||||
QVector<Core::SearchResultItem> resultItems;
|
||||
auto filter = [&](const IndexItem::Ptr &info) -> IndexItem::VisitorResult {
|
||||
if (matcher.match(info->symbolName()).hasMatch()) {
|
||||
QString text = info->symbolName();
|
||||
QString scope = info->symbolScope();
|
||||
if (info->type() == IndexItem::Function) {
|
||||
QString name;
|
||||
info->unqualifiedNameAndScope(info->symbolName(), &name, &scope);
|
||||
text = name + info->symbolType();
|
||||
} else if (info->type() == IndexItem::Declaration){
|
||||
text = info->representDeclaration();
|
||||
}
|
||||
|
||||
Core::SearchResultItem item;
|
||||
item.setPath(scope.split(QLatin1String("::"), Qt::SkipEmptyParts));
|
||||
item.setLineText(text);
|
||||
item.setIcon(info->icon());
|
||||
item.setUserData(QVariant::fromValue(info));
|
||||
resultItems << item;
|
||||
}
|
||||
|
||||
return IndexItem::Recurse;
|
||||
};
|
||||
search(it.value())->visitAllChildren(filter);
|
||||
if (!resultItems.isEmpty())
|
||||
future.reportResults(resultItems);
|
||||
}
|
||||
++it;
|
||||
++progress;
|
||||
future.setProgressValue(progress);
|
||||
}
|
||||
if (future.isPaused())
|
||||
future.waitForResume();
|
||||
}
|
||||
|
||||
private:
|
||||
const CPlusPlus::Snapshot m_snapshot;
|
||||
const Parameters m_parameters;
|
||||
const QSet<QString> m_fileNames;
|
||||
};
|
||||
|
||||
CppIndexingSupport::CppIndexingSupport()
|
||||
{
|
||||
m_synchronizer.setCancelOnWait(true);
|
||||
}
|
||||
|
||||
CppIndexingSupport::~CppIndexingSupport() = default;
|
||||
|
||||
bool CppIndexingSupport::isFindErrorsIndexingActive()
|
||||
{
|
||||
return Utils::qtcEnvironmentVariable("QTC_FIND_ERRORS_INDEXING") == "1";
|
||||
}
|
||||
|
||||
QFuture<void> CppIndexingSupport::refreshSourceFiles(const QSet<QString> &sourceFiles,
|
||||
CppModelManager::ProgressNotificationMode mode)
|
||||
{
|
||||
CppModelManager *mgr = CppModelManager::instance();
|
||||
|
||||
ParseParams params;
|
||||
params.indexerFileSizeLimitInMb = indexerFileSizeLimitInMb();
|
||||
params.headerPaths = mgr->headerPaths();
|
||||
params.workingCopy = mgr->workingCopy();
|
||||
params.sourceFiles = sourceFiles;
|
||||
|
||||
QFuture<void> result = Utils::runAsync(mgr->sharedThreadPool(), parse, params);
|
||||
m_synchronizer.addFuture(result);
|
||||
|
||||
if (mode == CppModelManager::ForcedProgressNotification || sourceFiles.count() > 1) {
|
||||
Core::ProgressManager::addTask(result, QCoreApplication::translate("CppEditor::Internal::BuiltinIndexingSupport", "Parsing C/C++ Files"),
|
||||
CppEditor::Constants::TASK_INDEX);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SymbolSearcher *CppIndexingSupport::createSymbolSearcher(
|
||||
const SymbolSearcher::Parameters ¶meters, const QSet<QString> &fileNames)
|
||||
{
|
||||
return new BuiltinSymbolSearcher(CppModelManager::instance()->snapshot(), parameters, fileNames);
|
||||
}
|
||||
|
||||
} // namespace CppEditor
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include "cppmodelmanager.h"
|
||||
|
||||
#include <coreplugin/find/textfindconstants.h>
|
||||
#include <utils/futuresynchronizer.h>
|
||||
|
||||
#include <QFuture>
|
||||
#include <QStringList>
|
||||
@@ -51,17 +52,20 @@ public:
|
||||
virtual void runSearch(QFutureInterface<Core::SearchResultItem> &future) = 0;
|
||||
};
|
||||
|
||||
|
||||
class CPPEDITOR_EXPORT CppIndexingSupport
|
||||
{
|
||||
public:
|
||||
virtual ~CppIndexingSupport() = 0;
|
||||
CppIndexingSupport();
|
||||
~CppIndexingSupport();
|
||||
|
||||
virtual QFuture<void> refreshSourceFiles(const QSet<QString> &sourceFiles,
|
||||
CppModelManager::ProgressNotificationMode mode)
|
||||
= 0;
|
||||
virtual SymbolSearcher *createSymbolSearcher(const SymbolSearcher::Parameters ¶meters,
|
||||
const QSet<QString> &fileNames) = 0;
|
||||
static bool isFindErrorsIndexingActive();
|
||||
|
||||
QFuture<void> refreshSourceFiles(const QSet<QString> &sourceFiles,
|
||||
CppModelManager::ProgressNotificationMode mode);
|
||||
SymbolSearcher *createSymbolSearcher(const SymbolSearcher::Parameters ¶meters,
|
||||
const QSet<QString> &fileNames);
|
||||
private:
|
||||
Utils::FutureSynchronizer m_synchronizer;
|
||||
};
|
||||
|
||||
} // namespace CppEditor
|
||||
|
@@ -5,7 +5,6 @@
|
||||
|
||||
#include "abstracteditorsupport.h"
|
||||
#include "baseeditordocumentprocessor.h"
|
||||
#include "builtinindexingsupport.h"
|
||||
#include "compileroptionsbuilder.h"
|
||||
#include "cppcodemodelinspectordumper.h"
|
||||
#include "cppcodemodelsettings.h"
|
||||
@@ -975,7 +974,7 @@ CppModelManager::CppModelManager()
|
||||
qRegisterMetaType<QList<Document::DiagnosticMessage>>(
|
||||
"QList<CPlusPlus::Document::DiagnosticMessage>");
|
||||
|
||||
d->m_internalIndexingSupport = new BuiltinIndexingSupport;
|
||||
d->m_internalIndexingSupport = new CppIndexingSupport;
|
||||
|
||||
initCppTools();
|
||||
}
|
||||
@@ -1696,7 +1695,7 @@ void CppModelManager::onActiveProjectChanged(ProjectExplorer::Project *project)
|
||||
|
||||
void CppModelManager::onSourceFilesRefreshed() const
|
||||
{
|
||||
if (BuiltinIndexingSupport::isFindErrorsIndexingActive()) {
|
||||
if (CppIndexingSupport::isFindErrorsIndexingActive()) {
|
||||
QTimer::singleShot(1, QCoreApplication::instance(), &QCoreApplication::quit);
|
||||
qDebug("FindErrorsIndexing: Done, requesting Qt Creator to quit.");
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "symbolsearcher_test.h"
|
||||
|
||||
#include "builtinindexingsupport.h"
|
||||
#include "cppindexingsupport.h"
|
||||
#include "cppmodelmanager.h"
|
||||
#include "cpptoolstestcase.h"
|
||||
#include "searchsymbols.h"
|
||||
|
Reference in New Issue
Block a user