Skip to content

Commit d38e714

Browse files
authored
Merge pull request swiftlang#18284 from rintaro/ide-semaannotator-rdar41147733
[IDE] Handle OpenExistentialExpr in SemaAnnotator
2 parents 6290d9b + f4fc479 commit d38e714

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed

lib/IDE/SourceEntityWalker.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class SemaAnnotator : public ASTWalker {
3333
SourceEntityWalker &SEWalker;
3434
SmallVector<ConstructorRefCallExpr *, 2> CtorRefs;
3535
SmallVector<ExtensionDecl *, 2> ExtDecls;
36+
llvm::SmallDenseMap<OpaqueValueExpr *, Expr *, 4> OpaqueValueMap;
3637
bool Cancelled = false;
3738
Optional<AccessKind> OpAccess;
3839

@@ -260,6 +261,10 @@ std::pair<bool, Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
260261

261262
if (!isa<InOutExpr>(E) &&
262263
!isa<LoadExpr>(E) &&
264+
!isa<OpenExistentialExpr>(E) &&
265+
!isa<MakeTemporarilyEscapableExpr>(E) &&
266+
!isa<CollectionUpcastConversionExpr>(E) &&
267+
!isa<OpaqueValueExpr>(E) &&
263268
E->isImplicit())
264269
return { true, E };
265270

@@ -422,6 +427,53 @@ std::pair<bool, Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
422427
if (!walkToExprPost(E))
423428
return { false, nullptr };
424429
return { false, E };
430+
} else if (auto OEE = dyn_cast<OpenExistentialExpr>(E)) {
431+
// Record opaque value.
432+
OpaqueValueMap[OEE->getOpaqueValue()] = OEE->getExistentialValue();
433+
SWIFT_DEFER {
434+
OpaqueValueMap.erase(OEE->getOpaqueValue());
435+
};
436+
437+
if (!OEE->getSubExpr()->walk(*this))
438+
return { false, nullptr };
439+
if (!walkToExprPost(E))
440+
return { false, nullptr };
441+
return { false, E };
442+
} else if (auto MTEE = dyn_cast<MakeTemporarilyEscapableExpr>(E)) {
443+
// Manually walk to original arguments in order. We don't handle
444+
// OpaqueValueExpr here.
445+
446+
// Original non-escaping closure.
447+
if (!MTEE->getNonescapingClosureValue()->walk(*this))
448+
return { false, nullptr };
449+
450+
// Body, which is called by synthesized CallExpr.
451+
auto *callExpr = cast<CallExpr>(MTEE->getSubExpr());
452+
if (!callExpr->getFn()->walk(*this))
453+
return { false, nullptr };
454+
455+
if (!walkToExprPost(E))
456+
return { false, nullptr };
457+
return { false, E };
458+
} else if (auto CUCE = dyn_cast<CollectionUpcastConversionExpr>(E)) {
459+
// Ignore conversion expressions. We don't handle OpaqueValueExpr here
460+
// because it's only in conversion expressions. Instead, just walk into
461+
// sub expression.
462+
if (!CUCE->getSubExpr()->walk(*this))
463+
return { false, nullptr };
464+
if (!walkToExprPost(E))
465+
return { false, nullptr };
466+
return { false, E };
467+
} else if (auto OVE = dyn_cast<OpaqueValueExpr>(E)) {
468+
// Walk into mapped value.
469+
auto value = OpaqueValueMap.find(OVE);
470+
if (value != OpaqueValueMap.end()) {
471+
if (!value->second->walk(*this))
472+
return { false, nullptr };
473+
if (!walkToExprPost(E))
474+
return { false, nullptr };
475+
return { false, E };
476+
}
425477
}
426478

427479
return { true, E };

test/IDE/range_info_expr.swift

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,19 @@ func foo1(_ c : CC) -> CC{
2424
return c.getSelf()
2525
}
2626

27+
protocol Foo {
28+
var bar: String { get }
29+
}
30+
func foo(x: Foo) {
31+
_ = x.bar
32+
}
33+
34+
func testWithoutActuallyEscaping(closure: (Int) -> Void) {
35+
withoutActuallyEscaping(closure) { escapable in
36+
_ = escapable
37+
}
38+
}
39+
2740
// RUN: %target-swift-ide-test -range -pos=7:8 -end-pos=7:19 -source-filename %s | %FileCheck %s -check-prefix=CHECK-BOOL
2841
// CHECK-BOOL: <Type>Bool</Type>
2942

