Skip to content

Commit 0c41310

Browse files
committed
[CodeComplete] Skip conjunction elements unrelated to the code completion token
1 parent 48dd99b commit 0c41310

File tree

4 files changed

+76
-9
lines changed

4 files changed

+76
-9
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,15 @@ class ResultBuilderTransform
195195
// Allocate variable with a placeholder type
196196
auto *resultVar = buildPlaceholderVar(stmt->getStartLoc(), newBody);
197197

198+
if (ctx.CompletionCallback && stmt->getSourceRange().isValid() &&
199+
!containsIDEInspectionTarget(stmt->getSourceRange(), ctx.SourceMgr) &&
200+
!isa<GuardStmt>(stmt)) {
201+
// A statement that doesn't contain the code completion expression can't
202+
// influence the type of the code completion expression, so we can skip
203+
// it to improve performance.
204+
return None;
205+
}
206+
198207
auto result = visit(stmt, resultVar);
199208
if (!result)
200209
return UnsupportedElt(stmt);
@@ -223,6 +232,16 @@ class ResultBuilderTransform
223232
// to rank code completion items that match the type expected by
224233
// buildBlock higher.
225234
buildBlockArguments.push_back(expr);
235+
} else if (ctx.CompletionCallback && expr->getSourceRange().isValid() &&
236+
!containsIDEInspectionTarget(expr->getSourceRange(),
237+
ctx.SourceMgr)) {
238+
// A statement that doesn't contain the code completion expression can't
239+
// influence the type of the code completion expression. Add a variable
240+
// for it that we can put into the buildBlock call but don't add the
241+
// expression itself into the transformed body to improve performance.
242+
auto *resultVar = buildPlaceholderVar(expr->getStartLoc(), newBody);
243+
buildBlockArguments.push_back(
244+
builder.buildVarRef(resultVar, expr->getStartLoc()));
226245
} else {
227246
auto *capture = captureExpr(expr, newBody);
228247
// A reference to the synthesized variable is passed as an argument

lib/Sema/CSSyntacticElement.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,17 +1167,26 @@ class SyntacticElementConstraintGenerator
11671167
for (auto element : braceStmt->getElements()) {
11681168
if (cs.isForCodeCompletion() &&
11691169
!cs.containsIDEInspectionTarget(element)) {
1170-
// Statements and expressions can't influence the expresion that
1171-
// contains the code completion token. To improve performance, skip
1172-
// type checking them entirely.
1173-
if (element.is<Expr *>() && !element.isExpr(ExprKind::TypeJoin)) {
1174-
// Type join expressions are not really pure expressions, they kind of
1175-
// declare new type variables and are important to a result builder's
1176-
// structure. Don't skip them.
1177-
continue;
1178-
} else if (element.is<Stmt *>() && !element.isStmt(StmtKind::Guard)) {
1170+
// To improve performance, skip type checking elements that can't
1171+
// influence the code completion token.
1172+
if (element.is<Stmt *>() && !element.isStmt(StmtKind::Guard) && !element.isStmt(StmtKind::Return)) {
1173+
// Statements can't influence the expresion that contains the code
1174+
// completion token.
11791175
// Guard statements might define variables that are used in the code
11801176
// completion expression. Don't skip them.
1177+
// Return statements influence the type of the closure itself. Don't
1178+
// skip them either.
1179+
continue;
1180+
}
1181+
if (element.isExpr(ExprKind::Assign)) {
1182+
// Assignments are also similar to statements and can't influence the
1183+
// code completion token.
1184+
continue;
1185+
}
1186+
if (element.isExpr(ExprKind::Error)) {
1187+
// ErrorExpr can't influcence the expresssion that contains the code
1188+
// completion token. Since they are causing type checking to abort
1189+
// early, just skip them.
11811190
continue;
11821191
}
11831192
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-ide-test -batch-code-completion -source-filename %s -filecheck %raw-FileCheck -completion-output-dir %t
3+
4+
struct MyStruct {
5+
func takeAnotherClosure(_ y: () -> Void) {}
6+
}
7+
8+
func takeClosure(_ x: () -> Void) -> MyStruct {}
9+
10+
func foo() {
11+
takeClosure {
12+
#^COMPLETE^#
13+
}.takeAnotherClosure {
14+
if true {
15+
1
16+
} else {
17+
1
18+
}
19+
}
20+
}
21+
22+
// COMPLETE: Begin completions
23+
// COMPLETE: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct
24+
// COMPLETE: End completions
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-swift-ide-test -batch-code-completion -source-filename %s -filecheck %raw-FileCheck -completion-output-dir %t
2+
3+
func takeClosure(x: () -> Void) {}
4+
func takeString(_ a: String) -> MyStruct {}
5+
6+
struct MyStruct {
7+
func style() {}
8+
}
9+
10+
func foo() {
11+
takeClosure {
12+
takeString("\(1)")
13+
.style(#^COMPLETE^#)
14+
}
15+
}

0 commit comments

Comments
 (0)