From: Douglas Gregor Date: Mon, 18 Apr 2011 14:13:53 +0000 (+0000) Subject: When producing code completion results for the Objective-C property X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=aa490cb6a70e7ff0335bdc4c88619e00ff0dab25;p=clang When producing code completion results for the Objective-C property implementation @synthesize = also produce a completion for a to-be-synthesized ivar named _. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129697 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index ab1eb0587a..fa76db4c63 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -5372,14 +5372,51 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, // Add all of the instance variables in this class and its superclasses. Results.EnterNewScope(); + bool SawSimilarlyNamedIvar = false; + std::string NameWithPrefix; + NameWithPrefix += '_'; + NameWithPrefix += PropertyName->getName().str(); + std::string NameWithSuffix = PropertyName->getName().str(); + NameWithSuffix += '_'; for(; Class; Class = Class->getSuperClass()) { // FIXME: We could screen the type of each ivar for compatibility with - // the property, but is that being too paternal? - for (ObjCInterfaceDecl::ivar_iterator IVar = Class->ivar_begin(), - IVarEnd = Class->ivar_end(); - IVar != IVarEnd; ++IVar) - Results.AddResult(Result(*IVar, 0), CurContext, 0, false); + // the property, but is that being too paternal? + for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar; + Ivar = Ivar->getNextIvar()) { + // Determine whether we've seen an ivar with a name similar to the + // property. + if (!SawSimilarlyNamedIvar && + (PropertyName->getName() == Ivar->getName() || + NameWithPrefix == Ivar->getName() || + NameWithSuffix == Ivar->getName())) + SawSimilarlyNamedIvar = true; + + Results.AddResult(Result(Ivar, 0), CurContext, 0, false); + } + } + + if (!SawSimilarlyNamedIvar) { + // Create ivar result _propName, that the user can use to synthesize + // an ivar of the appropriate type. + QualType T = Context.getObjCIdType(); + + if (Class) { + if (ObjCPropertyDecl *Property + = Class->FindPropertyDeclaration(PropertyName)) + T = Property->getType().getNonReferenceType().getUnqualifiedType(); + } + + unsigned Priority = CCP_MemberDeclaration; + typedef CodeCompletionResult Result; + CodeCompletionAllocator &Allocator = Results.getAllocator(); + CodeCompletionBuilder Builder(Allocator, Priority,CXAvailability_Available); + + Builder.AddResultTypeChunk(GetCompletionTypeString(T, Context, Allocator)); + Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix)); + Results.AddResult(Result(Builder.TakeString(), Priority, + CXCursor_ObjCIvarDecl)); } + Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, diff --git a/test/Index/complete-properties.m b/test/Index/complete-properties.m index 725f180f7c..c513a91e95 100644 --- a/test/Index/complete-properties.m +++ b/test/Index/complete-properties.m @@ -41,8 +41,10 @@ id test(I3 *i3) { // CHECK-CC2-NEXT: ObjCPropertyDecl:{ResultType id}{TypedText Prop3} // CHECK-CC2: ObjCPropertyDecl:{ResultType id}{TypedText Prop4} // RUN: c-index-test -code-completion-at=%s:20:35 %s | FileCheck -check-prefix=CHECK-CC3 %s -// CHECK-CC3: ObjCIvarDecl:{ResultType int}{TypedText RandomIVar} -// CHECK-CC3: ObjCIvarDecl:{ResultType id}{TypedText StoredProp3} +// CHECK-CC3: ObjCIvarDecl:{ResultType id}{TypedText _Prop3} (35) +// CHECK-CC3: ObjCIvarDecl:{ResultType int}{TypedText RandomIVar} (35) +// CHECK-CC3: ObjCIvarDecl:{ResultType id}{TypedText StoredProp3} (35) + // RUN: c-index-test -code-completion-at=%s:21:10 %s | FileCheck -check-prefix=CHECK-CC4 %s // CHECK-CC4: ObjCPropertyDecl:{ResultType int}{TypedText Prop0} // CHECK-CC4-NEXT: ObjCPropertyDecl:{ResultType id}{TypedText Prop4}