Skip to content

Commit 787736d

Browse files
committed
[Sema] Suggest #selector(self.foo) instead of #selector(TypeName.foo) when possible.
When inside a declaration or extension of TypeName, humans usually don't write the full typename like #selector(TypeName.foo), but instead prefer the neater form #selector(self.foo). The compiler has enough information to do this too. Fixes rdar://problem/25284692 .
1 parent 25fc3ed commit 787736d

File tree

3 files changed

+178
-3
lines changed

3 files changed

+178
-3
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3332,7 +3332,22 @@ class ObjCSelectorWalker : public ASTWalker {
33323332
name = bestMethod->getFullName();
33333333
}
33343334

3335-
out << nominal->getName().str() << "." << name.getBaseName();
3335+
auto typeName = nominal->getName().str();
3336+
// If we're inside a type Foo (or an extension of it) and the suggestion
3337+
// is going to be #selector(Foo.bar) (or #selector(SuperclassOfFoo.bar),
3338+
// then suggest the more natural #selector(self.bar) instead.
3339+
if (auto containingTypeContext = DC->getInnermostTypeContext()) {
3340+
auto methodNominalType = nominal->getDeclaredType();
3341+
auto containingNominalType =
3342+
containingTypeContext
3343+
->getAsNominalTypeOrNominalTypeExtensionContext()
3344+
->getDeclaredType();
3345+
if (methodNominalType->isEqual(containingNominalType) ||
3346+
methodNominalType->isExactSuperclassOf(containingNominalType))
3347+
typeName = "self";
3348+
}
3349+
3350+
out << typeName << "." << name.getBaseName();
33363351
auto argNames = name.getArgumentNames();
33373352

33383353
// Only print the parentheses if there are some argument

test/FixCode/fixits-apply-objc.swift

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,86 @@ import ObjectiveC
1313
}
1414
}
1515