@@ -37,6 +50,12 @@ func foo1(_ c : CC) -> CC{
3750
// RUN: %target-swift-ide-test -range -pos=23:20 -end-pos=23:30 -source-filename %s | %FileCheck %s -check-prefix=CHECK-PART-EXPR1
3851
// RUN: %target-swift-ide-test -range -pos=23:9 -end-pos=23:19 -source-filename %s | %FileCheck %s -check-prefix=CHECK-PART-EXPR1
3952

53+
// RUN: %target-swift-ide-test -range -pos=31:7 -end-pos=31:12 -source-filename %s | %FileCheck %s -check-prefix=CHECK-OEE-EXPR
54+
55+
// RUN: %target-swift-ide-test -range -pos=35:1 -end-pos=38:1 -source-filename %s | %FileCheck %s -check-prefix=CHECK-MTEE-EXPR-1
56+
// RUN: %target-swift-ide-test -range -pos=35:27 -end-pos=35:34 -source-filename %s | %FileCheck %s -check-prefix=CHECK-MTEE-EXPR-2
57+
// RUN: %target-swift-ide-test -range -pos=35:36 -end-pos=37:4 -source-filename %s | %FileCheck %s -check-prefix=CHECK-MTEE-EXPR-3
58+
4059
// CHECK-PART-EXPR: <Kind>PartOfExpression</Kind>
4160
// CHECK-PART-EXPR-NEXT: <Content>getSelf()</Content>
4261
// CHECK-PART-EXPR-NEXT: <Context>swift_ide_test.(file).foo1(_:)</Context>
@@ -50,3 +69,41 @@ func foo1(_ c : CC) -> CC{
5069
// CHECK-PART-EXPR2: <Parent>Call</Parent>
5170
// CHECK-PART-EXPR2: <ASTNodes>2</ASTNodes>
5271
// CHECK-PART-EXPR2: <end>
72+
73+
// CHECK-OEE-EXPR: <Kind>SingleExpression</Kind>
74+
// CHECK-OEE-EXPR-NEXT: <Content>x.bar</Content>
75+
// CHECK-OEE-EXPR-NEXT: <Type>String</Type><Exit>false</Exit>
76+
// CHECK-OEE-EXPR-NEXT: <Context>swift_ide_test.(file).foo(x:)</Context>
77+
// CHECK-OEE-EXPR-NEXT: <ASTNodes>1</ASTNodes>
78+
// CHECK-OEE-EXPR-NEXT: <end>
79+
80+
// CHECK-MTEE-EXPR-1: <Kind>SingleExpression</Kind>
81+
// CHECK-MTEE-EXPR-1-NEXT: <Content>withoutActuallyEscaping(closure) { escapable in
82+
// CHECK-MTEE-EXPR-1-NEXT: _ = escapable
83+
// CHECK-MTEE-EXPR-1-NEXT: }</Content>
84+
// CHECK-MTEE-EXPR-1-NEXT: <Type>()</Type><Exit>false</Exit>
85+
// CHECK-MTEE-EXPR-1-NEXT: <Context>swift_ide_test.(file).testWithoutActuallyEscaping(closure:)</Context>
86+
// CHECK-MTEE-EXPR-1-NEXT: <Declared>escapable</Declared><OutscopeReference>false</OutscopeReference>
87+
// CHECK-MTEE-EXPR-1-NEXT: <Referenced>closure</Referenced><Type>(Int) -> Void</Type>
88+
// CHECK-MTEE-EXPR-1-NEXT: <Referenced>escapable</Referenced><Type>(Int) -> Void</Type>
89+
// CHECK-MTEE-EXPR-1-NEXT: <ASTNodes>1</ASTNodes>
90+
// CHECK-MTEE-EXPR-1-NEXT: <end>
91+
92+
// CHECK-MTEE-EXPR-2: <Kind>SingleExpression</Kind>
93+
// CHECK-MTEE-EXPR-2-NEXT: <Content>closure</Content>
94+
// CHECK-MTEE-EXPR-2-NEXT: <Type>(Int) -> Void</Type><Exit>false</Exit>
95+
// CHECK-MTEE-EXPR-2-NEXT: <Context>swift_ide_test.(file).testWithoutActuallyEscaping(closure:)</Context>
96+
// CHECK-MTEE-EXPR-2-NEXT: <Referenced>closure</Referenced><Type>(Int) -> Void</Type>
97+
// CHECK-MTEE-EXPR-2-NEXT: <ASTNodes>1</ASTNodes>
98+
// CHECK-MTEE-EXPR-2-NEXT: <end>
99+
100+
// CHECK-MTEE-EXPR-3: <Kind>SingleExpression</Kind>
101+
// CHECK-MTEE-EXPR-3-NEXT: <Content>{ escapable in
102+
// CHECK-MTEE-EXPR-3-NEXT: _ = escapable
103+
// CHECK-MTEE-EXPR-3-NEXT: }</Content>
104+
// CHECK-MTEE-EXPR-3-NEXT: <Type>((Int) -> Void) -> ()</Type><Exit>false</Exit>
105+
// CHECK-MTEE-EXPR-3-NEXT: <Context>swift_ide_test.(file).testWithoutActuallyEscaping(closure:)</Context>
106+
// CHECK-MTEE-EXPR-3-NEXT: <Declared>escapable</Declared><OutscopeReference>false</OutscopeReference>
107+
// CHECK-MTEE-EXPR-3-NEXT: <Referenced>escapable</Referenced><Type>(Int) -> Void</Type>
108+
// CHECK-MTEE-EXPR-3-NEXT: <ASTNodes>1</ASTNodes>
109+
// CHECK-MTEE-EXPR-3-NEXT: <end>

0 commit comments

Comments
 (0)