forked from qt-creator/qt-creator
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:
@@ -568,7 +568,7 @@ void ClangCompletionAssistProcessor::completeIncludePath(const QString &realPath
|
|||||||
|
|
||||||
bool ClangCompletionAssistProcessor::completePreprocessorDirectives()
|
bool ClangCompletionAssistProcessor::completePreprocessorDirectives()
|
||||||
{
|
{
|
||||||
foreach (const QString &preprocessorCompletion, m_preprocessorCompletions)
|
foreach (const QString &preprocessorCompletion, preprocessorCompletions())
|
||||||
addCompletionItem(preprocessorCompletion,
|
addCompletionItem(preprocessorCompletion,
|
||||||
Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Macro));
|
Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Macro));
|
||||||
|
|
||||||
|
@@ -40,6 +40,7 @@
|
|||||||
#include <cplusplus/MatchingText.h>
|
#include <cplusplus/MatchingText.h>
|
||||||
#include <cppeditor/cppeditorconstants.h>
|
#include <cppeditor/cppeditorconstants.h>
|
||||||
#include <cppeditor/cppcodemodelsettings.h>
|
#include <cppeditor/cppcodemodelsettings.h>
|
||||||
|
#include <cppeditor/cppcompletionassistprocessor.h>
|
||||||
#include <cppeditor/cppcompletionassistprovider.h>
|
#include <cppeditor/cppcompletionassistprovider.h>
|
||||||
#include <cppeditor/cppdoxygen.h>
|
#include <cppeditor/cppdoxygen.h>
|
||||||
#include <cppeditor/cppeditorwidget.h>
|
#include <cppeditor/cppeditorwidget.h>
|
||||||
@@ -654,25 +655,47 @@ public:
|
|||||||
{ insert("publishDiagnostics", caps); }
|
{ insert("publishDiagnostics", caps); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class DoxygenAssistProcessor : public IAssistProcessor
|
|
||||||
|
enum class CustomAssistMode { Doxygen, Preprocessor };
|
||||||
|
class CustomAssistProcessor : public IAssistProcessor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DoxygenAssistProcessor(ClangdClient *client, int position, unsigned completionOperator)
|
CustomAssistProcessor(ClangdClient *client, int position, unsigned completionOperator,
|
||||||
|
CustomAssistMode mode)
|
||||||
: m_client(client)
|
: m_client(client)
|
||||||
, m_position(position)
|
, m_position(position)
|
||||||
, m_completionOperator(completionOperator)
|
, m_completionOperator(completionOperator)
|
||||||
|
, m_mode(mode)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IAssistProposal *perform(const AssistInterface *) override
|
IAssistProposal *perform(const AssistInterface *interface) override
|
||||||
{
|
{
|
||||||
QList<AssistProposalItemInterface *> completions;
|
QList<AssistProposalItemInterface *> completions;
|
||||||
|
switch (m_mode) {
|
||||||
|
case CustomAssistMode::Doxygen:
|
||||||
for (int i = 1; i < CppEditor::T_DOXY_LAST_TAG; ++i) {
|
for (int i = 1; i < CppEditor::T_DOXY_LAST_TAG; ++i) {
|
||||||
const auto item = new ClangPreprocessorAssistProposalItem;
|
completions << createItem(QLatin1String(CppEditor::doxygenTagSpell(i)),
|
||||||
item->setText(QLatin1String(CppEditor::doxygenTagSpell(i)));
|
CPlusPlus::Icons::keywordIcon());
|
||||||
item->setIcon(CPlusPlus::Icons::keywordIcon());
|
}
|
||||||
item->setCompletionOperator(m_completionOperator);
|
break;
|
||||||
completions.append(item);
|
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);
|
GenericProposalModelPtr model(new GenericProposalModel);
|
||||||
model->loadContent(completions);
|
model->loadContent(completions);
|
||||||
@@ -684,12 +707,21 @@ private:
|
|||||||
return proposal;
|
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;
|
ClangdClient * const m_client;
|
||||||
const int m_position;
|
const int m_position;
|
||||||
const unsigned m_completionOperator;
|
const unsigned m_completionOperator;
|
||||||
|
const CustomAssistMode m_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static qint64 getRevision(const TextDocument *doc)
|
static qint64 getRevision(const TextDocument *doc)
|
||||||
{
|
{
|
||||||
return doc->document()->revision();
|
return doc->document()->revision();
|
||||||
@@ -2813,9 +2845,15 @@ IAssistProcessor *ClangdClient::ClangdCompletionAssistProvider::createProcessor(
|
|||||||
qCDebug(clangdLog) << "completion changed to function hint";
|
qCDebug(clangdLog) << "completion changed to function hint";
|
||||||
return new ClangdFunctionHintProcessor(m_client);
|
return new ClangdFunctionHintProcessor(m_client);
|
||||||
case ClangCompletionContextAnalyzer::CompleteDoxygenKeyword:
|
case ClangCompletionContextAnalyzer::CompleteDoxygenKeyword:
|
||||||
return new DoxygenAssistProcessor(m_client,
|
return new CustomAssistProcessor(m_client,
|
||||||
contextAnalyzer.positionForProposal(),
|
contextAnalyzer.positionForProposal(),
|
||||||
contextAnalyzer.completionOperator());
|
contextAnalyzer.completionOperator(),
|
||||||
|
CustomAssistMode::Doxygen);
|
||||||
|
case ClangCompletionContextAnalyzer::CompletePreprocessorDirective:
|
||||||
|
return new CustomAssistProcessor(m_client,
|
||||||
|
contextAnalyzer.positionForProposal(),
|
||||||
|
contextAnalyzer.completionOperator(),
|
||||||
|
CustomAssistMode::Preprocessor);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -1462,20 +1462,19 @@ void ClangdTestCompletion::testCompletePreprocessorKeywords()
|
|||||||
ProposalModelPtr proposal;
|
ProposalModelPtr proposal;
|
||||||
getProposal("preprocessorKeywordsCompletion.cpp", proposal);
|
getProposal("preprocessorKeywordsCompletion.cpp", proposal);
|
||||||
QVERIFY(proposal);
|
QVERIFY(proposal);
|
||||||
QVERIFY(hasItem(proposal, " ifdef macro"));
|
QVERIFY(hasItem(proposal, "ifdef"));
|
||||||
QVERIFY(!hasSnippet(proposal, "class "));
|
QVERIFY(!hasSnippet(proposal, "class "));
|
||||||
|
|
||||||
proposal.clear();
|
proposal.clear();
|
||||||
getProposal("preprocessorKeywordsCompletion2.cpp", proposal);
|
getProposal("preprocessorKeywordsCompletion2.cpp", proposal);
|
||||||
QVERIFY(proposal);
|
QVERIFY(proposal);
|
||||||
QVERIFY(hasItem(proposal, " endif"));
|
QVERIFY(hasItem(proposal, "endif"));
|
||||||
QVERIFY(!hasSnippet(proposal, "class "));
|
QVERIFY(!hasSnippet(proposal, "class "));
|
||||||
|
|
||||||
proposal.clear();
|
proposal.clear();
|
||||||
getProposal("preprocessorKeywordsCompletion3.cpp", proposal);
|
getProposal("preprocessorKeywordsCompletion3.cpp", proposal);
|
||||||
QVERIFY(proposal);
|
QVERIFY(proposal);
|
||||||
QEXPECT_FAIL("", "TODO: Fix in clangd", Continue);
|
QVERIFY(hasItem(proposal, "endif"));
|
||||||
QVERIFY(hasItem(proposal, " endif"));
|
|
||||||
QVERIFY(!hasSnippet(proposal, "class "));
|
QVERIFY(!hasSnippet(proposal, "class "));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1302,7 +1302,7 @@ void InternalCppCompletionAssistProcessor::completeInclude(const QString &realPa
|
|||||||
|
|
||||||
void InternalCppCompletionAssistProcessor::completePreprocessor()
|
void InternalCppCompletionAssistProcessor::completePreprocessor()
|
||||||
{
|
{
|
||||||
foreach (const QString &preprocessorCompletion, m_preprocessorCompletions)
|
foreach (const QString &preprocessorCompletion, preprocessorCompletions())
|
||||||
addCompletionItem(preprocessorCompletion);
|
addCompletionItem(preprocessorCompletion);
|
||||||
|
|
||||||
if (objcKeywordsWanted())
|
if (objcKeywordsWanted())
|
||||||
|
@@ -41,18 +41,22 @@ using namespace CPlusPlus;
|
|||||||
namespace CppEditor {
|
namespace CppEditor {
|
||||||
|
|
||||||
CppCompletionAssistProcessor::CppCompletionAssistProcessor(int snippetItemOrder)
|
CppCompletionAssistProcessor::CppCompletionAssistProcessor(int snippetItemOrder)
|
||||||
: m_preprocessorCompletions(
|
: m_snippetCollector(QLatin1String(CppEditor::Constants::CPP_SNIPPETS_GROUP_ID),
|
||||||
QStringList({"define", "error", "include", "line", "pragma", "pragma once",
|
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 atomic", "pragma omp parallel", "pragma omp for",
|
||||||
"pragma omp ordered", "pragma omp parallel for", "pragma omp section",
|
"pragma omp ordered", "pragma omp parallel for", "pragma omp section",
|
||||||
"pragma omp sections", "pragma omp parallel sections", "pragma omp single",
|
"pragma omp sections", "pragma omp parallel sections", "pragma omp single",
|
||||||
"pragma omp master", "pragma omp critical", "pragma omp barrier",
|
"pragma omp master", "pragma omp critical", "pragma omp barrier",
|
||||||
"pragma omp flush", "pragma omp threadprivate", "undef", "if", "ifdef",
|
"pragma omp flush", "pragma omp threadprivate", "undef", "if", "ifdef",
|
||||||
"ifndef", "elif", "else", "endif"}))
|
"ifndef", "elif", "else", "endif"};
|
||||||
, m_snippetCollector(QLatin1String(CppEditor::Constants::CPP_SNIPPETS_GROUP_ID),
|
return list;
|
||||||
QIcon(QLatin1String(":/texteditor/images/snippet.png")),
|
|
||||||
snippetItemOrder)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCompletionAssistProcessor::addSnippets()
|
void CppCompletionAssistProcessor::addSnippets()
|
||||||
|
@@ -45,6 +45,8 @@ class CPPEDITOR_EXPORT CppCompletionAssistProcessor : public TextEditor::IAssist
|
|||||||
public:
|
public:
|
||||||
explicit CppCompletionAssistProcessor(int snippetItemOrder = 0);
|
explicit CppCompletionAssistProcessor(int snippetItemOrder = 0);
|
||||||
|
|
||||||
|
static const QStringList preprocessorCompletions();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void addSnippets();
|
void addSnippets();
|
||||||
|
|
||||||
@@ -60,7 +62,6 @@ protected:
|
|||||||
|
|
||||||
int m_positionForProposal = -1;
|
int m_positionForProposal = -1;
|
||||||
QList<TextEditor::AssistProposalItemInterface *> m_completions;
|
QList<TextEditor::AssistProposalItemInterface *> m_completions;
|
||||||
QStringList m_preprocessorCompletions;
|
|
||||||
TextEditor::IAssistProposal *m_hintProposal = nullptr;
|
TextEditor::IAssistProposal *m_hintProposal = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Reference in New Issue
Block a user