forked from qt-creator/qt-creator
Clang: Show function signature hint for constructors and functors
For "foo(|" [1] we requested a completion from libclang with the cursor position just before "foo" and then filtered the function declarations for functions matching the name "foo". This worked fine for ordinary functions, but obviously not for constructors and functors. Recent versions of libclang support proper function call completion with XCursor_OverloadCandidate, so make use of that. [1] '|' represents the cursor position Task-number: QTCREATORBUG-14882 Task-number: QTCREATORBUG-14884 Change-Id: I9d31b3960ccff6a8b9440dbcb7ff9f5ca9f61266 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -37,6 +37,7 @@ static const char *completionKindToString(CodeCompletion::Kind kind)
|
||||
case CodeCompletion::Other: return "Other";
|
||||
case CodeCompletion::FunctionCompletionKind: return "Function";
|
||||
case CodeCompletion::TemplateFunctionCompletionKind: return "TemplateFunction";
|
||||
case CodeCompletion::FunctionOverloadCompletionKind: return "FunctionOverload";
|
||||
case CodeCompletion::ConstructorCompletionKind: return "Constructor";
|
||||
case CodeCompletion::DestructorCompletionKind: return "Destructor";
|
||||
case CodeCompletion::VariableCompletionKind: return "Variable";
|
||||
|
||||
@@ -44,6 +44,7 @@ public:
|
||||
enum Kind : quint32 {
|
||||
Other = 0,
|
||||
FunctionCompletionKind,
|
||||
FunctionOverloadCompletionKind,
|
||||
TemplateFunctionCompletionKind,
|
||||
ConstructorCompletionKind,
|
||||
DestructorCompletionKind,
|
||||
|
||||
@@ -276,6 +276,8 @@ QIcon ClangAssistProposalItem::icon() const
|
||||
return snippetIcon;
|
||||
case CodeCompletion::Other:
|
||||
return Icons::iconForType(Icons::UnknownIconType);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QIcon();
|
||||
|
||||
@@ -175,11 +175,8 @@ void IpcReceiver::codeCompleted(const CodeCompletedMessage &message)
|
||||
const quint64 ticket = message.ticketNumber();
|
||||
QScopedPointer<ClangCompletionAssistProcessor> processor(m_assistProcessorsTable.take(ticket));
|
||||
if (processor) {
|
||||
const bool finished = processor->handleAvailableAsyncCompletions(
|
||||
message.codeCompletions(),
|
||||
processor->handleAvailableCompletions(message.codeCompletions(),
|
||||
message.neededCorrection());
|
||||
if (!finished)
|
||||
processor.take();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
|
||||
#include <clangbackendipc/filecontainer.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/mimetypes/mimedatabase.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
@@ -106,30 +107,6 @@ QList<AssistProposalItemInterface *> toAssistProposalItems(const CodeCompletions
|
||||
return results;
|
||||
}
|
||||
|
||||
bool isFunctionHintLikeCompletion(CodeCompletion::Kind kind)
|
||||
{
|
||||
return kind == CodeCompletion::FunctionCompletionKind
|
||||
|| kind == CodeCompletion::ConstructorCompletionKind
|
||||
|| kind == CodeCompletion::DestructorCompletionKind
|
||||
|| kind == CodeCompletion::SignalCompletionKind
|
||||
|| kind == CodeCompletion::SlotCompletionKind;
|
||||
}
|
||||
|
||||
CodeCompletions matchingFunctionCompletions(const CodeCompletions completions,
|
||||
const QString &functionName)
|
||||
{
|
||||
CodeCompletions matching;
|
||||
|
||||
foreach (const CodeCompletion &completion, completions) {
|
||||
if (isFunctionHintLikeCompletion(completion.completionKind())
|
||||
&& completion.text().toString() == functionName) {
|
||||
matching.append(completion);
|
||||
}
|
||||
}
|
||||
|
||||
return matching;
|
||||
}
|
||||
|
||||
} // Anonymous
|
||||
|
||||
using namespace CPlusPlus;
|
||||
@@ -157,25 +134,32 @@ IAssistProposal *ClangCompletionAssistProcessor::perform(const AssistInterface *
|
||||
return startCompletionHelper(); // == 0 if results are calculated asynchronously
|
||||
}
|
||||
|
||||
bool ClangCompletionAssistProcessor::handleAvailableAsyncCompletions(
|
||||
static CodeCompletions filterFunctionSignatures(const CodeCompletions &completions)
|
||||
{
|
||||
return ::Utils::filtered(completions, [](const CodeCompletion &completion) {
|
||||
return completion.completionKind() == CodeCompletion::FunctionOverloadCompletionKind;
|
||||
});
|
||||
}
|
||||
|
||||
void ClangCompletionAssistProcessor::handleAvailableCompletions(
|
||||
const CodeCompletions &completions,
|
||||
CompletionCorrection neededCorrection)
|
||||
{
|
||||
bool handled = true;
|
||||
QTC_CHECK(m_completions.isEmpty());
|
||||
|
||||
switch (m_sentRequestType) {
|
||||
case CompletionRequestType::NormalCompletion:
|
||||
handleAvailableCompletions(completions, neededCorrection);
|
||||
break;
|
||||
case CompletionRequestType::FunctionHintCompletion:
|
||||
handled = handleAvailableFunctionHintCompletions(completions);
|
||||
break;
|
||||
default:
|
||||
QTC_CHECK(!"Unhandled ClangCompletionAssistProcessor::CompletionRequestType");
|
||||
break;
|
||||
if (m_sentRequestType == NormalCompletion) {
|
||||
m_completions = toAssistProposalItems(completions);
|
||||
|
||||
if (m_addSnippets && !m_completions.isEmpty())
|
||||
addSnippets();
|
||||
|
||||
setAsyncProposalAvailable(createProposal(neededCorrection));
|
||||
} else {
|
||||
const CodeCompletions functionSignatures = filterFunctionSignatures(completions);
|
||||
if (!functionSignatures.isEmpty())
|
||||
setAsyncProposalAvailable(createFunctionHintProposal(functionSignatures));
|
||||
// else: Not a function call, but e.g. a function declaration like "void f("
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
const TextEditorWidget *ClangCompletionAssistProcessor::textEditorWidget() const
|
||||
@@ -268,7 +252,6 @@ IAssistProposal *ClangCompletionAssistProcessor::startCompletionHelper()
|
||||
}
|
||||
case ClangCompletionContextAnalyzer::PassThroughToLibClangAfterLeftParen: {
|
||||
m_sentRequestType = FunctionHintCompletion;
|
||||
m_functionName = analyzer.functionName();
|
||||
const bool requestSent = sendCompletionRequest(analyzer.positionForClang(), QByteArray());
|
||||
setPerformWasApplicable(requestSent);
|
||||
break;
|
||||
@@ -599,38 +582,12 @@ TextEditor::IAssistProposal *ClangCompletionAssistProcessor::createProposal(
|
||||
return new ClangAssistProposal(m_positionForProposal, model);
|
||||
}
|
||||
|
||||
void ClangCompletionAssistProcessor::handleAvailableCompletions(
|
||||
const CodeCompletions &completions,
|
||||
CompletionCorrection neededCorrection)
|
||||
IAssistProposal *ClangCompletionAssistProcessor::createFunctionHintProposal(
|
||||
const ClangBackEnd::CodeCompletions &completions) const
|
||||
{
|
||||
QTC_CHECK(m_completions.isEmpty());
|
||||
|
||||
m_completions = toAssistProposalItems(completions);
|
||||
if (m_addSnippets && !m_completions.isEmpty())
|
||||
addSnippets();
|
||||
|
||||
setAsyncProposalAvailable(createProposal(neededCorrection));
|
||||
}
|
||||
|
||||
bool ClangCompletionAssistProcessor::handleAvailableFunctionHintCompletions(
|
||||
const CodeCompletions &completions)
|
||||
{
|
||||
QTC_CHECK(!m_functionName.isEmpty());
|
||||
const auto relevantCompletions = matchingFunctionCompletions(completions, m_functionName);
|
||||
|
||||
if (!relevantCompletions.isEmpty()) {
|
||||
auto *model = new ClangFunctionHintModel(relevantCompletions);
|
||||
auto *model = new ClangFunctionHintModel(completions);
|
||||
auto *proposal = new FunctionHintProposal(m_positionForProposal, model);
|
||||
|
||||
setAsyncProposalAvailable(proposal);
|
||||
return true;
|
||||
} else {
|
||||
m_addSnippets = false;
|
||||
m_functionName.clear();
|
||||
m_sentRequestType = NormalCompletion;
|
||||
sendCompletionRequest(m_interface->position(), QByteArray());
|
||||
return false; // We are not yet finished.
|
||||
}
|
||||
return proposal;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
|
||||
TextEditor::IAssistProposal *perform(const TextEditor::AssistInterface *interface) override;
|
||||
|
||||
bool handleAvailableAsyncCompletions(const CodeCompletions &completions,
|
||||
void handleAvailableCompletions(const CodeCompletions &completions,
|
||||
CompletionCorrection neededCorrection);
|
||||
|
||||
const TextEditor::TextEditorWidget *textEditorWidget() const;
|
||||
@@ -63,6 +63,8 @@ private:
|
||||
|
||||
TextEditor::IAssistProposal *createProposal(
|
||||
CompletionCorrection neededCorrection = CompletionCorrection::NoCorrection) const;
|
||||
TextEditor::IAssistProposal *createFunctionHintProposal(
|
||||
const CodeCompletions &completions) const;
|
||||
|
||||
bool completeInclude(const QTextCursor &cursor);
|
||||
bool completeInclude(int position);
|
||||
@@ -82,15 +84,10 @@ private:
|
||||
void sendFileContent(const QByteArray &customFileContent);
|
||||
bool sendCompletionRequest(int position, const QByteArray &customFileContent);
|
||||
|
||||
void handleAvailableCompletions(const CodeCompletions &completions,
|
||||
CompletionCorrection neededCorrection);
|
||||
bool handleAvailableFunctionHintCompletions(const CodeCompletions &completions);
|
||||
|
||||
private:
|
||||
QScopedPointer<const ClangCompletionAssistInterface> m_interface;
|
||||
unsigned m_completionOperator;
|
||||
enum CompletionRequestType { NormalCompletion, FunctionHintCompletion } m_sentRequestType;
|
||||
QString m_functionName; // For type == Type::FunctionHintCompletion
|
||||
bool m_addSnippets = false; // For type == Type::NormalCompletion
|
||||
};
|
||||
|
||||
|
||||
@@ -167,7 +167,11 @@ void CompletionChunksToTextConverter::parse(
|
||||
|
||||
switch (codeCompletionChunk.kind()) {
|
||||
case CodeCompletionChunk::ResultType: parseResultType(codeCompletionChunk.text()); break;
|
||||
case CodeCompletionChunk::Placeholder: parsePlaceHolder(codeCompletionChunk); break;
|
||||
// Do not rely on CurrentParameter because it might be wrong for
|
||||
// invalid code. Instead, handle it as PlaceHolder.
|
||||
case CodeCompletionChunk::CurrentParameter:
|
||||
case CodeCompletionChunk::Placeholder:
|
||||
parsePlaceHolder(codeCompletionChunk); break;
|
||||
case CodeCompletionChunk::LeftParen: parseLeftParen(codeCompletionChunk); break;
|
||||
case CodeCompletionChunk::LeftBrace: parseLeftBrace(codeCompletionChunk); break;
|
||||
default: parseText(codeCompletionChunk.text()); break;
|
||||
|
||||
@@ -91,8 +91,7 @@ void ClangCompletionContextAnalyzer::analyze()
|
||||
}
|
||||
}
|
||||
|
||||
ClangCompletionContextAnalyzer::FunctionInfo
|
||||
ClangCompletionContextAnalyzer::analyzeFunctionCall(int endOfOperator) const
|
||||
bool ClangCompletionContextAnalyzer::looksLikeAFunctionCall(int endOfOperator) const
|
||||
{
|
||||
int index = ActivationSequenceContextProcessor::skipPrecedingWhitespace(m_interface,
|
||||
endOfOperator);
|
||||
@@ -104,15 +103,15 @@ ClangCompletionContextAnalyzer::analyzeFunctionCall(int endOfOperator) const
|
||||
index = ActivationSequenceContextProcessor::skipPrecedingWhitespace(m_interface, index);
|
||||
const int functionNameStart = ActivationSequenceContextProcessor::findStartOfName(m_interface,
|
||||
index);
|
||||
if (functionNameStart == -1)
|
||||
return false;
|
||||
|
||||
QTextCursor textCursor2(m_interface->textDocument());
|
||||
textCursor2.setPosition(functionNameStart);
|
||||
textCursor2.setPosition(index, QTextCursor::KeepAnchor);
|
||||
QTextCursor functionNameSelector(m_interface->textDocument());
|
||||
functionNameSelector.setPosition(functionNameStart);
|
||||
functionNameSelector.setPosition(index, QTextCursor::KeepAnchor);
|
||||
const QString functionName = functionNameSelector.selectedText().trimmed();
|
||||
|
||||
FunctionInfo info;
|
||||
info.functionNamePosition = functionNameStart;
|
||||
info.functionName = textCursor2.selectedText().trimmed();
|
||||
return info;
|
||||
return !functionName.isEmpty();
|
||||
}
|
||||
|
||||
void ClangCompletionContextAnalyzer::setActionAndClangPosition(CompletionAction action,
|
||||
@@ -158,18 +157,17 @@ void ClangCompletionContextAnalyzer::handleFunctionCall(int afterOperatorPositio
|
||||
// No function completion if cursor is not after '(' or ','
|
||||
m_positionForProposal = afterOperatorPosition;
|
||||
setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition);
|
||||
} else {
|
||||
const FunctionInfo functionInfo = analyzeFunctionCall(afterOperatorPosition);
|
||||
if (functionInfo.isValid()) {
|
||||
m_functionName = functionInfo.functionName;
|
||||
} else if (looksLikeAFunctionCall(afterOperatorPosition)) {
|
||||
// Always pass the position right after '(' to libclang because
|
||||
// positions after the comma might be problematic if a preceding
|
||||
// argument is invalid code.
|
||||
setActionAndClangPosition(PassThroughToLibClangAfterLeftParen,
|
||||
functionInfo.functionNamePosition);
|
||||
} else {
|
||||
m_positionForProposal);
|
||||
} else { // e.g. "(" without any function name in front
|
||||
m_positionForProposal = afterOperatorPosition;
|
||||
setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ClangCompletionContextAnalyzer::handleNonFunctionCall(int position)
|
||||
|
||||
@@ -58,18 +58,10 @@ public:
|
||||
int positionForClang() const { return m_positionForClang; }
|
||||
int positionEndOfExpression() const { return m_positionEndOfExpression; }
|
||||
|
||||
QString functionName() const { return m_functionName; }
|
||||
|
||||
private:
|
||||
ClangCompletionContextAnalyzer();
|
||||
|
||||
struct FunctionInfo {
|
||||
bool isValid() const { return functionNamePosition != -1 && !functionName.isEmpty(); }
|
||||
|
||||
int functionNamePosition = -1;
|
||||
QString functionName;
|
||||
};
|
||||
FunctionInfo analyzeFunctionCall(int endOfExpression) const;
|
||||
bool looksLikeAFunctionCall(int endOfExpression) const;
|
||||
|
||||
void setActionAndClangPosition(CompletionAction action, int position);
|
||||
void setAction(CompletionAction action);
|
||||
@@ -88,7 +80,6 @@ private:
|
||||
int m_positionForProposal = -1;
|
||||
int m_positionForClang = -1;
|
||||
int m_positionEndOfExpression = -1;
|
||||
QString m_functionName;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -819,13 +819,14 @@ void ClangCodeCompletionTest::testCompleteFunctions()
|
||||
QVERIFY(hasItem(t.proposal, "TType<QString> f(bool)"));
|
||||
}
|
||||
|
||||
void ClangCodeCompletionTest::testCompleteConstructorAndFallbackToGlobalCompletion()
|
||||
void ClangCodeCompletionTest::testCompleteConstructor()
|
||||
{
|
||||
ProjectLessCompletionTest t("constructorCompletion.cpp");
|
||||
|
||||
QVERIFY(hasItem(t.proposal, "globalVariable"));
|
||||
QVERIFY(hasItem(t.proposal, "GlobalClassWithCustomConstructor"));
|
||||
QVERIFY(!hasSnippet(t.proposal, "class"));
|
||||
QVERIFY(!hasItem(t.proposal, "globalVariable"));
|
||||
QVERIFY(!hasItem(t.proposal, "class"));
|
||||
QVERIFY(hasItem(t.proposal, "Foo(int)"));
|
||||
QVERIFY(hasItem(t.proposal, "Foo(int, double)"));
|
||||
}
|
||||
|
||||
// Explicitly Inserting The Dot
|
||||
|
||||
@@ -45,7 +45,7 @@ private slots:
|
||||
void testCompleteGlobals();
|
||||
void testCompleteMembers();
|
||||
void testCompleteFunctions();
|
||||
void testCompleteConstructorAndFallbackToGlobalCompletion();
|
||||
void testCompleteConstructor();
|
||||
|
||||
void testCompleteWithDotToArrowCorrection();
|
||||
void testDontCompleteWithDotToArrowCorrectionForFloats();
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
int globalVariable;
|
||||
|
||||
struct GlobalClassWithCustomConstructor {
|
||||
GlobalClassWithCustomConstructor(int) {}
|
||||
struct Foo {
|
||||
Foo(int) {}
|
||||
Foo(int, double) {}
|
||||
};
|
||||
|
||||
void f() {
|
||||
GlobalClassWithCustomConstructor foo( /* COMPLETE HERE */
|
||||
Foo foo( /* COMPLETE HERE */
|
||||
}
|
||||
|
||||
@@ -152,6 +152,9 @@ void CodeCompletionsExtractor::extractCompletionKind()
|
||||
case CXCursor_NotImplemented:
|
||||
currentCodeCompletion_.setCompletionKind(CodeCompletion::KeywordCompletionKind);
|
||||
break;
|
||||
case CXCursor_OverloadCandidate:
|
||||
currentCodeCompletion_.setCompletionKind(CodeCompletion::FunctionOverloadCompletionKind);
|
||||
break;
|
||||
default:
|
||||
currentCodeCompletion_.setCompletionKind(CodeCompletion::Other);
|
||||
}
|
||||
|
||||
@@ -238,28 +238,28 @@ TEST_F(ClangCompletionContextAnalyzer, ArgumentOneAtCall)
|
||||
{
|
||||
auto analyzer = runAnalyzer("f(@");
|
||||
|
||||
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -2, 0, positionInText));
|
||||
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText));
|
||||
}
|
||||
|
||||
TEST_F(ClangCompletionContextAnalyzer, ArgumentTwoAtCall)
|
||||
{
|
||||
auto analyzer = runAnalyzer("f(1,@");
|
||||
|
||||
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -4, -2, positionInText));
|
||||
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -2, -2, positionInText));
|
||||
}
|
||||
|
||||
TEST_F(ClangCompletionContextAnalyzer, ArgumentTwoWithSpaceAtCall)
|
||||
{
|
||||
auto analyzer = runAnalyzer("f(1, @");
|
||||
|
||||
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -5, -3, positionInText));
|
||||
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -3, -3, positionInText));
|
||||
}
|
||||
|
||||
TEST_F(ClangCompletionContextAnalyzer, WhitespaceAfterFunctionName)
|
||||
{
|
||||
auto analyzer = runAnalyzer("foo (@");
|
||||
|
||||
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -5, 0, positionInText));
|
||||
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText));
|
||||
}
|
||||
|
||||
TEST_F(ClangCompletionContextAnalyzer, AfterOpeningParenthesis)
|
||||
|
||||
@@ -153,6 +153,7 @@ protected:
|
||||
ClangBackEnd::UnsavedFiles unsavedFiles;
|
||||
ClangBackEnd::Documents documents{projects, unsavedFiles};
|
||||
Document functionDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_function.cpp"), project, Utf8StringVector(), documents};
|
||||
Document functionOverloadDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_functionoverload.cpp"), project, Utf8StringVector(), documents};
|
||||
Document variableDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_variable.cpp"), project, Utf8StringVector(), documents};
|
||||
Document classDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_class.cpp"), project, Utf8StringVector(), documents};
|
||||
Document namespaceDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_namespace.cpp"), project, Utf8StringVector(), documents};
|
||||
@@ -678,6 +679,21 @@ TEST_F(CodeCompletionsExtractorSlowTest, BriefComment)
|
||||
ASSERT_THAT(extractor, HasBriefComment(Utf8StringLiteral("BriefComment"), Utf8StringLiteral("A brief comment")));
|
||||
}
|
||||
|
||||
TEST_F(CodeCompletionsExtractorSlowTest, OverloadCandidate)
|
||||
{
|
||||
ClangCodeCompleteResults completeResults(getResults(functionOverloadDocument, 8, 13));
|
||||
|
||||
::CodeCompletionsExtractor extractor(completeResults.data());
|
||||
|
||||
ASSERT_THAT(extractor, HasCompletionChunks(Utf8String(),
|
||||
CodeCompletionChunks({
|
||||
{CodeCompletionChunk::Text, Utf8StringLiteral("Foo")},
|
||||
{CodeCompletionChunk::LeftParen, Utf8StringLiteral("(")},
|
||||
{CodeCompletionChunk::CurrentParameter, Utf8StringLiteral("const Foo &foo")},
|
||||
{CodeCompletionChunk::RightParen, Utf8StringLiteral(")")},
|
||||
})));
|
||||
}
|
||||
|
||||
ClangCodeCompleteResults CodeCompletionsExtractor::getResults(const Document &document,
|
||||
uint line,
|
||||
uint column,
|
||||
|
||||
@@ -53,7 +53,9 @@ protected:
|
||||
CodeCompletionChunk semicolon{CodeCompletionChunk::SemiColon, Utf8StringLiteral(";")};
|
||||
CodeCompletionChunk colonColonText{CodeCompletionChunk::Text, Utf8StringLiteral("::")};
|
||||
CodeCompletionChunk functionArgumentX{CodeCompletionChunk::Placeholder, Utf8StringLiteral("char x")};
|
||||
CodeCompletionChunk functionArgumentXAsCurrentParameter{CodeCompletionChunk::CurrentParameter, Utf8StringLiteral("char x")};
|
||||
CodeCompletionChunk functionArgumentY{CodeCompletionChunk::Placeholder, Utf8StringLiteral("int y")};
|
||||
CodeCompletionChunk functionArgumentYAsCurrentParamter{CodeCompletionChunk::CurrentParameter, Utf8StringLiteral("int y")};
|
||||
CodeCompletionChunk functionArgumentZ{CodeCompletionChunk::Placeholder, Utf8StringLiteral("int z")};
|
||||
CodeCompletionChunk functionArgumentTemplate{CodeCompletionChunk::Placeholder, Utf8StringLiteral("const Foo<int> &foo")};
|
||||
CodeCompletionChunk switchName{CodeCompletionChunk::TypedText, Utf8StringLiteral("switch")};
|
||||
@@ -78,6 +80,7 @@ protected:
|
||||
CodeCompletionChunk optionalEnableIfTType{CodeCompletionChunk::Placeholder, Utf8StringLiteral("_Tp"), true};
|
||||
CodeCompletionChunk optionalComma{CodeCompletionChunk::Comma, Utf8StringLiteral(", "), true};
|
||||
CodeCompletionChunk optionalFunctionArgumentY{CodeCompletionChunk::Placeholder, Utf8StringLiteral("int y"), true};
|
||||
CodeCompletionChunk optionalFunctionArgumentYAsCurrentParameter{CodeCompletionChunk::CurrentParameter, Utf8StringLiteral("int y"), true};
|
||||
CodeCompletionChunk optionalFunctionArgumentZ{CodeCompletionChunk::Placeholder, Utf8StringLiteral("int z"), true};
|
||||
};
|
||||
|
||||
@@ -117,7 +120,7 @@ TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithOneArgumen
|
||||
CodeCompletionChunks completionChunks({integerResultType,
|
||||
functionName,
|
||||
leftParen,
|
||||
functionArgumentX,
|
||||
functionArgumentXAsCurrentParameter,
|
||||
rightParen});
|
||||
|
||||
ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(completionChunks),
|
||||
@@ -129,7 +132,7 @@ TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithOneParamet
|
||||
CodeCompletionChunks completionChunks({integerResultType,
|
||||
functionName,
|
||||
leftParen,
|
||||
functionArgumentX,
|
||||
functionArgumentXAsCurrentParameter,
|
||||
rightParen});
|
||||
|
||||
ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(completionChunks, 1),
|
||||
@@ -143,7 +146,7 @@ TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithTwoParamet
|
||||
leftParen,
|
||||
functionArgumentX,
|
||||
comma,
|
||||
functionArgumentY,
|
||||
functionArgumentYAsCurrentParamter,
|
||||
rightParen});
|
||||
|
||||
ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(completionChunks, 2),
|
||||
@@ -157,7 +160,7 @@ TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithTwoParamet
|
||||
leftParen,
|
||||
functionArgumentX,
|
||||
optionalComma,
|
||||
optionalFunctionArgumentY,
|
||||
optionalFunctionArgumentYAsCurrentParameter,
|
||||
rightParen});
|
||||
|
||||
ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(completionChunks, 2),
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
struct Foo {
|
||||
Foo(const Foo &foo);
|
||||
Foo(char c);
|
||||
};
|
||||
|
||||
void f()
|
||||
{
|
||||
Foo foo(
|
||||
}
|
||||
Reference in New Issue
Block a user