For code completion in C++ member access expressions and tag names,

look into the current scope for anything that could start a
nested-names-specifier. These results are ranked worse than any of the
results actually found in the lexical scope.

Perform a little more pruning of the result set, eliminating
constructors, __va_list_tag, and any duplication of declarations in
the result set. For the latter, implemented
NamespaceDecl::getCanonicalDecl.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82231 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2009-09-18 17:42:29 +00:00
Родитель 9436ed50b0
Коммит 33224e61bf
4 изменённых файлов: 61 добавлений и 9 удалений

Просмотреть файл

@ -201,6 +201,8 @@ public:
}
void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; }
virtual NamespaceDecl *getCanonicalDecl() { return OrigNamespace; }
virtual SourceRange getSourceRange() const {
return SourceRange(getLocation(), RBracLoc);
}

Просмотреть файл

@ -15,6 +15,7 @@
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/SmallPtrSet.h"
#include <list>
#include <map>
#include <vector>
@ -25,6 +26,7 @@ class raw_ostream;
namespace clang {
class Decl;
class DeclContext;
class NamedDecl;
class Scope;
@ -89,6 +91,11 @@ public:
/// \brief The actual results we have found.
std::vector<Result> Results;
/// \brief A record of all of the declarations we have found and placed
/// into the result set, used to ensure that no declaration ever gets into
/// the result set twice.
llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
/// \brief A mapping from declaration names to the declarations that have
/// this name within a particular scope and their index within the list of
/// results.

Просмотреть файл

@ -53,8 +53,10 @@ CodeCompleteConsumer::CodeCompleteMemberReferenceExpr(Scope *S,
// The "template" keyword can follow "->" or "." in the grammar.
Results.MaybeAddResult(Result("template", NextRank++));
// FIXME: For C++, we also need to look into the current scope, since
// we could have the start of a nested-name-specifier.
// We could have the start of a nested-name-specifier. Add those
// results as well.
Results.setFilter(&CodeCompleteConsumer::IsNestedNameSpecifier);
CollectLookupResults(S, NextRank, Results);
}
// Hand off the results found for code completion.
@ -83,10 +85,14 @@ void CodeCompleteConsumer::CodeCompleteTag(Scope *S, ElaboratedType::TagKind TK)
}
ResultSet Results(*this, Filter);
CollectLookupResults(S, 0, Results);
unsigned NextRank = CollectLookupResults(S, 0, Results);
// FIXME: In C++, we could have the start of a nested-name-specifier.
// Add those results (with a poorer rank, naturally).
if (getSema().getLangOptions().CPlusPlus) {
// We could have the start of a nested-name-specifier. Add those
// results as well.
Results.setFilter(&CodeCompleteConsumer::IsNestedNameSpecifier);
CollectLookupResults(S, NextRank, Results);
}
ProcessCodeCompleteResults(Results.data(), Results.size());
}
@ -121,10 +127,6 @@ void CodeCompleteConsumer::ResultSet::MaybeAddResult(Result R) {
// FIXME: Using declarations
// FIXME: Separate overload sets
// Filter out any unwanted results.
if (Filter && !(Completer.*Filter)(R.Declaration))
return;
Decl *CanonDecl = R.Declaration->getCanonicalDecl();
unsigned IDNS = CanonDecl->getIdentifierNamespace();
@ -134,6 +136,23 @@ void CodeCompleteConsumer::ResultSet::MaybeAddResult(Result R) {
(IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend)))
return;
if (const IdentifierInfo *Id = R.Declaration->getIdentifier()) {
// __va_list_tag is a freak of nature. Find it and skip it.
if (Id->isStr("__va_list_tag"))
return;
// FIXME: Should we filter out other names in the implementation's
// namespace, e.g., those containing a __ or that start with _[A-Z]?
}
// C++ constructors are never found by name lookup.
if (isa<CXXConstructorDecl>(CanonDecl))
return;
// Filter out any unwanted results.
if (Filter && !(Completer.*Filter)(R.Declaration))
return;
ShadowMap &SMap = ShadowMaps.back();
ShadowMap::iterator I, IEnd;
for (llvm::tie(I, IEnd) = SMap.equal_range(R.Declaration->getDeclName());
@ -187,6 +206,10 @@ void CodeCompleteConsumer::ResultSet::MaybeAddResult(Result R) {
}
}
// Make sure that any given declaration only shows up in the result set once.
if (!AllDeclsFound.insert(CanonDecl))
return;
// Insert this result into the set of results and into the current shadow
// map.
SMap.insert(std::make_pair(R.Declaration->getDeclName(),

Просмотреть файл

@ -0,0 +1,20 @@
// RUN: clang-cc -fsyntax-only -code-completion-dump=1 %s -o - | FileCheck -check-prefix=CC1 %s &&
// RUN: true
class X { };
struct Y { };
namespace N {
template<typename> class Z;
}
namespace N {
class Y;
void test() {
// CHECK-CC1: Y : 2
// CHECK-CC1: Z : 2
// CHECK-CC1: X : 3
// CHECK-CC1: Y : 3
// CHECK-CC1: N : 6
class