CodeAssist: Ensure perfect match for keywords

...as otherwise the completion windows stays open and gets in the way.

Fixes: QTCREATORBUG-21767
Change-Id: Ib0a841b9d9de52109439f067c466478744361814
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Nikolai Kosjar
2019-05-22 10:21:56 +02:00
parent 76d44aea0d
commit 975173af11
6 changed files with 35 additions and 7 deletions

View File

@@ -489,6 +489,12 @@ QString ClangAssistProposalItem::detail() const
return detail; return detail;
} }
bool ClangAssistProposalItem::isKeyword() const
{
// KeywordCompletionKind includes real keywords but also "code patterns"/snippets.
return m_codeCompletions[0].completionKind == CodeCompletion::KeywordCompletionKind;
}
bool ClangAssistProposalItem::isSnippet() const bool ClangAssistProposalItem::isSnippet() const
{ {
return false; return false;

View File

@@ -47,6 +47,7 @@ public:
QString text() const final; QString text() const final;
QIcon icon() const final; QIcon icon() const final;
QString detail() const final; QString detail() const final;
bool isKeyword() const final;
bool isSnippet() const final; bool isSnippet() const final;
bool isValid() const final; bool isValid() const final;
quint64 hash() const final; quint64 hash() const final;

View File

@@ -92,7 +92,10 @@ public:
void keepCompletionOperator(unsigned compOp) { m_completionOperator = compOp; } void keepCompletionOperator(unsigned compOp) { m_completionOperator = compOp; }
void keepTypeOfExpression(const QSharedPointer<TypeOfExpression> &typeOfExp) void keepTypeOfExpression(const QSharedPointer<TypeOfExpression> &typeOfExp)
{ m_typeOfExpression = typeOfExp; } { m_typeOfExpression = typeOfExp; }
bool isKeyword() const final
{ return m_isKeyword; }
void setIsKeyword(bool isKeyword)
{ m_isKeyword = isKeyword; }
quint64 hash() const override; quint64 hash() const override;
@@ -101,6 +104,7 @@ private:
unsigned m_completionOperator = T_EOF_SYMBOL; unsigned m_completionOperator = T_EOF_SYMBOL;
mutable QChar m_typedChar; mutable QChar m_typedChar;
bool m_isOverloaded = false; bool m_isOverloaded = false;
bool m_isKeyword = false;
}; };
} // Internal } // Internal
@@ -1531,6 +1535,16 @@ bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope)
return !m_completions.isEmpty(); return !m_completions.isEmpty();
} }
void InternalCppCompletionAssistProcessor::addKeywordCompletionItem(const QString &text)
{
auto item = new CppAssistProposalItem;
item->setText(text);
item->setIcon(Icons::keywordIcon());
item->setOrder(KeywordsOrder);
item->setIsKeyword(true);
m_completions.append(item);
}
bool InternalCppCompletionAssistProcessor::completeMember(const QList<LookupItem> &baseResults) bool InternalCppCompletionAssistProcessor::completeMember(const QList<LookupItem> &baseResults)
{ {
const LookupContext &context = m_model->m_typeOfExpression->context(); const LookupContext &context = m_model->m_typeOfExpression->context();
@@ -1859,16 +1873,16 @@ void InternalCppCompletionAssistProcessor::addKeywords()
// keyword completion items. // keyword completion items.
for (int i = T_FIRST_KEYWORD; i < keywordLimit; ++i) for (int i = T_FIRST_KEYWORD; i < keywordLimit; ++i)
addCompletionItem(QLatin1String(Token::name(i)), Icons::keywordIcon(), KeywordsOrder); addKeywordCompletionItem(QLatin1String(Token::name(i)));
// primitive type completion items. // primitive type completion items.
for (int i = T_FIRST_PRIMITIVE; i <= T_LAST_PRIMITIVE; ++i) for (int i = T_FIRST_PRIMITIVE; i <= T_LAST_PRIMITIVE; ++i)
addCompletionItem(QLatin1String(Token::name(i)), Icons::keywordIcon(), KeywordsOrder); addKeywordCompletionItem(QLatin1String(Token::name(i)));
// "Identifiers with special meaning" // "Identifiers with special meaning"
if (m_interface->languageFeatures().cxx11Enabled) { if (m_interface->languageFeatures().cxx11Enabled) {
addCompletionItem(QLatin1String("override"), Icons::keywordIcon(), KeywordsOrder); addKeywordCompletionItem(QLatin1String("override"));
addCompletionItem(QLatin1String("final"), Icons::keywordIcon(), KeywordsOrder); addKeywordCompletionItem(QLatin1String("final"));
} }
} }

View File

@@ -138,6 +138,7 @@ private:
CPlusPlus::Scope *cursorScope); CPlusPlus::Scope *cursorScope);
bool globalCompletion(CPlusPlus::Scope *scope); bool globalCompletion(CPlusPlus::Scope *scope);
void addKeywordCompletionItem(const QString &text);
void addCompletionItem(const QString &text, void addCompletionItem(const QString &text,
const QIcon &icon = QIcon(), const QIcon &icon = QIcon(),
int order = 0, int order = 0,

View File

@@ -62,6 +62,7 @@ public:
virtual void apply(TextDocumentManipulatorInterface &manipulator, int basePosition) const = 0; virtual void apply(TextDocumentManipulatorInterface &manipulator, int basePosition) const = 0;
virtual QIcon icon() const = 0; virtual QIcon icon() const = 0;
virtual QString detail() const = 0; virtual QString detail() const = 0;
virtual bool isKeyword() const { return false; };
virtual bool isSnippet() const = 0; virtual bool isSnippet() const = 0;
virtual bool isValid() const = 0; virtual bool isValid() const = 0;
virtual quint64 hash() const = 0; // it is only for removing duplicates virtual quint64 hash() const = 0; // it is only for removing duplicates

View File

@@ -214,9 +214,14 @@ bool GenericProposalModel::isPerfectMatch(const QString &prefix) const
if (match == PerfectMatchType::StartsWith) if (match == PerfectMatchType::StartsWith)
return false; return false;
if (!hasFullMatch && match == PerfectMatchType::Full) if (match == PerfectMatchType::Full) {
if (proposalItem(i)->isKeyword())
return true;
if (!hasFullMatch)
hasFullMatch = true; hasFullMatch = true;
} }
}
return hasFullMatch; return hasFullMatch;
} }