[CodeComplete] Perform function name lookup to complete unresolved members.

For completing unresolved members, if constraint solver does not have solutions, we
look up the function names appearing in the same line of the code completion tokens,
and use their parameters that are of enum/optionset type to deliver the code
completion results.

Swift SVN r31256
This commit is contained in:
Xi Ge
2015-08-15 20:34:38 +00:00
parent 11376ca335
commit 5f8c122a79
2 changed files with 99 additions and 3 deletions

View File

@@ -696,6 +696,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
};
UnresolvedMemberExpr *UnresolvedExpr;
std::vector<std::string> TokensBeforeUnresolvedExpr;
CompletionKind Kind = CompletionKind::None;
Expr *ParsedExpr = nullptr;
SourceLoc DotLoc;
@@ -2114,6 +2115,63 @@ public:
RequestedCachedResults = RequestedResultsTy::toplevelResults();
}
class LookupFuncByName : public swift::VisibleDeclConsumer {
CompletionLookup &Lookup;
std::vector<std::string> &SortedFuncNames;
llvm::SmallPtrSet<Decl*, 3> HandledDecls;
bool isNameHit(StringRef Name) {
return std::binary_search(SortedFuncNames.begin(), SortedFuncNames.end(),
Name);
}
void collectFuncTypes(FuncDecl *FD) {
if (isNameHit(FD->getNameStr()) && FD->getType() &&
FD-> getType()->is<FunctionType>()) {
unboxType(FD->getType()->getAs<FunctionType>()->getInput());
unboxType(FD->getType()->getAs<FunctionType>()->getResult());
}
}
void unboxType(Type T) {
if (T->getKind() == TypeKind::Paren) {
unboxType(T->getDesugaredType());
} else if (T->getKind() == TypeKind::Tuple) {
for (auto Ele : T->getAs<TupleType>()->getElements()) {
unboxType(Ele.getType());
}
} else if (auto NTD = T->getNominalOrBoundGenericNominal()){
if (HandledDecls.count(NTD) == 0) {
auto Reason = DeclVisibilityKind::MemberOfCurrentNominal;
if (!Lookup.handleEnumElement(NTD, Reason)) {
Lookup.handleOptionSetType(NTD, Reason);
}
HandledDecls.insert(NTD);
}
}
}
public:
LookupFuncByName(CompletionLookup &Lookup,
std::vector<std::string> &SortedFuncNames) :
Lookup(Lookup), SortedFuncNames(SortedFuncNames) {
std::sort(SortedFuncNames.begin(), SortedFuncNames.end());
}
void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason) override {
if (auto FD = dyn_cast<FuncDecl>(VD)) {
collectFuncTypes(FD);
}
if (auto NTD = dyn_cast<NominalTypeDecl>(VD)) {
for (auto M : NTD->getMembers()) {
if (auto FD = dyn_cast<FuncDecl>(M)) {
collectFuncTypes(FD);
}
}
}
}
};
void getUnresolvedMemberCompletions(SourceLoc Loc, SmallVectorImpl<Type> &Types) {
NeedLeadingDot = !HaveDot;
for (auto T : Types) {
@@ -2126,6 +2184,13 @@ public:
}
}
void getUnresolvedMemberCompletions(SourceLoc Loc,
std::vector<std::string> &FuncNames) {
NeedLeadingDot = !HaveDot;
LookupFuncByName Lookup(*this, FuncNames);
lookupVisibleDecls(Lookup, CurrDeclContext, TypeResolver.get(), true);
}
void getTypeContextEnumElementCompletions(SourceLoc Loc) {
llvm::SaveAndRestore<LookupKind> ChangeLookupKind(
Kind, LookupKind::EnumElement);
@@ -2565,6 +2630,9 @@ void CodeCompletionCallbacksImpl::completeUnresolvedMember(UnresolvedMemberExpr
Kind = CompletionKind::UnresolvedMember;
CurDeclContext = P.CurDeclContext;
UnresolvedExpr = E;
for (auto Id : Identifiers) {
TokensBeforeUnresolvedExpr.push_back(Id);
}
}
void CodeCompletionCallbacksImpl::completeNominalMemberBeginning(
@@ -2900,12 +2968,18 @@ void CodeCompletionCallbacksImpl::doneParsing() {
ExprParentFinder Walker(CurDeclContext->getASTContext().SourceMgr,
UnresolvedExpr, [&](Expr* E) { return true; });
CurDeclContext->walkContext(Walker);
bool Success = false;
if(Walker.ParentExprFarthest) {
typeCheckUnresolvedMember(*CurDeclContext, UnresolvedExpr,
Walker.ParentExprFarthest, PossibleTypes);
Success = typeCheckUnresolvedMember(*CurDeclContext, UnresolvedExpr,
Walker.ParentExprFarthest,
PossibleTypes);
Lookup.getUnresolvedMemberCompletions(
P.Context.SourceMgr.getCodeCompletionLoc(), PossibleTypes);
}
if (!Success) {
Lookup.getUnresolvedMemberCompletions(
P.Context.SourceMgr.getCodeCompletionLoc(), TokensBeforeUnresolvedExpr);
}
break;
}
}