ClangCodeModel: Do not use clangd for completing #ifdef & friends

Annoyingly, LLVM does not complete preprocessor directives in disabled
code, so that we would not offer e.g. "#endif" after "#if 0" (but we
would offer it after "#if 1").
Fixing it would require messing with the clang libs (rather than just
clangd), so let's just keep using our existing code, which seems to work
fine.

Change-Id: I9dabf9a2a8f3a2f68e88a11b62c3df3b5e64a55c
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2021-09-28 15:10:47 +02:00
parent 94a59f15c6
commit 29c0512416
6 changed files with 71 additions and 29 deletions

View File

@@ -568,7 +568,7 @@ void ClangCompletionAssistProcessor::completeIncludePath(const QString &realPath
bool ClangCompletionAssistProcessor::completePreprocessorDirectives()
{
foreach (const QString &preprocessorCompletion, m_preprocessorCompletions)
foreach (const QString &preprocessorCompletion, preprocessorCompletions())
addCompletionItem(preprocessorCompletion,
Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Macro));

View File

@@ -40,6 +40,7 @@
#include <cplusplus/MatchingText.h>
#include <cppeditor/cppeditorconstants.h>
#include <cppeditor/cppcodemodelsettings.h>
#include <cppeditor/cppcompletionassistprocessor.h>
#include <cppeditor/cppcompletionassistprovider.h>
#include <cppeditor/cppdoxygen.h>
#include <cppeditor/cppeditorwidget.h>
@@ -654,25 +655,47 @@ public:
{ insert("publishDiagnostics", caps); }
};
class DoxygenAssistProcessor : public IAssistProcessor
enum class CustomAssistMode { Doxygen, Preprocessor };
class CustomAssistProcessor : public IAssistProcessor
{
public:
DoxygenAssistProcessor(ClangdClient *client, int position, unsigned completionOperator)
CustomAssistProcessor(ClangdClient *client, int position, unsigned completionOperator,
CustomAssistMode mode)
: m_client(client)
, m_position(position)
, m_completionOperator(completionOperator)
, m_mode(mode)
{}
private:
IAssistProposal *perform(const AssistInterface *) override
IAssistProposal *perform(const AssistInterface *interface) override
{
QList<AssistProposalItemInterface *> completions;
switch (m_mode) {
case CustomAssistMode::Doxygen:
for (int i = 1; i < CppEditor::T_DOXY_LAST_TAG; ++i) {
const auto item = new ClangPreprocessorAssistProposalItem;
item->setText(QLatin1String(CppEditor::doxygenTagSpell(i)));
item->setIcon(CPlusPlus::Icons::keywordIcon());
item->setCompletionOperator(m_completionOperator);
completions.append(item);
completions << createItem(QLatin1String(CppEditor::doxygenTagSpell(i)),
CPlusPlus::Icons::keywordIcon());
}
break;
case CustomAssistMode::Preprocessor:
static QIcon macroIcon = Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Macro);
for (const QString &completion
: CppEditor::CppCompletionAssistProcessor::preprocessorCompletions())
completions << createItem(completion, macroIcon);
const CppEditor::ProjectFile::Kind fileType
= CppEditor::ProjectFile::classify(interface->filePath().toString());
switch (fileType) {
case CppEditor::ProjectFile::ObjCHeader:
case CppEditor::ProjectFile::ObjCXXHeader:
case CppEditor::ProjectFile::ObjCSource:
case CppEditor::ProjectFile::ObjCXXSource:
completions << createItem("import", macroIcon);
break;
default:
break;
}
}
GenericProposalModelPtr model(new GenericProposalModel);
model->loadContent(completions);
@@ -684,12 +707,21 @@ private:
return proposal;
}
AssistProposalItemInterface *createItem(const QString &text, const QIcon &icon) const
{
const auto item = new ClangPreprocessorAssistProposalItem;
item->setText(text);
item->setIcon(icon);
item->setCompletionOperator(m_completionOperator);
return item;
}
ClangdClient * const m_client;
const int m_position;
const unsigned m_completionOperator;
const CustomAssistMode m_mode;
};
static qint64 getRevision(const TextDocument *doc)
{
return doc->document()->revision();
@@ -2813,9 +2845,15 @@ IAssistProcessor *ClangdClient::ClangdCompletionAssistProvider::createProcessor(
qCDebug(clangdLog) << "completion changed to function hint";
return new ClangdFunctionHintProcessor(m_client);
case ClangCompletionContextAnalyzer::CompleteDoxygenKeyword:
return new DoxygenAssistProcessor(m_client,
return new CustomAssistProcessor(m_client,
contextAnalyzer.positionForProposal(),
contextAnalyzer.completionOperator());
contextAnalyzer.completionOperator(),
CustomAssistMode::Doxygen);
case ClangCompletionContextAnalyzer::CompletePreprocessorDirective:
return new CustomAssistProcessor(m_client,
contextAnalyzer.positionForProposal(),
contextAnalyzer.completionOperator(),
CustomAssistMode::Preprocessor);
default:
break;
}

View File

@@ -1462,7 +1462,7 @@ void ClangdTestCompletion::testCompletePreprocessorKeywords()
ProposalModelPtr proposal;
getProposal("preprocessorKeywordsCompletion.cpp", proposal);
QVERIFY(proposal);
QVERIFY(hasItem(proposal, " ifdef macro"));
QVERIFY(hasItem(proposal, "ifdef"));
QVERIFY(!hasSnippet(proposal, "class "));
proposal.clear();
@@ -1474,7 +1474,6 @@ void ClangdTestCompletion::testCompletePreprocessorKeywords()
proposal.clear();
getProposal("preprocessorKeywordsCompletion3.cpp", proposal);
QVERIFY(proposal);
QEXPECT_FAIL("", "TODO: Fix in clangd", Continue);
QVERIFY(hasItem(proposal, "endif"));
QVERIFY(!hasSnippet(proposal, "class "));
}

