forked from qt-creator/qt-creator
ClangCodeModel: Take changes from header files into account immediately
... in the dependent sources. That's also how the built-in code model behaves, but clangd itself only does this when a document is saved. Change-Id: I52d6badb0b7f063e5924c05dbf83a6e9849c9f6f Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -90,6 +90,7 @@ void ClangCodeModelPlugin::initialize()
|
|||||||
addTest<Tests::ClangdTestFindReferences>();
|
addTest<Tests::ClangdTestFindReferences>();
|
||||||
addTest<Tests::ClangdTestFollowSymbol>();
|
addTest<Tests::ClangdTestFollowSymbol>();
|
||||||
addTest<Tests::ClangdTestHighlighting>();
|
addTest<Tests::ClangdTestHighlighting>();
|
||||||
|
addTest<Tests::ClangdTestIndirectChanges>();
|
||||||
addTest<Tests::ClangdTestLocalReferences>();
|
addTest<Tests::ClangdTestLocalReferences>();
|
||||||
addTest<Tests::ClangdTestTooltips>();
|
addTest<Tests::ClangdTestTooltips>();
|
||||||
addTest<Tests::ClangFixItTest>();
|
addTest<Tests::ClangFixItTest>();
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "clangeditordocumentprocessor.h"
|
#include "clangeditordocumentprocessor.h"
|
||||||
|
|
||||||
|
#include "clangdclient.h"
|
||||||
#include "clangmodelmanagersupport.h"
|
#include "clangmodelmanagersupport.h"
|
||||||
|
|
||||||
#include <cppeditor/builtincursorinfo.h>
|
#include <cppeditor/builtincursorinfo.h>
|
||||||
@@ -15,6 +16,8 @@
|
|||||||
#include <cppeditor/cppworkingcopy.h>
|
#include <cppeditor/cppworkingcopy.h>
|
||||||
#include <cppeditor/editordocumenthandle.h>
|
#include <cppeditor/editordocumenthandle.h>
|
||||||
|
|
||||||
|
#include <languageclient/languageclientmanager.h>
|
||||||
|
|
||||||
#include <texteditor/fontsettings.h>
|
#include <texteditor/fontsettings.h>
|
||||||
#include <texteditor/texteditor.h>
|
#include <texteditor/texteditor.h>
|
||||||
#include <texteditor/texteditorconstants.h>
|
#include <texteditor/texteditorconstants.h>
|
||||||
@@ -77,5 +80,13 @@ ClangEditorDocumentProcessor *ClangEditorDocumentProcessor::get(const Utils::Fil
|
|||||||
CppEditor::CppModelManager::cppEditorDocumentProcessor(filePath));
|
CppEditor::CppModelManager::cppEditorDocumentProcessor(filePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClangEditorDocumentProcessor::forceUpdate(TextEditor::TextDocument *doc)
|
||||||
|
{
|
||||||
|
if (const auto client = qobject_cast<ClangdClient *>(
|
||||||
|
LanguageClient::LanguageClientManager::clientForDocument(doc))) {
|
||||||
|
client->documentContentsChanged(doc, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ClangCodeModel
|
} // namespace ClangCodeModel
|
||||||
|
@@ -22,7 +22,6 @@ public:
|
|||||||
void setParserConfig(const CppEditor::BaseEditorDocumentParser::Configuration &config) override;
|
void setParserConfig(const CppEditor::BaseEditorDocumentParser::Configuration &config) override;
|
||||||
CppEditor::BaseEditorDocumentParser::Configuration parserConfig();
|
CppEditor::BaseEditorDocumentParser::Configuration parserConfig();
|
||||||
|
|
||||||
public:
|
|
||||||
static ClangEditorDocumentProcessor *get(const Utils::FilePath &filePath);
|
static ClangEditorDocumentProcessor *get(const Utils::FilePath &filePath);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@@ -30,6 +29,8 @@ signals:
|
|||||||
const CppEditor::BaseEditorDocumentParser::Configuration &config);
|
const CppEditor::BaseEditorDocumentParser::Configuration &config);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void forceUpdate(TextEditor::TextDocument *doc) override;
|
||||||
|
|
||||||
TextEditor::TextDocument &m_document;
|
TextEditor::TextDocument &m_document;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -2061,6 +2061,47 @@ void ClangdTestExternalChanges::test()
|
|||||||
QVERIFY(waitForSignalOrTimeout(newClient, &ClangdClient::textMarkCreated, timeOutInMs()));
|
QVERIFY(waitForSignalOrTimeout(newClient, &ClangdClient::textMarkCreated, timeOutInMs()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClangdTestIndirectChanges::ClangdTestIndirectChanges()
|
||||||
|
{
|
||||||
|
setProjectFileName("indirect-changes.pro");
|
||||||
|
setSourceFileNames({"main.cpp", "directheader.h", "indirectheader.h", "unrelatedheader.h"});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangdTestIndirectChanges::test()
|
||||||
|
{
|
||||||
|
// Initially, everything is fine.
|
||||||
|
const TextDocument * const src = document("main.cpp");
|
||||||
|
QVERIFY(src);
|
||||||
|
QVERIFY(src->marks().isEmpty());
|
||||||
|
|
||||||
|
// Write into an indirectly included header file. Our source file should have diagnostics now.
|
||||||
|
const TextDocument * const indirectHeader = document("indirectheader.h");
|
||||||
|
QVERIFY(indirectHeader);
|
||||||
|
QTextCursor cursor(indirectHeader->document());
|
||||||
|
cursor.insertText("blubb");
|
||||||
|
while (src->marks().isEmpty())
|
||||||
|
QVERIFY(waitForSignalOrTimeout(client(), &ClangdClient::textMarkCreated, timeOutInMs()));
|
||||||
|
|
||||||
|
// Remove the inserted text again; the diagnostics should disappear.
|
||||||
|
cursor.document()->undo();
|
||||||
|
QVERIFY(cursor.document()->toPlainText().isEmpty());
|
||||||
|
while (!src->marks().isEmpty()) {
|
||||||
|
QVERIFY(waitForSignalOrTimeout(client(), &ClangdClient::highlightingResultsReady,
|
||||||
|
timeOutInMs()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now write into a header file that is not included anywhere.
|
||||||
|
// We expect diagnostics only for the header itself.
|
||||||
|
const TextDocument * const unrelatedHeader = document("unrelatedheader.h");
|
||||||
|
QVERIFY(indirectHeader);
|
||||||
|
QTextCursor cursor2(unrelatedHeader->document());
|
||||||
|
cursor2.insertText("blubb");
|
||||||
|
while (waitForSignalOrTimeout(client(), &ClangdClient::textMarkCreated, timeOutInMs()))
|
||||||
|
;
|
||||||
|
QVERIFY(!unrelatedHeader->marks().isEmpty());
|
||||||
|
QVERIFY(src->marks().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Tests
|
} // namespace Tests
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ClangCodeModel
|
} // namespace ClangCodeModel
|
||||||
|
@@ -188,6 +188,17 @@ private slots:
|
|||||||
void test();
|
void test();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ClangdTestIndirectChanges : public ClangdTest
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ClangdTestIndirectChanges();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void test();
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Tests
|
} // namespace Tests
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ClangCodeModel
|
} // namespace ClangCodeModel
|
||||||
|
@@ -60,5 +60,10 @@
|
|||||||
<file>fixits/diagnostic_comparison_fixit.cpp</file>
|
<file>fixits/diagnostic_comparison_fixit.cpp</file>
|
||||||
<file>fixits/diagnostic_semicolon_fixit_expected.cpp</file>
|
<file>fixits/diagnostic_semicolon_fixit_expected.cpp</file>
|
||||||
<file>fixits/diagnostic_semicolon_fixit.cpp</file>
|
<file>fixits/diagnostic_semicolon_fixit.cpp</file>
|
||||||
|
<file>indirect-changes/directheader.h</file>
|
||||||
|
<file>indirect-changes/indirect-changes.pro</file>
|
||||||
|
<file>indirect-changes/indirectheader.h</file>
|
||||||
|
<file>indirect-changes/main.cpp</file>
|
||||||
|
<file>indirect-changes/unrelatedheader.h</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@@ -0,0 +1 @@
|
|||||||
|
#include "indirectheader.h"
|
@@ -0,0 +1,4 @@
|
|||||||
|
CONFIG -= qt
|
||||||
|
|
||||||
|
SOURCES = main.cpp
|
||||||
|
HEADERS = directheader.h indirectheader.h unrelatedheader.h
|
@@ -0,0 +1,3 @@
|
|||||||
|
#include "directheader.h"
|
||||||
|
|
||||||
|
int main() {}
|
@@ -283,6 +283,7 @@ void BuiltinEditorDocumentProcessor::onParserFinished(CPlusPlus::Document::Ptr d
|
|||||||
if (!cppDoc->includedFiles().contains(document->filePath()))
|
if (!cppDoc->includedFiles().contains(document->filePath()))
|
||||||
continue;
|
continue;
|
||||||
cppEditorDoc->scheduleProcessDocument();
|
cppEditorDoc->scheduleProcessDocument();
|
||||||
|
forceUpdate(cppEditorDoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -43,6 +43,8 @@ private:
|
|||||||
|
|
||||||
SemanticInfo::Source createSemanticInfoSource(bool force) const;
|
SemanticInfo::Source createSemanticInfoSource(bool force) const;
|
||||||
|
|
||||||
|
virtual void forceUpdate(TextEditor::TextDocument *) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BuiltinEditorDocumentParser::Ptr m_parser;
|
BuiltinEditorDocumentParser::Ptr m_parser;
|
||||||
QFuture<void> m_parserFuture;
|
QFuture<void> m_parserFuture;
|
||||||
|
Reference in New Issue
Block a user