[llvm-branch-commits] [cfe-tag] r90760 - in /cfe/tags/cremebrulee/cremebrulee-23.1: include/clang/Parse/Action.h lib/Parse/ParseObjc.cpp lib/Sema/Sema.h lib/Sema/SemaCodeComplete.cpp test/Index/complete-at-directives.m test/Index/complete-at-exprstmt.m test/Index/complete-objc-message.m

Douglas Gregor dgregor at apple.com
Mon Dec 7 02:30:11 PST 2009


Author: dgregor
Date: Mon Dec  7 04:30:09 2009
New Revision: 90760

URL: http://llvm.org/viewvc/llvm-project?rev=90760&view=rev
Log:
Merge Objective-C code-completion changes

Added:
    cfe/tags/cremebrulee/cremebrulee-23.1/test/Index/complete-at-directives.m
      - copied unchanged from r90756, cfe/trunk/test/Index/complete-at-directives.m
    cfe/tags/cremebrulee/cremebrulee-23.1/test/Index/complete-at-exprstmt.m
      - copied unchanged from r90757, cfe/trunk/test/Index/complete-at-exprstmt.m
Modified:
    cfe/tags/cremebrulee/cremebrulee-23.1/include/clang/Parse/Action.h
    cfe/tags/cremebrulee/cremebrulee-23.1/lib/Parse/ParseObjc.cpp
    cfe/tags/cremebrulee/cremebrulee-23.1/lib/Sema/Sema.h
    cfe/tags/cremebrulee/cremebrulee-23.1/lib/Sema/SemaCodeComplete.cpp
    cfe/tags/cremebrulee/cremebrulee-23.1/test/Index/complete-objc-message.m

Modified: cfe/tags/cremebrulee/cremebrulee-23.1/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/tags/cremebrulee/cremebrulee-23.1/include/clang/Parse/Action.h?rev=90760&r1=90759&r2=90760&view=diff

==============================================================================
--- cfe/tags/cremebrulee/cremebrulee-23.1/include/clang/Parse/Action.h (original)
+++ cfe/tags/cremebrulee/cremebrulee-23.1/include/clang/Parse/Action.h Mon Dec  7 04:30:09 2009
@@ -2394,6 +2394,24 @@
   /// \param S the scope in which the operator keyword occurs.
   virtual void CodeCompleteOperatorName(Scope *S) { }
 
+  /// \brief Code completion after the '@' at the top level.
+  ///
+  /// \param S the scope in which the '@' occurs.
+  ///
+  /// \param ObjCImpDecl the Objective-C implementation or category 
+  /// implementation.
+  ///
+  /// \param InInterface whether we are in an Objective-C interface or
+  /// protocol.
+  virtual void CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl,
+                                           bool InInterface) { }
+
+  /// \brief Code completion after the '@' in a statement.
+  virtual void CodeCompleteObjCAtStatement(Scope *S) { }
+
+  /// \brief Code completion after the '@' in an expression.
+  virtual void CodeCompleteObjCAtExpression(Scope *S) { }
+
   /// \brief Code completion for an ObjC property decl.
   ///
   /// This code completion action is invoked when the code-completion token is

Modified: cfe/tags/cremebrulee/cremebrulee-23.1/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/tags/cremebrulee/cremebrulee-23.1/lib/Parse/ParseObjc.cpp?rev=90760&r1=90759&r2=90760&view=diff

