@@ -22,7 +22,13 @@ extension SwiftLanguageServer {
22
22
let syntaxTree = await syntaxTreeManager. syntaxTree ( for: snapshot)
23
23
24
24
try Task . checkCancellation ( )
25
- return . documentSymbols( DocumentSymbolsFinder . find ( in: [ Syntax ( syntaxTree) ] , snapshot: snapshot) )
25
+ return . documentSymbols(
26
+ DocumentSymbolsFinder . find (
27
+ in: [ Syntax ( syntaxTree) ] ,
28
+ snapshot: snapshot,
29
+ range: syntaxTree. position..< syntaxTree. endPosition
30
+ )
31
+ )
26
32
}
27
33
}
28
34
@@ -32,17 +38,25 @@ fileprivate final class DocumentSymbolsFinder: SyntaxAnyVisitor {
32
38
/// The snapshot of the document for which we are getting document symbols.
33
39
private let snapshot : DocumentSnapshot
34
40
41
+ /// Only document symbols that intersect with this range get reported.
42
+ private let range : Range < AbsolutePosition >
43
+
35
44
/// Accumulating the result in here.
36
45
private var result : [ DocumentSymbol ] = [ ]
37
46
38
- private init ( snapshot: DocumentSnapshot ) {
47
+ private init ( snapshot: DocumentSnapshot , range : Range < AbsolutePosition > ) {
39
48
self . snapshot = snapshot
49
+ self . range = range
40
50
super. init ( viewMode: . sourceAccurate)
41
51
}
42
52
43
53
/// Designated entry point for `DocumentSymbolFinder`.
44
- static func find( in nodes: some Sequence < Syntax > , snapshot: DocumentSnapshot ) -> [ DocumentSymbol ] {
45
- let visitor = Self ( snapshot: snapshot)
54
+ static func find(
55
+ in nodes: some Sequence < Syntax > ,
56
+ snapshot: DocumentSnapshot ,
57
+ range: Range < AbsolutePosition >
58
+ ) -> [ DocumentSymbol ] {
59
+ let visitor = DocumentSymbolsFinder ( snapshot: snapshot, range: range)
46
60
for node in nodes {
47
61
visitor. walk ( node)
48
62
}
@@ -57,6 +71,9 @@ fileprivate final class DocumentSymbolsFinder: SyntaxAnyVisitor {
57
71
range: Range < AbsolutePosition > ,
58
72
selection: Range < AbsolutePosition >
59
73
) -> SyntaxVisitorContinueKind {
74
+ if !self . range. overlaps ( range) {
75
+ return . skipChildren
76
+ }
60
77
guard let rangeLowerBound = snapshot. position ( of: range. lowerBound) ,
61
78
let rangeUpperBound = snapshot. position ( of: range. upperBound) ,
62
79
let selectionLowerBound = snapshot. position ( of: selection. lowerBound) ,
@@ -65,8 +82,14 @@ fileprivate final class DocumentSymbolsFinder: SyntaxAnyVisitor {
65
82
return . skipChildren
66
83
}
67
84
68
- let children = DocumentSymbolsFinder . find ( in: node. children ( viewMode: . sourceAccurate) , snapshot: snapshot)
85
+ // Record MARK comments on the node's leading and trailing trivia in `result` not as a child of `node`.
86
+ visit ( node. leadingTrivia, position: node. position)
69
87
88
+ let children = DocumentSymbolsFinder . find (
89
+ in: node. children ( viewMode: . sourceAccurate) ,
90
+ snapshot: snapshot,
91
+ range: node. positionAfterSkippingLeadingTrivia..< node. endPositionBeforeTrailingTrivia
92
+ )
70
93
result. append (
71
94
DocumentSymbol (
72
95
name: name,
@@ -76,6 +99,7 @@ fileprivate final class DocumentSymbolsFinder: SyntaxAnyVisitor {
76
99
children: children
77
100
)
78
101
)
102
+ visit ( node. trailingTrivia, position: node. endPositionBeforeTrailingTrivia)
79
103
return . skipChildren
80
104
}
81
105
@@ -144,8 +168,12 @@ fileprivate final class DocumentSymbolsFinder: SyntaxAnyVisitor {
144
168
}
145
169
146
170
override func visit( _ node: TokenSyntax ) -> SyntaxVisitorContinueKind {
147
- self . visit ( node. leadingTrivia, position: node. position)
148
- self . visit ( node. trailingTrivia, position: node. endPositionBeforeTrailingTrivia)
171
+ if self . range. overlaps ( node. position..< node. positionAfterSkippingLeadingTrivia) {
172
+ self . visit ( node. leadingTrivia, position: node. position)
173
+ }
174
+ if range. overlaps ( node. endPositionBeforeTrailingTrivia..< node. endPosition) {
175
+ self . visit ( node. trailingTrivia, position: node. endPositionBeforeTrailingTrivia)
176
+ }
149
177
return . skipChildren
150
178
}
151
179
0 commit comments