[cfe-commits] r114379 - in /cfe/trunk: lib/Sema/SemaCodeComplete.cpp test/Index/complete-type-factors.m

Douglas Gregor dgregor at apple.com
Mon Sep 20 17:03:25 PDT 2010


Author: dgregor
Date: Mon Sep 20 19:03:25 2010
New Revision: 114379

URL: http://llvm.org/viewvc/llvm-project?rev=114379&view=rev
Log:
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.


Modified:
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/test/Index/complete-type-factors.m

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=114379&r1=114378&r2=114379&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Mon Sep 20 19:03:25 2010
@@ -216,6 +216,10 @@
       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 @@
                                       /*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 @@
                                         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 @@
                                            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 @@
       }
     }
   }
-
   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());

Modified: cfe/trunk/test/Index/complete-type-factors.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-type-factors.m?rev=114379&r1=114378&r2=114379&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-type-factors.m (original)
+++ cfe/trunk/test/Index/complete-type-factors.m Mon Sep 20 19:03:25 2010
@@ -22,9 +22,15 @@
   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.
+ at interface A
++ (void)method:(enum Color)color priority:(enum Priority)priority;
+- (void)method:(enum Color)color priority:(enum Priority)priority;
+ at 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 @@
 // 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)





More information about the cfe-commits mailing list