Improves overload completion result chunks.
The code building the code completion string for overloads was providing
less detail compared to the one building completion strings for function
declarations. There was no information about optionals and no information
about what's a parameter and what's a function identifier, everything
besides ResultType, CurrentParameter and special characters was classified
as Text.
This makes code completion strings for overload candidates to follow a
pattern very similar, but not identical, to the one in use for function
declarations:
- return type chunk: ResultType
- function identifier chunk: Text
- parameter chunks: Placeholder
- optional parameter chunks: Optional
- current parameter chunk: CurrentParameter
llvm-svn: 227309
diff --git a/clang/lib/Sema/CodeCompleteConsumer.cpp b/clang/lib/Sema/CodeCompleteConsumer.cpp
index b2dc2d7..92d2aeb 100644
--- a/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -483,6 +483,31 @@
}
}
+// This function is used solely to preserve the former presentation of overloads
+// by "clang -cc1 -code-completion-at", since CodeCompletionString::getAsString
+// needs to be improved for printing the newer and more detailed overload
+// chunks.
+static std::string getOverloadAsString(const CodeCompletionString &CCS) {
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+
+ for (auto &C : CCS) {
+ switch (C.Kind) {
+ case CodeCompletionString::CK_Informative:
+ case CodeCompletionString::CK_ResultType:
+ OS << "[#" << C.Text << "#]";
+ break;
+
+ case CodeCompletionString::CK_CurrentParameter:
+ OS << "<#" << C.Text << "#>";
+ break;
+
+ default: OS << C.Text; break;
+ }
+ }
+ return OS.str();
+}
+
void
PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
unsigned CurrentArg,
@@ -491,8 +516,9 @@
for (unsigned I = 0; I != NumCandidates; ++I) {
if (CodeCompletionString *CCS
= Candidates[I].CreateSignatureString(CurrentArg, SemaRef,
- getAllocator(), CCTUInfo)) {
- OS << "OVERLOAD: " << CCS->getAsString() << "\n";
+ getAllocator(), CCTUInfo,
+ includeBriefComments())) {
+ OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n";
}
}
}
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index ab097d4..5aa28cd 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -2815,73 +2815,116 @@
return Result.TakeString();
}
+/// \brief Add function overload parameter chunks to the given code completion
+/// string.
+static void AddOverloadParameterChunks(ASTContext &Context,
+ const PrintingPolicy &Policy,
+ const FunctionDecl *Function,
+ const FunctionProtoType *Prototype,
+ CodeCompletionBuilder &Result,
+ unsigned CurrentArg,
+ unsigned Start = 0,
+ bool InOptional = false) {
+ bool FirstParameter = true;
+ unsigned NumParams = Function ? Function->getNumParams()
+ : Prototype->getNumParams();
+
+ for (unsigned P = Start; P != NumParams; ++P) {
+ if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
+ // When we see an optional default argument, put that argument and
+ // the remaining default arguments into a new, optional string.
+ CodeCompletionBuilder Opt(Result.getAllocator(),
+ Result.getCodeCompletionTUInfo());
+ if (!FirstParameter)
+ Opt.AddChunk(CodeCompletionString::CK_Comma);
+ // Optional sections are nested.
+ AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
+ CurrentArg, P, /*InOptional=*/true);
+ Result.AddOptionalChunk(Opt.TakeString());
+ return;
+ }
+
+ if (FirstParameter)
+ FirstParameter = false;
+ else
+ Result.AddChunk(CodeCompletionString::CK_Comma);
+
+ InOptional = false;
+
+ // Format the placeholder string.
+ std::string Placeholder;
+ if (Function)
+ Placeholder = FormatFunctionParameter(Context, Policy,
+ Function->getParamDecl(P));
+ else
+ Placeholder = Prototype->getParamType(P).getAsString(Policy);
+
+ if (P == CurrentArg)
+ Result.AddCurrentParameterChunk(
+ Result.getAllocator().CopyString(Placeholder));
+ else
+ Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
+ }
+
+ if (Prototype && Prototype->isVariadic()) {
+ CodeCompletionBuilder Opt(Result.getAllocator(),
+ Result.getCodeCompletionTUInfo());
+ if (!FirstParameter)
+ Opt.AddChunk(CodeCompletionString::CK_Comma);
+
+ if (CurrentArg < NumParams)
+ Opt.AddPlaceholderChunk("...");
+ else
+ Opt.AddCurrentParameterChunk("...");
+
+ Result.AddOptionalChunk(Opt.TakeString());
+ }
+}
+
CodeCompletionString *
CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
- unsigned CurrentArg,
- Sema &S,
- CodeCompletionAllocator &Allocator,
- CodeCompletionTUInfo &CCTUInfo) const {
+ unsigned CurrentArg, Sema &S,
+ CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo,
+ bool IncludeBriefComments) const {
PrintingPolicy Policy = getCompletionPrintingPolicy(S);
// FIXME: Set priority, availability appropriately.
CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
FunctionDecl *FDecl = getFunction();
- AddResultTypeChunk(S.Context, Policy, FDecl, Result);
- const FunctionProtoType *Proto
+ const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(getFunctionType());
if (!FDecl && !Proto) {
// Function without a prototype. Just give the return type and a
// highlighted ellipsis.
const FunctionType *FT = getFunctionType();
- Result.AddTextChunk(GetCompletionTypeString(FT->getReturnType(), S.Context,
- Policy, Result.getAllocator()));
+ Result.AddResultTypeChunk(Result.getAllocator().CopyString(
+ FT->getReturnType().getAsString(Policy)));
Result.AddChunk(CodeCompletionString::CK_LeftParen);
Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Result.AddChunk(CodeCompletionString::CK_RightParen);
return Result.TakeString();
}
-
- if (FDecl)
+
+ if (FDecl) {
+ if (IncludeBriefComments && CurrentArg < FDecl->getNumParams())
+ if (auto RC = S.getASTContext().getRawCommentForAnyRedecl(
+ FDecl->getParamDecl(CurrentArg)))
+ Result.addBriefComment(RC->getBriefText(S.getASTContext()));
+ AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Result.AddTextChunk(
- Result.getAllocator().CopyString(FDecl->getNameAsString()));
- else
- Result.AddTextChunk(Result.getAllocator().CopyString(
+ Result.getAllocator().CopyString(FDecl->getNameAsString()));
+ } else {
+ Result.AddResultTypeChunk(
+ Result.getAllocator().CopyString(
Proto->getReturnType().getAsString(Policy)));
+ }
Result.AddChunk(CodeCompletionString::CK_LeftParen);
- unsigned NumParams = FDecl ? FDecl->getNumParams() : Proto->getNumParams();
- for (unsigned I = 0; I != NumParams; ++I) {
- if (I)
- Result.AddChunk(CodeCompletionString::CK_Comma);
-
- std::string ArgString;
- QualType ArgType;
-
- if (FDecl) {
- ArgString = FDecl->getParamDecl(I)->getNameAsString();
- ArgType = FDecl->getParamDecl(I)->getOriginalType();
- } else {
- ArgType = Proto->getParamType(I);
- }
-
- ArgType.getAsStringInternal(ArgString, Policy);
-
- if (I == CurrentArg)
- Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
- Result.getAllocator().CopyString(ArgString));
- else
- Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
- }
-
- if (Proto && Proto->isVariadic()) {
- Result.AddChunk(CodeCompletionString::CK_Comma);
- if (CurrentArg < NumParams)
- Result.AddTextChunk("...");
- else
- Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
- }
+ AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
+ CurrentArg);
Result.AddChunk(CodeCompletionString::CK_RightParen);
-
+
return Result.TakeString();
}
@@ -3894,7 +3937,6 @@
// results. We may want to revisit this strategy in the future,
// e.g., by merging the two kinds of results.
- // FIXME: Provide support for highlighting optional parameters.
// FIXME: Provide support for variadic template functions.
// Ignore type-dependent call expressions entirely.
@@ -3934,7 +3976,7 @@
else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn))
FD = dyn_cast<FunctionDecl>(DRE->getDecl());
if (FD) { // We check whether it's a resolved function declaration.
- if (!getLangOpts().CPlusPlus ||
+ if (!getLangOpts().CPlusPlus ||
!FD->getType()->getAs<FunctionProtoType>())
Results.push_back(ResultCandidate(FD));
else
@@ -3994,7 +4036,6 @@
// FIXME: Provide support for member initializers.
// FIXME: Provide support for variadic template constructors.
- // FIXME: Provide support for highlighting optional parameters.
OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);