16+
@objc class OtherClass {
17+
func test(s: Selectors) {
18+
s.takeSel("mySel")
19+
s.takeSel(Selector("mySel"))
20+
}
21+
}
22+
23+
@objc class Base {
24+
func baseSel() {}
25+
}
26+
27+
@objc class Outer {
28+
func takeSel(_: Selector) {}
29+
func outerSel() {}
30+
31+
@objc class Inner: Base {
32+
func takeSel(_: Selector) {}
33+
34+
func innerSel() {}
35+
36+
func test(s: Selectors, o: Outer) {
37+
s.takeSel("mySel")
38+
s.takeSel(Selector("mySel"))
39+
40+
takeSel("innerSel")
41+
takeSel(Selector("innerSel"))
42+
43+
takeSel("baseSel")
44+
takeSel(Selector("baseSel"))
45+
46+
o.takeSel("outerSel")
47+
o.takeSel(Selector("outerSel"))
48+
}
49+
}
50+
51+
func test(s: Selectors, i: Inner) {
52+
s.takeSel("mySel")
53+
s.takeSel(Selector("mySel"))
54+
55+
i.takeSel("innerSel")
56+
i.takeSel(Selector("innerSel"))
57+
58+
i.takeSel("baseSel")
59+
i.takeSel(Selector("baseSel"))
60+
61+
takeSel("outerSel")
62+
takeSel(Selector("outerSel"))
63+
}
64+
}
65+
66+
extension Outer {
67+
func test2(s: Selectors, i: Inner) {
68+
s.takeSel("mySel")
69+
s.takeSel(Selector("mySel"))
70+
71+
i.takeSel("innerSel")
72+
i.takeSel(Selector("innerSel"))
73+
74+
i.takeSel("baseSel")
75+
i.takeSel(Selector("baseSel"))
76+
77+
takeSel("outerSel")
78+
takeSel(Selector("outerSel"))
79+
}
80+
}
81+
82+
func freeTest(s: Selectors, o: Outer, i: Outer.Inner) {
83+
s.takeSel("mySel")
84+
s.takeSel(Selector("mySel"))
85+
86+
i.takeSel("innerSel")
87+
i.takeSel(Selector("innerSel"))
88+
89+
i.takeSel("baseSel")
90+
i.takeSel(Selector("baseSel"))
91+
92+
o.takeSel("outerSel")
93+
o.takeSel(Selector("outerSel"))
94+
}
95+
1696
func foo(an : Any) {
1797
let a1 : AnyObject
1898
a1 = an

test/FixCode/fixits-apply-objc.swift.result

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,91 @@ import ObjectiveC
88
func takeSel(_: Selector) {}
99
func mySel() {}
1010
func test() {
11-
takeSel(#selector(Selectors.mySel))
12-
takeSel(#selector(Selectors.mySel))
11+
takeSel(#selector(self.mySel))
12+
takeSel(#selector(self.mySel))
1313
}
1414
}
1515

16+
@objc class OtherClass {
17+
func test(s: Selectors) {
18+
s.takeSel(#selector(Selectors.mySel))
19+
s.takeSel(#selector(Selectors.mySel))
20+
}
21+
}
22+
23+
@objc class Base {
24+
func baseSel() {}
25+
}
26+
27+
@objc class Outer {
28+
func takeSel(_: Selector) {}
29+
func outerSel() {}
30+
31+
@objc class Inner: Base {
32+
func takeSel(_: Selector) {}
33+
34+
func innerSel() {}
35+
36+
func test(s: Selectors, o: Outer) {
37+
s.takeSel(#selector(Selectors.mySel))
38+
s.takeSel(#selector(Selectors.mySel))
39+
40+
takeSel(#selector(self.innerSel))
41+
takeSel(#selector(self.innerSel))
42+
43+
takeSel(#selector(self.baseSel))
44+
takeSel(#selector(self.baseSel))
45+
46+
o.takeSel(#selector(Outer.outerSel))
47+
o.takeSel(#selector(Outer.outerSel))
48+
}
49+
}
50+
51+
func test(s: Selectors, i: Inner) {
52+
s.takeSel(#selector(Selectors.mySel))
53+
s.takeSel(#selector(Selectors.mySel))
54+
55+
i.takeSel(#selector(Inner.innerSel))
56+
i.takeSel(#selector(Inner.innerSel))
57+
58+
i.takeSel(#selector(Base.baseSel))
59+
i.takeSel(#selector(Base.baseSel))
60+
61+
takeSel(#selector(self.outerSel))
62+
takeSel(#selector(self.outerSel))
63+
}
64+
}
65+
66+
extension Outer {
67+
func test2(s: Selectors, i: Inner) {
68+
s.takeSel(#selector(Selectors.mySel))
69+
s.takeSel(#selector(Selectors.mySel))
70+
71+
i.takeSel(#selector(Inner.innerSel))
72+
i.takeSel(#selector(Inner.innerSel))
73+
74+
i.takeSel(#selector(Base.baseSel))
75+
i.takeSel(#selector(Base.baseSel))
76+
77+
takeSel(#selector(self.outerSel))
78+
takeSel(#selector(self.outerSel))
79+
}
80+
}
81+
82+
func freeTest(s: Selectors, o: Outer, i: Outer.Inner) {
83+
s.takeSel(#selector(Selectors.mySel))
84+
s.takeSel(#selector(Selectors.mySel))
85+
86+
i.takeSel(#selector(Inner.innerSel))
87+
i.takeSel(#selector(Inner.innerSel))
88+
89+
i.takeSel(#selector(Base.baseSel))
90+
i.takeSel(#selector(Base.baseSel))
91+
92+
o.takeSel(#selector(Outer.outerSel))
93+
o.takeSel(#selector(Outer.outerSel))
94+
}
95+
1696
func foo(an : Any) {
1797
let a1 : AnyObject
1898
a1 = an as AnyObject

0 commit comments

Comments
 (0)