From 6cf1f7968f8dac84825f96515ea3adbeeb6b2734 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Tue, 22 Nov 2016 15:17:42 +0100 Subject: [PATCH] Clang: Fix initial document parse with modified content Reproduce with: 1. Create a new class named Foo with the wizard. 2. Close foo.h 3. In foo.cpp, add some class member function. 4. In foo.cpp, trigger the refactoring action "Add public Declaration" for the just defined member function. As a result, foo.h will be opened. ==> While the declaration was added, the header file is not yet reparsed with the new content - this can be verified by setting a custom color for "Function". In this use case, the refactoring action opens the editor and immediately modifies the document (RefactoringFile::apply). Fix by sending the document content along for the very first RegisterTranslationUnitForEditorMessage if the document was already modified. Change-Id: If20615a45b72dd0bef87e1870e403d0b277bc5d6 Reviewed-by: David Schulz --- src/libs/clangbackendipc/filecontainer.h | 15 +++++++++++++++ .../clangbackendipcintegration.cpp | 15 +++++---------- .../clangcompletionassistprocessor.cpp | 13 ++++--------- .../clangeditordocumentprocessor.cpp | 19 +++++++++++++++++++ .../clangeditordocumentprocessor.h | 2 ++ src/plugins/clangcodemodel/clangutils.cpp | 12 ++++++++++++ src/plugins/clangcodemodel/clangutils.h | 7 +++++++ 7 files changed, 64 insertions(+), 19 deletions(-) diff --git a/src/libs/clangbackendipc/filecontainer.h b/src/libs/clangbackendipc/filecontainer.h index 5c8f6c4386a..054f37bf26e 100644 --- a/src/libs/clangbackendipc/filecontainer.h +++ b/src/libs/clangbackendipc/filecontainer.h @@ -51,6 +51,21 @@ public: { } + FileContainer(const Utf8String &filePath, + const Utf8String &projectPartId, + const Utf8StringVector &fileArguments, + const Utf8String &unsavedFileContent = Utf8String(), + bool hasUnsavedFileContent = false, + quint32 documentRevision = 0) + : filePath_(filePath), + projectPartId_(projectPartId), + fileArguments_(fileArguments), + unsavedFileContent_(unsavedFileContent), + documentRevision_(documentRevision), + hasUnsavedFileContent_(hasUnsavedFileContent) + { + } + FileContainer(const Utf8String &filePath, const Utf8String &projectPartId, const Utf8StringVector &fileArguments, diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp index e38d5b10d55..0b1d9895a7e 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp @@ -90,11 +90,6 @@ static QString backendProcessPath() + QStringLiteral(QTC_HOST_EXE_SUFFIX); } -static CppTools::CppEditorDocumentHandle *cppDocument(const QString &filePath) -{ - return CppTools::CppModelManager::instance()->cppEditorDocument(filePath); -} - static bool printAliveMessageHelper() { const bool print = qEnvironmentVariableIntValue("QTC_CLANG_FORCE_VERBOSE_ALIVE"); @@ -540,14 +535,14 @@ void IpcCommunicator::registerProjectsParts(const QListcontents(), document->revision()); } void IpcCommunicator::updateUnsavedFileFromCppEditorDocument(const QString &filePath) { - const CppTools::CppEditorDocumentHandle *document = cppDocument(filePath); + const CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath); updateUnsavedFile(filePath, document->contents(), document->revision()); } @@ -584,7 +579,7 @@ void IpcCommunicator::updateUnsavedFile(const QString &filePath, const QByteArra static bool documentHasChanged(const QString &filePath, uint revision) { - if (CppTools::CppEditorDocumentHandle *document = cppDocument(filePath)) + if (CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath)) return document->sendTracker().shouldSendRevision(revision); return true; @@ -592,7 +587,7 @@ static bool documentHasChanged(const QString &filePath, uint revision) static void setLastSentDocumentRevision(const QString &filePath, uint revision) { - if (CppTools::CppEditorDocumentHandle *document = cppDocument(filePath)) + if (CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath)) document->sendTracker().setLastSentRevision(int(revision)); } @@ -625,7 +620,7 @@ void IpcCommunicator::updateTranslationUnitWithRevisionCheck(Core::IDocument *do void IpcCommunicator::updateChangeContentStartPosition(const QString &filePath, int position) { - if (CppTools::CppEditorDocumentHandle *document = cppDocument(filePath)) + if (CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath)) document->sendTracker().applyContentChange(position); } diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp index f979a33af8a..54ca38d3b2d 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp @@ -519,15 +519,10 @@ void ClangCompletionAssistProcessor::sendFileContent(const QByteArray &customFil uint(m_interface->textDocument()->revision())}}); } namespace { -CppTools::CppEditorDocumentHandle *cppDocument(const QString &filePath) -{ - return CppTools::CppModelManager::instance()->cppEditorDocument(filePath); -} - bool shouldSendDocumentForCompletion(const QString &filePath, int completionPosition) { - auto *document = cppDocument(filePath); + CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath); if (document) { auto &sendTracker = document->sendTracker(); @@ -541,7 +536,7 @@ bool shouldSendDocumentForCompletion(const QString &filePath, bool shouldSendCodeCompletion(const QString &filePath, int completionPosition) { - auto *document = cppDocument(filePath); + CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath); if (document) { auto &sendTracker = document->sendTracker(); @@ -553,7 +548,7 @@ bool shouldSendCodeCompletion(const QString &filePath, void setLastDocumentRevision(const QString &filePath) { - auto *document = cppDocument(filePath); + CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath); if (document) document->sendTracker().setLastSentRevision(int(document->revision())); @@ -562,7 +557,7 @@ void setLastDocumentRevision(const QString &filePath) void setLastCompletionPosition(const QString &filePath, int completionPosition) { - auto *document = cppDocument(filePath); + CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath); if (document) document->sendTracker().setLastCompletionPosition(completionPosition); diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 769d2d0e377..6192232be0d 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -325,6 +326,10 @@ void ClangEditorDocumentProcessor::registerTranslationUnitForEditor(CppTools::Pr m_ipcCommunicator.unregisterTranslationUnitsForEditor({fileContainerWithArguments()}); m_ipcCommunicator.registerTranslationUnitsForEditor({fileContainerWithArguments(projectPart)}); } + } else if (revision() != 1) { + // E.g. a refactoring action opened the document and modified it immediately. + m_ipcCommunicator.registerTranslationUnitsForEditor({{fileContainerWithArgumentsAndDocumentContent(projectPart)}}); + ClangCodeModel::Utils::setLastSentDocumentRevision(filePath(), revision()); } else { m_ipcCommunicator.registerTranslationUnitsForEditor({{fileContainerWithArguments(projectPart)}}); } @@ -438,6 +443,20 @@ ClangEditorDocumentProcessor::fileContainerWithArguments(CppTools::ProjectPart * return {filePath(), projectPartId, Utf8StringVector(theFileArguments), revision()}; } +ClangBackEnd::FileContainer +ClangEditorDocumentProcessor::fileContainerWithArgumentsAndDocumentContent( + CppTools::ProjectPart *projectPart) const +{ + const QStringList theFileArguments = fileArguments(filePath(), projectPart); + + return ClangBackEnd::FileContainer(filePath(), + projectPart->id(), + Utf8StringVector(theFileArguments), + textDocument()->toPlainText(), + true, + revision()); +} + ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithDocumentContent(const QString &projectpartId) const { diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h index 10355e349d7..094ea95925e 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h @@ -100,6 +100,8 @@ private: HeaderErrorDiagnosticWidgetCreator creatorForHeaderErrorDiagnosticWidget( const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic); ClangBackEnd::FileContainer fileContainerWithArguments(CppTools::ProjectPart *projectPart) const; + ClangBackEnd::FileContainer fileContainerWithArgumentsAndDocumentContent( + CppTools::ProjectPart *projectPart) const; ClangBackEnd::FileContainer fileContainerWithDocumentContent(const QString &projectpartId) const; private: diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index ac8f3849a30..4f21f169c0a 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -231,5 +232,16 @@ QString projectPartIdForFile(const QString &filePath) return QString(); } +CppEditorDocumentHandle *cppDocument(const QString &filePath) +{ + return CppTools::CppModelManager::instance()->cppEditorDocument(filePath); +} + +void setLastSentDocumentRevision(const QString &filePath, uint revision) +{ + if (CppEditorDocumentHandle *document = cppDocument(filePath)) + document->sendTracker().setLastSentRevision(int(revision)); +} + } // namespace Utils } // namespace Clang diff --git a/src/plugins/clangcodemodel/clangutils.h b/src/plugins/clangcodemodel/clangutils.h index dcec4491397..edd26ba7552 100644 --- a/src/plugins/clangcodemodel/clangutils.h +++ b/src/plugins/clangcodemodel/clangutils.h @@ -27,9 +27,16 @@ #include +namespace CppTools { +class CppEditorDocumentHandle; +} + namespace ClangCodeModel { namespace Utils { +CppTools::CppEditorDocumentHandle *cppDocument(const QString &filePath); +void setLastSentDocumentRevision(const QString &filePath, uint revision); + QStringList createClangOptions(const CppTools::ProjectPart::Ptr &pPart, CppTools::ProjectFile::Kind fileKind); QStringList createClangOptions(const CppTools::ProjectPart::Ptr &pPart,