[cfe-commits] r111843 - in /cfe/trunk: include/clang/Sema/Action.h include/clang/Sema/Sema.h lib/Parse/ParseStmt.cpp lib/Sema/SemaCodeComplete.cpp test/Index/complete-declarators.m

Douglas Gregor dgregor at apple.com
Mon Aug 23 14:17:50 PDT 2010


Author: dgregor
Date: Mon Aug 23 16:17:50 2010
New Revision: 111843

URL: http://llvm.org/viewvc/llvm-project?rev=111843&view=rev
Log:
Introduce a code-completion hook for the Objective-C collection
argument in a for-each statement (e.g., "for (id x in <blah>)"), which
restricts the expression completions provided to Objective-C types (or
class types in C++).

Modified:
    cfe/trunk/include/clang/Sema/Action.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParseStmt.cpp
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/test/Index/complete-declarators.m

Modified: cfe/trunk/include/clang/Sema/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Action.h?rev=111843&r1=111842&r2=111843&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Action.h (original)
+++ cfe/trunk/include/clang/Sema/Action.h Mon Aug 23 16:17:50 2010
@@ -3052,6 +3052,15 @@
                                                IdentifierInfo **SelIdents,
                                                unsigned NumSelIdents) { }
 
+  /// \brief Code completion for the collection argument of an Objective-C
+  /// for-each statement.
+  ///
+  /// \param S The Scope in which the completion occurs.
+  ///
+  /// \param IterationBar The iteration variable declaration.
+  virtual void CodeCompleteObjCForCollection(Scope *S, 
+                                             DeclGroupPtrTy IterationVar) { }
+  
   /// \brief Code completion for a list of protocol references in Objective-C,
   /// such as P1 and P2 in \c id<P1,P2>.
   ///

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=111843&r1=111842&r2=111843&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Aug 23 16:17:50 2010
@@ -4643,8 +4643,10 @@
   virtual void CodeCompleteDeclarator(Scope *S,
                                       bool AllowNonIdentifiers,
                                       bool AllowNestedNameSpecifiers);
-  virtual void CodeCompleteExpression(Scope *S, QualType T,
-                                      bool IntegralConstantExpression = false);
+  
+  struct CodeCompleteExpressionData;
+  virtual void CodeCompleteExpression(Scope *S, 
+                                      const CodeCompleteExpressionData &Data);
   virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base,
                                                SourceLocation OpLoc,
                                                bool IsArrow);
@@ -4686,6 +4688,8 @@
   virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
                                                IdentifierInfo **SelIdents,
                                                unsigned NumSelIdents);
+  virtual void CodeCompleteObjCForCollection(Scope *S, 
+                                             DeclGroupPtrTy IterationVar);
   virtual void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
                                                   unsigned NumProtocols);
   virtual void CodeCompleteObjCProtocolDecl(Scope *S);

Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=111843&r1=111842&r2=111843&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Mon Aug 23 16:17:50 2010
@@ -1023,6 +1023,11 @@
       Actions.ActOnForEachDeclStmt(DG);
       // ObjC: for (id x in expr)
       ConsumeToken(); // consume 'in'
+      
+      if (Tok.is(tok::code_completion)) {
+        Actions.CodeCompleteObjCForCollection(getCurScope(), DG);
+        ConsumeCodeCompletionToken();
+      }
       Collection = ParseExpression();
     } else {
       Diag(Tok, diag::err_expected_semi_for);
@@ -1039,6 +1044,11 @@
       ConsumeToken();
     } else if ((ForEach = isTokIdentifier_in())) {
       ConsumeToken(); // consume 'in'
+      
+      if (Tok.is(tok::code_completion)) {
+        Actions.CodeCompleteObjCForCollection(getCurScope(), DeclGroupPtrTy());
+        ConsumeCodeCompletionToken();
+      }
       Collection = ParseExpression();
     } else {
       if (!Value.isInvalid()) Diag(Tok, diag::err_expected_semi_for);

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=111843&r1=111842&r2=111843&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Mon Aug 23 16:17:50 2010
@@ -239,6 +239,7 @@
     bool IsMember(NamedDecl *ND) const;
     bool IsObjCIvar(NamedDecl *ND) const;
     bool IsObjCMessageReceiver(NamedDecl *ND) const;
+    bool IsObjCCollection(NamedDecl *ND) const;
     //@}    
   };  
 }
