From ba41b21163722e3e3c76adf2b32751bb6d79b323 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Mon, 19 Feb 2024 13:35:55 -0800 Subject: [PATCH] =?UTF-8?q?Don=E2=80=99t=20display=20MARK=20comments=20as?= =?UTF-8?q?=20children=20of=20the=20nodes=20they=20are=20attached=20to?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We used to walk the leading and trailing trivia when walking the token that’s a child of the node. This caused us to eg. report the `MARK` comment in the following as a child of `myFunc` instead of a as a sibling of `myFunc`. ```swift struct Foo { // MARK: Marker func myFunc() {} } ``` rdar://121600714 --- .../SourceKitLSP/Swift/DocumentSymbols.swift | 42 +++++++++++++++---- .../DocumentSymbolTests.swift | 37 +++++++++++++++- 2 files changed, 71 insertions(+), 8 deletions(-) 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..