forked from qt-creator/qt-creator
Clang: Provide all overloads for function definition completion
When we complete a function definition with the parameter list it is important to have multiple entries to select. Change-Id: I25e94b58cfe4831387d66eecdec74712addb7ec5 Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
@@ -27,7 +27,6 @@
|
|||||||
|
|
||||||
#include <QTextDocument>
|
#include <QTextDocument>
|
||||||
#include <QTextBlock>
|
#include <QTextBlock>
|
||||||
#include <QTextCursor>
|
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
namespace Text {
|
namespace Text {
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
#include "utils_global.h"
|
#include "utils_global.h"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QTextCursor>
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QTextDocument)
|
QT_FORWARD_DECLARE_CLASS(QTextDocument)
|
||||||
QT_FORWARD_DECLARE_CLASS(QTextCursor)
|
QT_FORWARD_DECLARE_CLASS(QTextCursor)
|
||||||
@@ -54,5 +55,42 @@ QTCREATOR_UTILS_EXPORT QTextCursor flippedCursor(const QTextCursor &cursor);
|
|||||||
|
|
||||||
QTCREATOR_UTILS_EXPORT QTextCursor wordStartCursor(const QTextCursor &cursor);
|
QTCREATOR_UTILS_EXPORT QTextCursor wordStartCursor(const QTextCursor &cursor);
|
||||||
|
|
||||||
|
template <class CharacterProvider>
|
||||||
|
void moveToPrevChar(CharacterProvider &provider, QTextCursor &cursor)
|
||||||
|
{
|
||||||
|
cursor.movePosition(QTextCursor::PreviousCharacter);
|
||||||
|
while (provider.characterAt(cursor.position()).isSpace())
|
||||||
|
cursor.movePosition(QTextCursor::PreviousCharacter);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharacterProvider>
|
||||||
|
bool matchPreviousWord(CharacterProvider &provider, QTextCursor cursor, QString pattern)
|
||||||
|
{
|
||||||
|
cursor.movePosition(QTextCursor::PreviousWord);
|
||||||
|
while (provider.characterAt(cursor.position()) == ':')
|
||||||
|
cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor, 2);
|
||||||
|
|
||||||
|
int previousWordStart = cursor.position();
|
||||||
|
cursor.movePosition(QTextCursor::NextWord);
|
||||||
|
moveToPrevChar(provider, cursor);
|
||||||
|
QString toMatch = provider.textAt(previousWordStart, cursor.position() - previousWordStart + 1);
|
||||||
|
|
||||||
|
pattern = pattern.simplified();
|
||||||
|
while (!pattern.isEmpty() && pattern.endsWith(toMatch)) {
|
||||||
|
pattern.chop(toMatch.length());
|
||||||
|
if (pattern.endsWith(' '))
|
||||||
|
pattern.chop(1);
|
||||||
|
if (!pattern.isEmpty()) {
|
||||||
|
cursor.movePosition(QTextCursor::StartOfWord);
|
||||||
|
cursor.movePosition(QTextCursor::PreviousWord);
|
||||||
|
previousWordStart = cursor.position();
|
||||||
|
cursor.movePosition(QTextCursor::NextWord);
|
||||||
|
moveToPrevChar(provider, cursor);
|
||||||
|
toMatch = provider.textAt(previousWordStart, cursor.position() - previousWordStart + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pattern.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
} // Text
|
} // Text
|
||||||
} // Utils
|
} // Utils
|
||||||
|
@@ -57,7 +57,7 @@ bool ClangAssistProposalItem::prematurelyApplies(const QChar &typedCharacter) co
|
|||||||
applies = QString::fromLatin1("(,").contains(typedCharacter);
|
applies = QString::fromLatin1("(,").contains(typedCharacter);
|
||||||
else if (m_completionOperator == T_STRING_LITERAL || m_completionOperator == T_ANGLE_STRING_LITERAL)
|
else if (m_completionOperator == T_STRING_LITERAL || m_completionOperator == T_ANGLE_STRING_LITERAL)
|
||||||
applies = (typedCharacter == QLatin1Char('/')) && text().endsWith(QLatin1Char('/'));
|
applies = (typedCharacter == QLatin1Char('/')) && text().endsWith(QLatin1Char('/'));
|
||||||
else if (codeCompletion().completionKind == CodeCompletion::ObjCMessageCompletionKind)
|
else if (firstCodeCompletion().completionKind == CodeCompletion::ObjCMessageCompletionKind)
|
||||||
applies = QString::fromLatin1(";.,").contains(typedCharacter);
|
applies = QString::fromLatin1(";.,").contains(typedCharacter);
|
||||||
else
|
else
|
||||||
applies = QString::fromLatin1(";.,:(").contains(typedCharacter);
|
applies = QString::fromLatin1(";.,:(").contains(typedCharacter);
|
||||||
@@ -73,14 +73,6 @@ bool ClangAssistProposalItem::implicitlyApplies() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void moveToPrevChar(TextEditor::TextDocumentManipulatorInterface &manipulator,
|
|
||||||
QTextCursor &cursor)
|
|
||||||
{
|
|
||||||
cursor.movePosition(QTextCursor::PreviousCharacter);
|
|
||||||
while (manipulator.characterAt(cursor.position()).isSpace())
|
|
||||||
cursor.movePosition(QTextCursor::PreviousCharacter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString textUntilPreviousStatement(TextEditor::TextDocumentManipulatorInterface &manipulator,
|
static QString textUntilPreviousStatement(TextEditor::TextDocumentManipulatorInterface &manipulator,
|
||||||
int startPosition)
|
int startPosition)
|
||||||
{
|
{
|
||||||
@@ -118,10 +110,35 @@ static bool isAtUsingDeclaration(TextEditor::TextDocumentManipulatorInterface &m
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QString methodDefinitionParameters(const CodeCompletionChunks &chunks)
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
|
||||||
|
auto typedTextChunkIt = std::find_if(chunks.begin(), chunks.end(),
|
||||||
|
[](const CodeCompletionChunk &chunk) {
|
||||||
|
return chunk.kind == CodeCompletionChunk::TypedText;
|
||||||
|
});
|
||||||
|
if (typedTextChunkIt == chunks.end())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
std::for_each(++typedTextChunkIt, chunks.end(), [&result](const CodeCompletionChunk &chunk) {
|
||||||
|
if (chunk.kind == CodeCompletionChunk::Placeholder && chunk.text.contains('=')) {
|
||||||
|
Utf8String text = chunk.text.mid(0, chunk.text.indexOf('='));
|
||||||
|
if (text.endsWith(' '))
|
||||||
|
text.chop(1);
|
||||||
|
result += text;
|
||||||
|
} else {
|
||||||
|
result += chunk.text;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void ClangAssistProposalItem::apply(TextEditor::TextDocumentManipulatorInterface &manipulator,
|
void ClangAssistProposalItem::apply(TextEditor::TextDocumentManipulatorInterface &manipulator,
|
||||||
int basePosition) const
|
int basePosition) const
|
||||||
{
|
{
|
||||||
const CodeCompletion ccr = codeCompletion();
|
const CodeCompletion ccr = firstCodeCompletion();
|
||||||
|
|
||||||
if (!ccr.requiredFixIts.empty()) {
|
if (!ccr.requiredFixIts.empty()) {
|
||||||
ClangFixItOperation fixItOperation(Utf8String(), ccr.requiredFixIts);
|
ClangFixItOperation fixItOperation(Utf8String(), ccr.requiredFixIts);
|
||||||
@@ -173,40 +190,23 @@ void ClangAssistProposalItem::apply(TextEditor::TextDocumentManipulatorInterface
|
|||||||
// inserted closing parenthesis.
|
// inserted closing parenthesis.
|
||||||
const bool skipClosingParenthesis = m_typedCharacter != QLatin1Char('(');
|
const bool skipClosingParenthesis = m_typedCharacter != QLatin1Char('(');
|
||||||
QTextCursor cursor = manipulator.textCursorAt(basePosition);
|
QTextCursor cursor = manipulator.textCursorAt(basePosition);
|
||||||
cursor.movePosition(QTextCursor::PreviousWord);
|
|
||||||
while (manipulator.characterAt(cursor.position()) == ':')
|
|
||||||
cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor, 2);
|
|
||||||
|
|
||||||
const int previousWordStart = cursor.position();
|
|
||||||
// Move to the last character in the previous word
|
|
||||||
cursor.movePosition(QTextCursor::NextWord);
|
|
||||||
moveToPrevChar(manipulator, cursor);
|
|
||||||
const QString previousWord = manipulator.textAt(previousWordStart,
|
|
||||||
cursor.position() - previousWordStart + 1);
|
|
||||||
|
|
||||||
bool abandonParen = false;
|
bool abandonParen = false;
|
||||||
if (previousWord == "&") {
|
if (Utils::Text::matchPreviousWord(manipulator, cursor, "&")) {
|
||||||
moveToPrevChar(manipulator, cursor);
|
Utils::Text::moveToPrevChar(manipulator, cursor);
|
||||||
|
Utils::Text::moveToPrevChar(manipulator, cursor);
|
||||||
const QChar prevChar = manipulator.characterAt(cursor.position());
|
const QChar prevChar = manipulator.characterAt(cursor.position());
|
||||||
|
cursor.setPosition(basePosition);
|
||||||
abandonParen = QString("(;,{}").contains(prevChar);
|
abandonParen = QString("(;,{}").contains(prevChar);
|
||||||
}
|
}
|
||||||
if (!abandonParen)
|
if (!abandonParen)
|
||||||
abandonParen = isAtUsingDeclaration(manipulator, basePosition);
|
abandonParen = isAtUsingDeclaration(manipulator, basePosition);
|
||||||
|
|
||||||
if (!abandonParen && ccr.completionKind == CodeCompletion::FunctionDefinitionCompletionKind) {
|
if (!abandonParen && ccr.completionKind == CodeCompletion::FunctionDefinitionCompletionKind) {
|
||||||
const CodeCompletionChunk resultType = ccr.chunks.first();
|
const CodeCompletionChunk resultType = ccr.chunks.first();
|
||||||
QTC_ASSERT(resultType.kind == CodeCompletionChunk::ResultType, return;);
|
QTC_ASSERT(resultType.kind == CodeCompletionChunk::ResultType, return;);
|
||||||
if (previousWord == resultType.text.toString()) {
|
if (Utils::Text::matchPreviousWord(manipulator, cursor, resultType.text.toString())) {
|
||||||
bool skipChunks = true;
|
extraCharacters += methodDefinitionParameters(ccr.chunks);
|
||||||
for (const CodeCompletionChunk &chunk : ccr.chunks) {
|
|
||||||
if (chunk.kind == CodeCompletionChunk::TypedText) {
|
|
||||||
skipChunks = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (skipChunks)
|
|
||||||
continue;
|
|
||||||
extraCharacters += chunk.text;
|
|
||||||
}
|
|
||||||
|
|
||||||
// To skip the next block.
|
// To skip the next block.
|
||||||
abandonParen = true;
|
abandonParen = true;
|
||||||
}
|
}
|
||||||
@@ -308,10 +308,15 @@ QString ClangAssistProposalItem::text() const
|
|||||||
return m_text + (requiresFixIts() ? fixItText() : QString());
|
return m_text + (requiresFixIts() ? fixItText() : QString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QVector<ClangBackEnd::FixItContainer> &ClangAssistProposalItem::firstCompletionFixIts() const
|
||||||
|
{
|
||||||
|
return firstCodeCompletion().requiredFixIts;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Indicate required fix-it without adding extra text.
|
// FIXME: Indicate required fix-it without adding extra text.
|
||||||
QString ClangAssistProposalItem::fixItText() const
|
QString ClangAssistProposalItem::fixItText() const
|
||||||
{
|
{
|
||||||
const FixItContainer &fixIt = m_codeCompletion.requiredFixIts.first();
|
const FixItContainer &fixIt = firstCompletionFixIts().first();
|
||||||
const SourceRangeContainer &range = fixIt.range;
|
const SourceRangeContainer &range = fixIt.range;
|
||||||
return QCoreApplication::translate("ClangCodeModel::ClangAssistProposalItem",
|
return QCoreApplication::translate("ClangCodeModel::ClangAssistProposalItem",
|
||||||
" (requires to correct [%1:%2-%3:%4] to \"%5\")")
|
" (requires to correct [%1:%2-%3:%4] to \"%5\")")
|
||||||
@@ -325,12 +330,13 @@ QString ClangAssistProposalItem::fixItText() const
|
|||||||
int ClangAssistProposalItem::fixItsShift(
|
int ClangAssistProposalItem::fixItsShift(
|
||||||
const TextEditor::TextDocumentManipulatorInterface &manipulator) const
|
const TextEditor::TextDocumentManipulatorInterface &manipulator) const
|
||||||
{
|
{
|
||||||
if (m_codeCompletion.requiredFixIts.empty())
|
const QVector<ClangBackEnd::FixItContainer> &requiredFixIts = firstCompletionFixIts();
|
||||||
|
if (requiredFixIts.empty())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int shift = 0;
|
int shift = 0;
|
||||||
QTextCursor cursor = manipulator.textCursorAt(0);
|
QTextCursor cursor = manipulator.textCursorAt(0);
|
||||||
for (const FixItContainer &fixIt : m_codeCompletion.requiredFixIts) {
|
for (const FixItContainer &fixIt : requiredFixIts) {
|
||||||
const int fixItStartPos = Utils::Text::positionInText(
|
const int fixItStartPos = Utils::Text::positionInText(
|
||||||
cursor.document(),
|
cursor.document(),
|
||||||
static_cast<int>(fixIt.range.start.line),
|
static_cast<int>(fixIt.range.start.line),
|
||||||
@@ -350,7 +356,8 @@ QIcon ClangAssistProposalItem::icon() const
|
|||||||
static const char SNIPPET_ICON_PATH[] = ":/texteditor/images/snippet.png";
|
static const char SNIPPET_ICON_PATH[] = ":/texteditor/images/snippet.png";
|
||||||
static const QIcon snippetIcon = QIcon(QLatin1String(SNIPPET_ICON_PATH));
|
static const QIcon snippetIcon = QIcon(QLatin1String(SNIPPET_ICON_PATH));
|
||||||
|
|
||||||
switch (m_codeCompletion.completionKind) {
|
const ClangBackEnd::CodeCompletion &completion = firstCodeCompletion();
|
||||||
|
switch (completion.completionKind) {
|
||||||
case CodeCompletion::ClassCompletionKind:
|
case CodeCompletion::ClassCompletionKind:
|
||||||
case CodeCompletion::TemplateClassCompletionKind:
|
case CodeCompletion::TemplateClassCompletionKind:
|
||||||
case CodeCompletion::TypeAliasCompletionKind:
|
case CodeCompletion::TypeAliasCompletionKind:
|
||||||
@@ -365,7 +372,7 @@ QIcon ClangAssistProposalItem::icon() const
|
|||||||
case CodeCompletion::FunctionDefinitionCompletionKind:
|
case CodeCompletion::FunctionDefinitionCompletionKind:
|
||||||
case CodeCompletion::TemplateFunctionCompletionKind:
|
case CodeCompletion::TemplateFunctionCompletionKind:
|
||||||
case CodeCompletion::ObjCMessageCompletionKind:
|
case CodeCompletion::ObjCMessageCompletionKind:
|
||||||
switch (m_codeCompletion.availability) {
|
switch (completion.availability) {
|
||||||
case CodeCompletion::Available:
|
case CodeCompletion::Available:
|
||||||
case CodeCompletion::Deprecated:
|
case CodeCompletion::Deprecated:
|
||||||
return Icons::iconForType(Icons::FuncPublicIconType);
|
return Icons::iconForType(Icons::FuncPublicIconType);
|
||||||
@@ -375,7 +382,7 @@ QIcon ClangAssistProposalItem::icon() const
|
|||||||
case CodeCompletion::SignalCompletionKind:
|
case CodeCompletion::SignalCompletionKind:
|
||||||
return Icons::iconForType(Icons::SignalIconType);
|
return Icons::iconForType(Icons::SignalIconType);
|
||||||
case CodeCompletion::SlotCompletionKind:
|
case CodeCompletion::SlotCompletionKind:
|
||||||
switch (m_codeCompletion.availability) {
|
switch (completion.availability) {
|
||||||
case CodeCompletion::Available:
|
case CodeCompletion::Available:
|
||||||
case CodeCompletion::Deprecated:
|
case CodeCompletion::Deprecated:
|
||||||
return Icons::iconForType(Icons::SlotPublicIconType);
|
return Icons::iconForType(Icons::SlotPublicIconType);
|
||||||
@@ -389,7 +396,7 @@ QIcon ClangAssistProposalItem::icon() const
|
|||||||
case CodeCompletion::PreProcessorCompletionKind:
|
case CodeCompletion::PreProcessorCompletionKind:
|
||||||
return Icons::iconForType(Icons::MacroIconType);
|
return Icons::iconForType(Icons::MacroIconType);
|
||||||
case CodeCompletion::VariableCompletionKind:
|
case CodeCompletion::VariableCompletionKind:
|
||||||
switch (m_codeCompletion.availability) {
|
switch (completion.availability) {
|
||||||
case CodeCompletion::Available:
|
case CodeCompletion::Available:
|
||||||
case CodeCompletion::Deprecated:
|
case CodeCompletion::Deprecated:
|
||||||
return Icons::iconForType(Icons::VarPublicIconType);
|
return Icons::iconForType(Icons::VarPublicIconType);
|
||||||
@@ -411,11 +418,15 @@ QIcon ClangAssistProposalItem::icon() const
|
|||||||
|
|
||||||
QString ClangAssistProposalItem::detail() const
|
QString ClangAssistProposalItem::detail() const
|
||||||
{
|
{
|
||||||
QString detail = CompletionChunksToTextConverter::convertToToolTipWithHtml(
|
QString detail;
|
||||||
m_codeCompletion.chunks, m_codeCompletion.completionKind);
|
for (const ClangBackEnd::CodeCompletion &codeCompletion : m_codeCompletions) {
|
||||||
|
if (!detail.isEmpty())
|
||||||
if (!m_codeCompletion.briefComment.isEmpty())
|
detail += "<br>";
|
||||||
detail += QStringLiteral("\n\n") + m_codeCompletion.briefComment.toString();
|
detail += CompletionChunksToTextConverter::convertToToolTipWithHtml(
|
||||||
|
codeCompletion.chunks, codeCompletion.completionKind);
|
||||||
|
if (!codeCompletion.briefComment.isEmpty())
|
||||||
|
detail += "<br>" + codeCompletion.briefComment.toString();
|
||||||
|
}
|
||||||
|
|
||||||
return detail;
|
return detail;
|
||||||
}
|
}
|
||||||
@@ -437,7 +448,7 @@ quint64 ClangAssistProposalItem::hash() const
|
|||||||
|
|
||||||
bool ClangAssistProposalItem::requiresFixIts() const
|
bool ClangAssistProposalItem::requiresFixIts() const
|
||||||
{
|
{
|
||||||
return !m_codeCompletion.requiredFixIts.empty();
|
return !firstCompletionFixIts().empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClangAssistProposalItem::hasOverloadsWithParameters() const
|
bool ClangAssistProposalItem::hasOverloadsWithParameters() const
|
||||||
@@ -455,14 +466,14 @@ void ClangAssistProposalItem::keepCompletionOperator(unsigned compOp)
|
|||||||
m_completionOperator = compOp;
|
m_completionOperator = compOp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangAssistProposalItem::setCodeCompletion(const CodeCompletion &codeCompletion)
|
void ClangAssistProposalItem::appendCodeCompletion(const CodeCompletion &codeCompletion)
|
||||||
{
|
{
|
||||||
m_codeCompletion = codeCompletion;
|
m_codeCompletions.push_back(codeCompletion);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ClangBackEnd::CodeCompletion &ClangAssistProposalItem::codeCompletion() const
|
const ClangBackEnd::CodeCompletion &ClangAssistProposalItem::firstCodeCompletion() const
|
||||||
{
|
{
|
||||||
return m_codeCompletion;
|
return m_codeCompletions.at(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -57,14 +57,15 @@ public:
|
|||||||
bool hasOverloadsWithParameters() const;
|
bool hasOverloadsWithParameters() const;
|
||||||
void setHasOverloadsWithParameters(bool hasOverloadsWithParameters);
|
void setHasOverloadsWithParameters(bool hasOverloadsWithParameters);
|
||||||
|
|
||||||
void setCodeCompletion(const ClangBackEnd::CodeCompletion &codeCompletion);
|
void appendCodeCompletion(const ClangBackEnd::CodeCompletion &firstCodeCompletion);
|
||||||
const ClangBackEnd::CodeCompletion &codeCompletion() const;
|
const ClangBackEnd::CodeCompletion &firstCodeCompletion() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const QVector<ClangBackEnd::FixItContainer> &firstCompletionFixIts() const;
|
||||||
QString fixItText() const;
|
QString fixItText() const;
|
||||||
int fixItsShift(const TextEditor::TextDocumentManipulatorInterface &manipulator) const;
|
int fixItsShift(const TextEditor::TextDocumentManipulatorInterface &manipulator) const;
|
||||||
|
|
||||||
ClangBackEnd::CodeCompletion m_codeCompletion;
|
std::vector<ClangBackEnd::CodeCompletion> m_codeCompletions;
|
||||||
QList<ClangBackEnd::CodeCompletion> m_overloads;
|
QList<ClangBackEnd::CodeCompletion> m_overloads;
|
||||||
bool m_hasOverloadsWithParameters = false;
|
bool m_hasOverloadsWithParameters = false;
|
||||||
QString m_text;
|
QString m_text;
|
||||||
|
@@ -64,14 +64,51 @@ namespace Internal {
|
|||||||
using ClangBackEnd::CodeCompletion;
|
using ClangBackEnd::CodeCompletion;
|
||||||
using TextEditor::AssistProposalItemInterface;
|
using TextEditor::AssistProposalItemInterface;
|
||||||
|
|
||||||
namespace {
|
static void addAssistProposalItem(QList<AssistProposalItemInterface *> &items,
|
||||||
|
const CodeCompletion &codeCompletion,
|
||||||
|
const QString &name)
|
||||||
|
{
|
||||||
|
ClangAssistProposalItem *item = new ClangAssistProposalItem;
|
||||||
|
items.push_back(item);
|
||||||
|
|
||||||
QList<AssistProposalItemInterface *> toAssistProposalItems(const CodeCompletions &completions)
|
item->setText(name);
|
||||||
|
item->setOrder(int(codeCompletion.priority));
|
||||||
|
item->appendCodeCompletion(codeCompletion);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addFunctionOverloadAssistProposalItem(QList<AssistProposalItemInterface *> &items,
|
||||||
|
const ClangCompletionAssistInterface *interface,
|
||||||
|
const CodeCompletion &codeCompletion,
|
||||||
|
const QString &name)
|
||||||
|
{
|
||||||
|
ClangBackEnd::CodeCompletionChunk resultType = codeCompletion.chunks.first();
|
||||||
|
QTC_ASSERT(resultType.kind == ClangBackEnd::CodeCompletionChunk::ResultType,
|
||||||
|
return;);
|
||||||
|
|
||||||
|
auto *item = static_cast<ClangAssistProposalItem *>(items.last());
|
||||||
|
item->setHasOverloadsWithParameters(true);
|
||||||
|
QTextCursor cursor = interface->textEditorWidget()->textCursor();
|
||||||
|
cursor.setPosition(interface->position());
|
||||||
|
cursor.movePosition(QTextCursor::StartOfWord);
|
||||||
|
|
||||||
|
if (::Utils::Text::matchPreviousWord(*interface->textEditorWidget(),
|
||||||
|
cursor,
|
||||||
|
resultType.text.toString())) {
|
||||||
|
addAssistProposalItem(items, codeCompletion, name);
|
||||||
|
} else {
|
||||||
|
item->appendCodeCompletion(codeCompletion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static QList<AssistProposalItemInterface *> toAssistProposalItems(
|
||||||
|
const CodeCompletions &completions,
|
||||||
|
const ClangCompletionAssistInterface *interface)
|
||||||
{
|
{
|
||||||
bool signalCompletion = false; // TODO
|
bool signalCompletion = false; // TODO
|
||||||
bool slotCompletion = false; // TODO
|
bool slotCompletion = false; // TODO
|
||||||
|
|
||||||
QHash<QString, ClangAssistProposalItem *> items;
|
QList<AssistProposalItemInterface *> items;
|
||||||
|
items.reserve(completions.size());
|
||||||
for (const CodeCompletion &codeCompletion : completions) {
|
for (const CodeCompletion &codeCompletion : completions) {
|
||||||
if (codeCompletion.text.isEmpty()) // TODO: Make isValid()?
|
if (codeCompletion.text.isEmpty()) // TODO: Make isValid()?
|
||||||
continue;
|
continue;
|
||||||
@@ -80,35 +117,19 @@ QList<AssistProposalItemInterface *> toAssistProposalItems(const CodeCompletions
|
|||||||
if (slotCompletion && codeCompletion.completionKind != CodeCompletion::SlotCompletionKind)
|
if (slotCompletion && codeCompletion.completionKind != CodeCompletion::SlotCompletionKind)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QString name;
|
const QString name = codeCompletion.completionKind == CodeCompletion::KeywordCompletionKind
|
||||||
if (codeCompletion.completionKind == CodeCompletion::KeywordCompletionKind)
|
? CompletionChunksToTextConverter::convertToName(codeCompletion.chunks)
|
||||||
name = CompletionChunksToTextConverter::convertToName(codeCompletion.chunks);
|
: codeCompletion.text.toString();
|
||||||
|
|
||||||
|
if (!items.empty() && items.last()->text() == name && codeCompletion.hasParameters)
|
||||||
|
addFunctionOverloadAssistProposalItem(items, interface, codeCompletion, name);
|
||||||
else
|
else
|
||||||
name = codeCompletion.text.toString();
|
addAssistProposalItem(items, codeCompletion, name);
|
||||||
|
|
||||||
ClangAssistProposalItem *item = items.value(name, 0);
|
|
||||||
if (item) {
|
|
||||||
if (codeCompletion.hasParameters)
|
|
||||||
item->setHasOverloadsWithParameters(true);
|
|
||||||
} else {
|
|
||||||
item = new ClangAssistProposalItem;
|
|
||||||
items.insert(name, item);
|
|
||||||
|
|
||||||
item->setText(name);
|
|
||||||
item->setOrder(int(codeCompletion.priority));
|
|
||||||
item->setCodeCompletion(codeCompletion);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<AssistProposalItemInterface *> results;
|
return items;
|
||||||
results.reserve(items.size());
|
|
||||||
std::copy(items.cbegin(), items.cend(), std::back_inserter(results));
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Anonymous
|
|
||||||
|
|
||||||
using namespace CPlusPlus;
|
using namespace CPlusPlus;
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
|
|
||||||
@@ -147,7 +168,7 @@ void ClangCompletionAssistProcessor::handleAvailableCompletions(
|
|||||||
QTC_CHECK(m_completions.isEmpty());
|
QTC_CHECK(m_completions.isEmpty());
|
||||||
|
|
||||||
if (m_sentRequestType == NormalCompletion) {
|
if (m_sentRequestType == NormalCompletion) {
|
||||||
m_completions = toAssistProposalItems(completions);
|
m_completions = toAssistProposalItems(completions, m_interface.data());
|
||||||
|
|
||||||
if (m_addSnippets && !m_completions.isEmpty())
|
if (m_addSnippets && !m_completions.isEmpty())
|
||||||
addSnippets();
|
addSnippets();
|
||||||
|
Reference in New Issue
Block a user