зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
9436ed50b0
Коммит
33224e61bf
|
@ -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
|
Загрузка…
Ссылка в новой задаче