diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index 4859c3cccbac8d985df70b6684433dc8500d59a0..7209e0a843cd1683076f9ea0d604d2e0eda2d412 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -2388,7 +2388,9 @@ public: /// \brief Code completion occurs within an Objective-C implementation or /// category implementation CCC_ObjCImplementation, - /// \brief Code completion occurs within + /// \brief Code completion occurs within the list of instance variables + /// in an Objective-C interface, protocol, category, or implementation. + CCC_ObjCInstanceVariableList, /// \brief Code completion occurs following one or more template /// headers. CCC_Template, @@ -2531,6 +2533,9 @@ public: virtual void CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl, bool InInterface) { } + /// \brief Code completion after the '@' in the list of instance variables. + virtual void CodeCompleteObjCAtVisibility(Scope *S) { } + /// \brief Code completion after the '@' in a statement. virtual void CodeCompleteObjCAtStatement(Scope *S) { } diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index fa3c35683ee449a24c1ff194f47803d652ee29c0..5e2363535320f8fd5354d98a642a43f7b0888e21 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -973,6 +973,12 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, // Set the default visibility to private. if (Tok.is(tok::at)) { // parse objc-visibility-spec ConsumeToken(); // eat the @ sign + + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteObjCAtVisibility(CurScope); + ConsumeToken(); + } + switch (Tok.getObjCKeywordID()) { case tok::objc_private: case tok::objc_public: @@ -987,6 +993,12 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, } } + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteOrdinaryName(CurScope, + Action::CCC_ObjCInstanceVariableList); + ConsumeToken(); + } + struct ObjCIvarCallback : FieldCallback { Parser &P; DeclPtrTy IDecl; diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 956776cf29e6fab431438134982fc439d83c7d37..8fc34880c1103bef20b054847206e594e0da9665 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -3851,6 +3851,7 @@ public: virtual void CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl, bool InInterface); + virtual void CodeCompleteObjCAtVisibility(Scope *S); virtual void CodeCompleteObjCAtStatement(Scope *S); virtual void CodeCompleteObjCAtExpression(Scope *S); virtual void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS); diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 9f92641f0dfd03280f3ccb5c62b5d0d16d000e71..b828a02255ab5928e942bdc1532290546deb71a5 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -893,6 +893,7 @@ static void AddFunctionSpecifiers(Action::CodeCompletionContext CCC, Results.MaybeAddResult(Result("inline", Rank)); break; + case Action::CCC_ObjCInstanceVariableList: case Action::CCC_Expression: case Action::CCC_Statement: case Action::CCC_ForInit: @@ -905,6 +906,10 @@ static void AddObjCExpressionResults(unsigned Rank, ResultBuilder &Results, bool NeedAt); static void AddObjCStatementResults(unsigned Rank, ResultBuilder &Results, bool NeedAt); +static void AddObjCVisibilityResults(unsigned Rank, + const LangOptions &LangOpts, + ResultBuilder &Results, + bool NeedAt); static void AddObjCImplementationResults(unsigned Rank, const LangOptions &LangOpts, ResultBuilder &Results, @@ -1053,6 +1058,10 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC, AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Rank, Results); break; + case Action::CCC_ObjCInstanceVariableList: + AddObjCVisibilityResults(Rank, SemaRef.getLangOptions(), Results, true); + break; + case Action::CCC_Statement: { Results.MaybeAddResult(Result("typedef", Rank)); @@ -1971,6 +1980,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, case CCC_Class: case CCC_ObjCInterface: case CCC_ObjCImplementation: + case CCC_ObjCInstanceVariableList: case CCC_Template: case CCC_MemberTemplate: Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName); @@ -2672,8 +2682,27 @@ static void AddObjCStatementResults(unsigned Rank, ResultBuilder &Results, Results.MaybeAddResult(Result(Pattern, 0)); } -void Sema::CodeCompleteObjCAtStatement(Scope *S) { +static void AddObjCVisibilityResults(unsigned Rank, + const LangOptions &LangOpts, + ResultBuilder &Results, + bool NeedAt) { typedef CodeCompleteConsumer::Result Result; + Results.MaybeAddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private), Rank)); + Results.MaybeAddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected), Rank)); + Results.MaybeAddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public), Rank)); + if (LangOpts.ObjC2) + Results.MaybeAddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package), Rank)); +} + +void Sema::CodeCompleteObjCAtVisibility(Scope *S) { + ResultBuilder Results(*this); + Results.EnterNewScope(); + AddObjCVisibilityResults(0, getLangOptions(), Results, false); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCAtStatement(Scope *S) { ResultBuilder Results(*this); Results.EnterNewScope(); AddObjCStatementResults(0, Results, false); diff --git a/clang/test/Index/complete-at-directives.m b/clang/test/Index/complete-at-directives.m index a8aa499d10a5ad93bf57f45d1f298edb09f33ad6..6db47d20ebcfaee81c75d7209695faa076870741 100644 --- a/clang/test/Index/complete-at-directives.m +++ b/clang/test/Index/complete-at-directives.m @@ -1,5 +1,5 @@ /* Run lines are at the end, since line/column matter in this test. */ -@interface MyClass { } +@interface MyClass { @public } @end @implementation MyClass @@ -44,3 +44,16 @@ // CHECK-CC5: ObjCInterfaceDecl:{TypedText MyClass} // CHECK-CC5: TypedefDecl:{TypedText SEL} // CHECK-CC5: NotImplemented:{TypedText _Bool} + +// RUN: c-index-test -code-completion-at=%s:2:23 %s | FileCheck -check-prefix=CHECK-CC6 %s +// CHECK-CC6: NotImplemented:{TypedText package} +// CHECK-CC6: NotImplemented:{TypedText private} +// CHECK-CC6: NotImplemented:{TypedText protected} +// CHECK-CC6: NotImplemented:{TypedText public} + +// RUN: c-index-test -code-completion-at=%s:2:22 %s | FileCheck -check-prefix=CHECK-CC7 %s +// CHECK-CC7: NotImplemented:{TypedText @package} +// CHECK-CC7: NotImplemented:{TypedText @private} +// CHECK-CC7: NotImplemented:{TypedText @protected} +// CHECK-CC7: NotImplemented:{TypedText @public} +// CHECK-CC7: NotImplemented:{TypedText _Bool}