Skip to content

Commit a6b9815

Browse files
authored
Merge pull request #32946 from rintaro/ide-completion-rdar65692922
[CodeCompletion] Fast completion inside function builder function
2 parents 500929f + e953e52 commit a6b9815

File tree

5 files changed

+73
-8
lines changed

5 files changed

+73
-8
lines changed

include/swift/AST/Stmt.h

+7
Original file line numberDiff line numberDiff line change
@@ -1353,6 +1353,13 @@ class PoundAssertStmt : public Stmt {
13531353
}
13541354
};
13551355

1356+
inline void simple_display(llvm::raw_ostream &out, Stmt *S) {
1357+
if (S)
1358+
out << Stmt::getKindName(S->getKind());
1359+
else
1360+
out << "(null)";
1361+
};
1362+
13561363
} // end namespace swift
13571364

13581365
#endif // SWIFT_AST_STMT_H

include/swift/AST/TypeCheckRequests.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -1836,7 +1836,8 @@ enum class FunctionBuilderBodyPreCheck : uint8_t {
18361836

18371837
class PreCheckFunctionBuilderRequest
18381838
: public SimpleRequest<PreCheckFunctionBuilderRequest,
1839-
FunctionBuilderBodyPreCheck(AnyFunctionRef),
1839+
FunctionBuilderBodyPreCheck(AnyFunctionRef,
1840+
BraceStmt *),
18401841
RequestFlags::Cached> {
18411842
public:
18421843
using SimpleRequest::SimpleRequest;
@@ -1845,8 +1846,8 @@ class PreCheckFunctionBuilderRequest
18451846
friend SimpleRequest;
18461847

18471848
// Evaluation.
1848-
FunctionBuilderBodyPreCheck
1849-
evaluate(Evaluator &evaluator, AnyFunctionRef fn) const;
1849+
FunctionBuilderBodyPreCheck evaluate(Evaluator &evaluator, AnyFunctionRef fn,
1850+
BraceStmt *body) const;
18501851

18511852
public:
18521853
// Separate caching.

include/swift/AST/TypeCheckerTypeIDZone.def

+1-1
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ SWIFT_REQUEST(TypeChecker, HasUserDefinedDesignatedInitRequest,
231231
SWIFT_REQUEST(TypeChecker, HasMemberwiseInitRequest,
232232
bool(StructDecl *), Cached, NoLocationInfo)
233233
SWIFT_REQUEST(TypeChecker, PreCheckFunctionBuilderRequest,
234-
FunctionBuilderClosurePreCheck(AnyFunctionRef),
234+
FunctionBuilderClosurePreCheck(AnyFunctionRef, BraceStmt *),
235235
Cached, NoLocationInfo)
236236
SWIFT_REQUEST(TypeChecker, ResolveImplicitMemberRequest,
237237
evaluator::SideEffect(NominalTypeDecl *, ImplicitMemberAction),

lib/Sema/BuilderTransform.cpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -1464,7 +1464,7 @@ Optional<BraceStmt *> TypeChecker::applyFunctionBuilderBodyTransform(
14641464
// If we encountered an error or there was an explicit result type,
14651465
// bail out and report that to the caller.
14661466
auto &ctx = func->getASTContext();
1467-
auto request = PreCheckFunctionBuilderRequest{func};
1467+
auto request = PreCheckFunctionBuilderRequest{func, func->getBody()};
14681468
switch (evaluateOrDefault(
14691469
ctx.evaluator, request, FunctionBuilderBodyPreCheck::Error)) {
14701470
case FunctionBuilderBodyPreCheck::Okay:
@@ -1592,7 +1592,7 @@ ConstraintSystem::matchFunctionBuilder(
15921592

15931593
// Pre-check the body: pre-check any expressions in it and look
15941594
// for return statements.
1595-
auto request = PreCheckFunctionBuilderRequest{fn};
1595+
auto request = PreCheckFunctionBuilderRequest{fn, fn.getBody()};
15961596
switch (evaluateOrDefault(getASTContext().evaluator, request,
15971597
FunctionBuilderBodyPreCheck::Error)) {
15981598
case FunctionBuilderBodyPreCheck::Okay:
@@ -1755,8 +1755,14 @@ class PreCheckFunctionBuilderApplication : public ASTWalker {
17551755
}
17561756

17571757
FunctionBuilderBodyPreCheck
1758-
PreCheckFunctionBuilderRequest::evaluate(Evaluator &eval,
1759-
AnyFunctionRef fn) const {
1758+
PreCheckFunctionBuilderRequest::evaluate(Evaluator &eval, AnyFunctionRef fn,
1759+
BraceStmt *body) const {
1760+
// NOTE: 'body' is passed only for the request evaluater caching key.
1761+
// Since source tooling (e.g. code completion) might replace the body,
1762+
// the function alone is not sufficient for the key.
1763+
assert(fn.getBody() == body &&
1764+
"body must be the current body of the function");
1765+
17601766
// We don't want to do the precheck if it will already have happened in
17611767
// the enclosing expression.
17621768
bool skipPrecheck = false;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
protocol Entity {}
2+
struct Empty: Entity {
3+
var value: Void = ()
4+
}
5+
6+
@_functionBuilder
7+
struct Builder {
8+
static func buildBlock() -> { Empty() }
9+
static func buildBlock<T: Entity>(_ t: T) -> T { t }
10+
}
11+
12+
struct MyValue {
13+
var id: Int
14+
var title: String
15+
}
16+
17+
func build(_ arg: (MyValue) -> String) -> Empty { Empty() }
18+
19+
struct MyStruct {
20+
@Builder var body: some Entity {
21+
build { value in
22+
value./*HERE * 2*/
23+
} /*HERE*/
24+
}
25+
}
26+
27+
// RUN: %sourcekitd-test \
28+
// RUN: -req=complete -pos=22:13 %s -- %s == \
29+
// RUN: -req=complete -pos=22:13 %s -- %s == \
30+
// RUN: -req=complete -pos=23:7 %s -- %s \
31+
// RUN: | tee %t.result | %FileCheck %s
32+
33+
// CHECK-LABEL: key.results: [
34+
// CHECK-DAG: key.description: "id"
35+
// CHECK-DAG: key.description: "title"
36+
// CHECK-DAG: key.description: "self"
37+
// CHECK: ]
38+
// CHECK-NOT: key.reusingastcontext: 1
39+
40+
// CHECK-LABEL: key.results: [
41+
// CHECK-DAG: key.description: "id"
42+
// CHECK-DAG: key.description: "title"
43+
// CHECK-DAG: key.description: "self"
44+
// CHECK: ]
45+
// CHECK: key.reusingastcontext: 1
46+
47+
// CHECK-LABEL: key.results: [
48+
// CHECK-DAG: key.description: "value"
49+
// CHECK: ]
50+
// CHECK: key.reusingastcontext: 1
51+

0 commit comments

Comments
 (0)