From 8c79d5bc23e4b555625dfa368ca9f74e6d14540b Mon Sep 17 00:00:00 2001 From: Erik Verbruggen <erik.verbruggen@digia.com> Date: Mon, 30 Sep 2013 14:37:50 +0200 Subject: [PATCH] C++: add code-model support for defines-per-editor. The UI side will come in another commit. Change-Id: I1038a438587fe4cef70408f7f627d08837fc192d Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com> --- src/plugins/cpptools/cppmodelmanager_test.cpp | 96 +++++++++++++++++++ src/plugins/cpptools/cpppreprocessor.cpp | 7 +- src/plugins/cpptools/cppsnapshotupdater.cpp | 27 +++++- src/plugins/cpptools/cppsnapshotupdater.h | 3 + src/plugins/cpptools/cpptoolsplugin.h | 1 + 5 files changed, 132 insertions(+), 2 deletions(-) diff --git a/src/plugins/cpptools/cppmodelmanager_test.cpp b/src/plugins/cpptools/cppmodelmanager_test.cpp index db76d6ecc12..8dd05281c4b 100644 --- a/src/plugins/cpptools/cppmodelmanager_test.cpp +++ b/src/plugins/cpptools/cppmodelmanager_test.cpp @@ -970,3 +970,99 @@ void CppToolsPlugin::test_modelmanager_defines_per_project_pch() QCOMPARE(decl->name()->identifier()->chars(), "two"); } } + +void CppToolsPlugin::test_modelmanager_defines_per_editor() +{ + ModelManagerTestHelper helper; + + MyTestDataDir testDataDirectory(QLatin1String("testdata_defines")); + const QString main1File = testDataDirectory.file(QLatin1String("main1.cpp")); + const QString main2File = testDataDirectory.file(QLatin1String("main2.cpp")); + const QString header = testDataDirectory.file(QLatin1String("header.h")); + + CppModelManager *mm = CppModelManager::instance(); + + Project *project = helper.createProject( + QLatin1String("test_modelmanager_defines_per_editor")); + + ProjectPart::Ptr part1(new ProjectPart); + part1->files.append(ProjectFile(main1File, ProjectFile::CXXSource)); + part1->files.append(ProjectFile(header, ProjectFile::CXXHeader)); + part1->cxxVersion = ProjectPart::CXX11; + part1->qtVersion = ProjectPart::NoQt; + part1->includePaths = QStringList() << testDataDirectory.includeDir(false); + + ProjectPart::Ptr part2(new ProjectPart); + part2->files.append(ProjectFile(main2File, ProjectFile::CXXSource)); + part2->files.append(ProjectFile(header, ProjectFile::CXXHeader)); + part2->cxxVersion = ProjectPart::CXX11; + part2->qtVersion = ProjectPart::NoQt; + part2->includePaths = QStringList() << testDataDirectory.includeDir(false); + + ProjectInfo pi = mm->projectInfo(project); + pi.appendProjectPart(part1); + pi.appendProjectPart(part2); + + mm->updateProjectInfo(pi); + + helper.waitForRefreshedSourceFiles(); + + QCOMPARE(mm->snapshot().size(), 4); + + // Open a file in the editor + QCOMPARE(Core::EditorManager::documentModel()->openedDocuments().size(), 0); + + { + Core::IEditor *editor = Core::EditorManager::openEditor(main1File); + EditorCloser closer(editor); + QVERIFY(editor); + QCOMPARE(Core::EditorManager::documentModel()->openedDocuments().size(), 1); + QVERIFY(mm->isCppEditor(editor)); + + CppEditorSupport *sup = mm->cppEditorSupport( + qobject_cast<TextEditor::BaseTextEditor *>(editor)); + while (sup->lastSemanticInfoDocument().isNull()) + QCoreApplication::processEvents(); + + sup->snapshotUpdater()->setEditorDefines(QByteArray("#define SUB1\n")); + sup->snapshotUpdater()->update(mm->workingCopy()); + + Document::Ptr doc = mm->snapshot().document(main1File); + QVERIFY(doc); + QVERIFY(doc->globalNamespace()); + QCOMPARE(doc->globalSymbolCount(), 1U); + CPlusPlus::Symbol *s = doc->globalSymbolAt(0); + QVERIFY(s); + CPlusPlus::Declaration *decl = s->asDeclaration(); + QVERIFY(decl); + QVERIFY(decl->type()->isIntegerType()); + QCOMPARE(decl->name()->identifier()->chars(), "one"); + } + + { + Core::IEditor *editor = Core::EditorManager::openEditor(main2File); + EditorCloser closer(editor); + QVERIFY(editor); + QCOMPARE(Core::EditorManager::documentModel()->openedDocuments().size(), 1); + QVERIFY(mm->isCppEditor(editor)); + + CppEditorSupport *sup = mm->cppEditorSupport( + qobject_cast<TextEditor::BaseTextEditor *>(editor)); + while (sup->lastSemanticInfoDocument().isNull()) + QCoreApplication::processEvents(); + + sup->snapshotUpdater()->setEditorDefines(QByteArray("#define SUB2\n")); + sup->snapshotUpdater()->update(mm->workingCopy()); + + Document::Ptr doc = mm->snapshot().document(main2File); + QVERIFY(doc); + QVERIFY(doc->globalNamespace()); + QCOMPARE(doc->globalSymbolCount(), 1U); + CPlusPlus::Symbol *s = doc->globalSymbolAt(0); + QVERIFY(s); + CPlusPlus::Declaration *decl = s->asDeclaration(); + QVERIFY(decl); + QVERIFY(decl->type()->isIntegerType()); + QCOMPARE(decl->name()->identifier()->chars(), "two"); + } +} diff --git a/src/plugins/cpptools/cpppreprocessor.cpp b/src/plugins/cpptools/cpppreprocessor.cpp index 1e3f5b1bf02..f60c853b832 100644 --- a/src/plugins/cpptools/cpppreprocessor.cpp +++ b/src/plugins/cpptools/cpppreprocessor.cpp @@ -223,10 +223,15 @@ QString CppPreprocessor::cleanPath(const QString &path) return result; } +static inline bool isInjectedFile(const QString &fileName) +{ + return fileName.startsWith(QLatin1Char('<')) && fileName.endsWith(QLatin1Char('>')); +} + QString CppPreprocessor::resolveFile_helper(const QString &fileName, IncludeType type) { const QFileInfo fileInfo(fileName); - if (fileName == Preprocessor::configurationFileName || fileInfo.isAbsolute()) + if (isInjectedFile(fileName) || fileInfo.isAbsolute()) return fileName; if (type == IncludeLocal && m_currentDoc) { diff --git a/src/plugins/cpptools/cppsnapshotupdater.cpp b/src/plugins/cpptools/cppsnapshotupdater.cpp index 473ec66b607..6d9a4d3a6f1 100644 --- a/src/plugins/cpptools/cppsnapshotupdater.cpp +++ b/src/plugins/cpptools/cppsnapshotupdater.cpp @@ -39,6 +39,7 @@ using namespace CppTools::Internal; SnapshotUpdater::SnapshotUpdater(const QString &fileInEditor) : m_mutex(QMutex::Recursive) , m_fileInEditor(fileInEditor) + , m_editorDefinesChangedSinceLastUpdate(false) , m_usePrecompiledHeaders(false) { } @@ -50,7 +51,7 @@ void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy) if (m_fileInEditor.isEmpty()) return; - bool invalidateSnapshot = false, invalidateConfig = false; + bool invalidateSnapshot = false, invalidateConfig = false, editorDefinesChanged = false; CppModelManager *modelManager = dynamic_cast<CppModelManager *>(CppModelManagerInterface::instance()); @@ -75,6 +76,12 @@ void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy) invalidateConfig = true; } + if (m_editorDefinesChangedSinceLastUpdate) { + invalidateSnapshot = true; + editorDefinesChanged = true; + m_editorDefinesChangedSinceLastUpdate = false; + } + if (includePaths != m_includePaths) { m_includePaths = includePaths; invalidateSnapshot = true; @@ -131,6 +138,12 @@ void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy) workingCopy.insert(configurationFileName, m_configFile); m_snapshot.remove(m_fileInEditor); + static const QString editorDefinesFileName = QLatin1String("<per-editor-defines>"); + if (editorDefinesChanged) { + m_snapshot.remove(editorDefinesFileName); + workingCopy.insert(editorDefinesFileName, m_editorDefines); + } + CppPreprocessor preproc(modelManager, m_snapshot); Snapshot globalSnapshot = modelManager->snapshot(); globalSnapshot.remove(fileInEditor()); @@ -142,6 +155,8 @@ void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy) if (m_usePrecompiledHeaders) foreach (const QString &precompiledHeader, m_precompiledHeaders) preproc.run(precompiledHeader); + if (!m_editorDefines.isEmpty()) + preproc.run(editorDefinesFileName); preproc.run(m_fileInEditor); m_snapshot = preproc.snapshot(); @@ -178,6 +193,16 @@ void SnapshotUpdater::setUsePrecompiledHeaders(bool usePrecompiledHeaders) m_usePrecompiledHeaders = usePrecompiledHeaders; } +void SnapshotUpdater::setEditorDefines(const QByteArray &editorDefines) +{ + QMutexLocker locker(&m_mutex); + + if (editorDefines != m_editorDefines) { + m_editorDefines = editorDefines; + m_editorDefinesChangedSinceLastUpdate = true; + } +} + void SnapshotUpdater::updateProjectPart() { CppModelManager *cmm = dynamic_cast<CppModelManager *>(CppModelManagerInterface::instance()); diff --git a/src/plugins/cpptools/cppsnapshotupdater.h b/src/plugins/cpptools/cppsnapshotupdater.h index 6f0f90ac4f9..1cc8772709d 100644 --- a/src/plugins/cpptools/cppsnapshotupdater.h +++ b/src/plugins/cpptools/cppsnapshotupdater.h @@ -65,6 +65,7 @@ public: { return m_frameworkPaths; } void setUsePrecompiledHeaders(bool usePrecompiledHeaders); + void setEditorDefines(const QByteArray &editorDefines); private: void updateProjectPart(); @@ -75,6 +76,8 @@ private: QString m_fileInEditor; ProjectPart::Ptr m_projectPart; QByteArray m_configFile; + bool m_editorDefinesChangedSinceLastUpdate; + QByteArray m_editorDefines; QStringList m_includePaths; QStringList m_frameworkPaths; QStringList m_precompiledHeaders; diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h index 3a0c4b90241..da09cbe15eb 100644 --- a/src/plugins/cpptools/cpptoolsplugin.h +++ b/src/plugins/cpptools/cpptoolsplugin.h @@ -213,6 +213,7 @@ private slots: void test_modelmanager_dont_gc_opened_files(); void test_modelmanager_defines_per_project(); void test_modelmanager_defines_per_project_pch(); + void test_modelmanager_defines_per_editor(); void test_cpplocatorfilters_CppLocatorFilter(); void test_cpplocatorfilters_CppLocatorFilter_data(); -- GitLab