@@ -366,8 +367,12 @@
     DeclContext *Parent = TargetParents.back();
     TargetParents.pop_back();
     
-    if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent))
+    if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
+      if (!Namespace->getIdentifier())
+        continue;
+
       Result = NestedNameSpecifier::Create(Context, Result, Namespace);
+    }
     else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
       Result = NestedNameSpecifier::Create(Context, Result,
                                            false,
@@ -946,6 +951,20 @@
   return isObjCReceiverType(SemaRef.Context, T);
 }
 
+bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
+  if ((SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryName(ND)) ||
+      (!SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
+    return false;
+  
+  QualType T = getDeclUsageType(SemaRef.Context, ND);
+  if (T.isNull())
+    return false;
+  
+  T = SemaRef.Context.getBaseElementType(T);
+  return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
+         T->isObjCIdType() || 
+         (SemaRef.getLangOptions().CPlusPlus && T->isRecordType());
+}
 
 /// \rief Determines whether the given declaration is an Objective-C
 /// instance variable.
@@ -2303,23 +2322,42 @@
                             Results.data(), Results.size());
 }
 
+struct Sema::CodeCompleteExpressionData {
+  CodeCompleteExpressionData(QualType PreferredType = QualType()) 
+    : PreferredType(PreferredType), IntegralConstantExpression(false),
+      ObjCCollection(false) { }
+  
+  QualType PreferredType;
+  bool IntegralConstantExpression;
+  bool ObjCCollection;
+  llvm::SmallVector<Decl *, 4> IgnoreDecls;
+};
+
 /// \brief Perform code-completion in an expression context when we know what
 /// type we're looking for.
 ///
 /// \param IntegralConstantExpression Only permit integral constant 
 /// expressions.
-void Sema::CodeCompleteExpression(Scope *S, QualType T,
-                                  bool IntegralConstantExpression) {
+void Sema::CodeCompleteExpression(Scope *S, 
+                                  const CodeCompleteExpressionData &Data) {
   typedef CodeCompleteConsumer::Result Result;
   ResultBuilder Results(*this);
   
-  if (IntegralConstantExpression)
+  if (Data.ObjCCollection)
+    Results.setFilter(&ResultBuilder::IsObjCCollection);
+  else if (Data.IntegralConstantExpression)
     Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
   else if (WantTypesInContext(PCC_Expression, getLangOptions()))
     Results.setFilter(&ResultBuilder::IsOrdinaryName);
   else
     Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
-  Results.setPreferredType(T.getNonReferenceType());
+
+  if (!Data.PreferredType.isNull())
+    Results.setPreferredType(Data.PreferredType.getNonReferenceType());
+  
+  // Ignore any declarations that we were told that we don't care about.
+  for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
+    Results.Ignore(Data.IgnoreDecls[I]);
   
   CodeCompletionDeclConsumer Consumer(Results, CurContext);
   LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
@@ -2330,14 +2368,16 @@
   Results.ExitScope();
   
   bool PreferredTypeIsPointer = false;
-  if (!T.isNull())
-    PreferredTypeIsPointer = T->isAnyPointerType() || 
-      T->isMemberPointerType() || T->isBlockPointerType();
+  if (!Data.PreferredType.isNull())
+    PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
+      || Data.PreferredType->isMemberPointerType() 
+      || Data.PreferredType->isBlockPointerType();
   
   if (CodeCompleter->includeMacros())
     AddMacroResults(PP, Results, PreferredTypeIsPointer);
   HandleCodeCompleteResults(this, CodeCompleter, 
-                CodeCompletionContext(CodeCompletionContext::CCC_Expression, T),
+                CodeCompletionContext(CodeCompletionContext::CCC_Expression, 
+                                      Data.PreferredType),
                             Results.data(),Results.size());
 }
 
@@ -2534,7 +2574,9 @@
   
   SwitchStmt *Switch = getSwitchStack().back();
   if (!Switch->getCond()->getType()->isEnumeralType()) {
-    CodeCompleteExpression(S, Switch->getCond()->getType(), true);
+    CodeCompleteExpressionData Data(Switch->getCond()->getType());
+    Data.IntegralConstantExpression = true;
+    CodeCompleteExpression(S, Data);
     return;
   }
   
@@ -3752,6 +3794,22 @@
                             Results.data(),Results.size());
 }
 
