Skip to content

Commit bb4e019

Browse files
authored
Merge pull request #17876 from rintaro/4.2-rdar41073182
[4.2][IDE] Don't widen source range for AccessorDecl
2 parents 703930f + d4ff279 commit bb4e019

File tree

2 files changed

+155
-1
lines changed

2 files changed

+155
-1
lines changed

lib/AST/Decl.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,9 +369,44 @@ case DeclKind::ID: return cast<ID##Decl>(this)->getSourceRange();
369369

370370
SourceRange Decl::getSourceRangeIncludingAttrs() const {
371371
auto Range = getSourceRange();
372+
373+
// Attributes on AccessorDecl may syntactically belong to PatternBindingDecl.
374+
// e.g. 'override'.
375+
if (auto *AD = dyn_cast<AccessorDecl>(this)) {
376+
// If this is implicit getter, accessor range should not include attributes.
377+
if (!AD->getAccessorKeywordLoc().isValid())
378+
return Range;
379+
380+
// Otherwise, include attributes directly attached to the accessor.
381+
SourceLoc VarLoc = AD->getStorage()->getStartLoc();
382+
for (auto Attr : getAttrs()) {
383+
if (!Attr->getRange().isValid())
384+
continue;
385+
386+
SourceLoc AttrStartLoc = Attr->getRangeWithAt().Start;
387+
if (getASTContext().SourceMgr.isBeforeInBuffer(VarLoc, AttrStartLoc))
388+
Range.widen(AttrStartLoc);
389+
}
390+
return Range;
391+
}
392+
393+
// Attributes on VarDecl syntactically belong to PatternBindingDecl.
394+
if (isa<VarDecl>(this))
395+
return Range;
396+
397+
// Attributes on PatternBindingDecls are attached to VarDecls in AST.
398+
if (auto *PBD = dyn_cast<PatternBindingDecl>(this)) {
399+
for (auto Entry : PBD->getPatternList())
400+
Entry.getPattern()->forEachVariable([&](VarDecl *VD) {
401+
for (auto Attr : VD->getAttrs())
402+
if (Attr->getRange().isValid())
403+
Range.widen(Attr->getRangeWithAt());
404+
});
405+
}
406+
372407
for (auto Attr : getAttrs()) {
373408
if (Attr->getRange().isValid())
374-
Range.widen(Attr->getRange());
409+
Range.widen(Attr->getRangeWithAt());
375410
}
376411
return Range;
377412
}

test/IDE/range_info_declattr.swift

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
class ObjCBase {
2+
var foo: Int { return 1 }
3+
}
4+
@objc class ObjCClass : ObjCBase {
5+
override var foo: Int {
6+
return 42
7+
}
8+
@objc var bar = 12, baz = 13
9+
}
10+
class Derived : ObjCBase {
11+
@available(*, unavailable)
12+
override var quux: Int {
13+
@inlinable get { return 0 }
14+
}
15+
16+
subscript(idx: Int) -> Int {
17+
@available(*, unavailable)
18+
get { return 0 }
19+
20+
@available(*, unavailable)
21+
@inlineable
22+
set { }
23+
}
24+
}
25+
26+
// RUN: %target-swift-ide-test -range -pos=4:1 -end-pos=9:2 -source-filename %s | %FileCheck %s -check-prefix=CHECK1
27+
// RUN: %target-swift-ide-test -range -pos=5:3 -end-pos=7:4 -source-filename %s | %FileCheck %s -check-prefix=CHECK2
28+
// RUN: %target-swift-ide-test -range -pos=5:25 -end-pos=7:4 -source-filename %s | %FileCheck %s -check-prefix=CHECK3
29+
// RUN: %target-swift-ide-test -range -pos=8:3 -end-pos=8:31 -source-filename %s | %FileCheck %s -check-prefix=CHECK4
30+
// RUN: %target-swift-ide-test -range -pos=13:5 -end-pos=13:32 -source-filename %s | %FileCheck %s -check-prefix=CHECK5
31+
// RUN: %target-swift-ide-test -range -pos=13:16 -end-pos=13:32 -source-filename %s | %FileCheck %s -check-prefix=CHECK6
32+
// RUN: %target-swift-ide-test -range -pos=12:26 -end-pos=14:4 -source-filename %s | %FileCheck %s -check-prefix=CHECK7
33+
// RUN: %target-swift-ide-test -range -pos=17:5 -end-pos=18:21 -source-filename %s | %FileCheck %s -check-prefix=CHECK8
34+
// RUN: %target-swift-ide-test -range -pos=20:5 -end-pos=22:12 -source-filename %s | %FileCheck %s -check-prefix=CHECK9
35+
// RUN: %target-swift-ide-test -range -pos=21:5 -end-pos=22:12 -source-filename %s | %FileCheck %s -check-prefix=CHECK10
36+
37+
// CHECK1: <Kind>SingleDecl</Kind>
38+
// CHECK1-NEXT: <Content>@objc class ObjCClass : ObjCBase {
39+
// CHECK1-NEXT: override var foo: Int {
40+
// CHECK1-NEXT: return 42
41+
// CHECK1-NEXT: }
42+
// CHECK1-NEXT: @objc var bar = 12, baz = 13
43+
// CHECK1-NEXT: }</Content>
44+
// CHECK1-NEXT: <Context>swift_ide_test.(file)</Context>
45+
// CHECK1-NEXT: <Declared>ObjCClass</Declared><OutscopeReference>false</OutscopeReference>
46+
// CHECK1-NEXT: <Declared>foo</Declared><OutscopeReference>false</OutscopeReference>
47+
// CHECK1-NEXT: <Declared>_</Declared><OutscopeReference>false</OutscopeReference>
48+
// CHECK1-NEXT: <Declared>bar</Declared><OutscopeReference>false</OutscopeReference>
49+
// CHECK1-NEXT: <Declared>baz</Declared><OutscopeReference>false</OutscopeReference>
50+
// CHECK1-NEXT: <ASTNodes>1</ASTNodes>
51+
// CHECK1-NEXT: <end>
52+
53+
// CHECK2: <Kind>SingleDecl</Kind>
54+
// CHECK2-NEXT: <Content>override var foo: Int {
55+
// CHECK2-NEXT: return 42
56+
// CHECK2-NEXT: }</Content>
57+
// CHECK2-NEXT: <Context>swift_ide_test.(file).ObjCClass</Context>
58+
// CHECK2-NEXT: <Declared>foo</Declared><OutscopeReference>false</OutscopeReference>
59+
// CHECK2-NEXT: <ASTNodes>1</ASTNodes>
60+
// CHECK2-NEXT: <end>
61+
62+
// CHECK3: <Kind>SingleDecl</Kind>
63+
// CHECK3-NEXT: <Content>{
64+
// CHECK3-NEXT: return 42
65+
// CHECK3-NEXT: }</Content>
66+
// CHECK3-NEXT: <Context>swift_ide_test.(file).ObjCClass</Context>
67+
// CHECK3-NEXT: <Declared>_</Declared><OutscopeReference>false</OutscopeReference>
68+
// CHECK3-NEXT: <ASTNodes>1</ASTNodes>
69+
// CHECK3-NEXT: <end>
70+
71+
// CHECK4: <Kind>SingleDecl</Kind>
72+
// CHECK4-NEXT: <Content>@objc var bar = 12, baz = 13</Content>
73+
// CHECK4-NEXT: <Context>swift_ide_test.(file).ObjCClass</Context>
74+
// CHECK4-NEXT: <Declared>bar</Declared><OutscopeReference>false</OutscopeReference>
75+
// CHECK4-NEXT: <Declared>baz</Declared><OutscopeReference>false</OutscopeReference>
76+
// CHECK4-NEXT: <ASTNodes>1</ASTNodes>
77+
// CHECK4-NEXT: <end>
78+
79+
// CHECK5: <Kind>SingleDecl</Kind>
80+
// CHECK5-NEXT: <Content>@inlinable get { return 0 }</Content>
81+
// CHECK5-NEXT: <Context>swift_ide_test.(file).Derived</Context>
82+
// CHECK5-NEXT: <Declared>_</Declared><OutscopeReference>false</OutscopeReference>
83+
// CHECK5-NEXT: <ASTNodes>1</ASTNodes>
84+
// CHECK5-NEXT: <end>
85+
86+
// CHECK6: <Kind>Invalid</Kind>
87+
// CHECK6-NEXT: <Content>get { return 0 }</Content>
88+
// CHECK6-NEXT: <ASTNodes>0</ASTNodes>
89+
// CHECK6-NEXT: <end>
90+
91+
// CHECK7: <Kind>Invalid</Kind>
92+
// CHECK7-NEXT: <Content>{
93+
// CHECK7-NEXT: @inlinable get { return 0 }
94+
// CHECK7-NEXT: }</Content>
95+
// CHECK7-NEXT: <ASTNodes>0</ASTNodes>
96+
// CHECK7-NEXT: <end>
97+
98+
// CHECK8: <Kind>SingleDecl</Kind>
99+
// CHECK8-NEXT: <Content>@available(*, unavailable)
100+
// CHECK8-NEXT: get { return 0 }</Content>
101+
// CHECK8-NEXT: <Context>swift_ide_test.(file).Derived</Context>
102+
// CHECK8-NEXT: <Declared>_</Declared><OutscopeReference>false</OutscopeReference>
103+
// CHECK8-NEXT: <ASTNodes>1</ASTNodes>
104+
// CHECK8-NEXT: <end>
105+
106+
// CHECK9: <Kind>SingleDecl</Kind>
107+
// CHECK9-NEXT: <Content>@available(*, unavailable)
108+
// CHECK9-NEXT: @inlineable
109+
// CHECK9-NEXT: set { }</Content>
110+
// CHECK9-NEXT: <Context>swift_ide_test.(file).Derived</Context>
111+
// CHECK9-NEXT: <Declared>_</Declared><OutscopeReference>false</OutscopeReference>
112+
// CHECK9-NEXT: <ASTNodes>1</ASTNodes>
113+
// CHECK9-NEXT: <end>
114+
115+
// CHECK10: <Kind>Invalid</Kind>
116+
// CHECK10-NEXT: <Content>@inlineable
117+
// CHECK10-NEXT: set { }</Content>
118+
// CHECK10-NEXT: <ASTNodes>0</ASTNodes>
119+
// CHECK10-NEXT: <end>

0 commit comments

Comments
 (0)