]> granicus.if.org Git - clang/commitdiff
Extend the code-completion caching infrastructure to include global
authorDouglas Gregor <dgregor@apple.com>
Sun, 15 Aug 2010 06:18:01 +0000 (06:18 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sun, 15 Aug 2010 06:18:01 +0000 (06:18 +0000)
declarations (in addition to macros). Each kind of declaration maps to
a certain set of completion contexts, and the ASTUnit completion logic
introduces the completion strings for those declarations if the actual
code-completion occurs in one of the contexts where it matters.

There are a few new code-completion-context kinds. Without these,
certain completions (e.g., after "using namespace") would need to
suppress all global completions, which would be unfortunate.

Note that we don't get the priorities right for global completions,
because we don't have enough type information. We'll need a way to
compare types in an ASTContext-agnostic way before this can be
implemented.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111093 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
include/clang/Driver/CC1Options.td
include/clang/Frontend/CompilerInstance.h
include/clang/Frontend/FrontendOptions.h
include/clang/Sema/CodeCompleteConsumer.h
include/clang/Sema/Sema.h
lib/Frontend/ASTUnit.cpp
lib/Frontend/CompilerInstance.cpp
lib/Frontend/CompilerInvocation.cpp
lib/Sema/SemaCodeComplete.cpp
lib/Sema/SemaLookup.cpp
test/Index/complete-exprs.c
tools/libclang/CIndexCodeCompletion.cpp

index bfa8c8ba02e5626a18de8ef17b5e851ab67475d4..ea7175da53334c864a27033336bfa48546cc0b6a 100644 (file)
@@ -264,6 +264,8 @@ def code_completion_macros : Flag<"-code-completion-macros">,
   HelpText<"Include macros in code-completion results">;
 def code_completion_patterns : Flag<"-code-completion-patterns">,
   HelpText<"Include code patterns in code-completion results">;
+def no_code_completion_globals : Flag<"-no-code-completion-globals">,
+  HelpText<"Do not include global declarations in code-completion results.">;
 def disable_free : Flag<"-disable-free">,
   HelpText<"Disable freeing of memory on exit">;
 def help : Flag<"-help">,
index bd1791dae8c6bd4354ccb8e67c050a80cc83b7b8..2a0a7a7747bb97ff83e53f83ee7734f738e8d8fa 100644 (file)
@@ -544,7 +544,8 @@ public:
   createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename,
                                unsigned Line, unsigned Column,
                                bool UseDebugPrinter, bool ShowMacros,
-                               bool ShowCodePatterns, llvm::raw_ostream &OS);
+                               bool ShowCodePatterns, bool ShowGlobals,
+                               llvm::raw_ostream &OS);
 
   /// \brief Create the Sema object to be used for parsing.
   void createSema(bool CompleteTranslationUnit,
index 48ce5074faaed15e725ce036f1b01b657239d719..e24f3a0be1a7b1aaee0814c8e32688c4c043456c 100644 (file)
@@ -69,6 +69,8 @@ public:
                                            /// results.
   unsigned ShowCodePatternsInCodeCompletion : 1; ///< Show code patterns in code
                                                  /// completion results.
+  unsigned ShowGlobalSymbolsInCodeCompletion : 1; ///< Show top-level decls in
+                                                  /// code completion results.
   unsigned ShowStats : 1;                  ///< Show frontend performance
                                            /// metrics and statistics.
   unsigned ShowTimers : 1;                 ///< Show timers for individual
@@ -122,6 +124,7 @@ public:
     ShowHelp = 0;
     ShowMacrosInCodeCompletion = 0;
     ShowCodePatternsInCodeCompletion = 0;
+    ShowGlobalSymbolsInCodeCompletion = 1;
     ShowStats = 0;
     ShowTimers = 0;
     ShowVersion = 0;
index 48e422383f4e001aa3ce130b4df1a70be20e028b..16dd69d40135735b0370bdcc283744b5de192c84 100644 (file)
@@ -127,7 +127,12 @@ public:
     /// to indicate a struct or class name.
     CCC_ClassOrStructTag,
     /// \brief Code completion occurred where a protocol name is expected.
-    CCC_ObjCProtocolName
+    CCC_ObjCProtocolName,
+    /// \brief Code completion occurred where a namespace or namespace alias
+    /// is expected.
+    CCC_Namespace,
+    /// \brief Code completion occurred where a type name is expected.
+    CCC_Type
   };
 
 private:
@@ -382,6 +387,10 @@ protected:
   /// the completion results.
   bool IncludeCodePatterns;
   
+  /// \brief Whether to include global (top-level) declarations and names in
+  /// the completion results.
+  bool IncludeGlobals;
+  
   /// \brief Whether the output format for the code-completion consumer is
   /// binary.
   bool OutputIsBinary;
@@ -588,12 +597,12 @@ public:
   };
   
   CodeCompleteConsumer() : IncludeMacros(false), IncludeCodePatterns(false),
-                           OutputIsBinary(false) { }
+                           IncludeGlobals(true), OutputIsBinary(false) { }
   
   CodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns,
-                       bool OutputIsBinary)
+                       bool IncludeGlobals, bool OutputIsBinary)
     : IncludeMacros(IncludeMacros), IncludeCodePatterns(IncludeCodePatterns),
-      OutputIsBinary(OutputIsBinary) { }
+      IncludeGlobals(IncludeGlobals), OutputIsBinary(OutputIsBinary) { }
   
   /// \brief Whether the code-completion consumer wants to see macros.
   bool includeMacros() const { return IncludeMacros; }
@@ -601,6 +610,9 @@ public:
   /// \brief Whether the code-completion consumer wants to see code patterns.
   bool includeCodePatterns() const { return IncludeCodePatterns; }
   
+  /// \brief Whether to include global (top-level) declaration results.
+  bool includeGlobals() const { return IncludeGlobals; }
+  
   /// \brief Determine whether the output of this consumer is binary.
   bool isOutputBinary() const { return OutputIsBinary; }
   
@@ -639,8 +651,10 @@ public:
   /// \brief Create a new printing code-completion consumer that prints its
   /// results to the given raw output stream.
   PrintingCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns,
+                               bool IncludeGlobals,
                                llvm::raw_ostream &OS)
-    : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, false), OS(OS) {}
+    : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
+                           false), OS(OS) {}
   
   /// \brief Prints the finalized code-completion results.
   virtual void ProcessCodeCompleteResults(Sema &S, 
@@ -664,8 +678,9 @@ public:
   /// results to the given raw output stream in a format readable to the CIndex
   /// library.
   CIndexCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns,
-                             llvm::raw_ostream &OS)
-    : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, true), OS(OS) {}
+                             bool IncludeGlobals, llvm::raw_ostream &OS)
+    : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
+                           true), OS(OS) {}
   
   /// \brief Prints the finalized code-completion results.
   virtual void ProcessCodeCompleteResults(Sema &S, 
index 5ef8e5f0700ddc484a62d5255da82c6e17ce9878..a57a5a78c771057186f6317df4684427ec857ec6 100644 (file)
@@ -1486,7 +1486,9 @@ public:
     /// C99 6.2.2p4-5 and C++ [basic.link]p6.
     LookupRedeclarationWithLinkage,
     /// Look up the name of an Objective-C protocol.
-    LookupObjCProtocolName
+    LookupObjCProtocolName,
+    /// \brief Look up any declaration with any name.
+    LookupAnyName
   };
 
   /// \brief Specifies whether (or how) name lookup is being performed for a
@@ -1534,9 +1536,11 @@ public:
                                ADLResult &Functions);
 
   void LookupVisibleDecls(Scope *S, LookupNameKind Kind,
-                          VisibleDeclConsumer &Consumer);
+                          VisibleDeclConsumer &Consumer,
+                          bool IncludeGlobalScope = true);
   void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
-                          VisibleDeclConsumer &Consumer);
+                          VisibleDeclConsumer &Consumer,
+                          bool IncludeGlobalScope = true);
   
   /// \brief The context in which typo-correction occurs.
   ///
index e6bae6b72734b90e9e99961a7c1617d06d90e3e5..8d49d4e786317baeb0fa9484328e3beec48efa35 100644 (file)
@@ -88,6 +88,79 @@ void ASTUnit::CleanTemporaryFiles() {
   TemporaryFiles.clear();
 }
 
+/// \brief Determine the set of code-completion contexts in which this 
+/// declaration should be shown.
+static unsigned getDeclShowContexts(NamedDecl *ND,
+                                    const LangOptions &LangOpts) {
+  if (isa<UsingShadowDecl>(ND))
+    ND = dyn_cast<NamedDecl>(ND->getUnderlyingDecl());
+  if (!ND)
+    return 0;
+  
+  unsigned Contexts = 0;
+  if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) || 
+      isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND)) {
+    // Types can appear in these contexts.
+    if (LangOpts.CPlusPlus || !isa<TagDecl>(ND))
+      Contexts |= (1 << (CodeCompletionContext::CCC_TopLevel - 1))
+                | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
+                | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
+                | (1 << (CodeCompletionContext::CCC_Statement - 1))
+                | (1 << (CodeCompletionContext::CCC_Type - 1));
+
+    // In C++, types can appear in expressions contexts (for functional casts).
+    if (LangOpts.CPlusPlus)
+      Contexts |= (1 << (CodeCompletionContext::CCC_Expression - 1));
+    
+    // In Objective-C, message sends can send interfaces. In Objective-C++,
+    // all types are available due to functional casts.
+    if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))
+      Contexts |= (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
+
+    // Deal with tag names.
+    if (isa<EnumDecl>(ND)) {
+      Contexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1));
+      
+      // Part of the nested-name-specifier.
+      if (LangOpts.CPlusPlus0x)
+        Contexts |= (1 << (CodeCompletionContext::CCC_MemberAccess - 1));
+    } else if (RecordDecl *Record = dyn_cast<RecordDecl>(ND)) {
+      if (Record->isUnion())
+        Contexts |= (1 << (CodeCompletionContext::CCC_UnionTag - 1));
+      else
+        Contexts |= (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
+      
+      // Part of the nested-name-specifier.
+      if (LangOpts.CPlusPlus)
+        Contexts |= (1 << (CodeCompletionContext::CCC_MemberAccess - 1));
+    }
+  } else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
+    // Values can appear in these contexts.
+    Contexts = (1 << (CodeCompletionContext::CCC_Statement - 1))
+             | (1 << (CodeCompletionContext::CCC_Expression - 1))
+             | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
+  } else if (isa<ObjCProtocolDecl>(ND)) {
+    Contexts = (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1));
+  } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {
+    Contexts = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
+             | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
+             | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
+             | (1 << (CodeCompletionContext::CCC_Statement - 1))
+             | (1 << (CodeCompletionContext::CCC_Expression - 1))
+             | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
+             | (1 << (CodeCompletionContext::CCC_Namespace - 1));
+   
+    // Part of the nested-name-specifier.
+    Contexts |= (1 << (CodeCompletionContext::CCC_MemberAccess - 1))
+             | (1 << (CodeCompletionContext::CCC_EnumTag - 1))
+             | (1 << (CodeCompletionContext::CCC_UnionTag - 1))
+             | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1))
+             | (1 << (CodeCompletionContext::CCC_Type - 1));
+  }
+  
+  return Contexts;
+}
+
 void ASTUnit::CacheCodeCompletionResults() {
   if (!TheSema)
     return;
@@ -111,10 +184,17 @@ void ASTUnit::CacheCodeCompletionResults() {
   // Translate global code completions into cached completions.
   for (unsigned I = 0, N = Results.size(); I != N; ++I) {
     switch (Results[I].Kind) {
-    case Result::RK_Declaration:
-      // FIXME: Handle declarations!
+    case Result::RK_Declaration: {
+      CachedCodeCompletionResult CachedResult;
+      CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema);
+      CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration,
+                                                        Ctx->getLangOptions());
+      CachedResult.Priority = Results[I].Priority;
+      CachedResult.Kind = Results[I].CursorKind;
+      CachedCompletionResults.push_back(CachedResult);
       break;
-      
+    }
+        
     case Result::RK_Keyword:
     case Result::RK_Pattern:
       // Ignore keywords and patterns; we don't care, since they are so
@@ -1287,8 +1367,9 @@ namespace {
     
   public:
     AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,
-                                  bool IncludeMacros, bool IncludeCodePatterns)
-      : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns,
+                                  bool IncludeMacros, bool IncludeCodePatterns,
+                                  bool IncludeGlobals)
+      : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
                              Next.isOutputBinary()), AST(AST), Next(Next) 
     { 
       // Compute the set of contexts in which we will look when we don't have
@@ -1387,6 +1468,8 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
   FrontendOpts.ShowMacrosInCodeCompletion
     = IncludeMacros && CachedCompletionResults.empty();
   FrontendOpts.ShowCodePatternsInCodeCompletion = IncludeCodePatterns;
+  FrontendOpts.ShowGlobalSymbolsInCodeCompletion
+    = CachedCompletionResults.empty();
   FrontendOpts.CodeCompletionAt.FileName = File;
   FrontendOpts.CodeCompletionAt.Line = Line;
   FrontendOpts.CodeCompletionAt.Column = Column;
@@ -1447,7 +1530,8 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
   // code-completion results.
   AugmentedCodeCompleteConsumer 
   AugmentedConsumer(*this, Consumer, FrontendOpts.ShowMacrosInCodeCompletion,
-                    FrontendOpts.ShowCodePatternsInCodeCompletion);
+                    FrontendOpts.ShowCodePatternsInCodeCompletion,
+                    FrontendOpts.ShowGlobalSymbolsInCodeCompletion);
   Clang.setCodeCompletionConsumer(&AugmentedConsumer);
 
   // If we have a precompiled preamble, try to use it. We only allow
index 06ec80589c77b1792a129f4dac098e52ac182679..8e1dbcb9d24954cef8b6512a961d12c40ce6c0f2 100644 (file)
@@ -328,6 +328,7 @@ void CompilerInstance::createCodeCompletionConsumer() {
                                    getFrontendOpts().DebugCodeCompletionPrinter,
                                    getFrontendOpts().ShowMacrosInCodeCompletion,
                              getFrontendOpts().ShowCodePatternsInCodeCompletion,
+                           getFrontendOpts().ShowGlobalSymbolsInCodeCompletion,
                                    llvm::outs()));
     if (!CompletionConsumer)
       return;
@@ -356,15 +357,18 @@ CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
                                                bool UseDebugPrinter,
                                                bool ShowMacros,
                                                bool ShowCodePatterns,
+                                               bool ShowGlobals,
                                                llvm::raw_ostream &OS) {
   if (EnableCodeCompletion(PP, Filename, Line, Column))
     return 0;
 
   // Set up the creation routine for code-completion.
   if (UseDebugPrinter)
-    return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns, OS);
+    return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns, 
+                                            ShowGlobals, OS);
   else
-    return new CIndexCodeCompleteConsumer(ShowMacros, ShowCodePatterns, OS);
+    return new CIndexCodeCompleteConsumer(ShowMacros, ShowCodePatterns, 
+                                          ShowGlobals, OS);
 }
 
 void CompilerInstance::createSema(bool CompleteTranslationUnit,
index aa6888bd1d725e23dc366230d6488f2e500dc5a2..5605f16dacee22a27b9b183081d4c146acf868ea 100644 (file)
@@ -363,6 +363,8 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts,
     Res.push_back("-code-completion-macros");
   if (Opts.ShowCodePatternsInCodeCompletion)
     Res.push_back("-code-completion-patterns");
+  if (!Opts.ShowGlobalSymbolsInCodeCompletion)
+    Res.push_back("-no-code-completion-globals");
   if (Opts.ShowStats)
     Res.push_back("-print-stats");
   if (Opts.ShowTimers)
@@ -1047,6 +1049,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
   Opts.ShowMacrosInCodeCompletion = Args.hasArg(OPT_code_completion_macros);
   Opts.ShowCodePatternsInCodeCompletion
     = Args.hasArg(OPT_code_completion_patterns);
+  Opts.ShowGlobalSymbolsInCodeCompletion
+    = !Args.hasArg(OPT_no_code_completion_globals);
   Opts.ShowStats = Args.hasArg(OPT_print_stats);
   Opts.ShowTimers = Args.hasArg(OPT_ftime_report);
   Opts.ShowVersion = Args.hasArg(OPT_version);
index 31185683a1a15d73248a4c8f8a87a750d1c2d9ab..599a10fd90a5f1c4878a3b1f3b2f2b5485e078d4 100644 (file)
@@ -2308,7 +2308,8 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
   }
 
   CodeCompletionDeclConsumer Consumer(Results, CurContext);
-  LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                     CodeCompleter->includeGlobals());
 
   Results.EnterNewScope();
   AddOrdinaryNameResults(CompletionContext, S, *this, Results);
@@ -2340,7 +2341,8 @@ void Sema::CodeCompleteExpression(Scope *S, QualType T,
   Results.setPreferredType(T.getNonReferenceType());
   
   CodeCompletionDeclConsumer Consumer(Results, CurContext);
-  LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                     CodeCompleter->includeGlobals());
   
   Results.EnterNewScope();
   AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
@@ -2432,7 +2434,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
     // Access to a C/C++ class, struct, or union.
     Results.allowNestedNameSpecifiers();
     CodeCompletionDeclConsumer Consumer(Results, CurContext);
-    LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer);
+    LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
+                       CodeCompleter->includeGlobals());
 
     if (getLangOptions().CPlusPlus) {
       if (!Results.empty()) {
@@ -2480,7 +2483,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
     if (Class) {
       CodeCompletionDeclConsumer Consumer(Results, CurContext);
       Results.setFilter(&ResultBuilder::IsObjCIvar);
-      LookupVisibleDecls(Class, LookupMemberName, Consumer);
+      LookupVisibleDecls(Class, LookupMemberName, Consumer,
+                         CodeCompleter->includeGlobals());
     }
   }
   
@@ -2530,11 +2534,14 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
 
   // First pass: look for tags.
   Results.setFilter(Filter);
-  LookupVisibleDecls(S, LookupTagName, Consumer);
+  LookupVisibleDecls(S, LookupTagName, Consumer,
+                     CodeCompleter->includeGlobals());
 
-  // Second pass: look for nested name specifiers.
-  Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
-  LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
+  if (CodeCompleter->includeGlobals()) {
+    // Second pass: look for nested name specifiers.
+    Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
+    LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
+  }
   
   HandleCodeCompleteResults(this, CodeCompleter, ContextKind,
                             Results.data(),Results.size());
@@ -2836,7 +2843,8 @@ void Sema::CodeCompleteUsing(Scope *S) {
   // After "using", we can see anything that would start a 
   // nested-name-specifier.
   CodeCompletionDeclConsumer Consumer(Results, CurContext);
-  LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                     CodeCompleter->includeGlobals());
   Results.ExitScope();
   
   HandleCodeCompleteResults(this, CodeCompleter, 
@@ -2853,10 +2861,11 @@ void Sema::CodeCompleteUsingDirective(Scope *S) {
   ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
   Results.EnterNewScope();
   CodeCompletionDeclConsumer Consumer(Results, CurContext);
-  LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                     CodeCompleter->includeGlobals());
   Results.ExitScope();
   HandleCodeCompleteResults(this, CodeCompleter, 
-                            CodeCompletionContext::CCC_Other,
+                            CodeCompletionContext::CCC_Namespace,
                             Results.data(),Results.size());
 }
 
@@ -2903,9 +2912,10 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S)  {
   // After "namespace", we expect to see a namespace or alias.
   ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
   CodeCompletionDeclConsumer Consumer(Results, CurContext);
-  LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                     CodeCompleter->includeGlobals());
   HandleCodeCompleteResults(this, CodeCompleter, 
-                            CodeCompletionContext::CCC_Other,
+                            CodeCompletionContext::CCC_Namespace,
                             Results.data(),Results.size());
 }
 
@@ -2926,14 +2936,15 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
   // Add any type names visible from the current scope
   Results.allowNestedNameSpecifiers();
   CodeCompletionDeclConsumer Consumer(Results, CurContext);
-  LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                     CodeCompleter->includeGlobals());
   
   // Add any type specifiers
   AddTypeSpecifierResults(getLangOptions(), Results);
   Results.ExitScope();
   
   HandleCodeCompleteResults(this, CodeCompleter, 
-                            CodeCompletionContext::CCC_Other,
+                            CodeCompletionContext::CCC_Type,
                             Results.data(),Results.size());
 }
 
@@ -3514,7 +3525,8 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
   Results.setFilter(&ResultBuilder::IsObjCMessageReceiver);
   CodeCompletionDeclConsumer Consumer(Results, CurContext);
   Results.EnterNewScope();
-  LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                     CodeCompleter->includeGlobals());
   
   // If we are in an Objective-C method inside a class that has a superclass,
   // add "super" as an option.
@@ -4341,13 +4353,12 @@ void Sema::GatherGlobalCodeCompletions(
                  llvm::SmallVectorImpl<CodeCompleteConsumer::Result> &Results) {
   ResultBuilder Builder(*this);
 
-#if 0
-  // FIXME: We need a name lookup that means "look for everything", 
-  CodeCompletionDeclConsumer Consumer(Builder, 
-                                      Context.getTranslationUnitDecl());
-  LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupOrdinaryName, 
-                     Consumer);
-#endif
+  if (!CodeCompleter || CodeCompleter->includeGlobals()) {
+    CodeCompletionDeclConsumer Consumer(Builder, 
+                                        Context.getTranslationUnitDecl());
+    LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName, 
+                       Consumer);
+  }
   
   if (!CodeCompleter || CodeCompleter->includeMacros())
     AddMacroResults(PP, Builder);
index 1ffea89acdaa7b42b9ea9b3ad991a844fdff1b98..994b633db8edd540266a09cc4ada32602dd06622 100644 (file)
@@ -254,6 +254,12 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
   case Sema::LookupObjCProtocolName:
     IDNS = Decl::IDNS_ObjCProtocol;
     break;
+      
+  case Sema::LookupAnyName:
+    IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member 
+      | Decl::IDNS_Using | Decl::IDNS_Namespace | Decl::IDNS_ObjCProtocol
+      | Decl::IDNS_Type;
+    break;
   }
   return IDNS;
 }
@@ -1199,6 +1205,17 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
   return Found;
 }
 
+/// \brief Callback that looks for any member of a class with the given name.
+static bool LookupAnyMember(const CXXBaseSpecifier *Specifier, 
+                            CXXBasePath &Path,
+                            void *Name) {
+  RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+  
+  DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
+  Path.Decls = BaseRecord->lookup(N);
+  return Path.Decls.first != Path.Decls.second;
+}
+
 /// \brief Perform qualified name lookup into a given context.
 ///
 /// Qualified name lookup (C++ [basic.lookup.qual]) is used to find
@@ -1294,6 +1311,10 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
       BaseCallback = &CXXRecordDecl::FindTagMember;
       break;
 
+    case LookupAnyName:
+      BaseCallback = &LookupAnyMember;
+      break;
+      
     case LookupUsingDeclName:
       // This lookup is for redeclarations only.
       
@@ -2223,6 +2244,10 @@ public:
     return !VisitedContexts.insert(Ctx);
   }
 
+  bool alreadyVisitedContext(DeclContext *Ctx) {
+    return VisitedContexts.count(Ctx);
+  }
+
   /// \brief Determine whether the given declaration is hidden in the
   /// current scope.
   ///
@@ -2503,7 +2528,9 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
   if (!S)
     return;
 
-  if (!S->getEntity() || !S->getParent() ||
+  if (!S->getEntity() || 
+      (!S->getParent() && 
+       !Visited.alreadyVisitedContext((DeclContext *)S->getEntity())) ||
       ((DeclContext *)S->getEntity())->isFunctionOrMethod()) {
     // Walk through the declarations in this Scope.
     for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
@@ -2581,7 +2608,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
 }
 
 void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind,
-                              VisibleDeclConsumer &Consumer) {
+                              VisibleDeclConsumer &Consumer,
+                              bool IncludeGlobalScope) {
   // Determine the set of using directives available during
   // unqualified name lookup.
   Scope *Initial = S;
@@ -2598,14 +2626,19 @@ void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind,
   // Look for visible declarations.
   LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
   VisibleDeclsRecord Visited;
+  if (!IncludeGlobalScope)
+    Visited.visitedContext(Context.getTranslationUnitDecl());
   ShadowContextRAII Shadow(Visited);
   ::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited);
 }
 
 void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
-                              VisibleDeclConsumer &Consumer) {
+                              VisibleDeclConsumer &Consumer,
+                              bool IncludeGlobalScope) {
   LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
   VisibleDeclsRecord Visited;
+  if (!IncludeGlobalScope)
+    Visited.visitedContext(Context.getTranslationUnitDecl());
   ShadowContextRAII Shadow(Visited);
   ::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true, 
                        /*InBaseClass=*/false, Consumer, Visited);
index ef19d1484d4600c8d765d4e4ea885aad80a516e0..7dfe280d9e9da6f627a381d7156ab7ee4d49d393 100644 (file)
@@ -19,6 +19,12 @@ const char *str = "Hello, \nWorld";
 // CHECK-CC1-NOT: NotImplemented:{TypedText float} (40)
 // CHECK-CC1: ParmDecl:{ResultType int}{TypedText j} (2)
 // CHECK-CC1: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1a %s
+// FIXME: Priorities aren't right
+// CHECK-CC1a: ParmDecl:{ResultType int}{TypedText j} (2)
+// CHECK-CC1a: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
+// CHECK-CC1a: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50)
+// CHECK-CC1a: macro definition:{TypedText __VERSION__} (70)
 // RUN: c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
 // RUN: env CINDEXTEST_EDITING=1 c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
 // CHECK-CC3: macro definition:{TypedText __VERSION__} (70)
index f0e90212f7fb3227c150812c7c85559be79de131..48bbe7d46bc859ab72a357d77c5331f3ea6d5003 100644 (file)
@@ -547,7 +547,8 @@ namespace {
 
   public:
     explicit CaptureCompletionResults(AllocatedCXCodeCompleteResults &Results)
-      : CodeCompleteConsumer(true, false, false), AllocatedResults(Results) { }
+      : CodeCompleteConsumer(true, false, true, false), 
+        AllocatedResults(Results) { }
 
     virtual void ProcessCodeCompleteResults(Sema &S, 
                                             CodeCompletionContext Context,