forked from OSchip/llvm-project
Switch code-completion for ordinary names over to the new(ish)
LookupVisibleDecls, unifying the name lookup mechanisms used by code completion and typo correction. Aside from the software-engineering improvements, this makes code-completion see through using directives and see ivars when performing unqualified name lookup in an Objective-C instance method. llvm-svn: 93397
This commit is contained in:
parent
a1709fd822
commit
c580c5205f
|
@ -11,6 +11,7 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
#include "Sema.h"
|
#include "Sema.h"
|
||||||
|
#include "Lookup.h"
|
||||||
#include "clang/Sema/CodeCompleteConsumer.h"
|
#include "clang/Sema/CodeCompleteConsumer.h"
|
||||||
#include "clang/AST/ExprCXX.h"
|
#include "clang/AST/ExprCXX.h"
|
||||||
#include "clang/AST/ExprObjC.h"
|
#include "clang/AST/ExprObjC.h"
|
||||||
|
@ -150,11 +151,21 @@ namespace {
|
||||||
/// of the shadow maps), or replace an existing result (for, e.g., a
|
/// of the shadow maps), or replace an existing result (for, e.g., a
|
||||||
/// redeclaration).
|
/// redeclaration).
|
||||||
///
|
///
|
||||||
/// \param R the result to add (if it is unique).
|
/// \param CurContext the result to add (if it is unique).
|
||||||
///
|
///
|
||||||
/// \param R the context in which this result will be named.
|
/// \param R the context in which this result will be named.
|
||||||
void MaybeAddResult(Result R, DeclContext *CurContext = 0);
|
void MaybeAddResult(Result R, DeclContext *CurContext = 0);
|
||||||
|
|
||||||
|
/// \brief Add a new result to this result set, where we already know
|
||||||
|
/// the hiding declation (if any).
|
||||||
|
///
|
||||||
|
/// \param R the result to add (if it is unique).
|
||||||
|
///
|
||||||
|
/// \param CurContext the context in which this result will be named.
|
||||||
|
///
|
||||||
|
/// \param Hiding the declaration that hides the result.
|
||||||
|
void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding);
|
||||||
|
|
||||||
/// \brief Enter into a new scope.
|
/// \brief Enter into a new scope.
|
||||||
void EnterNewScope();
|
void EnterNewScope();
|
||||||
|
|
||||||
|
@ -505,6 +516,52 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
|
||||||
Results.push_back(R);
|
Results.push_back(R);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
|
||||||
|
NamedDecl *Hiding) {
|
||||||
|
assert(R.Kind == Result::RK_Declaration &&
|
||||||
|
"Only declaration results are supported");
|
||||||
|
|
||||||
|
// Look through using declarations.
|
||||||
|
if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
|
||||||
|
AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isInterestingDecl(R.Declaration))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Make sure that any given declaration only shows up in the result set once.
|
||||||
|
if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If the filter is for nested-name-specifiers, then this result starts a
|
||||||
|
// nested-name-specifier.
|
||||||
|
if ((Filter == &ResultBuilder::IsNestedNameSpecifier) ||
|
||||||
|
(Filter == &ResultBuilder::IsMember &&
|
||||||
|
isa<CXXRecordDecl>(R.Declaration) &&
|
||||||
|
cast<CXXRecordDecl>(R.Declaration)->isInjectedClassName()))
|
||||||
|
R.StartsNestedNameSpecifier = true;
|
||||||
|
|
||||||
|
// If this result is supposed to have an informative qualifier, add one.
|
||||||
|
if (R.QualifierIsInformative && !R.Qualifier &&
|
||||||
|
!R.StartsNestedNameSpecifier) {
|
||||||
|
DeclContext *Ctx = R.Declaration->getDeclContext();
|
||||||
|
if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
|
||||||
|
R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
|
||||||
|
else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
|
||||||
|
R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
|
||||||
|
SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
|
||||||
|
else
|
||||||
|
R.QualifierIsInformative = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert this result into the set of results.
|
||||||
|
Results.push_back(R);
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Enter into a new scope.
|
/// \brief Enter into a new scope.
|
||||||
void ResultBuilder::EnterNewScope() {
|
void ResultBuilder::EnterNewScope() {
|
||||||
ShadowMaps.push_back(ShadowMap());
|
ShadowMaps.push_back(ShadowMap());
|
||||||
|
@ -527,7 +584,9 @@ bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
|
||||||
unsigned IDNS = Decl::IDNS_Ordinary;
|
unsigned IDNS = Decl::IDNS_Ordinary;
|
||||||
if (SemaRef.getLangOptions().CPlusPlus)
|
if (SemaRef.getLangOptions().CPlusPlus)
|
||||||
IDNS |= Decl::IDNS_Tag;
|
IDNS |= Decl::IDNS_Tag;
|
||||||
|
else if (SemaRef.getLangOptions().ObjC1 && isa<ObjCIvarDecl>(ND))
|
||||||
|
return true;
|
||||||
|
|
||||||
return ND->getIdentifierNamespace() & IDNS;
|
return ND->getIdentifierNamespace() & IDNS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,6 +668,23 @@ bool ResultBuilder::IsMember(NamedDecl *ND) const {
|
||||||
isa<ObjCPropertyDecl>(ND);
|
isa<ObjCPropertyDecl>(ND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
/// \brief Visible declaration consumer that adds a code-completion result
|
||||||
|
/// for each visible declaration.
|
||||||
|
class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
|
||||||
|
ResultBuilder &Results;
|
||||||
|
DeclContext *CurContext;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
|
||||||
|
: Results(Results), CurContext(CurContext) { }
|
||||||
|
|
||||||
|
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding) {
|
||||||
|
Results.AddResult(ND, CurContext, Hiding);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Find the next outer declaration context corresponding to this scope.
|
// Find the next outer declaration context corresponding to this scope.
|
||||||
static DeclContext *findOuterContext(Scope *S) {
|
static DeclContext *findOuterContext(Scope *S) {
|
||||||
for (S = S->getParent(); S; S = S->getParent())
|
for (S = S->getParent(); S; S = S->getParent())
|
||||||
|
@ -1970,8 +2046,8 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectLookupResults(S, Context.getTranslationUnitDecl(), CurContext,
|
CodeCompletionDeclConsumer Consumer(Results, CurContext);
|
||||||
Results);
|
LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
|
||||||
|
|
||||||
Results.EnterNewScope();
|
Results.EnterNewScope();
|
||||||
AddOrdinaryNameResults(CompletionContext, S, *this, Results);
|
AddOrdinaryNameResults(CompletionContext, S, *this, Results);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* The run lines are below, because this test is line- and
|
/* The run lines are below, because this test is line- and
|
||||||
column-number sensitive. */
|
column-number sensitive. */
|
||||||
@interface MyClass { }
|
@interface MyClass { int ivar; }
|
||||||
- (int)myMethod:(int)arg;
|
- (int)myMethod:(int)arg;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
||||||
// CHECK-CC3: ParmDecl:{ResultType int}{TypedText arg}
|
// CHECK-CC3: ParmDecl:{ResultType int}{TypedText arg}
|
||||||
// CHECK-CC3: TypedefDecl:{TypedText Class}
|
// CHECK-CC3: TypedefDecl:{TypedText Class}
|
||||||
// CHECK-CC3: TypedefDecl:{TypedText id}
|
// CHECK-CC3: TypedefDecl:{TypedText id}
|
||||||
|
// CHECK-CC3: ObjCIvarDecl:{ResultType int}{TypedText ivar}
|
||||||
// CHECK-CC3: ObjCInterfaceDecl:{TypedText MyClass}
|
// CHECK-CC3: ObjCInterfaceDecl:{TypedText MyClass}
|
||||||
// CHECK-CC3: TypedefDecl:{TypedText SEL}
|
// CHECK-CC3: TypedefDecl:{TypedText SEL}
|
||||||
// CHECK-CC3: NotImplemented:{ResultType MyClass *}{TypedText self}
|
// CHECK-CC3: NotImplemented:{ResultType MyClass *}{TypedText self}
|
||||||
|
|
Loading…
Reference in New Issue