[CodeComplete] Teach type context analyzer to handle pattern initializer. rdar://22804344

Swift SVN r32154
This commit is contained in:
Xi Ge
2015-09-22 21:06:58 +00:00
parent 034ec91f1a
commit 3ace989167
3 changed files with 138 additions and 7 deletions

View File

@@ -3209,6 +3209,18 @@ namespace {
Ancestors.pop_back();
return S;
}
bool walkToDeclPre(Decl *D) override {
if (Predicate(D))
Ancestors.push_back(D);
return true;
}
bool walkToDeclPost(Decl *D) override {
if (Predicate(D))
Ancestors.pop_back();
return true;
}
};
}
@@ -3217,11 +3229,12 @@ namespace {
class CodeCompletionTypeContextAnalyzer {
DeclContext *DC;
Expr *ParsedExpr;
SourceManager &SM;
ExprParentFinder Finder;
public:
CodeCompletionTypeContextAnalyzer(DeclContext *DC, Expr *ParsedExpr) : DC(DC),
ParsedExpr(ParsedExpr),
ParsedExpr(ParsedExpr), SM(DC->getASTContext().SourceMgr),
Finder(ParsedExpr, [](ASTNode Node) {
if (auto E = Node.dyn_cast<Expr *>()) {
switch(E->getKind()) {
@@ -3238,6 +3251,13 @@ public:
default:
return false;
}
} else if (auto D = Node.dyn_cast<Decl *>()) {
switch (D->getKind()) {
case DeclKind::PatternBinding:
return true;
default:
return false;
}
} else
return false;
}) {}
@@ -3277,13 +3297,37 @@ public:
}
}
void analyzeDecl(Decl *D, std::vector<Type> &PotentialTypes) {
switch (D->getKind()) {
case DeclKind::PatternBinding: {
auto PBD = cast<PatternBindingDecl>(D);
for (unsigned I = 0; I < PBD->getNumPatternEntries(); ++ I) {
if (auto Init = PBD->getInit(I)) {
if (SM.rangeContains(Init->getSourceRange(), ParsedExpr->getLoc())) {
PotentialTypes.push_back(PBD->getPattern(I)->getType());
break;
}
}
}
break;
}
default:
llvm_unreachable("Unhandled decl kinds.");
}
}
bool Analyze(llvm::SmallVectorImpl<Type> &PossibleTypes) {
// We cannot analyze without target.
if (!ParsedExpr)
return false;
DC->walkContext(Finder);
std::vector<Type> PotentialTypes;
if (auto Parent = Finder.ParentClosest.dyn_cast<Expr*>()) {
analyzeExpr(Parent, PotentialTypes);
} else if (auto Parent = Finder.ParentClosest.dyn_cast<Stmt *>()) {
analyzeStmt(Parent, PotentialTypes);
} else if (auto Parent = Finder.ParentClosest.dyn_cast<Decl *>()) {
analyzeDecl(Parent, PotentialTypes);
}
for (auto Ty : PotentialTypes) {
if (Ty && Ty->getKind() != TypeKind::Error) {
@@ -3379,6 +3423,12 @@ void CodeCompletionCallbacksImpl::doneParsing() {
}
case CompletionKind::PostfixExprBeginning: {
CodeCompletionTypeContextAnalyzer Analyzer(CurDeclContext,
CodeCompleteTokenExpr);
llvm::SmallVector<Type, 1> Types;
if (Analyzer.Analyze(Types)) {
Lookup.setExpectedTypes(Types);
}
DoPostfixExprBeginning();
break;
}