[llvm-branch-commits] [cfe-branch] r105036 - in /cfe/branches/Apple/whitney: include/clang/Parse/Action.h lib/Parse/ParseObjc.cpp lib/Sema/Sema.h lib/Sema/SemaCodeComplete.cpp test/Index/complete-objc-message.m
Daniel Dunbar
daniel at zuster.org
Fri May 28 16:06:42 PDT 2010
Author: ddunbar
Date: Fri May 28 18:06:41 2010
New Revision: 105036
URL: http://llvm.org/viewvc/llvm-project?rev=105036&view=rev
Log:
Merge r104895:
--
Author: Douglas Gregor <dgregor at apple.com>
Date: Thu May 27 23:06:34 2010 +0000
Implement a code-completion hook for the receiver of an Objective-C
message. This completion gives better results than just using the
"expression" completion, which is effectively what happened before.
Modified:
cfe/branches/Apple/whitney/include/clang/Parse/Action.h
cfe/branches/Apple/whitney/lib/Parse/ParseObjc.cpp
cfe/branches/Apple/whitney/lib/Sema/Sema.h
cfe/branches/Apple/whitney/lib/Sema/SemaCodeComplete.cpp
cfe/branches/Apple/whitney/test/Index/complete-objc-message.m
Modified: cfe/branches/Apple/whitney/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/include/clang/Parse/Action.h?rev=105036&r1=105035&r2=105036&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/include/clang/Parse/Action.h (original)
+++ cfe/branches/Apple/whitney/include/clang/Parse/Action.h Fri May 28 18:06:41 2010
@@ -2853,6 +2853,14 @@
unsigned NumMethods) {
}
+ /// \brief Code completion for the receiver in an Objective-C message send.
+ ///
+ /// This code completion action is invoked when we see a '[' that indicates
+ /// the start of an Objective-C message send.
+ ///
+ /// \param S The scope in which the Objective-C message send occurs.
+ virtual void CodeCompleteObjCMessageReceiver(Scope *S) { }
+
/// \brief Code completion for an ObjC message expression that sends
/// a message to the superclass.
///
Modified: cfe/branches/Apple/whitney/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/Parse/ParseObjc.cpp?rev=105036&r1=105035&r2=105036&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/Parse/ParseObjc.cpp (original)
+++ cfe/branches/Apple/whitney/lib/Parse/ParseObjc.cpp Fri May 28 18:06:41 2010
@@ -1807,6 +1807,13 @@
assert(Tok.is(tok::l_square) && "'[' expected");
SourceLocation LBracLoc = ConsumeBracket(); // consume '['
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCMessageReceiver(CurScope);
+ ConsumeCodeCompletionToken();
+ SkipUntil(tok::r_square);
+ return ExprError();
+ }
+
if (getLang().CPlusPlus) {
// We completely separate the C and C++ cases because C++ requires
// more complicated (read: slower) parsing.
Modified: cfe/branches/Apple/whitney/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/Sema/Sema.h?rev=105036&r1=105035&r2=105036&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/Sema/Sema.h (original)
+++ cfe/branches/Apple/whitney/lib/Sema/Sema.h Fri May 28 18:06:41 2010
@@ -4440,7 +4440,7 @@
virtual void CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ClassDecl,
DeclPtrTy *Methods,
unsigned NumMethods);
-
+ virtual void CodeCompleteObjCMessageReceiver(Scope *S);
virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
IdentifierInfo **SelIdents,
unsigned NumSelIdents);
Modified: cfe/branches/Apple/whitney/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/Sema/SemaCodeComplete.cpp?rev=105036&r1=105035&r2=105036&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/branches/Apple/whitney/lib/Sema/SemaCodeComplete.cpp Fri May 28 18:06:41 2010
@@ -222,6 +222,7 @@
bool IsType(NamedDecl *ND) const;
bool IsMember(NamedDecl *ND) const;
bool IsObjCIvar(NamedDecl *ND) const;
+ bool IsObjCMessageReceiver(NamedDecl *ND) const;
//@}
};
}
@@ -732,6 +733,78 @@
isa<ObjCPropertyDecl>(ND);
}
+/// \brief Get the type that a given expression will have if this declaration
+/// is used as an expression in its "typical" code-completion form.
+static QualType getDeclUsageType(ASTContext &C, NamedDecl *ND) {
+ ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+
+ if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
+ return C.getTypeDeclType(Type);
+ if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
+ return C.getObjCInterfaceType(Iface);
+
+ QualType T;
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
+ T = Function->getResultType();
+ else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
+ T = Method->getResultType();
+ else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
+ T = FunTmpl->getTemplatedDecl()->getResultType();
+ else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
+ T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
+ else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
+ T = Property->getType();
+ else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
+ T = Value->getType();
+ else
+ return QualType();
+
+ return T.getNonReferenceType();
+}
+
+static bool isObjCReceiverType(ASTContext &C, QualType T) {
+ T = C.getCanonicalType(T);
+ switch (T->getTypeClass()) {
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
+ return true;
+
+ case Type::Builtin:
+ switch (cast<BuiltinType>(T)->getKind()) {
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ return true;
+
+ default:
+ break;
+ }
+ return false;
+
+ default:
+ break;
+ }
+
+ if (!C.getLangOptions().CPlusPlus)
+ return false;
+
+ // FIXME: We could perform more analysis here to determine whether a
+ // particular class type has any conversions to Objective-C types. For now,
+ // just accept all class types.
+ return T->isDependentType() || T->isRecordType();
+}
+
+bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
+ QualType T = getDeclUsageType(SemaRef.Context, ND);
+ if (T.isNull())
+ return false;
+
+ T = SemaRef.Context.getBaseElementType(T);
+ return isObjCReceiverType(SemaRef.Context, T);
+}
+
+
/// \rief Determines whether the given declaration is an Objective-C
/// instance variable.
bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
@@ -3021,6 +3094,31 @@
.Default(0);
}
+void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
+ typedef CodeCompleteConsumer::Result Result;
+ ResultBuilder Results(*this);
+
+ // Find anything that looks like it could be a message receiver.
+ Results.setFilter(&ResultBuilder::IsObjCMessageReceiver);
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ Results.EnterNewScope();
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+
+ // If we are in an Objective-C method inside a class that has a superclass,
+ // add "super" as an option.
+ if (ObjCMethodDecl *Method = getCurMethodDecl())
+ if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
+ if (Iface->getSuperClass())
+ Results.AddResult(Result("super"));
+
+ Results.ExitScope();
+
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, Results);
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+
+}
+
void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
IdentifierInfo **SelIdents,
unsigned NumSelIdents) {
Modified: cfe/branches/Apple/whitney/test/Index/complete-objc-message.m
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/test/Index/complete-objc-message.m?rev=105036&r1=105035&r2=105036&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/test/Index/complete-objc-message.m (original)
+++ cfe/branches/Apple/whitney/test/Index/complete-objc-message.m Fri May 28 18:06:41 2010
@@ -51,7 +51,7 @@
return 3;
}
@end
-
+MyClass *getMyClass();
@implementation MySubClass
+ (int)MySubClassMethod {
return 2;
@@ -160,14 +160,13 @@
// CHECK-CC9: ObjCInstanceMethodDecl:{ResultType int}{Informative Method:}{Informative Arg1:}{TypedText Arg2:}{Placeholder (int)i2}
// CHECK-CC9: ObjCInstanceMethodDecl:{ResultType int}{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: {ResultType SEL}{TypedText _cmd}
// CHECK-CCA: TypedefDecl:{TypedText Class}
-// CHECK-CCA: ObjCInterfaceDecl:{TypedText Foo}
-// CHECK-CCA: FunctionDecl:{ResultType void}{TypedText func}{LeftParen (}{RightParen )}
+// CHECK-CCA-NEXT: ObjCInterfaceDecl:{TypedText Foo}
+// CHECK-CCA-NOT: FunctionDecl:{ResultType void}{TypedText func}{LeftParen (}{RightParen )}
+// CHECK-CCA:FunctionDecl:{ResultType MyClass *}{TypedText getMyClass}{LeftParen (}{RightParen )}
// CHECK-CCA: TypedefDecl:{TypedText id}
// CHECK-CCA: ObjCInterfaceDecl:{TypedText MyClass}
// CHECK-CCA: ObjCInterfaceDecl:{TypedText MySubClass}
-// CHECK-CCA: TypedefDecl:{TypedText SEL}
// CHECK-CCA: {ResultType Class}{TypedText self}
// CHECK-CCA: {TypedText super}
// RUN: c-index-test -code-completion-at=%s:103:6 %s | FileCheck -check-prefix=CHECK-CCB %s
@@ -188,14 +187,12 @@
// CHECK-CCE: ObjCClassMethodDecl:{ResultType int}{Informative Method:}{Informative Arg1:}{TypedText Arg2:}{Placeholder (int)i2}
// CHECK-CCE: ObjCClassMethodDecl:{ResultType int}{Informative Method:}{Informative Arg1:}{TypedText OtherArg:}{Placeholder (id)obj}
// RUN: c-index-test -code-completion-at=%s:61:11 %s | FileCheck -check-prefix=CHECK-CCF %s
-// CHECK-CCF: {ResultType SEL}{TypedText _cmd}
// CHECK-CCF: TypedefDecl:{TypedText Class}
// CHECK-CCF: ObjCInterfaceDecl:{TypedText Foo}
-// CHECK-CCF: FunctionDecl:{ResultType void}{TypedText func}{LeftParen (}{RightParen )}
+// CHECK-CCF-NOT: FunctionDecl:{ResultType void}{TypedText func}{LeftParen (}{RightParen )}
// CHECK-CCF: TypedefDecl:{TypedText id}
// CHECK-CCF: ObjCInterfaceDecl:{TypedText MyClass}
// CHECK-CCF: ObjCInterfaceDecl:{TypedText MySubClass}
-// CHECK-CCF: TypedefDecl:{TypedText SEL}
// CHECK-CCF: {ResultType Class}{TypedText self}
// CHECK-CCF: {TypedText super}
// RUN: c-index-test -code-completion-at=%s:120:6 %s | FileCheck -check-prefix=CHECK-CCG %s
@@ -230,4 +227,3 @@
// CHECK-CCH: ObjCClassMethodDecl:{ResultType id}{TypedText new}
// CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText OtherMethod:}{Placeholder (float)f}{HorizontalSpace }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text Arg2:}{Placeholder (int)i2}
// CHECK-CCH: ObjCClassMethodDecl:{ResultType id}{TypedText protocolClassMethod}
-
More information about the llvm-branch-commits
mailing list