==============================================================================
--- cfe/tags/cremebrulee/cremebrulee-23.1/lib/Parse/ParseObjc.cpp (original)
+++ cfe/tags/cremebrulee/cremebrulee-23.1/lib/Parse/ParseObjc.cpp Mon Dec  7 04:30:09 2009
@@ -30,6 +30,11 @@
 Parser::DeclPtrTy Parser::ParseObjCAtDirectives() {
   SourceLocation AtLoc = ConsumeToken(); // the "@"
 
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, false);
+    ConsumeToken();
+  }
+
   switch (Tok.getObjCKeywordID()) {
   case tok::objc_class:
     return ParseObjCAtClassDeclaration(AtLoc);
@@ -288,6 +293,12 @@
 
     // Otherwise, we have an @ directive, eat the @.
     SourceLocation AtLoc = ConsumeToken(); // the "@"
+    if (Tok.is(tok::code_completion)) {
+      Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, true);
+      ConsumeToken();
+      break;
+    }
+
     tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID();
 
     if (DirectiveKind == tok::objc_end) { // @end -> terminate list
@@ -397,7 +408,10 @@
 
   // We break out of the big loop in two cases: when we see @end or when we see
   // EOF.  In the former case, eat the @end.  In the later case, emit an error.
-  if (Tok.isObjCAtKeyword(tok::objc_end))
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, true);
+    ConsumeToken();
+  } else if (Tok.isObjCAtKeyword(tok::objc_end))
     ConsumeToken(); // the "end" identifier
   else
     Diag(Tok, diag::err_objc_missing_end);
@@ -1545,7 +1559,11 @@
 }
 
 Parser::OwningStmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
-  if (Tok.isObjCAtKeyword(tok::objc_try)) {
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteObjCAtStatement(CurScope);
+    ConsumeToken();
+    return StmtError();
+  } else if (Tok.isObjCAtKeyword(tok::objc_try)) {
     return ParseObjCTryStmt(AtLoc);
   } else if (Tok.isObjCAtKeyword(tok::objc_throw))
     return ParseObjCThrowStmt(AtLoc);
@@ -1566,6 +1584,11 @@
 
 Parser::OwningExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
   switch (Tok.getKind()) {
+  case tok::code_completion:
+    Actions.CodeCompleteObjCAtExpression(CurScope);
+    ConsumeToken();
+    return ExprError();
+
   case tok::string_literal:    // primary-expression: string-literal
   case tok::wide_string_literal:
     return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));

Modified: cfe/tags/cremebrulee/cremebrulee-23.1/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/tags/cremebrulee/cremebrulee-23.1/lib/Sema/Sema.h?rev=90760&r1=90759&r2=90760&view=diff

==============================================================================
--- cfe/tags/cremebrulee/cremebrulee-23.1/lib/Sema/Sema.h (original)
+++ cfe/tags/cremebrulee/cremebrulee-23.1/lib/Sema/Sema.h Mon Dec  7 04:30:09 2009
@@ -3733,6 +3733,10 @@
   virtual void CodeCompleteNamespaceAliasDecl(Scope *S);
   virtual void CodeCompleteOperatorName(Scope *S);
   
+  virtual void CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl,
+                                           bool InInterface);
+  virtual void CodeCompleteObjCAtStatement(Scope *S);
+  virtual void CodeCompleteObjCAtExpression(Scope *S);
   virtual void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS);
   virtual void CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl,
                                               DeclPtrTy *Methods,

Modified: cfe/tags/cremebrulee/cremebrulee-23.1/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/tags/cremebrulee/cremebrulee-23.1/lib/Sema/SemaCodeComplete.cpp?rev=90760&r1=90759&r2=90760&view=diff

==============================================================================
--- cfe/tags/cremebrulee/cremebrulee-23.1/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/tags/cremebrulee/cremebrulee-23.1/lib/Sema/SemaCodeComplete.cpp Mon Dec  7 04:30:09 2009
@@ -778,7 +778,7 @@
 }
 
 /// \brief Add type specifiers for the current language as keyword results.
-static void AddTypeSpecifierResults(const LangOptions &LangOpts, unsigned Rank, 
+static void AddTypeSpecifierResults(const LangOptions &LangOpts, unsigned Rank,
                                     ResultBuilder &Results) {
   typedef CodeCompleteConsumer::Result Result;
   Results.MaybeAddResult(Result("short", Rank));
@@ -1356,9 +1356,23 @@
 }
 
 void Sema::CodeCompleteOrdinaryName(Scope *S) {
+  typedef CodeCompleteConsumer::Result Result;
   ResultBuilder Results(*this, &ResultBuilder::IsOrdinaryName);
   unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), 
                                            0, CurContext, Results);