+void Sema::CodeCompleteObjCForCollection(Scope *S, 
+                                         DeclGroupPtrTy IterationVar) {
+  CodeCompleteExpressionData Data;
+  Data.ObjCCollection = true;
+  
+  if (IterationVar.getAsOpaquePtr()) {
+    DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
+    for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
+      if (*I)
+        Data.IgnoreDecls.push_back(*I);
+    }
+  }
+  
+  CodeCompleteExpression(S, Data);
+}
+
 /// \brief Add all of the protocol declarations that we find in the given
 /// (translation unit) context.
 static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,

Modified: cfe/trunk/test/Index/complete-declarators.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-declarators.m?rev=111843&r1=111842&r2=111843&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-declarators.m (original)
+++ cfe/trunk/test/Index/complete-declarators.m Mon Aug 23 16:17:50 2010
@@ -11,7 +11,12 @@
 
 @implementation A
 - (int)method:(id)param1 {
-  for(id x in param1) {
+  int q2;
+  for(id q in param1) {
+    int y;
+  }
+  id q;
+  for(q in param1) {
     int y;
   }
 }
@@ -21,9 +26,20 @@
 // CHECK-CC1-NOT: NotImplemented:{TypedText extern} (30)
 // CHECK-CC1: NotImplemented:{TypedText param1} (30)
 // RUN: c-index-test -code-completion-at=%s:9:15 %s | FileCheck -check-prefix=CHECK-CC2 %s
-// RUN: c-index-test -code-completion-at=%s:14:10 %s | FileCheck -check-prefix=CHECK-CC2 %s
-// RUN: c-index-test -code-completion-at=%s:15:9 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: c-index-test -code-completion-at=%s:15:10 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: c-index-test -code-completion-at=%s:16:9 %s | FileCheck -check-prefix=CHECK-CC2 %s
 // CHECK-CC2: NotImplemented:{TypedText const} (30)
 // CHECK-CC2-NOT: int
 // CHECK-CC2: NotImplemented:{TypedText restrict} (30)
 // CHECK-CC2: NotImplemented:{TypedText volatile} (30)
+// RUN: c-index-test -code-completion-at=%s:15:15 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3: ParmDecl:{ResultType id}{TypedText param1} (8)
+// CHECK-CC3-NOT: VarDecl:{ResultType int}{TypedText q2} (8)
+// CHECK-CC3-NOT: VarDecl:{ResultType id}{TypedText q} (8)
+// CHECK-CC3: NotImplemented:{ResultType A *}{TypedText self} (8)
+// CHECK-CC3: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
+// RUN: c-index-test -code-completion-at=%s:15:15 %s | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC4: ParmDecl:{ResultType id}{TypedText param1} (8)
+// CHECK-CC4-NOT: VarDecl:{ResultType int}{TypedText q2} (8)
+// CHECK-CC4: NotImplemented:{ResultType A *}{TypedText self} (8)
+// CHECK-CC4: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)





More information about the cfe-commits mailing list