[cfe-commits] r111843 - in /cfe/trunk: include/clang/Sema/Action.h include/clang/Sema/Sema.h lib/Parse/ParseStmt.cpp lib/Sema/SemaCodeComplete.cpp test/Index/complete-declarators.m
Douglas Gregor
dgregor at apple.com
Mon Aug 23 14:17:50 PDT 2010
Author: dgregor
Date: Mon Aug 23 16:17:50 2010
New Revision: 111843
URL: http://llvm.org/viewvc/llvm-project?rev=111843&view=rev
Log:
Introduce a code-completion hook for the Objective-C collection
argument in a for-each statement (e.g., "for (id x in <blah>)"), which
restricts the expression completions provided to Objective-C types (or
class types in C++).
Modified:
cfe/trunk/include/clang/Sema/Action.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParseStmt.cpp
cfe/trunk/lib/Sema/SemaCodeComplete.cpp
cfe/trunk/test/Index/complete-declarators.m
Modified: cfe/trunk/include/clang/Sema/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Action.h?rev=111843&r1=111842&r2=111843&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Action.h (original)
+++ cfe/trunk/include/clang/Sema/Action.h Mon Aug 23 16:17:50 2010
@@ -3052,6 +3052,15 @@
IdentifierInfo **SelIdents,
unsigned NumSelIdents) { }
+ /// \brief Code completion for the collection argument of an Objective-C
+ /// for-each statement.
+ ///
+ /// \param S The Scope in which the completion occurs.
+ ///
+ /// \param IterationBar The iteration variable declaration.
+ virtual void CodeCompleteObjCForCollection(Scope *S,
+ DeclGroupPtrTy IterationVar) { }
+
/// \brief Code completion for a list of protocol references in Objective-C,
/// such as P1 and P2 in \c id<P1,P2>.
///
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=111843&r1=111842&r2=111843&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Aug 23 16:17:50 2010
@@ -4643,8 +4643,10 @@
virtual void CodeCompleteDeclarator(Scope *S,
bool AllowNonIdentifiers,
bool AllowNestedNameSpecifiers);
- virtual void CodeCompleteExpression(Scope *S, QualType T,
- bool IntegralConstantExpression = false);
+
+ struct CodeCompleteExpressionData;
+ virtual void CodeCompleteExpression(Scope *S,
+ const CodeCompleteExpressionData &Data);
virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base,
SourceLocation OpLoc,
bool IsArrow);
@@ -4686,6 +4688,8 @@
virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
IdentifierInfo **SelIdents,
unsigned NumSelIdents);
+ virtual void CodeCompleteObjCForCollection(Scope *S,
+ DeclGroupPtrTy IterationVar);
virtual void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
unsigned NumProtocols);
virtual void CodeCompleteObjCProtocolDecl(Scope *S);
Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=111843&r1=111842&r2=111843&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Mon Aug 23 16:17:50 2010
@@ -1023,6 +1023,11 @@
Actions.ActOnForEachDeclStmt(DG);
// ObjC: for (id x in expr)
ConsumeToken(); // consume 'in'
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCForCollection(getCurScope(), DG);
+ ConsumeCodeCompletionToken();
+ }
Collection = ParseExpression();
} else {
Diag(Tok, diag::err_expected_semi_for);
@@ -1039,6 +1044,11 @@
ConsumeToken();
} else if ((ForEach = isTokIdentifier_in())) {
ConsumeToken(); // consume 'in'
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCForCollection(getCurScope(), DeclGroupPtrTy());
+ ConsumeCodeCompletionToken();
+ }
Collection = ParseExpression();
} else {
if (!Value.isInvalid()) Diag(Tok, diag::err_expected_semi_for);
Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=111843&r1=111842&r2=111843&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Mon Aug 23 16:17:50 2010
@@ -239,6 +239,7 @@
bool IsMember(NamedDecl *ND) const;
bool IsObjCIvar(NamedDecl *ND) const;
bool IsObjCMessageReceiver(NamedDecl *ND) const;
+ bool IsObjCCollection(NamedDecl *ND) const;
//@}
};
}
@@ -366,8 +367,12 @@
DeclContext *Parent = TargetParents.back();
TargetParents.pop_back();
- if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent))
+ if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
+ if (!Namespace->getIdentifier())
+ continue;
+
Result = NestedNameSpecifier::Create(Context, Result, Namespace);
+ }
else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
Result = NestedNameSpecifier::Create(Context, Result,
false,
@@ -946,6 +951,20 @@
return isObjCReceiverType(SemaRef.Context, T);
}
+bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
+ if ((SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryName(ND)) ||
+ (!SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
+ return false;
+
+ QualType T = getDeclUsageType(SemaRef.Context, ND);
+ if (T.isNull())
+ return false;
+
+ T = SemaRef.Context.getBaseElementType(T);
+ return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
+ T->isObjCIdType() ||
+ (SemaRef.getLangOptions().CPlusPlus && T->isRecordType());
+}
/// \rief Determines whether the given declaration is an Objective-C
/// instance variable.
@@ -2303,23 +2322,42 @@
Results.data(), Results.size());
}
+struct Sema::CodeCompleteExpressionData {
+ CodeCompleteExpressionData(QualType PreferredType = QualType())
+ : PreferredType(PreferredType), IntegralConstantExpression(false),
+ ObjCCollection(false) { }
+
+ QualType PreferredType;
+ bool IntegralConstantExpression;
+ bool ObjCCollection;
+ llvm::SmallVector<Decl *, 4> IgnoreDecls;
+};
+
/// \brief Perform code-completion in an expression context when we know what
/// type we're looking for.
///
/// \param IntegralConstantExpression Only permit integral constant
/// expressions.
-void Sema::CodeCompleteExpression(Scope *S, QualType T,
- bool IntegralConstantExpression) {
+void Sema::CodeCompleteExpression(Scope *S,
+ const CodeCompleteExpressionData &Data) {
typedef CodeCompleteConsumer::Result Result;
ResultBuilder Results(*this);
- if (IntegralConstantExpression)
+ if (Data.ObjCCollection)
+ Results.setFilter(&ResultBuilder::IsObjCCollection);
+ else if (Data.IntegralConstantExpression)
Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
else if (WantTypesInContext(PCC_Expression, getLangOptions()))
Results.setFilter(&ResultBuilder::IsOrdinaryName);
else
Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
- Results.setPreferredType(T.getNonReferenceType());
+
+ if (!Data.PreferredType.isNull())
+ Results.setPreferredType(Data.PreferredType.getNonReferenceType());
+
+ // Ignore any declarations that we were told that we don't care about.
+ for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
+ Results.Ignore(Data.IgnoreDecls[I]);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
@@ -2330,14 +2368,16 @@
Results.ExitScope();
bool PreferredTypeIsPointer = false;
- if (!T.isNull())
- PreferredTypeIsPointer = T->isAnyPointerType() ||
- T->isMemberPointerType() || T->isBlockPointerType();
+ if (!Data.PreferredType.isNull())
+ PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
+ || Data.PreferredType->isMemberPointerType()
+ || Data.PreferredType->isBlockPointerType();
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, PreferredTypeIsPointer);
HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext(CodeCompletionContext::CCC_Expression, T),
+ CodeCompletionContext(CodeCompletionContext::CCC_Expression,
+ Data.PreferredType),
Results.data(),Results.size());
}
@@ -2534,7 +2574,9 @@
SwitchStmt *Switch = getSwitchStack().back();
if (!Switch->getCond()->getType()->isEnumeralType()) {
- CodeCompleteExpression(S, Switch->getCond()->getType(), true);
+ CodeCompleteExpressionData Data(Switch->getCond()->getType());
+ Data.IntegralConstantExpression = true;
+ CodeCompleteExpression(S, Data);
return;
}
@@ -3752,6 +3794,22 @@
Results.data(),Results.size());
}
+void Sema::CodeCompleteObjCForCollection(Scope *S,
+ DeclGroupPtrTy IterationVar) {
+ CodeCompleteExpressionData Data;
+ Data.ObjCCollection = true;
+
+ if (IterationVar.getAsOpaquePtr()) {
+ DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
+ for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
+ if (*I)
+ Data.IgnoreDecls.push_back(*I);
+ }
+ }
+
+ CodeCompleteExpression(S, Data);
+}
+
/// \brief Add all of the protocol declarations that we find in the given
/// (translation unit) context.
static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Modified: cfe/trunk/test/Index/complete-declarators.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-declarators.m?rev=111843&r1=111842&r2=111843&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-declarators.m (original)
+++ cfe/trunk/test/Index/complete-declarators.m Mon Aug 23 16:17:50 2010
@@ -11,7 +11,12 @@
@implementation A
- (int)method:(id)param1 {
- for(id x in param1) {
+ int q2;
+ for(id q in param1) {
+ int y;
+ }
+ id q;
+ for(q in param1) {
int y;
}
}
@@ -21,9 +26,20 @@
// CHECK-CC1-NOT: NotImplemented:{TypedText extern} (30)
// CHECK-CC1: NotImplemented:{TypedText param1} (30)
// RUN: c-index-test -code-completion-at=%s:9:15 %s | FileCheck -check-prefix=CHECK-CC2 %s
-// RUN: c-index-test -code-completion-at=%s:14:10 %s | FileCheck -check-prefix=CHECK-CC2 %s
-// RUN: c-index-test -code-completion-at=%s:15:9 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: c-index-test -code-completion-at=%s:15:10 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: c-index-test -code-completion-at=%s:16:9 %s | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2: NotImplemented:{TypedText const} (30)
// CHECK-CC2-NOT: int
// CHECK-CC2: NotImplemented:{TypedText restrict} (30)
// CHECK-CC2: NotImplemented:{TypedText volatile} (30)
+// RUN: c-index-test -code-completion-at=%s:15:15 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3: ParmDecl:{ResultType id}{TypedText param1} (8)
+// CHECK-CC3-NOT: VarDecl:{ResultType int}{TypedText q2} (8)
+// CHECK-CC3-NOT: VarDecl:{ResultType id}{TypedText q} (8)
+// CHECK-CC3: NotImplemented:{ResultType A *}{TypedText self} (8)
+// CHECK-CC3: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
+// RUN: c-index-test -code-completion-at=%s:15:15 %s | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC4: ParmDecl:{ResultType id}{TypedText param1} (8)
+// CHECK-CC4-NOT: VarDecl:{ResultType int}{TypedText q2} (8)
+// CHECK-CC4: NotImplemented:{ResultType A *}{TypedText self} (8)
+// CHECK-CC4: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
More information about the cfe-commits
mailing list