forked from OSchip/llvm-project
When providing code completions for an argument in an Objective-C
message send, e.g., [[NSString alloc] initWithCString:<CC> look up all of the possible methods and determine the preferred type for the argument expression based on the type of the corresponding parameter. llvm-svn: 114379
This commit is contained in:
parent
dba0a0fbef
commit
7466127a4b
|
@ -216,6 +216,10 @@ namespace {
|
|||
AllowNestedNameSpecifiers = Allow;
|
||||
}
|
||||
|
||||
/// \brief Return the semantic analysis object for which we are collecting
|
||||
/// code completion results.
|
||||
Sema &getSema() const { return SemaRef; }
|
||||
|
||||
/// \brief Determine whether the given declaration is at all interesting
|
||||
/// as a code-completion result.
|
||||
///
|
||||
|
@ -4362,6 +4366,40 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
|
|||
/*IsSuper=*/true);
|
||||
}
|
||||
|
||||
/// \brief Given a set of code-completion results for the argument of a message
|
||||
/// send, determine the preferred type (if any) for that argument expression.
|
||||
static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
|
||||
unsigned NumSelIdents) {
|
||||
typedef CodeCompletionResult Result;
|
||||
ASTContext &Context = Results.getSema().Context;
|
||||
|
||||
QualType PreferredType;
|
||||
unsigned BestPriority = CCP_Unlikely * 2;
|
||||
Result *ResultsData = Results.data();
|
||||
for (unsigned I = 0, N = Results.size(); I != N; ++I) {
|
||||
Result &R = ResultsData[I];
|
||||
if (R.Kind == Result::RK_Declaration &&
|
||||
isa<ObjCMethodDecl>(R.Declaration)) {
|
||||
if (R.Priority <= BestPriority) {
|
||||
ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
|
||||
if (NumSelIdents <= Method->param_size()) {
|
||||
QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
|
||||
->getType();
|
||||
if (R.Priority < BestPriority || PreferredType.isNull()) {
|
||||
BestPriority = R.Priority;
|
||||
PreferredType = MyPreferredType;
|
||||
} else if (!Context.hasSameUnqualifiedType(PreferredType,
|
||||
MyPreferredType)) {
|
||||
PreferredType = QualType();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PreferredType;
|
||||
}
|
||||
|
||||
static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
|
||||
ParsedType Receiver,
|
||||
IdentifierInfo **SelIdents,
|
||||
|
@ -4446,12 +4484,25 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
|
|||
unsigned NumSelIdents,
|
||||
bool AtArgumentExpression,
|
||||
bool IsSuper) {
|
||||
if (AtArgumentExpression)
|
||||
return CodeCompleteOrdinaryName(S, PCC_Expression);
|
||||
|
||||
ResultBuilder Results(*this);
|
||||
AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
|
||||
AtArgumentExpression, IsSuper, Results);
|
||||
|
||||
// If we're actually at the argument expression (rather than prior to the
|
||||
// selector), we're actually performing code completion for an expression.
|
||||
// Determine whether we have a single, best method. If so, we can
|
||||
// code-complete the expression using the corresponding parameter type as
|
||||
// our preferred type, improving completion results.
|
||||
if (AtArgumentExpression) {
|
||||
QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
|
||||
NumSelIdents);
|
||||
if (PreferredType.isNull())
|
||||
CodeCompleteOrdinaryName(S, PCC_Expression);
|
||||
else
|
||||
CodeCompleteExpression(S, PreferredType);
|
||||
return;
|
||||
}
|
||||
|
||||
HandleCodeCompleteResults(this, CodeCompleter,
|
||||
CodeCompletionContext::CCC_Other,
|
||||
Results.data(), Results.size());
|
||||
|
@ -4462,9 +4513,6 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
|
|||
unsigned NumSelIdents,
|
||||
bool AtArgumentExpression,
|
||||
bool IsSuper) {
|
||||
if (AtArgumentExpression)
|
||||
return CodeCompleteOrdinaryName(S, PCC_Expression);
|
||||
|
||||
typedef CodeCompletionResult Result;
|
||||
|
||||
Expr *RecExpr = static_cast<Expr *>(Receiver);
|
||||
|
@ -4577,8 +4625,24 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Results.ExitScope();
|
||||
|
||||
|
||||
// If we're actually at the argument expression (rather than prior to the
|
||||
// selector), we're actually performing code completion for an expression.
|
||||
// Determine whether we have a single, best method. If so, we can
|
||||
// code-complete the expression using the corresponding parameter type as
|
||||
// our preferred type, improving completion results.
|
||||
if (AtArgumentExpression) {
|
||||
QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
|
||||
NumSelIdents);
|
||||
if (PreferredType.isNull())
|
||||
CodeCompleteOrdinaryName(S, PCC_Expression);
|
||||
else
|
||||
CodeCompleteExpression(S, PreferredType);
|
||||
return;
|
||||
}
|
||||
|
||||
HandleCodeCompleteResults(this, CodeCompleter,
|
||||
CodeCompletionContext::CCC_Other,
|
||||
Results.data(),Results.size());
|
||||
|
|
|
@ -22,9 +22,15 @@ enum Priority test1(enum Priority priority, enum Color color, int integer) {
|
|||
c = color;
|
||||
}
|
||||
|
||||
// FIXME: It would be great for message sends to have the same
|
||||
// benefits as function calls, but we don't quite have the
|
||||
// infrastructure yet.
|
||||
@interface A
|
||||
+ (void)method:(enum Color)color priority:(enum Priority)priority;
|
||||
- (void)method:(enum Color)color priority:(enum Priority)priority;
|
||||
@end
|
||||
|
||||
void test2(A *a) {
|
||||
[a method:Red priority:High];
|
||||
[A method:Red priority:Low];
|
||||
}
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:16:11 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// CHECK-CC1: EnumConstantDecl:{ResultType enum Color}{TypedText Blue} (32)
|
||||
|
@ -105,3 +111,27 @@ enum Priority test1(enum Priority priority, enum Color color, int integer) {
|
|||
// CHECK-CC6: EnumConstantDecl:{ResultType enum Color}{TypedText Red} (16)
|
||||
// CHECK-CC6: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
|
||||
// CHECK-CC6: FunctionDecl:{ResultType enum Priority}{TypedText test1}{LeftParen (}{Placeholder enum Priority priority}{Comma , }{Placeholder enum Color color}{Comma , }{Placeholder int integer}{RightParen )} (50)
|
||||
// RUN: c-index-test -code-completion-at=%s:31:13 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC7 %s
|
||||
// RUN: c-index-test -code-completion-at=%s:32:13 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC7 %s
|
||||
// CHECK-CC7: ParmDecl:{ResultType A *}{TypedText a} (8)
|
||||
// CHECK-CC7: EnumConstantDecl:{ResultType enum Color}{TypedText Blue} (16)
|
||||
// CHECK-CC7: FunctionDecl:{ResultType int}{TypedText func1}{LeftParen (}{Placeholder enum Color}{RightParen )} (25)
|
||||
// CHECK-CC7: FunctionDecl:{ResultType enum Priority}{TypedText func2}{LeftParen (}{Placeholder int}{RightParen )} (50)
|
||||
// CHECK-CC7: FunctionDecl:{ResultType void}{TypedText func3}{LeftParen (}{Placeholder float}{RightParen )} (50)
|
||||
// CHECK-CC7: EnumConstantDecl:{ResultType enum Color}{TypedText Green} (16)
|
||||
// CHECK-CC7: EnumConstantDecl:{ResultType enum Priority}{TypedText High} (65)
|
||||
// CHECK-CC7: EnumConstantDecl:{ResultType enum Priority}{TypedText Low} (65)
|
||||
// CHECK-CC7: EnumConstantDecl:{ResultType enum Color}{TypedText Red} (16)
|
||||
// CHECK-CC7: FunctionDecl:{ResultType enum Priority}{TypedText test1}{LeftParen (}{Placeholder enum Priority priority}{Comma , }{Placeholder enum Color color}{Comma , }{Placeholder int integer}{RightParen )} (50)
|
||||
// RUN: c-index-test -code-completion-at=%s:31:26 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC8 %s
|
||||
// RUN: c-index-test -code-completion-at=%s:32:26 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC8 %s
|
||||
// CHECK-CC8: ParmDecl:{ResultType A *}{TypedText a} (8)
|
||||
// CHECK-CC8: EnumConstantDecl:{ResultType enum Color}{TypedText Blue} (65)
|
||||
// CHECK-CC8: FunctionDecl:{ResultType int}{TypedText func1}{LeftParen (}{Placeholder enum Color}{RightParen )} (25)
|
||||
// CHECK-CC8: FunctionDecl:{ResultType enum Priority}{TypedText func2}{LeftParen (}{Placeholder int}{RightParen )} (12)
|
||||
// CHECK-CC8: FunctionDecl:{ResultType void}{TypedText func3}{LeftParen (}{Placeholder float}{RightParen )} (50)
|
||||
// CHECK-CC8: EnumConstantDecl:{ResultType enum Color}{TypedText Green} (65)
|
||||
// CHECK-CC8: EnumConstantDecl:{ResultType enum Priority}{TypedText High} (16)
|
||||
// CHECK-CC8: EnumConstantDecl:{ResultType enum Priority}{TypedText Low} (16)
|
||||
// CHECK-CC8: EnumConstantDecl:{ResultType enum Color}{TypedText Red} (65)
|
||||
// CHECK-CC8: FunctionDecl:{ResultType enum Priority}{TypedText test1}{LeftParen (}{Placeholder enum Priority priority}{Comma , }{Placeholder enum Color color}{Comma , }{Placeholder int integer}{RightParen )} (12)
|
||||
|
|
Loading…
Reference in New Issue