Skip to content

Commit c547e68

Browse files
author
Nathan Hawes
committed
[test] Add more index/refactoring/cursor-info tests for property wrappers
Make sure they handle the case when a property wrapper type's constructor is called with the first argument coming from the var initializer, and the rest from the custom attribute's argument.
1 parent c7e8b3f commit c547e68

File tree

7 files changed

+99
-4
lines changed

7 files changed

+99
-4
lines changed

lib/IDE/SourceEntityWalker.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,8 +552,11 @@ std::pair<bool, Pattern *> SemaAnnotator::walkToPatternPre(Pattern *P) {
552552
}
553553

554554
bool SemaAnnotator::handleCustomAttributes(Decl *D) {
555+
// CustomAttrs of non-param VarDecls are handled when this method is called
556+
// on their containing PatternBindingDecls (see below).
555557
if (isa<VarDecl>(D) && !isa<ParamDecl>(D))
556558
return true;
559+
557560
if (auto *PBD = dyn_cast<PatternBindingDecl>(D)) {
558561
if (auto *SingleVar = PBD->getSingleVar()) {
559562
D = SingleVar;

lib/Index/Index.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -495,9 +495,9 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
495495
}
496496

497497
Decl *getContainingDecl() const {
498-
auto Containers = (SymbolRoleSet)SymbolRole::Definition | (SymbolRoleSet)SymbolRole::Declaration;
499498
for (const auto &Entity: EntitiesStack) {
500-
if (isa<AbstractFunctionDecl>(Entity.D) && (Entity.Roles & Containers)) {
499+
if (isa<AbstractFunctionDecl>(Entity.D) &&
500+
(Entity.Roles & (SymbolRoleSet)SymbolRole::Definition)) {
501501
return Entity.D;
502502
}
503503
}

test/Index/property_wrappers.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public struct HasWrappers {
2424
@Wrapper
2525
// CHECK: [[@LINE-1]]:4 | struct/Swift | Wrapper | [[Wrapper_USR]] | Ref | rel: 0
2626
public var x: Int = globalInt
27-
// CHECK-NOT: [[@LINE-1]]:23 | variable/Swift | globalInt | [[globalInt_USR]] | Ref,Read | rel: 0
27+
// CHECK-NOT: [[@LINE-1]]:23 | variable/Swift | globalInt
2828
// CHECK: [[@LINE-4]]:4 | constructor/Swift | init(initialValue:) | [[WrapperInit_USR]] | Ref,Call,Impl | rel: 0
2929
// CHECK: [[@LINE-3]]:14 | instance-property/Swift | x | [[x_USR:.*]] | Def,RelChild | rel: 1
3030
// CHECK: [[@LINE-4]]:23 | variable/Swift | globalInt | [[globalInt_USR]] | Ref,Read | rel: 0
@@ -35,7 +35,7 @@ public struct HasWrappers {
3535
// CHECK: [[@LINE-3]]:4 | constructor/Swift | init(body:) | [[WrapperBodyInit_USR]] | Ref,Call | rel: 0
3636
public var y: Int
3737
// CHECK: [[@LINE-1]]:14 | instance-property/Swift | y | [[y_USR:.*]] | Def,RelChild | rel: 1
38-
// CHECK-NOT: [[@LINE-6]]:20 | variable/Swift | globalInt | [[globalInt_USR]] | Ref,Read | rel: 0
38+
// CHECK-NOT: [[@LINE-6]]:20 | variable/Swift | globalInt
3939

4040
@Wrapper(body: {
4141
// CHECK: [[@LINE-1]]:4 | struct/Swift | Wrapper | [[Wrapper_USR]] | Ref | rel: 0

test/SourceKit/CursorInfo/cursor_info_property_wrappers.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ struct MyStruct {
1515
}
1616
}
1717

18+
// Split between custom attr and initializer
19+
extension Wrapper {
20+
init(initialValue: T, fieldNumber: Int, special: Bool = false) {
21+
wrappedValue = initialValue
22+
}
23+
}
24+
25+
let someValue = 10
26+
struct OtherStruct {
27+
@Wrapper(fieldNumber: someValue, special: true)
28+
var complex: Int = someValue
29+
}
30+
1831
// Tests that CursorInfo falls through to the wrapped property on
1932
// property wrapper backing properties occurreces, and that global
2033
// rename is reported as available on both (i.e. from foo and $foo).
@@ -28,3 +41,14 @@ struct MyStruct {
2841
// CHECK: ACTIONS BEGIN
2942
// CHECK: source.refactoring.kind.rename.global
3043
// CHECK: ACTIONS END
44+
//
45+
// Tests that CursofInfo finds occurrences within a property wrapper
46+
// constructor call where the arguments are split across the custom
47+
// attribute argument and the var initializer.
48+
//
49+
// RUN: %sourcekitd-test -req=cursor -pos=25:5 %s -- %s | %FileCheck -check-prefixes=CHECK2,CHECK2_DECL %s
50+
// RUN: %sourcekitd-test -req=cursor -pos=27:27 %s -- %s | %FileCheck -check-prefixes=CHECK2,CHECK2_REF %s
51+
// RUN: %sourcekitd-test -req=cursor -pos=28:24 %s -- %s | %FileCheck -check-prefixes=CHECK2,CHECK2_REF %s
52+
// CHECK2_DECL: source.lang.swift.decl.var.global (25:5-25:14)
53+
// CHECK2_REF: source.lang.swift.ref.var.global (25:5-25:14)
54+
// CHECK2-NEXT: someValue
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
@propertyWrapper
2+
struct Wrapper<T> {
3+
var wrappedValue: T
4+
/*split:def*/init(initialValue: T, fieldName: String, special: Bool = false) {
5+
wrappedValue = initialValue
6+
}
7+
}
8+
let /*someValue:def*/<base>someValue</base> = "some"
9+
struct User {
10+
@/*split:call*/Wrapper(fieldName: "bar")
11+
var bar = 10
12+
13+
@/*split:call*/Wrapper(fieldName: {
14+
return /*someValue*/<base>someValue</base>
15+
}(), special: true)
16+
var complex: Int = {
17+
return /*someValue*/<base>someValue</base>.starts(with: "b") ? 43 : 0
18+
}()
19+
}
20+
21+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
@propertyWrapper
2+
struct Wrapper<T> {
3+
var wrappedValue: T
4+
/*split:def*/<keywordBase>init</keywordBase>(<arglabel index=0>initialValue</arglabel><param index=0></param>: T, <arglabel index=1>fieldName</arglabel><param index=1></param>: String, <arglabel index=2>special</arglabel><param index=2></param>: Bool = false) {
5+
wrappedValue = initialValue
6+
}
7+
}
8+
let /*someValue:def*/someValue = "some"
9+
struct User {
10+
@/*split:call*/Wrapper(<callarg index=1>fieldName</callarg><callcolon index=1>: </callcolon>"bar")
11+
var bar = 10
12+
13+
@/*split:call*/Wrapper(<callarg index=1>fieldName</callarg><callcolon index=1>: </callcolon>{
14+
return /*someValue*/someValue
15+
}(), <callarg index=2>special</callarg><callcolon index=2>: </callcolon>true)
16+
var complex: Int = {
17+
return /*someValue*/someValue.starts(with: "b") ? 43 : 0
18+
}()
19+
}
20+
21+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
@propertyWrapper
2+
struct Wrapper<T> {
3+
var wrappedValue: T
4+
/*split:def*/init(initialValue: T, fieldName: String, special: Bool = false) {
5+
wrappedValue = initialValue
6+
}
7+
}
8+
let /*someValue:def*/someValue = "some"
9+
struct User {
10+
@/*split:call*/Wrapper(fieldName: "bar")
11+
var bar = 10
12+
13+
@/*split:call*/Wrapper(fieldName: {
14+
return /*someValue*/someValue
15+
}(), special: true)
16+
var complex: Int = {
17+
return /*someValue*/someValue.starts(with: "b") ? 43 : 0
18+
}()
19+
}
20+
21+
22+
// RUN: %empty-directory(%t.ranges)
23+
// RUN: %refactor -find-rename-ranges -source-filename %s -pos="someValue" -old-name "someValue" >> %t.ranges/property-wrapper-split-someValue.swift
24+
// RUN: diff -u %S/FindRangeOutputs/property-wrapper-split/someValue.swift.expected %t.ranges/property-wrapper-split-someValue.swift
25+
// RUN: %refactor -find-rename-ranges -source-filename %s -pos="split" -is-function-like -old-name "init(initialValue:fieldName:special:)" >> %t.ranges/property-wrapper-split-split.swift
26+
// RUN: diff -u %S/FindRangeOutputs/property-wrapper-split/split.swift.expected %t.ranges/property-wrapper-split-split.swift

0 commit comments

Comments
 (0)