Skip to content

Commit 46b3232

Browse files
committed
Apply PR suggestions regarding semantic tokens
- Make makeToken a fileprivate initializer instead - Fix doc comments on withMutableTokensOfEachKind - Rename `previousLineCount` to `replacedLineCount` - Fix token shifting logic - Add another test case for inserting tokens - Return empty document tokens if we don't get an edit response - Update DocumentSymbol.children to be non-optional - Rename DocumentSymbolTest to DocumentSymbolTests ...to be consistent with the file name and the other test modules. - Fix indentation in DocumentSymbolTests - Fix doc comment on Modifier.lspName - Remove no-longer-needed useName from token parser These were only needed for syntactic tokens, which we decided not to include in #414 for now. - Add test case for identifiers only backticked on one side - Parse tokens into inout array
1 parent 58424fc commit 46b3232

File tree

9 files changed

+227
-201
lines changed

9 files changed

+227
-201
lines changed

Sources/LanguageServerProtocol/Requests/DocumentSymbolRequest.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public struct DocumentSymbol: Hashable, Codable {
9191
public var selectionRange: Range<Position>
9292

9393
/// Children of this symbol, e.g. properties of a class.
94-
public var children: [DocumentSymbol]?
94+
public var children: [DocumentSymbol]
9595

9696
public init(
9797
name: String,
@@ -100,7 +100,7 @@ public struct DocumentSymbol: Hashable, Codable {
100100
deprecated: Bool? = nil,
101101
range: Range<Position>,
102102
selectionRange: Range<Position>,
103-
children: [DocumentSymbol]? = nil)
103+
children: [DocumentSymbol] = [])
104104
{
105105
self.name = name
106106
self.detail = detail

Sources/SourceKitLSP/DocumentManager.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,13 @@ public final class DocumentManager {
150150

151151
// Remove all tokens in the updated range and shift later ones.
152152

153-
let previousLineCount = 1 + range.upperBound.line - range.lowerBound.line
153+
let replacedLineCount = 1 + range.upperBound.line - range.lowerBound.line
154154
let newLines = edit.text.split(separator: "\n", omittingEmptySubsequences: false)
155-
let lastLineReplaceLength = (
156-
range.lowerBound.line == range.upperBound.line ? range.upperBound.utf16index : 0
157-
) - range.lowerBound.utf16index
158-
let lastLineLengthDelta = newLines.last!.count - lastLineReplaceLength
159-
let lineDelta = newLines.count - previousLineCount
155+
let upperUtf16IndexAfterEdit = (
156+
newLines.count == 1 ? range.lowerBound.utf16index : 0
157+
) + newLines.last!.utf16.count
158+
let charDelta = upperUtf16IndexAfterEdit - range.upperBound.utf16index
159+
let lineDelta = newLines.count - replacedLineCount // may be negative
160160

161161
document.latestTokens.withMutableTokensOfEachKind { tokens in
162162
tokens = Array(tokens.lazy
@@ -169,7 +169,7 @@ public final class DocumentManager {
169169
var token = $0
170170
if token.start.line == range.upperBound.line
171171
&& token.start.utf16index >= range.upperBound.utf16index {
172-
token.move(lineDelta: lineDelta, utf16indexDelta: lastLineLengthDelta)
172+
token.move(lineDelta: lineDelta, utf16indexDelta: charDelta)
173173
} else if token.start.line > range.upperBound.line {
174174
token.move(lineDelta: lineDelta)
175175
}

Sources/SourceKitLSP/DocumentTokens.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public struct DocumentTokens {
2727
}
2828

2929
/// Modifies the syntax highlighting tokens of each kind
30-
/// (lexical, syntactic, semantic) according to `action`.
30+
/// (lexical and semantic) according to `action`.
3131
public mutating func withMutableTokensOfEachKind(_ action: (inout [SyntaxHighlightingToken]) -> Void) {
3232
action(&lexical)
3333
action(&semantic)

Sources/SourceKitLSP/Swift/SwiftLanguageServer.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ public final class SwiftLanguageServer: ToolchainLanguageServer {
200200

201201
if let syntaxMap: SKDResponseArray = response[keys.syntaxmap] {
202202
let tokenParser = SyntaxHighlightingTokenParser(sourcekitd: sourcekitd)
203-
let tokens = tokenParser.parseTokens(syntaxMap, in: snapshot)
203+
var tokens: [SyntaxHighlightingToken] = []
204+
tokenParser.parseTokens(syntaxMap, in: snapshot, into: &tokens)
204205

205206
docTokens.replaceLexical(in: range, with: tokens)
206207
}
@@ -237,7 +238,8 @@ public final class SwiftLanguageServer: ToolchainLanguageServer {
237238

238239
if let skTokens: SKDResponseArray = response[keys.annotations] {
239240
let tokenParser = SyntaxHighlightingTokenParser(sourcekitd: sourcekitd)
240-
let tokens = tokenParser.parseTokens(skTokens, in: snapshot)
241+
var tokens: [SyntaxHighlightingToken] = []
242+
tokenParser.parseTokens(skTokens, in: snapshot, into: &tokens)
241243

242244
docTokens.semantic = tokens
243245
}
@@ -531,7 +533,7 @@ extension SwiftLanguageServer {
531533
if let dict = lastResponse {
532534
return self.updatedLexicalTokens(response: dict, for: after)
533535
} else {
534-
return nil
536+
return DocumentTokens()
535537
}
536538
}
537539

Sources/SourceKitLSP/Swift/SyntaxHighlightingToken.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ public struct SyntaxHighlightingToken: Hashable {
171171

172172
/// The name of the modifier used by LSP, if this
173173
/// is a single modifier. Note that every modifier
174-
/// in `allCases` must have an associated `lspName`.
174+
/// in `allModifiers` must have an associated `lspName`.
175175
var lspName: String? {
176176
switch self {
177177
case .declaration: return "declaration"

Sources/SourceKitLSP/Swift/SyntaxHighlightingTokenParser.swift

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,37 +17,20 @@ import LSPLogging
1717
/// Parses tokens from sourcekitd response dictionaries.
1818
struct SyntaxHighlightingTokenParser {
1919
private let sourcekitd: SourceKitD
20-
/// Use `keys.nameoffset` and `keys.namelength` instead of `keys.offset`
21-
/// and `keys.length`. This is useful in AST structures provided by
22-
/// sourcekitd, since these contain both a name range and a normal range,
23-
/// where the latter refers to the entire node (e.g. the entire function
24-
/// declaration).
25-
private let useName: Bool
26-
27-
init(sourcekitd: SourceKitD, useName: Bool = false) {
20+
21+
init(sourcekitd: SourceKitD) {
2822
self.sourcekitd = sourcekitd
29-
self.useName = useName
3023
}
3124

32-
func parseTokens(_ response: SKDResponseDictionary, in snapshot: DocumentSnapshot) -> [SyntaxHighlightingToken] {
25+
func parseTokens(_ response: SKDResponseDictionary, in snapshot: DocumentSnapshot, into tokens: inout [SyntaxHighlightingToken]) {
3326
let keys = sourcekitd.keys
34-
var tokens: [SyntaxHighlightingToken] = []
3527

36-
if let offset: Int = useName ? response[keys.nameoffset] : response[keys.offset],
37-
var length: Int = useName ? response[keys.namelength] : response[keys.length],
28+
if let offset: Int = response[keys.offset],
29+
var length: Int = response[keys.length],
3830
let start: Position = snapshot.positionOf(utf8Offset: offset),
3931
let skKind: sourcekitd_uid_t = response[keys.kind],
4032
case (let kind, var modifiers)? = parseKindAndModifiers(skKind) {
4133

42-
// We treat function declaration and enum member name tokens as a special
43-
// case, e.g. SourceKit returns `f(x: Int, y: Int)` as a name instead of just `f`.
44-
if useName && [.function, .method, .enumMember].contains(kind) && modifiers.contains(.declaration),
45-
let name: String = response[keys.name],
46-
name.contains("("),
47-
let funcNameLength: Int = name.split(separator: "(").first?.utf8.count {
48-
length = funcNameLength
49-
}
50-
5134
// If the name is escaped in backticks, we need to add two characters to the
5235
// length for the backticks.
5336
if modifiers.contains(.declaration),
@@ -74,19 +57,15 @@ struct SyntaxHighlightingTokenParser {
7457
}
7558

7659
if let substructure: SKDResponseArray = response[keys.substructure] {
77-
tokens += parseTokens(substructure, in: snapshot)
60+
parseTokens(substructure, in: snapshot, into: &tokens)
7861
}
79-
80-
return tokens
8162
}
8263

83-
func parseTokens(_ response: SKDResponseArray, in snapshot: DocumentSnapshot) -> [SyntaxHighlightingToken] {
84-
var result: [SyntaxHighlightingToken] = []
64+
func parseTokens(_ response: SKDResponseArray, in snapshot: DocumentSnapshot, into tokens: inout [SyntaxHighlightingToken]) {
8565
response.forEach { (_, value) in
86-
result += parseTokens(value, in: snapshot)
66+
parseTokens(value, in: snapshot, into: &tokens)
8767
return true
8868
}
89-
return result
9069
}
9170

9271
private func parseKindAndModifiers(_ uid: sourcekitd_uid_t) -> (SyntaxHighlightingToken.Kind, SyntaxHighlightingToken.Modifiers)? {

Tests/SourceKitLSPTests/DocumentSymbolTests.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import SKTestSupport
1616
import SourceKitLSP
1717
import XCTest
1818

19-
final class DocumentSymbolTest: XCTestCase {
19+
final class DocumentSymbolTests: XCTestCase {
2020
typealias DocumentSymbolCapabilities = TextDocumentClientCapabilities.DocumentSymbol
2121

2222
/// Connection and lifetime management for the service.
@@ -25,12 +25,12 @@ final class DocumentSymbolTest: XCTestCase {
2525
/// The primary interface to make requests to the SourceKitServer.
2626
var sk: TestClient! = nil
2727

28-
override func tearDown() {
29-
sk = nil
30-
connection = nil
31-
}
28+
override func tearDown() {
29+
sk = nil
30+
connection = nil
31+
}
3232

33-
func initialize(capabilities: DocumentSymbolCapabilities) {
33+
func initialize(capabilities: DocumentSymbolCapabilities) {
3434
connection = TestSourceKitServer()
3535
sk = connection.client
3636
var documentCapabilities = TextDocumentClientCapabilities()

0 commit comments

Comments
 (0)