View File

@@ -1302,7 +1302,7 @@ void InternalCppCompletionAssistProcessor::completeInclude(const QString &realPa
void InternalCppCompletionAssistProcessor::completePreprocessor()
{
foreach (const QString &preprocessorCompletion, m_preprocessorCompletions)
foreach (const QString &preprocessorCompletion, preprocessorCompletions())
addCompletionItem(preprocessorCompletion);
if (objcKeywordsWanted())

View File

@@ -41,18 +41,22 @@ using namespace CPlusPlus;
namespace CppEditor {
CppCompletionAssistProcessor::CppCompletionAssistProcessor(int snippetItemOrder)
: m_preprocessorCompletions(
QStringList({"define", "error", "include", "line", "pragma", "pragma once",
: m_snippetCollector(QLatin1String(CppEditor::Constants::CPP_SNIPPETS_GROUP_ID),
QIcon(QLatin1String(":/texteditor/images/snippet.png")),
snippetItemOrder)
{
}
const QStringList CppCompletionAssistProcessor::preprocessorCompletions()
{
static QStringList list{"define", "error", "include", "line", "pragma", "pragma once",
"pragma omp atomic", "pragma omp parallel", "pragma omp for",
"pragma omp ordered", "pragma omp parallel for", "pragma omp section",
"pragma omp sections", "pragma omp parallel sections", "pragma omp single",
"pragma omp master", "pragma omp critical", "pragma omp barrier",
"pragma omp flush", "pragma omp threadprivate", "undef", "if", "ifdef",
"ifndef", "elif", "else", "endif"}))
, m_snippetCollector(QLatin1String(CppEditor::Constants::CPP_SNIPPETS_GROUP_ID),
QIcon(QLatin1String(":/texteditor/images/snippet.png")),
snippetItemOrder)
{
"ifndef", "elif", "else", "endif"};
return list;
}
void CppCompletionAssistProcessor::addSnippets()

View File

@@ -45,6 +45,8 @@ class CPPEDITOR_EXPORT CppCompletionAssistProcessor : public TextEditor::IAssist
public:
explicit CppCompletionAssistProcessor(int snippetItemOrder = 0);
static const QStringList preprocessorCompletions();
protected:
void addSnippets();
@@ -60,7 +62,6 @@ protected:
int m_positionForProposal = -1;
QList<TextEditor::AssistProposalItemInterface *> m_completions;
QStringList m_preprocessorCompletions;
TextEditor::IAssistProposal *m_hintProposal = nullptr;
private: