]> granicus.if.org Git - clang/commitdiff
Implement name hiding of cached global code-completion results.
authorDouglas Gregor <dgregor@apple.com>
Mon, 16 Aug 2010 21:18:39 +0000 (21:18 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 16 Aug 2010 21:18:39 +0000 (21:18 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111184 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Frontend/ASTUnit.h
lib/Frontend/ASTUnit.cpp
test/Index/complete-hiding.c [new file with mode: 0644]

index 77a641a2c5d036ab0b9a96bbead4fe69c7f604bf..d0c08a08fff935f9aaaed1d95c62da8ea457c17b 100644 (file)
@@ -25,6 +25,7 @@
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/System/Path.h"
 #include "llvm/Support/Timer.h"
 #include <map>
index 2c827e41da8e14e62fca804e294f1ccd12e80583..f8dea65d5416ad4f02bd64e555ca511d2c172672 100644 (file)
@@ -1435,15 +1435,85 @@ namespace {
   };
 }
 
+/// \brief Helper function that computes which global names are hidden by the
+/// local code-completion results.
+void CalculateHiddenNames(const CodeCompletionContext &Context,
+                          CodeCompleteConsumer::Result *Results,
+                          unsigned NumResults,
+                          ASTContext &Ctx,
+                          llvm::StringSet<> &HiddenNames) {
+  bool OnlyTagNames = false;
+  switch (Context.getKind()) {
+  case CodeCompletionContext::CCC_Other:
+  case CodeCompletionContext::CCC_TopLevel:
+  case CodeCompletionContext::CCC_ObjCInterface:
+  case CodeCompletionContext::CCC_ObjCImplementation:
+  case CodeCompletionContext::CCC_ObjCIvarList:
+  case CodeCompletionContext::CCC_ClassStructUnion:
+  case CodeCompletionContext::CCC_Statement:
+  case CodeCompletionContext::CCC_Expression:
+  case CodeCompletionContext::CCC_ObjCMessageReceiver:
+  case CodeCompletionContext::CCC_MemberAccess:
+  case CodeCompletionContext::CCC_Namespace:
+  case CodeCompletionContext::CCC_Type:
+    break;
+    
+  case CodeCompletionContext::CCC_EnumTag:
+  case CodeCompletionContext::CCC_UnionTag:
+  case CodeCompletionContext::CCC_ClassOrStructTag:
+    OnlyTagNames = true;
+    break;
+    
+  case CodeCompletionContext::CCC_ObjCProtocolName:
+    // If we're just looking for protocol names, nothing can hide them.
+    return;
+  }
+  
+  typedef CodeCompleteConsumer::Result Result;
+  for (unsigned I = 0; I != NumResults; ++I) {
+    if (Results[I].Kind != Result::RK_Declaration)
+      continue;
+    
+    unsigned IDNS
+      = Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace();
+
+    bool Hiding = false;
+    if (OnlyTagNames)
+      Hiding = (IDNS & Decl::IDNS_Tag);
+    else {
+      unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member | 
+                            Decl::IDNS_Namespace | Decl::IDNS_Ordinary |
+                            Decl::IDNS_NonMemberOperator);
+      if (Ctx.getLangOptions().CPlusPlus)
+        HiddenIDNS |= Decl::IDNS_Tag;
+      Hiding = (IDNS & HiddenIDNS);
+    }
+  
+    if (!Hiding)
+      continue;
+    
+    DeclarationName Name = Results[I].Declaration->getDeclName();
+    if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo())
+      HiddenNames.insert(Identifier->getName());
+    else
+      HiddenNames.insert(Name.getAsString());
+  }
+}
+
+
 void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
                                             CodeCompletionContext Context,
                                             Result *Results,
                                             unsigned NumResults) { 
   // Merge the results we were given with the results we cached.
   bool AddedResult = false;
-  unsigned InContexts = 
-  (Context.getKind() == CodeCompletionContext::CCC_Other? NormalContexts
-   : (1 << (Context.getKind() - 1)));
+  unsigned InContexts  
+    = (Context.getKind() == CodeCompletionContext::CCC_Other? NormalContexts
+                                            : (1 << (Context.getKind() - 1)));
+
+  // Contains the set of names that are hidden by "local" completion results.
+  llvm::StringSet<> HiddenNames;
+  
   typedef CodeCompleteConsumer::Result Result;
   llvm::SmallVector<Result, 8> AllResults;
   for (ASTUnit::cached_completion_iterator 
@@ -1457,10 +1527,18 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
     
     // If we haven't added any results previously, do so now.
     if (!AddedResult) {
+      CalculateHiddenNames(Context, Results, NumResults, S.Context, 
+                           HiddenNames);
       AllResults.insert(AllResults.end(), Results, Results + NumResults);
       AddedResult = true;
     }
     
+    // Determine whether this global completion result is hidden by a local
+    // completion result. If so, skip it.
+    if (C->Kind != CXCursor_MacroDefinition &&
+        HiddenNames.count(C->Completion->getTypedText()))
+      continue;
+    
     // Adjust priority based on similar type classes.
     unsigned Priority = C->Priority;
     if (!Context.getPreferredType().isNull()) {
diff --git a/test/Index/complete-hiding.c b/test/Index/complete-hiding.c
new file mode 100644 (file)
index 0000000..0505abf
--- /dev/null
@@ -0,0 +1,29 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+struct StructA { };
+struct StructB { };
+struct StructC { };
+int ValueA;
+int ValueB;
+
+void f() {
+
+  int ValueA = 0;
+  int StructA = 0;
+  struct StructB { };
+  
+  struct StructA sa = { };
+}
+
+// RUN: c-index-test -code-completion-at=%s:16:3 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:16:3 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: VarDecl:{ResultType int}{TypedText StructA} (8)
+// CHECK-CC1: VarDecl:{ResultType int}{TypedText ValueA} (8)
+// CHECK-CC1-NOT: VarDecl:{ResultType int}{TypedText ValueA} (50)
+// CHECK-CC1: VarDecl:{ResultType int}{TypedText ValueB} (50)
+// RUN: c-index-test -code-completion-at=%s:16:10 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: StructDecl:{TypedText StructA} (40)
+// CHECK-CC2-NOT: StructDecl:{TypedText StructB} (40)
+// CHECK-CC2: StructDecl:{TypedText StructC} (40)
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:16:10 %s | FileCheck -check-prefix=CHECK-CC2 %s