Skip to content

Commit 28d00a9

Browse files
authored
Merge pull request #1066 from ahoppen/ahoppen/nested-mark-comments
Don’t display MARK comments as children of the nodes they are attached to
2 parents eca0979 + ba41b21 commit 28d00a9

File tree

2 files changed

+71
-8
lines changed

2 files changed

+71
-8
lines changed

Sources/SourceKitLSP/Swift/DocumentSymbols.swift

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,13 @@ extension SwiftLanguageServer {
2222
let syntaxTree = await syntaxTreeManager.syntaxTree(for: snapshot)
2323

2424
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+
)
2632
}
2733
}
2834

@@ -32,17 +38,25 @@ fileprivate final class DocumentSymbolsFinder: SyntaxAnyVisitor {
3238
/// The snapshot of the document for which we are getting document symbols.
3339
private let snapshot: DocumentSnapshot
3440

41+
/// Only document symbols that intersect with this range get reported.
42+
private let range: Range<AbsolutePosition>
43+
3544
/// Accumulating the result in here.
3645
private var result: [DocumentSymbol] = []
3746

38-
private init(snapshot: DocumentSnapshot) {
47+
private init(snapshot: DocumentSnapshot, range: Range<AbsolutePosition>) {
3948
self.snapshot = snapshot
49+
self.range = range
4050
super.init(viewMode: .sourceAccurate)
4151
}
4252

4353
/// 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)
4660
for node in nodes {
4761
visitor.walk(node)
4862
}
@@ -57,6 +71,9 @@ fileprivate final class DocumentSymbolsFinder: SyntaxAnyVisitor {
5771
range: Range<AbsolutePosition>,
5872
selection: Range<AbsolutePosition>
5973
) -> SyntaxVisitorContinueKind {
74+
if !self.range.overlaps(range) {
75+
return .skipChildren
76+
}
6077
guard let rangeLowerBound = snapshot.position(of: range.lowerBound),
6178
let rangeUpperBound = snapshot.position(of: range.upperBound),
6279
let selectionLowerBound = snapshot.position(of: selection.lowerBound),
@@ -65,8 +82,14 @@ fileprivate final class DocumentSymbolsFinder: SyntaxAnyVisitor {
6582
return .skipChildren
6683
}
6784

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)
6987

88+
let children = DocumentSymbolsFinder.find(
89+
in: node.children(viewMode: .sourceAccurate),
90+
snapshot: snapshot,
91+
range: node.positionAfterSkippingLeadingTrivia..<node.endPositionBeforeTrailingTrivia
92+
)
7093
result.append(
7194
DocumentSymbol(
7295
name: name,
@@ -76,6 +99,7 @@ fileprivate final class DocumentSymbolsFinder: SyntaxAnyVisitor {
7699
children: children
77100
)
78101
)
102+
visit(node.trailingTrivia, position: node.endPositionBeforeTrailingTrivia)
79103
return .skipChildren
80104
}
81105

@@ -144,8 +168,12 @@ fileprivate final class DocumentSymbolsFinder: SyntaxAnyVisitor {
144168
}
145169

146170
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+
}
149177
return .skipChildren
150178
}
151179

Tests/SourceKitLSPTests/DocumentSymbolTests.swift

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ final class DocumentSymbolTests: XCTestCase {
668668
}
669669
}
670670

671-
func testIncludeNestedMarkComments() async throws {
671+
func testNestedMarkComment() async throws {
672672
try await assertDocumentSymbols(
673673
"""
674674
1️⃣struct 2️⃣Foo3️⃣ {
@@ -694,6 +694,41 @@ final class DocumentSymbolTests: XCTestCase {
694694
]
695695
}
696696
}
697+
698+
func testNestedMarkCommentFollowedAttachedToChild() async throws {
699+
try await assertDocumentSymbols(
700+
"""
701+
1️⃣struct 2️⃣Foo3️⃣ {
702+
4️⃣// MARK: Marker5️⃣
703+
6️⃣func 7️⃣myFunc()8️⃣ { }9️⃣
704+
}🔟
705+
"""
706+
) { positions in
707+
[
708+
DocumentSymbol(
709+
name: "Foo",
710+
kind: .struct,
711+
range: positions["1️⃣"]..<positions["🔟"],
712+
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
713+
children: [
714+
DocumentSymbol(
715+
name: "Marker",
716+
kind: .namespace,
717+
range: positions["4️⃣"]..<positions["5️⃣"],
718+
selectionRange: positions["4️⃣"]..<positions["5️⃣"]
719+
),
720+
DocumentSymbol(
721+
name: "myFunc()",
722+
kind: .method,
723+
range: positions["6️⃣"]..<positions["9️⃣"],
724+
selectionRange: positions["7️⃣"]..<positions["8️⃣"],
725+
children: []
726+
),
727+
]
728+
)
729+
]
730+
}
731+
}
697732
}
698733

699734
fileprivate func assertDocumentSymbols(

0 commit comments

Comments
 (0)