diff --git a/src/plugins/cpptools/builtinindexingsupport.cpp b/src/plugins/cpptools/builtinindexingsupport.cpp index ad0d1f4211e29da78f784c32336b5fd5e77111b4..60874352c9812fde84f8289d538d0173b298c233 100644 --- a/src/plugins/cpptools/builtinindexingsupport.cpp +++ b/src/plugins/cpptools/builtinindexingsupport.cpp @@ -1,23 +1,29 @@ #include "builtinindexingsupport.h" +#include "cppchecksymbols.h" #include "cppmodelmanager.h" +#include "cppprojectfile.h" +#include "cppsnapshotupdater.h" #include "cppsourceprocessor.h" -#include "searchsymbols.h" #include "cpptoolsconstants.h" #include "cpptoolsplugin.h" -#include "cppprojectfile.h" +#include "searchsymbols.h" #include #include +#include +#include #include #include +#include using namespace CppTools; using namespace CppTools::Internal; static const bool DumpFileNameWhileParsing = qgetenv("QTC_DUMP_FILENAME_WHILE_PARSING") == "1"; +static const bool FindErrorsIndexing = qgetenv("QTC_FIND_ERRORS_INDEXING") == "1"; namespace { @@ -36,11 +42,125 @@ public: QStringList sourceFiles; }; -static void parse(QFutureInterface &future, const ParseParams params) +class WriteTaskFileForDiagnostics { - if (params.sourceFiles.isEmpty()) - return; + Q_DISABLE_COPY(WriteTaskFileForDiagnostics) + +public: + WriteTaskFileForDiagnostics() + : m_processedDiagnostics(0) + { + const QString fileName = QDir::tempPath() + + QLatin1String("/qtc_findErrorsIndexing.diagnostics.") + + QDateTime::currentDateTime().toString(QLatin1String("yyMMdd_HHmm")) + + QLatin1String(".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())); + } + + int processedDiagnostics() const { return m_processedDiagnostics; } + + void process(const CPlusPlus::Document::Ptr document) + { + using namespace CPlusPlus; + const QString fileName = document->fileName(); + + foreach (const Document::DiagnosticMessage &message, document->diagnosticMessages()) { + ++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; +}; + +void classifyFiles(const QStringList &files, QStringList *headers, QStringList *sources) +{ + foreach (const QString &file, files) { + if (ProjectFile::isSource(ProjectFile::classify(file))) + sources->append(file); + else + headers->append(file); + } +} + +void indexFindErrors(QFutureInterface &future, const ParseParams params) +{ + QStringList files = params.sourceFiles; + files.sort(); + QStringList sources, headers; + classifyFiles(files, &headers, &sources); + files = sources + headers; + + WriteTaskFileForDiagnostics taskFileWriter; + QElapsedTimer timer; + timer.start(); + + for (int i = 0, end = files.size(); i < end ; ++i) { + if (future.isPaused()) + future.waitForResume(); + if (future.isCanceled()) + break; + + const QString file = files.at(i); + qDebug("FindErrorsIndexing: \"%s\"", qPrintable(file)); + + // Parse the file as precisely as possible + SnapshotUpdater updater(file); + updater.setReleaseSourceAndAST(false); + updater.update(params.workingCopy); + CPlusPlus::Document::Ptr document = updater.document(); + QTC_ASSERT(document, return); + // Write diagnostic messages + taskFileWriter.process(document); + + // Look up symbols + CPlusPlus::LookupContext context(document, updater.snapshot()); + CheckSymbols::go(document, context, QList()).waitForFinished(); + + document->releaseSourceAndAST(); + + future.setProgressValue(files.size() - (files.size() - (i + 1))); + } + + const QTime format = QTime(0, 0, 0, 0).addMSecs(timer.elapsed() + 500); + const QString time = format.toString(QLatin1String("hh:mm:ss")); + qDebug("FindErrorsIndexing: Finished after %s.", qPrintable(time)); +} + +void index(QFutureInterface &future, const ParseParams params) +{ QScopedPointer sourceProcessor(CppModelManager::createSourceProcessor()); sourceProcessor->setDumpFileNameWhileParsing(params.dumpFileNameWhileParsing); sourceProcessor->setRevision(params.revision); @@ -48,16 +168,13 @@ static void parse(QFutureInterface &future, const ParseParams params) sourceProcessor->setWorkingCopy(params.workingCopy); QStringList files = params.sourceFiles; + QStringList sources; QStringList headers; + classifyFiles(files, &headers, &sources); - foreach (const QString &file, files) { + foreach (const QString &file, files) sourceProcessor->removeFromCache(file); - if (ProjectFile::isSource(ProjectFile::classify(file))) - sources.append(file); - else - headers.append(file); - } const int sourceCount = sources.size(); files = sources; @@ -65,8 +182,6 @@ static void parse(QFutureInterface &future, const ParseParams params) sourceProcessor->setTodo(files); - future.setProgressRange(0, files.size()); - const QString conf = CppModelManagerInterface::configurationFileName(); bool processingHeaders = false; @@ -102,9 +217,23 @@ static void parse(QFutureInterface &future, const ParseParams params) if (isSourceFile) sourceProcessor->resetEnvironment(); } +} + +void parse(QFutureInterface &future, const ParseParams params) +{ + const QStringList files = params.sourceFiles; + if (files.isEmpty()) + return; + + future.setProgressRange(0, files.size()); + + if (FindErrorsIndexing) + indexFindErrors(future, params); + else + index(future, params); future.setProgressValue(files.size()); - cmm->finishedRefreshingSourceFiles(files); + CppModelManager::instance()->finishedRefreshingSourceFiles(files); } class BuiltinSymbolSearcher: public SymbolSearcher @@ -236,3 +365,8 @@ SymbolSearcher *BuiltinIndexingSupport::createSymbolSearcher(SymbolSearcher::Par { return new BuiltinSymbolSearcher(CppModelManager::instance()->snapshot(), parameters, fileNames); } + +bool BuiltinIndexingSupport::isFindErrorsIndexingActive() +{ + return FindErrorsIndexing; +} diff --git a/src/plugins/cpptools/builtinindexingsupport.h b/src/plugins/cpptools/builtinindexingsupport.h index 02f267a2268656f8cfea5f1b1fdf82b8693a395c..8a8669d3350d15af3dcdf0757e69fe3808736b8d 100644 --- a/src/plugins/cpptools/builtinindexingsupport.h +++ b/src/plugins/cpptools/builtinindexingsupport.h @@ -51,6 +51,9 @@ public: virtual SymbolSearcher *createSymbolSearcher(SymbolSearcher::Parameters parameters, QSet fileNames); +public: + static bool isFindErrorsIndexingActive(); + private: QFutureSynchronizer m_synchronizer; unsigned m_revision; diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 8924f64cd898bfbc329a6f61e626aa0cb1cf6fc2..39fd4d81f0885f47ba87a9bf3d97a337ec59e078 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -225,6 +225,8 @@ CppModelManager::CppModelManager(QObject *parent) this, SIGNAL(globalSnapshotChanged())); connect(this, SIGNAL(aboutToRemoveFiles(QStringList)), this, SIGNAL(globalSnapshotChanged())); + connect(this, SIGNAL(sourceFilesRefreshed(QStringList)), + this, SLOT(onSourceFilesRefreshed())); m_findReferences = new CppFindReferences(this); m_indexerEnabled = qgetenv("QTC_NO_CODE_INDEXER") != "1"; @@ -792,6 +794,14 @@ void CppModelManager::onAboutToRemoveProject(ProjectExplorer::Project *project) delayedGC(); } +void CppModelManager::onSourceFilesRefreshed() const +{ + if (BuiltinIndexingSupport::isFindErrorsIndexingActive()) { + QTimer::singleShot(1, QCoreApplication::instance(), SLOT(quit())); + qDebug("FindErrorsIndexing: Done, requesting Qt Creator to quit."); + } +} + void CppModelManager::onAboutToLoadSession() { if (m_delayedGcTimer->isActive()) diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index 7936019a140592b74bf1a385324e832a9d4cec44..c029bcb67e0b05c7fd92505cae23335fab705798 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -165,6 +165,7 @@ private slots: void onAboutToUnloadSession(); void onProjectAdded(ProjectExplorer::Project *project); void onAboutToRemoveProject(ProjectExplorer::Project *project); + void onSourceFilesRefreshed() const; void onCoreAboutToClose(); private: diff --git a/src/plugins/cpptools/cppsnapshotupdater.cpp b/src/plugins/cpptools/cppsnapshotupdater.cpp index a6900d3d2c0ac9a5e5baa038734f31deb4689840..a534da4d5758ecc8e905f73e86c398c84f93741e 100644 --- a/src/plugins/cpptools/cppsnapshotupdater.cpp +++ b/src/plugins/cpptools/cppsnapshotupdater.cpp @@ -42,6 +42,7 @@ SnapshotUpdater::SnapshotUpdater(const QString &fileInEditor) , m_editorDefinesChangedSinceLastUpdate(false) , m_usePrecompiledHeaders(false) , m_forceSnapshotInvalidation(false) + , m_releaseSourceAndAST(true) { } @@ -161,7 +162,8 @@ void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy) newRev = qMax(rev + 1, newRev); doc->setRevision(newRev); modelManager->emitDocumentUpdated(doc); - doc->releaseSourceAndAST(); + if (m_releaseSourceAndAST) + doc->releaseSourceAndAST(); }); Snapshot globalSnapshot = modelManager->snapshot(); globalSnapshot.remove(fileInEditor()); @@ -245,6 +247,12 @@ void SnapshotUpdater::setEditorDefines(const QByteArray &editorDefines) } } +void SnapshotUpdater::setReleaseSourceAndAST(bool onoff) +{ + QMutexLocker locker(&m_mutex); + m_releaseSourceAndAST = onoff; +} + void SnapshotUpdater::updateProjectPart() { if (m_manuallySetProjectPart) { diff --git a/src/plugins/cpptools/cppsnapshotupdater.h b/src/plugins/cpptools/cppsnapshotupdater.h index b7d786f3ed5906a318897e5ef880decd60e36895..69e054ba75ca580706c1e560f114065451528dfa 100644 --- a/src/plugins/cpptools/cppsnapshotupdater.h +++ b/src/plugins/cpptools/cppsnapshotupdater.h @@ -64,6 +64,8 @@ public: void setUsePrecompiledHeaders(bool usePrecompiledHeaders); void setEditorDefines(const QByteArray &editorDefines); + void setReleaseSourceAndAST(bool onoff); + private: void updateProjectPart(); void addFileAndDependencies(QSet *toRemove, const QString &fileName) const; @@ -82,6 +84,7 @@ private: CPlusPlus::DependencyTable m_deps; bool m_usePrecompiledHeaders; bool m_forceSnapshotInvalidation; + bool m_releaseSourceAndAST; }; } // namespace CppTools