Skip to content

Commit 7df16ca

Browse files
committed
[IDE] Don't widen source range for AccessorDecl
Syntactically, Attributes for AccessorDecl are not part of AccessorDecl, but part of PatternBindingDecl. When the selected range is the brace for implicit getter, it should be considered as selecting getter decl regardless of the attributes. Conversely, we should widen source range for PatternBindingDecl by looking into declared VarDecls because, in AST, attributes on PatternBindingDecl are attached to VarDecls. rdar://problem/41073182
1 parent 19d325b commit 7df16ca

File tree

2 files changed

+73
-1
lines changed

2 files changed

+73
-1
lines changed

lib/AST/Decl.cpp

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

370370
SourceRange Decl::getSourceRangeIncludingAttrs() const {
371371
auto Range = getSourceRange();
372+
373+
// Attributes on AccessorDecl are syntactically belong to PatternBindingDecl.
374+
if (isa<AccessorDecl>(this) || isa<VarDecl>(this))
375+
return Range;
376+
377+
// Attributes on PatternBindingDecls are attached to VarDecls in AST.
378+
if (const PatternBindingDecl *PBD = dyn_cast<PatternBindingDecl>(this)) {
379+
for (auto Entry : PBD->getPatternList())
380+
Entry.getPattern()->forEachVariable([&](VarDecl *VD) {
381+
for (auto Attr : VD->getAttrs())
382+
if (Attr->getRange().isValid())
383+
Range.widen(Attr->getRangeWithAt());
384+
});
385+
}
386+
372387
for (auto Attr : getAttrs()) {
373388
if (Attr->getRange().isValid())
374-
Range.widen(Attr->getRange());
389+
Range.widen(Attr->getRangeWithAt());
375390
}
376391
return Range;
377392
}

test/IDE/range_info_declattr.swift

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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+
11+
// RUN: %target-swift-ide-test -range -pos=4:1 -end-pos=9:2 -source-filename %s | %FileCheck %s -check-prefix=CHECK1
12+
// RUN: %target-swift-ide-test -range -pos=5:3 -end-pos=7:4 -source-filename %s | %FileCheck %s -check-prefix=CHECK2
13+
// RUN: %target-swift-ide-test -range -pos=5:25 -end-pos=7:4 -source-filename %s | %FileCheck %s -check-prefix=CHECK3
14+
// RUN: %target-swift-ide-test -range -pos=8:3 -end-pos=8:31 -source-filename %s | %FileCheck %s -check-prefix=CHECK4
15+
16+
// CHECK1: <Kind>SingleDecl</Kind>
17+
// CHECK1-NEXT: <Content>@objc class ObjCClass : ObjCBase {
18+
// CHECK1-NEXT: override var foo: Int {
19+
// CHECK1-NEXT: return 42
20+
// CHECK1-NEXT: }
21+
// CHECK1-NEXT: @objc var bar = 12, baz = 13
22+
// CHECK1-NEXT: }</Content>
23+
// CHECK1-NEXT: <Context>swift_ide_test.(file)</Context>
24+
// CHECK1-NEXT: <Declared>ObjCClass</Declared><OutscopeReference>false</OutscopeReference>
25+
// CHECK1-NEXT: <Declared>foo</Declared><OutscopeReference>false</OutscopeReference>
26+
// CHECK1-NEXT: <Declared>_</Declared><OutscopeReference>false</OutscopeReference>
27+
// CHECK1-NEXT: <Declared>bar</Declared><OutscopeReference>false</OutscopeReference>
28+
// CHECK1-NEXT: <Declared>baz</Declared><OutscopeReference>false</OutscopeReference>
29+
// CHECK1-NEXT: <ASTNodes>1</ASTNodes>
30+
// CHECK1-NEXT: <end>
31+
32+
// CHECK2: <Kind>SingleDecl</Kind>
33+
// CHECK2-NEXT: <Content>override var foo: Int {
34+
// CHECK2-NEXT: return 42
35+
// CHECK2-NEXT: }</Content>
36+
// CHECK2-NEXT: <Context>swift_ide_test.(file).ObjCClass</Context>
37+
// CHECK2-NEXT: <Declared>foo</Declared><OutscopeReference>false</OutscopeReference>
38+
// CHECK2-NEXT: <ASTNodes>1</ASTNodes>
39+
// CHECK2-NEXT: <end>
40+
41+
// CHECK3: <Kind>SingleDecl</Kind>
42+
// CHECK3-NEXT: <Content>{
43+
// CHECK3-NEXT: return 42
44+
// CHECK3-NEXT: }</Content>
45+
// CHECK3-NEXT: <Context>swift_ide_test.(file).ObjCClass</Context>
46+
// CHECK3-NEXT: <Declared>_</Declared><OutscopeReference>false</OutscopeReference>
47+
// CHECK3-NEXT: <ASTNodes>1</ASTNodes>
48+
// CHECK3-NEXT: <end>
49+
50+
51+
// CHECK4: <Kind>SingleDecl</Kind>
52+
// CHECK4-NEXT: <Content>@objc var bar = 12, baz = 13</Content>
53+
// CHECK4-NEXT: <Context>swift_ide_test.(file).ObjCClass</Context>
54+
// CHECK4-NEXT: <Declared>bar</Declared><OutscopeReference>false</OutscopeReference>
55+
// CHECK4-NEXT: <Declared>baz</Declared><OutscopeReference>false</OutscopeReference>
56+
// CHECK4-NEXT: <ASTNodes>1</ASTNodes>
57+
// CHECK4-NEXT: <end>

0 commit comments

Comments
 (0)