aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaCodeComplete.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-02-15 15:34:24 +0000
committerDouglas Gregor <dgregor@apple.com>2012-02-15 15:34:24 +0000
commit81f3bff7c202d688c9298bc049fdb5b6f77057b1 (patch)
tree3351f7acd82263793c2a57f316ddf5a08c0e5c20 /lib/Sema/SemaCodeComplete.cpp
parent31c4690047f5f362ecf886f1586844b1aef0c4d2 (diff)
Implement code completion support for lambda capture lists.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150583 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaCodeComplete.cpp')
-rw-r--r--lib/Sema/SemaCodeComplete.cpp105
1 files changed, 92 insertions, 13 deletions
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 7d384486cb..e74e70c725 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -274,9 +274,9 @@ namespace {
/// of the shadow maps), or replace an existing result (for, e.g., a
/// redeclaration).
///
- /// \param CurContext the result to add (if it is unique).
+ /// \param R the result to add (if it is unique).
///
- /// \param R the context in which this result will be named.
+ /// \param CurContext the context in which this result will be named.
void MaybeAddResult(Result R, DeclContext *CurContext = 0);
/// \brief Add a new result to this result set, where we already know
@@ -325,6 +325,7 @@ namespace {
bool IsMember(NamedDecl *ND) const;
bool IsObjCIvar(NamedDecl *ND) const;
bool IsObjCMessageReceiver(NamedDecl *ND) const;
+ bool IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const;
bool IsObjCCollection(NamedDecl *ND) const;
bool IsImpossibleToSatisfy(NamedDecl *ND) const;
//@}
@@ -1152,6 +1153,17 @@ bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
return isObjCReceiverType(SemaRef.Context, T);
}
+bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const {
+ if (IsObjCMessageReceiver(ND))
+ return true;
+
+ VarDecl *Var = dyn_cast<VarDecl>(ND);
+ if (!Var)
+ return false;
+
+ return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
+}
+
bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
if ((SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryName(ND)) ||
(!SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
@@ -1423,6 +1435,23 @@ static const char *GetCompletionTypeString(QualType T,
return Allocator.CopyString(Result);
}
+/// \brief Add a completion for "this", if we're in a member function.
+static void addThisCompletion(Sema &S, ResultBuilder &Results) {
+ QualType ThisTy = S.getCurrentThisType();
+ if (ThisTy.isNull())
+ return;
+
+ CodeCompletionAllocator &Allocator = Results.getAllocator();
+ CodeCompletionBuilder Builder(Allocator);
+ PrintingPolicy Policy = getCompletionPrintingPolicy(S);
+ Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
+ S.Context,
+ Policy,
+ Allocator));
+ Builder.AddTypedTextChunk("this");
+ Results.AddResult(CodeCompletionResult(Builder.TakeString()));
+}
+
/// \brief Add language constructs that show up for "ordinary" names.
static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Scope *S,
@@ -1758,15 +1787,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
case Sema::PCC_Expression: {
if (SemaRef.getLangOptions().CPlusPlus) {
// 'this', if we're in a non-static member function.
- QualType ThisTy = SemaRef.getCurrentThisType();
- if (!ThisTy.isNull()) {
- Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
- SemaRef.Context,
- Policy,
- Allocator));
- Builder.AddTypedTextChunk("this");
- Results.AddResult(Result(Builder.TakeString()));
- }
+ addThisCompletion(SemaRef, Results);
// true
Builder.AddResultTypeChunk("bool");
@@ -3665,7 +3686,6 @@ void Sema::CodeCompleteCase(Scope *S) {
kind = CodeCompletionContext::CCC_OtherWithMacros;
}
-
HandleCodeCompleteResults(this, CodeCompleter,
kind,
Results.data(),Results.size());
@@ -4181,6 +4201,60 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Results.data(), Results.size());
}
+/// \brief Determine whether this scope denotes a namespace.
+static bool isNamespaceScope(Scope *S) {
+ DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
+ if (!DC)
+ return false;
+
+ return DC->isFileContext();
+}
+
+void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
+ bool AfterAmpersand) {
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+ Results.EnterNewScope();
+
+ // Note what has already been captured.
+ llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
+ bool IncludedThis = false;
+ for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
+ CEnd = Intro.Captures.end();
+ C != CEnd; ++C) {
+ if (C->Kind == LCK_This) {
+ IncludedThis = true;
+ continue;
+ }
+
+ Known.insert(C->Id);
+ }
+
+ // Look for other capturable variables.
+ for (; S && !isNamespaceScope(S); S = S->getParent()) {
+ for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
+ D != DEnd; ++D) {
+ VarDecl *Var = dyn_cast<VarDecl>(*D);
+ if (!Var ||
+ !Var->hasLocalStorage() ||
+ Var->hasAttr<BlocksAttr>())
+ continue;
+
+ if (Known.insert(Var->getIdentifier()))
+ Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
+ }
+ }
+
+ // Add 'this', if it would be valid.
+ if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
+ addThisCompletion(*this, Results);
+
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
+}
+
// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
// true or false.
#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
@@ -4980,7 +5054,9 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompletionContext::CCC_ObjCMessageReceiver,
- &ResultBuilder::IsObjCMessageReceiver);
+ getLangOptions().CPlusPlus0x
+ ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
+ : &ResultBuilder::IsObjCMessageReceiver);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
Results.EnterNewScope();
@@ -4997,6 +5073,9 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
}
+ if (getLangOptions().CPlusPlus0x)
+ addThisCompletion(*this, Results);
+
Results.ExitScope();
if (CodeCompleter->includeMacros())