+
+  Results.EnterNewScope();
+  AddTypeSpecifierResults(getLangOptions(), NextRank, Results);
+  
+  if (getLangOptions().ObjC1) {
+    // Add the "super" keyword, if appropriate.
+    if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
+      if (Method->getClassInterface()->getSuperClass())
+        Results.MaybeAddResult(Result("super", NextRank));
+  }
+
+  Results.ExitScope();
+
   if (CodeCompleter->includeMacros())
     AddMacroResults(PP, NextRank, Results);
   HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
@@ -1847,6 +1861,183 @@
   HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
 
+void Sema::CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl,
+                                       bool InInterface) {
+  typedef CodeCompleteConsumer::Result Result;
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+  if (ObjCImpDecl) {
+    // Since we have an implementation, we can end it.
+    Results.MaybeAddResult(Result("end", 0));
+
+    CodeCompletionString *Pattern = 0;
+    Decl *ImpDecl = ObjCImpDecl.getAs<Decl>();
+    if (isa<ObjCImplementationDecl>(ImpDecl) || 
+        isa<ObjCCategoryImplDecl>(ImpDecl)) {
+      // @dynamic
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("dynamic");
+      Pattern->AddTextChunk(" ");
+      Pattern->AddPlaceholderChunk("property");
+      Results.MaybeAddResult(Result(Pattern, 0));
+
+      // @synthesize
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("synthesize");
+      Pattern->AddTextChunk(" ");
+      Pattern->AddPlaceholderChunk("property");
+      Results.MaybeAddResult(Result(Pattern, 0));
+    }
+  } else if (InInterface) {
+    // Since we have an interface or protocol, we can end it.
+    Results.MaybeAddResult(Result("end", 0));
+
+    if (LangOpts.ObjC2) {
+      // @property
+      Results.MaybeAddResult(Result("property", 0));
+    }
+
+    // @required
+    Results.MaybeAddResult(Result("required", 0));
+
+    // @optional
+    Results.MaybeAddResult(Result("optional", 0));
+  } else {
+    CodeCompletionString *Pattern = 0;
+
+    // @class name ;
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("class");
+    Pattern->AddTextChunk(" ");
+    Pattern->AddPlaceholderChunk("identifier");
+    Pattern->AddTextChunk(";"); // add ';' chunk
+    Results.MaybeAddResult(Result(Pattern, 0));
+
+    // @interface name 
+    // FIXME: Could introduce the whole pattern, including superclasses and 
+    // such.
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("interface");
+    Pattern->AddTextChunk(" ");
+    Pattern->AddPlaceholderChunk("class");
+    Results.MaybeAddResult(Result(Pattern, 0));
+
+    // @protocol name
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("protocol");
+    Pattern->AddTextChunk(" ");
+    Pattern->AddPlaceholderChunk("protocol");
+    Results.MaybeAddResult(Result(Pattern, 0));
+
+    // @implementation name
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("implementation");
+    Pattern->AddTextChunk(" ");
+    Pattern->AddPlaceholderChunk("class");
+    Results.MaybeAddResult(Result(Pattern, 0));
+
+    // @compatibility_alias name
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("compatibility_alias");
+    Pattern->AddTextChunk(" ");
+    Pattern->AddPlaceholderChunk("alias");
+    Pattern->AddTextChunk(" ");
+    Pattern->AddPlaceholderChunk("class");
+    Results.MaybeAddResult(Result(Pattern, 0));
+  }
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+static void AddObjCExpressionResults(unsigned Rank, ResultBuilder &Results) {
+  typedef CodeCompleteConsumer::Result Result;
+  CodeCompletionString *Pattern = 0;
+
+  // @encode ( type-name )
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk("encode");
+  Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+  Pattern->AddPlaceholderChunk("type-name");
+  Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+  Results.MaybeAddResult(Result(Pattern, Rank));
+  
+  // @protocol ( protocol-name )
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk("protocol");
+  Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+  Pattern->AddPlaceholderChunk("protocol-name");
+  Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+  Results.MaybeAddResult(Result(Pattern, Rank));
+
+  // @selector ( selector )
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk("selector");
+  Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+  Pattern->AddPlaceholderChunk("selector");
+  Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+  Results.MaybeAddResult(Result(Pattern, Rank));
+}
+
+void Sema::CodeCompleteObjCAtStatement(Scope *S) {
+  typedef CodeCompleteConsumer::Result Result;
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+
+  CodeCompletionString *Pattern = 0;
+
+  // @try { statements } @catch ( declaration ) { statements } @finally
+  //   { statements }
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk("try");
+  Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+  Pattern->AddPlaceholderChunk("statements");
+  Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+  Pattern->AddTextChunk("@catch");
+  Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+  Pattern->AddPlaceholderChunk("parameter");
+  Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+  Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+  Pattern->AddPlaceholderChunk("statements");
+  Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+  Pattern->AddTextChunk("@finally");
+  Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+  Pattern->AddPlaceholderChunk("statements");
+  Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+  Results.MaybeAddResult(Result(Pattern, 0));
+
+  // @throw
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk("throw");
+  Pattern->AddTextChunk(" ");
+  Pattern->AddPlaceholderChunk("expression");
+  Pattern->AddTextChunk(";");
+  Results.MaybeAddResult(Result(Pattern, 0)); // FIXME: add ';' chunk
+
+  // @synchronized ( expression ) { statements }
+  Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk("synchronized");
+  Pattern->AddTextChunk(" ");
+  Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+  Pattern->AddPlaceholderChunk("expression");
+  Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+  Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+  Pattern->AddPlaceholderChunk("statements");
+  Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+  Results.MaybeAddResult(Result(Pattern, 0)); // FIXME: add ';' chunk
+
+  AddObjCExpressionResults(0, Results);
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCAtExpression(Scope *S) {
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
+  AddObjCExpressionResults(0, Results);
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
 /// \brief Determine whether the addition of the given flag to an Objective-C
 /// property's attributes will cause a conflict.
 static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {

Modified: cfe/tags/cremebrulee/cremebrulee-23.1/test/Index/complete-objc-message.m
URL: http://llvm.org/viewvc/llvm-project/cfe/tags/cremebrulee/cremebrulee-23.1/test/Index/complete-objc-message.m?rev=90760&r1=90759&r2=90760&view=diff

==============================================================================
--- cfe/tags/cremebrulee/cremebrulee-23.1/test/Index/complete-objc-message.m (original)
+++ cfe/tags/cremebrulee/cremebrulee-23.1/test/Index/complete-objc-message.m Mon Dec  7 04:30:09 2009
@@ -132,3 +132,15 @@
 // RUN: c-index-test -code-completion-at=%s:95:24 %s | FileCheck -check-prefix=CHECK-CC9 %s
 // CHECK-CC9: ObjCInstanceMethodDecl:{Informative Method:}{Informative Arg1:}{TypedText Arg2:}{Placeholder (int)i2}
 // CHECK-CC9: ObjCInstanceMethodDecl:{Informative Method:}{Informative Arg1:}{TypedText OtherArg:}{Placeholder (id)obj}
+// RUN: c-index-test -code-completion-at=%s:61:11 %s | FileCheck -check-prefix=CHECK-CCA %s
+// CHECK-CCA: {TypedText _cmd}
+// CHECK-CCA: {TypedText self}
+// CHECK-CCA: TypedefDecl:{TypedText Class}
+// CHECK-CCA: ObjCInterfaceDecl:{TypedText Foo}
+// CHECK-CCA: ObjCCategoryDecl:{TypedText FooTestCategory}
+// CHECK-CCA: FunctionDecl:{TypedText func}{LeftParen (}{RightParen )}
+// CHECK-CCA: TypedefDecl:{TypedText id}
+// CHECK-CCA: ObjCInterfaceDecl:{TypedText MyClass}
+// CHECK-CCA: ObjCInterfaceDecl:{TypedText MySubClass}
+// CHECK-CCA: TypedefDecl:{TypedText SEL}
+// CHECK-CCA: {TypedText super}





More information about the llvm-branch-commits mailing list