ClangCodeModel: Forward to the built-in code model

... if the user tries to complete inside a comment or string.

Fixes: QTCREATORBUG-20828
Change-Id: I245e1bd16acaf696601cabe33f27210da21cc12a
Reviewed-by: David Schulz <david.schulz@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
Christian Kandeler
2023-10-17 10:34:57 +02:00
parent 57a485b9e7
commit d16d1718f3
8 changed files with 24 additions and 44 deletions

View File

@@ -12,7 +12,6 @@
#include <cppeditor/cppcompletionassistprocessor.h>
#include <cppeditor/cppcompletionassistprovider.h>
#include <cppeditor/cppdoxygen.h>
#include <cppeditor/cppeditorconstants.h>
#include <cppeditor/cppmodelmanager.h>
#include <cppeditor/cppprojectfile.h>
@@ -44,7 +43,7 @@ namespace ClangCodeModel::Internal {
static Q_LOGGING_CATEGORY(clangdLogCompletion, "qtc.clangcodemodel.clangd.completion",
QtWarningMsg);
enum class CustomAssistMode { Doxygen, Preprocessor, IncludePath };
enum class CustomAssistMode { Preprocessor, IncludePath };
class CustomAssistProcessor : public IAssistProcessor
{
@@ -126,6 +125,12 @@ IAssistProcessor *ClangdCompletionAssistProvider::createProcessor(
<< interface->textAt(interface->position(), -10);
qCDebug(clangdLogCompletion) << "text after cursor is"
<< interface->textAt(interface->position(), 10);
if (!interface->isBaseObject()) {
qCDebug(clangdLogCompletion) << "encountered assist interface for built-in code model";
return CppEditor::getCppCompletionAssistProcessor();
}
ClangCompletionContextAnalyzer contextAnalyzer(interface->textDocument(),
interface->position(), false, {});
contextAnalyzer.analyze();
@@ -133,13 +138,6 @@ IAssistProcessor *ClangdCompletionAssistProvider::createProcessor(
case ClangCompletionContextAnalyzer::PassThroughToLibClangAfterLeftParen:
qCDebug(clangdLogCompletion) << "creating function hint processor";
return new ClangdFunctionHintProcessor(m_client);
case ClangCompletionContextAnalyzer::CompleteDoxygenKeyword:
qCDebug(clangdLogCompletion) << "creating doxygen processor";
return new CustomAssistProcessor(m_client,
contextAnalyzer.positionForProposal(),
contextAnalyzer.positionEndOfExpression(),
contextAnalyzer.completionOperator(),
CustomAssistMode::Doxygen);
case ClangCompletionContextAnalyzer::CompletePreprocessorDirective:
qCDebug(clangdLogCompletion) << "creating macro processor";
return new CustomAssistProcessor(m_client,
@@ -147,10 +145,6 @@ IAssistProcessor *ClangdCompletionAssistProvider::createProcessor(
contextAnalyzer.positionEndOfExpression(),
contextAnalyzer.completionOperator(),
CustomAssistMode::Preprocessor);
case ClangCompletionContextAnalyzer::CompleteSignal:
case ClangCompletionContextAnalyzer::CompleteSlot:
if (!interface->isBaseObject())
return CppEditor::getCppCompletionAssistProcessor();
default:
break;
}
@@ -415,12 +409,6 @@ IAssistProposal *CustomAssistProcessor::perform()
{
QList<AssistProposalItemInterface *> completions;
switch (m_mode) {
case CustomAssistMode::Doxygen:
for (int i = 1; i < T_DOXY_LAST_TAG; ++i) {
completions << createItem(QLatin1String(doxygenTagSpell(i)),
CPlusPlus::Icons::keywordIcon());
}
break;
case CustomAssistMode::Preprocessor: {
static QIcon macroIcon = Utils::CodeModelIcon::iconForType(CodeModelIcon::Macro);
for (const QString &completion

View File

@@ -1500,7 +1500,7 @@ ClangdTestCompletion::ClangdTestCompletion()
setProjectFileName("completion.pro");
setSourceFileNames({"completionWithProject.cpp", "constructorCompletion.cpp",
"classAndConstructorCompletion.cpp", "dotToArrowCorrection.cpp",
"doxygenKeywordsCompletion.cpp", "functionAddress.cpp",
"functionAddress.cpp",
"functionCompletion.cpp", "functionCompletionFiltered2.cpp",
"functionCompletionFiltered.cpp", "globalCompletion.cpp",
"includeDirectiveCompletion.cpp", "mainwindow.cpp",
@@ -1518,18 +1518,6 @@ void ClangdTestCompletion::initTestCase()
startCollectingHighlightingInfo();
}
void ClangdTestCompletion::testCompleteDoxygenKeywords()
{
ProposalModelPtr proposal;
getProposal("doxygenKeywordsCompletion.cpp", proposal);
QVERIFY(proposal);
QVERIFY(hasItem(proposal, "brief"));
QVERIFY(hasItem(proposal, "param"));
QVERIFY(hasItem(proposal, "return"));
QVERIFY(!hasSnippet(proposal, "class "));
}
void ClangdTestCompletion::testCompletePreprocessorKeywords()
{
ProposalModelPtr proposal;

View File

@@ -137,7 +137,6 @@ public:
private slots:
void initTestCase() override;
void testCompleteDoxygenKeywords();
void testCompletePreprocessorKeywords();
void testCompleteIncludeDirective();

View File

@@ -29,7 +29,6 @@
<file>completion/classAndConstructorCompletion.cpp</file>
<file>completion/completionWithProject.cpp</file>
<file>completion/constructorCompletion.cpp</file>
<file>completion/doxygenKeywordsCompletion.cpp</file>
<file>completion/functionCompletion.cpp</file>
<file>completion/functionCompletionFiltered.cpp</file>
<file>completion/functionCompletionFiltered2.cpp</file>

View File

@@ -1 +0,0 @@
//! \ /* COMPLETE HERE */

View File

@@ -1268,7 +1268,8 @@ std::unique_ptr<AssistInterface> CppEditorWidget::createAssistInterface(AssistKi
if (cap)
return cap->createAssistInterface(textDocument()->filePath(), this, getFeatures(), reason);
if (isOldStyleSignalOrSlot()) {
if (isOldStyleSignalOrSlot()
|| isInCommentOrString(textCursor(), LanguageFeatures::defaultFeatures())) {
return CppModelManager::completionAssistProvider()
->createAssistInterface(textDocument()->filePath(), this, getFeatures(), reason);
}

View File

@@ -293,29 +293,33 @@ bool isInCommentOrString(const TextEditor::AssistInterface *interface,
{
QTextCursor tc(interface->textDocument());
tc.setPosition(interface->position());
return isInCommentOrString(tc, features);
}
bool isInCommentOrString(const QTextCursor &cursor, CPlusPlus::LanguageFeatures features)
{
SimpleLexer tokenize;
features.qtMocRunEnabled = true;
tokenize.setLanguageFeatures(features);
tokenize.setSkipComments(false);
const Tokens &tokens = tokenize(tc.block().text(),
BackwardsScanner::previousBlockState(tc.block()));
const int tokenIdx = SimpleLexer::tokenBefore(tokens, qMax(0, tc.positionInBlock() - 1));
const Tokens &tokens = tokenize(cursor.block().text(),
BackwardsScanner::previousBlockState(cursor.block()));
const int tokenIdx = SimpleLexer::tokenBefore(tokens, qMax(0, cursor.positionInBlock() - 1));
const Token tk = (tokenIdx == -1) ? Token() : tokens.at(tokenIdx);
if (tk.isComment())
return true;
if (!tk.isLiteral())
if (!tk.isStringLiteral())
return false;
if (tokens.size() == 3 && tokens.at(0).kind() == T_POUND
&& tokens.at(1).kind() == T_IDENTIFIER) {
const QString &line = tc.block().text();
&& tokens.at(1).kind() == T_IDENTIFIER) {
const QString &line = cursor.block().text();
const Token &idToken = tokens.at(1);
QStringView identifier = QStringView(line).mid(idToken.utf16charsBegin(),
idToken.utf16chars());
if (identifier == QLatin1String("include")
|| identifier == QLatin1String("include_next")
|| (features.objCEnabled && identifier == QLatin1String("import"))) {
|| identifier == QLatin1String("include_next")
|| (features.objCEnabled && identifier == QLatin1String("import"))) {
return false;
}
}

View File

@@ -54,6 +54,8 @@ const CPlusPlus::Macro CPPEDITOR_EXPORT *findCanonicalMacro(const QTextCursor &c
bool CPPEDITOR_EXPORT isInCommentOrString(const TextEditor::AssistInterface *interface,
CPlusPlus::LanguageFeatures features);
bool CPPEDITOR_EXPORT isInCommentOrString(const QTextCursor &cursor,
CPlusPlus::LanguageFeatures features);
TextEditor::QuickFixOperations CPPEDITOR_EXPORT
quickFixOperations(const TextEditor::AssistInterface *interface);