Commit cb0d1369 authored by Nikolai Kosjar's avatar Nikolai Kosjar

CppTools: Update document on activation

...if the project was updated in the meanwhile.

If a project is updated mark invisible editor documents dirty and update
them if they get focus.

This also fixes document highlighting when restoring a session for
documents that the user "switched away" before the project info is
pushed to CppModelManager.

This completes

    CppTools: Update visible documents on project update
    commit c2eb91e0

which only takes care of visible documents.

Task-number: QTCREATORBUG-13270
Change-Id: Id445e7f509deac5d03194aecc54ce4629b7926ce
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@theqtcompany.com>
parent 9cd552a1
...@@ -300,6 +300,10 @@ CppModelManager::CppModelManager(QObject *parent) ...@@ -300,6 +300,10 @@ CppModelManager::CppModelManager(QObject *parent)
this, SLOT(onAboutToLoadSession())); this, SLOT(onAboutToLoadSession()));
connect(sessionManager, SIGNAL(aboutToUnloadSession(QString)), connect(sessionManager, SIGNAL(aboutToUnloadSession(QString)),
this, SLOT(onAboutToUnloadSession())); this, SLOT(onAboutToUnloadSession()));
connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged,
this, &CppModelManager::onCurrentEditorChanged);
connect(Core::DocumentManager::instance(), &Core::DocumentManager::allDocumentsRenamed, connect(Core::DocumentManager::instance(), &Core::DocumentManager::allDocumentsRenamed,
this, &CppModelManager::renameIncludes); this, &CppModelManager::renameIncludes);
...@@ -687,21 +691,32 @@ void CppModelManager::recalculateFileToProjectParts() ...@@ -687,21 +691,32 @@ void CppModelManager::recalculateFileToProjectParts()
} }
} }
void CppModelManager::updateVisibleEditorDocuments() const void CppModelManager::updateCppEditorDocuments() const
{ {
QSet<QString> visibleDocumentsInEditMode; // Refresh visible documents
QSet<Core::IDocument *> visibleCppEditorDocuments;
foreach (Core::IEditor *editor, Core::EditorManager::visibleEditors()) { foreach (Core::IEditor *editor, Core::EditorManager::visibleEditors()) {
if (const Core::IDocument *document = editor->document()) { if (Core::IDocument *document = editor->document()) {
const QString filePath = document->filePath(); const QString filePath = document->filePath();
if (!filePath.isEmpty()) if (filePath.isEmpty())
visibleDocumentsInEditMode.insert(filePath); continue;
if (EditorDocumentHandle *editor = editorDocument(filePath)) {
visibleCppEditorDocuments.insert(document);
editor->processor()->run();
}
} }
} }
// Re-process these documents // Mark invisible documents dirty
foreach (const QString &filePath, visibleDocumentsInEditMode) { QSet<Core::IDocument *> invisibleCppEditorDocuments
if (EditorDocumentHandle *editor = editorDocument(filePath)) = Core::DocumentModel::openedDocuments().toSet();
editor->processor()->run(); invisibleCppEditorDocuments.subtract(visibleCppEditorDocuments);
foreach (Core::IDocument *document, invisibleCppEditorDocuments) {
const QString filePath = document->filePath();
if (filePath.isEmpty())
continue;
if (EditorDocumentHandle *document = editorDocument(filePath))
document->setNeedsRefresh(true);
} }
} }
...@@ -784,7 +799,7 @@ QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectIn ...@@ -784,7 +799,7 @@ QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectIn
// However, on e.g. a session restore first the editor documents are created and then the // 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 // project updates come in. That is, there are no reasonable dependency tables based on
// resolved includes that we could rely on. // resolved includes that we could rely on.
updateVisibleEditorDocuments(); updateCppEditorDocuments();
// Trigger reindexing // Trigger reindexing
return updateSourceFiles(filesToReindex, ForcedProgressNotification); return updateSourceFiles(filesToReindex, ForcedProgressNotification);
...@@ -871,6 +886,19 @@ void CppModelManager::onSourceFilesRefreshed() const ...@@ -871,6 +886,19 @@ void CppModelManager::onSourceFilesRefreshed() const
} }
} }
void CppModelManager::onCurrentEditorChanged(Core::IEditor *editor)
{
if (!editor || !editor->document())
return;
if (EditorDocumentHandle *cppEditorDocument = editorDocument(editor->document()->filePath())) {
if (cppEditorDocument->needsRefresh()) {
cppEditorDocument->setNeedsRefresh(false);
cppEditorDocument->processor()->run();
}
}
}
void CppModelManager::onAboutToLoadSession() void CppModelManager::onAboutToLoadSession()
{ {
if (d->m_delayedGcTimer.isActive()) if (d->m_delayedGcTimer.isActive())
......
...@@ -184,12 +184,13 @@ private slots: ...@@ -184,12 +184,13 @@ private slots:
void onProjectAdded(ProjectExplorer::Project *project); void onProjectAdded(ProjectExplorer::Project *project);
void onAboutToRemoveProject(ProjectExplorer::Project *project); void onAboutToRemoveProject(ProjectExplorer::Project *project);
void onSourceFilesRefreshed() const; void onSourceFilesRefreshed() const;
void onCurrentEditorChanged(Core::IEditor *editor);
void onCoreAboutToClose(); void onCoreAboutToClose();
private: private:
void delayedGC(); void delayedGC();
void recalculateFileToProjectParts(); void recalculateFileToProjectParts();
void updateVisibleEditorDocuments() const; void updateCppEditorDocuments() const;
void replaceSnapshot(const CPlusPlus::Snapshot &newSnapshot); void replaceSnapshot(const CPlusPlus::Snapshot &newSnapshot);
void removeFilesFromSnapshot(const QSet<QString> &removedFiles); void removeFilesFromSnapshot(const QSet<QString> &removedFiles);
......
...@@ -1037,6 +1037,69 @@ void CppToolsPlugin::test_modelmanager_defines_per_editor() ...@@ -1037,6 +1037,69 @@ void CppToolsPlugin::test_modelmanager_defines_per_editor()
} }
} }
void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate()
{
ModelManagerTestHelper helper;
CppModelManager *mm = CppModelManager::instance();
MyTestDataDir testDataDirectory(_("testdata_defines"));
const QString fileA = testDataDirectory.file(_("main1.cpp")); // content not relevant
const QString fileB = testDataDirectory.file(_("main2.cpp")); // content not relevant
// Open file A in editor
Core::IEditor *editorA = Core::EditorManager::openEditor(fileA);
QVERIFY(editorA);
EditorCloser closerA(editorA);
QCOMPARE(Core::DocumentModel::openedDocuments().size(), 1);
EditorDocumentHandle *editorDocumentA = mm->editorDocument(fileA);
QVERIFY(editorDocumentA);
ProjectPart::Ptr documentAProjectPart = editorDocumentA->processor()->parser()->projectPart();
QVERIFY(!documentAProjectPart->project);
// Open file B in editor
Core::IEditor *editorB = Core::EditorManager::openEditor(fileB);
QVERIFY(editorB);
EditorCloser closerB(editorB);
QCOMPARE(Core::DocumentModel::openedDocuments().size(), 2);
EditorDocumentHandle *editorDocumentB = mm->editorDocument(fileB);
QVERIFY(editorDocumentB);
ProjectPart::Ptr documentBProjectPart = editorDocumentB->processor()->parser()->projectPart();
QVERIFY(!documentBProjectPart->project);
// Switch back to document A
Core::EditorManager::activateEditor(editorA);
// Open/update related project
Project *project = helper.createProject(_("test_modelmanager_updateEditorsAfterProjectUpdate"));
ProjectPart::Ptr part(new ProjectPart);
part->project = project;
part->files.append(ProjectFile(fileA, ProjectFile::CXXSource));
part->files.append(ProjectFile(fileB, ProjectFile::CXXSource));
part->languageVersion = ProjectPart::CXX11;
part->qtVersion = ProjectPart::NoQt;
ProjectInfo pi = mm->projectInfo(project);
pi.appendProjectPart(part);
pi.finish();
updateProjectInfo(mm, &helper, pi);
// ... and check for updated editor document A
while (editorDocumentA->processor()->isParserRunning())
QCoreApplication::processEvents();
documentAProjectPart = editorDocumentA->processor()->parser()->projectPart();
QCOMPARE(documentAProjectPart->project, project);
// Switch back to document B and check if that's updated, too
Core::EditorManager::activateEditor(editorB);
while (editorDocumentB->processor()->isParserRunning())
QCoreApplication::processEvents();
documentBProjectPart = editorDocumentB->processor()->parser()->projectPart();
QCOMPARE(documentBProjectPart->project, project);
}
void CppToolsPlugin::test_modelmanager_renameIncludes() void CppToolsPlugin::test_modelmanager_renameIncludes()
{ {
struct ModelManagerGCHelper { struct ModelManagerGCHelper {
......
...@@ -151,6 +151,7 @@ private slots: ...@@ -151,6 +151,7 @@ private slots:
void test_modelmanager_dont_gc_opened_files(); void test_modelmanager_dont_gc_opened_files();
void test_modelmanager_defines_per_project(); void test_modelmanager_defines_per_project();
void test_modelmanager_defines_per_editor(); void test_modelmanager_defines_per_editor();
void test_modelmanager_updateEditorsAfterProjectUpdate();
void test_modelmanager_precompiled_headers(); void test_modelmanager_precompiled_headers();
void test_modelmanager_renameIncludes(); void test_modelmanager_renameIncludes();
......
...@@ -40,6 +40,7 @@ namespace CppTools { ...@@ -40,6 +40,7 @@ namespace CppTools {
*/ */
EditorDocumentHandle::EditorDocumentHandle() EditorDocumentHandle::EditorDocumentHandle()
: m_needsRefresh(false)
{ {
} }
...@@ -47,4 +48,14 @@ EditorDocumentHandle::~EditorDocumentHandle() ...@@ -47,4 +48,14 @@ EditorDocumentHandle::~EditorDocumentHandle()
{ {
} }
bool EditorDocumentHandle::needsRefresh() const
{
return m_needsRefresh;
}
void EditorDocumentHandle::setNeedsRefresh(bool needsRefresh)
{
m_needsRefresh = needsRefresh;
}
} // namespace CppTools } // namespace CppTools
...@@ -42,6 +42,9 @@ public: ...@@ -42,6 +42,9 @@ public:
EditorDocumentHandle(); EditorDocumentHandle();
virtual ~EditorDocumentHandle(); virtual ~EditorDocumentHandle();
bool needsRefresh() const;
void setNeedsRefresh(bool needsRefresh);
// For the Working Copy // For the Working Copy
virtual QString filePath() const = 0; virtual QString filePath() const = 0;
virtual QByteArray contents() const = 0; virtual QByteArray contents() const = 0;
...@@ -49,6 +52,9 @@ public: ...@@ -49,6 +52,9 @@ public:
// For updating if new project info is set // For updating if new project info is set
virtual BaseEditorDocumentProcessor *processor() = 0; virtual BaseEditorDocumentProcessor *processor() = 0;
private:
bool m_needsRefresh;
}; };
} // namespace CppTools } // namespace CppTools
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment