diff --git a/Sources/SourceKitLSP/Swift/DocumentSymbols.swift b/Sources/SourceKitLSP/Swift/DocumentSymbols.swift index e3092c1c..26e85112 100644 --- a/Sources/SourceKitLSP/Swift/DocumentSymbols.swift +++ b/Sources/SourceKitLSP/Swift/DocumentSymbols.swift @@ -22,7 +22,13 @@ extension SwiftLanguageServer { let syntaxTree = await syntaxTreeManager.syntaxTree(for: snapshot) try Task.checkCancellation() - return .documentSymbols(DocumentSymbolsFinder.find(in: [Syntax(syntaxTree)], snapshot: snapshot)) + return .documentSymbols( + DocumentSymbolsFinder.find( + in: [Syntax(syntaxTree)], + snapshot: snapshot, + range: syntaxTree.position.. + /// Accumulating the result in here. private var result: [DocumentSymbol] = [] - private init(snapshot: DocumentSnapshot) { + private init(snapshot: DocumentSnapshot, range: Range) { self.snapshot = snapshot + self.range = range super.init(viewMode: .sourceAccurate) } /// Designated entry point for `DocumentSymbolFinder`. - static func find(in nodes: some Sequence, snapshot: DocumentSnapshot) -> [DocumentSymbol] { - let visitor = Self(snapshot: snapshot) + static func find( + in nodes: some Sequence, + snapshot: DocumentSnapshot, + range: Range + ) -> [DocumentSymbol] { + let visitor = DocumentSymbolsFinder(snapshot: snapshot, range: range) for node in nodes { visitor.walk(node) } @@ -57,6 +71,9 @@ fileprivate final class DocumentSymbolsFinder: SyntaxAnyVisitor { range: Range, selection: Range ) -> SyntaxVisitorContinueKind { + if !self.range.overlaps(range) { + return .skipChildren + } guard let rangeLowerBound = snapshot.position(of: range.lowerBound), let rangeUpperBound = snapshot.position(of: range.upperBound), let selectionLowerBound = snapshot.position(of: selection.lowerBound), @@ -65,8 +82,14 @@ fileprivate final class DocumentSymbolsFinder: SyntaxAnyVisitor { return .skipChildren } - let children = DocumentSymbolsFinder.find(in: node.children(viewMode: .sourceAccurate), snapshot: snapshot) + // Record MARK comments on the node's leading and trailing trivia in `result` not as a child of `node`. + visit(node.leadingTrivia, position: node.position) + let children = DocumentSymbolsFinder.find( + in: node.children(viewMode: .sourceAccurate), + snapshot: snapshot, + range: node.positionAfterSkippingLeadingTrivia.. SyntaxVisitorContinueKind { - self.visit(node.leadingTrivia, position: node.position) - self.visit(node.trailingTrivia, position: node.endPositionBeforeTrailingTrivia) + if self.range.overlaps(node.position..