From 936354c62aafa6aa5c79ba5c5c0536a6b4552aa8 Mon Sep 17 00:00:00 2001 From: Steve Naroff Date: Thu, 8 Oct 2009 21:55:05 +0000 Subject: [PATCH] Add code completion support for ObjC property declarations/attributes. llvm-svn: 83579 --- clang/clang.xcodeproj/project.pbxproj | 2 ++ clang/include/clang/Parse/Action.h | 8 ++++++++ clang/lib/Parse/ParseObjc.cpp | 4 ++++ clang/lib/Sema/Sema.h | 2 ++ clang/lib/Sema/SemaCodeComplete.cpp | 27 +++++++++++++++++++++++++ clang/test/CodeCompletion/property.m | 29 +++++++++++++++++++++++++++ 6 files changed, 72 insertions(+) create mode 100644 clang/test/CodeCompletion/property.m diff --git a/clang/clang.xcodeproj/project.pbxproj b/clang/clang.xcodeproj/project.pbxproj index 26a603f19f0b..8c71b76100af 100644 --- a/clang/clang.xcodeproj/project.pbxproj +++ b/clang/clang.xcodeproj/project.pbxproj @@ -503,6 +503,7 @@ 35F9B1560D1C6B2E00DDFDAE /* UninitializedValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UninitializedValues.h; path = clang/Analysis/Analyses/UninitializedValues.h; sourceTree = ""; }; 35FE6BCE0DF6EE1F00739712 /* DeclBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = DeclBase.cpp; path = lib/AST/DeclBase.cpp; sourceTree = ""; tabWidth = 2; }; 72D16C1E0D9975C400E6DA4A /* HTMLRewrite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLRewrite.cpp; path = lib/Rewrite/HTMLRewrite.cpp; sourceTree = ""; }; + 7F270AFE107A90010031B377 /* CodeCompleteConsumer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CodeCompleteConsumer.h; path = clang/Sema/CodeCompleteConsumer.h; sourceTree = ""; }; 84AF36A00CB17A3B00C820A5 /* DeclObjC.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = DeclObjC.h; path = clang/AST/DeclObjC.h; sourceTree = ""; tabWidth = 2; }; 84D9A8870C1A57E100AC7ABC /* AttributeList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = AttributeList.cpp; path = lib/Parse/AttributeList.cpp; sourceTree = ""; tabWidth = 2; }; 84D9A88B0C1A581300AC7ABC /* AttributeList.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = AttributeList.h; path = clang/Parse/AttributeList.h; sourceTree = ""; tabWidth = 2; }; @@ -1229,6 +1230,7 @@ DE67E7260C02108300F66BC5 /* Sema */ = { isa = PBXGroup; children = ( + 7F270AFE107A90010031B377 /* CodeCompleteConsumer.h */, 9063F2210F9E8BDF002F7251 /* ExternalSemaSource.h */, 9063F2220F9E8BDF002F7251 /* SemaConsumer.h */, DE67E7270C02109800F66BC5 /* ParseAST.h */, diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index 4be5a763a92d..5e0a360df196 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -2340,6 +2340,14 @@ public: /// /// \param S the scope in which the operator keyword occurs. virtual void CodeCompleteOperatorName(Scope *S) { } + + /// \brief Code completion for an ObjC property decl. + /// + /// This code completion action is invoked when the code-completion token is + /// found after the left paren. + /// + /// \param S the scope in which the operator keyword occurs. + virtual void CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) { } //@} }; diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 014f10edd40f..1d29f319c584 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -390,6 +390,10 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { SourceLocation LHSLoc = ConsumeParen(); // consume '(' while (1) { + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteObjCProperty(CurScope, DS); + ConsumeToken(); + } const IdentifierInfo *II = Tok.getIdentifierInfo(); // If this is not an identifier at all, bail out early. diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 08cb06db5616..f85c1a821b9c 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -3699,6 +3699,8 @@ public: virtual void CodeCompleteNamespaceDecl(Scope *S); virtual void CodeCompleteNamespaceAliasDecl(Scope *S); virtual void CodeCompleteOperatorName(Scope *S); + + virtual void CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS); //@} //===--------------------------------------------------------------------===// diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 7a916ef03602..b64870265012 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -1393,3 +1393,30 @@ void Sema::CodeCompleteOperatorName(Scope *S) { HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); } +void Sema::CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) { + if (!CodeCompleter) + return; + unsigned Attributes = ODS.getPropertyAttributes(); + + typedef CodeCompleteConsumer::Result Result; + ResultBuilder Results(*this); + Results.EnterNewScope(); + if (!(Attributes & ObjCDeclSpec::DQ_PR_readonly)) + Results.MaybeAddResult(CodeCompleteConsumer::Result("readonly", 0)); + if (!(Attributes & ObjCDeclSpec::DQ_PR_assign)) + Results.MaybeAddResult(CodeCompleteConsumer::Result("assign", 0)); + if (!(Attributes & ObjCDeclSpec::DQ_PR_readwrite)) + Results.MaybeAddResult(CodeCompleteConsumer::Result("readwrite", 0)); + if (!(Attributes & ObjCDeclSpec::DQ_PR_retain)) + Results.MaybeAddResult(CodeCompleteConsumer::Result("retain", 0)); + if (!(Attributes & ObjCDeclSpec::DQ_PR_copy)) + Results.MaybeAddResult(CodeCompleteConsumer::Result("copy", 0)); + if (!(Attributes & ObjCDeclSpec::DQ_PR_nonatomic)) + Results.MaybeAddResult(CodeCompleteConsumer::Result("nonatomic", 0)); + if (!(Attributes & ObjCDeclSpec::DQ_PR_setter)) + Results.MaybeAddResult(CodeCompleteConsumer::Result("setter", 0)); + if (!(Attributes & ObjCDeclSpec::DQ_PR_getter)) + Results.MaybeAddResult(CodeCompleteConsumer::Result("getter", 0)); + Results.ExitScope(); + HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); +} diff --git a/clang/test/CodeCompletion/property.m b/clang/test/CodeCompletion/property.m new file mode 100644 index 000000000000..a8dd2ba2eb4d --- /dev/null +++ b/clang/test/CodeCompletion/property.m @@ -0,0 +1,29 @@ +// Note: the run lines follow their respective tests, since line/column +// matter in this test. + +@interface Foo { + void *isa; +} +@property(copy) Foo *myprop; +@property(retain, nonatomic) id xx; +// RUN: clang-cc -fsyntax-only -code-completion-at=%s:7:11 %s -o - | FileCheck -check-prefix=CC1 %s && +// CC1: readonly +// CC1-NEXT: assign +// CC1-NEXT: readwrite +// CC1-NEXT: retain +// CC1-NEXT: copy +// CC1-NEXT: nonatomic +// CC1-NEXT: setter +// CC1-NEXT: getter +// RUN: clang-cc -fsyntax-only -code-completion-at=%s:8:18 %s -o - | FileCheck -check-prefix=CC2 %s +// CC2: readonly +// CC2-NEXT: assign +// CC2-NEXT: readwrite +// CC2-NEXT: copy +// CC2-NEXT: nonatomic +// CC2-NEXT: setter +// CC2-NEXT: getter +@end + + + -- GitLab