Skip to content

Commit 2c616f7

Browse files
committed
Refactor SemanticTokenTypes, SemanticTokenModifiers
1 parent e4c2a3f commit 2c616f7

File tree

6 files changed

+175
-148
lines changed

6 files changed

+175
-148
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import Foundation
14+
15+
/// Additional metadata about a token.
16+
///
17+
/// Similar to `SemanticTokenTypes`, the bit indices should
18+
/// be numbered starting at 0.
19+
public struct SemanticTokenModifiers: OptionSet, Hashable {
20+
public let rawValue: UInt32
21+
22+
public init(rawValue: UInt32) {
23+
self.rawValue = rawValue
24+
}
25+
26+
public static let declaration = Self(rawValue: 1 << 0)
27+
public static let definition = Self(rawValue: 1 << 1)
28+
public static let readonly = Self(rawValue: 1 << 2)
29+
public static let `static` = Self(rawValue: 1 << 3)
30+
public static let deprecated = Self(rawValue: 1 << 4)
31+
public static let abstract = Self(rawValue: 1 << 5)
32+
public static let async = Self(rawValue: 1 << 6)
33+
public static let modification = Self(rawValue: 1 << 7)
34+
public static let documentation = Self(rawValue: 1 << 8)
35+
public static let defaultLibrary = Self(rawValue: 1 << 9)
36+
37+
public var name: String? {
38+
switch self {
39+
case .declaration: return "declaration"
40+
case .definition: return "definition"
41+
case .readonly: return "readonly"
42+
case .static: return "static"
43+
case .deprecated: return "deprecated"
44+
case .abstract: return "abstract"
45+
case .async: return "async"
46+
case .modification: return "modification"
47+
case .documentation: return "documentation"
48+
case .defaultLibrary: return "defaultLibrary"
49+
default: return nil
50+
}
51+
}
52+
53+
/// All available modifiers, in ascending order of the bit index
54+
/// they are represented with (starting at the rightmost bit).
55+
public static let predefined: [Self] = [
56+
.declaration,
57+
.definition,
58+
.readonly,
59+
.static,
60+
.deprecated,
61+
.abstract,
62+
.async,
63+
.modification,
64+
.documentation,
65+
.defaultLibrary,
66+
]
67+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import Foundation
14+
15+
/// The predefined token type values
16+
///
17+
/// The protocol defines a set of token types and modifiers but clients are
18+
/// allowed to extend these and announce the values they support in the
19+
/// corresponding client capability.
20+
public struct SemanticTokenTypes: Hashable {
21+
public let name: String
22+
public init(_ name: String) {
23+
self.name = name
24+
}
25+
26+
public static let namespace = Self("namespace")
27+
/// Represents a generic type. Acts as a fallback for types which
28+
/// can't be mapped to a specific type like class or enum.
29+
public static let type = Self("type")
30+
public static let `class` = Self("class")
31+
public static let `enum` = Self("enum")
32+
public static let interface = Self("interface")
33+
public static let `struct` = Self("struct")
34+
public static let typeParameter = Self("typeParameter")
35+
public static let parameter = Self("parameter")
36+
public static let variable = Self("variable")
37+
public static let property = Self("property")
38+
public static let enumMember = Self("enumMember")
39+
public static let event = Self("event")
40+
public static let function = Self("function")
41+
public static let method = Self("method")
42+
public static let macro = Self("macro")
43+
public static let keyword = Self("keyword")
44+
public static let modifier = Self("modifier")
45+
public static let comment = Self("comment")
46+
public static let string = Self("string")
47+
public static let number = Self("number")
48+
public static let regexp = Self("regexp")
49+
public static let `operator` = Self("operator")
50+
/// since 3.17.0
51+
public static let decorator = Self("decorator")
52+
53+
public static var predefined: [Self] = [
54+
.namespace,
55+
.type,
56+
.class,
57+
.enum,
58+
.interface,
59+
.struct,
60+
.typeParameter,
61+
.parameter,
62+
.variable,
63+
.property,
64+
.enumMember,
65+
.event,
66+
.function,
67+
.method,
68+
.macro,
69+
.keyword,
70+
.modifier,
71+
.comment,
72+
.string,
73+
.number,
74+
.regexp,
75+
.operator,
76+
]
77+
}

Sources/SKTestSupport/Array+SyntaxHighlightingToken.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ extension Array where Element == SyntaxHighlightingToken {
3737
current.utf16index = charDelta
3838
}
3939

40-
guard let kind = SyntaxHighlightingToken.Kind(rawValue: rawKind) else { continue }
40+
let kind = SyntaxHighlightingToken.Kind.all[Int(rawKind)]
4141
let modifiers = SyntaxHighlightingToken.Modifiers(rawValue: rawModifiers)
4242

4343
append(

Sources/SourceKitLSP/Swift/SwiftLanguageServer.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,8 @@ extension SwiftLanguageServer {
231231
),
232232
semanticTokensProvider: SemanticTokensOptions(
233233
legend: SemanticTokensLegend(
234-
tokenTypes: SyntaxHighlightingToken.Kind.allCases.map(\.lspName),
235-
tokenModifiers: SyntaxHighlightingToken.Modifiers.allModifiers.map { $0.lspName! }
234+
tokenTypes: SyntaxHighlightingToken.Kind.all.map(\.name),
235+
tokenModifiers: SyntaxHighlightingToken.Modifiers.all.compactMap(\.name)
236236
),
237237
range: .bool(true),
238238
full: .bool(true)

Sources/SourceKitLSP/Swift/SyntaxHighlightingToken.swift

Lines changed: 24 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -47,146 +47,8 @@ public struct SyntaxHighlightingToken: Hashable {
4747
self.init(range: range, kind: kind, modifiers: modifiers)
4848
}
4949

50-
/// The token type.
51-
///
52-
/// Represented using an int to make the conversion to
53-
/// LSP tokens efficient. The order of this enum does not have to be
54-
/// stable, since we provide a `SemanticTokensLegend` during initialization.
55-
/// It is, however, important that the values are numbered from 0 due to
56-
/// the way the kinds are encoded in LSP.
57-
/// Also note that we intentionally use an enum here instead of e.g. a
58-
/// `RawRepresentable` struct, since we want to have a conversion to
59-
/// strings for known kinds and since these kinds are only provided by the
60-
/// server, i.e. there is no need to handle cases where unknown kinds
61-
/// have to be decoded.
62-
public enum Kind: UInt32, CaseIterable, Hashable {
63-
case namespace = 0
64-
case type
65-
case actor
66-
case `class`
67-
case `enum`
68-
case interface
69-
case `struct`
70-
case typeParameter
71-
case parameter
72-
case variable
73-
case property
74-
case enumMember
75-
case event
76-
case function
77-
case method
78-
case macro
79-
case keyword
80-
case modifier
81-
case comment
82-
case string
83-
case number
84-
case regexp
85-
case `operator`
86-
case decorator
87-
/// **(LSP Extension)**
88-
case identifier
89-
90-
/// The name of the token type used by LSP.
91-
var lspName: String {
92-
switch self {
93-
case .namespace: return "namespace"
94-
case .type: return "type"
95-
case .actor: return "class" // LSP doesn’t know about actors. Display actors as classes.
96-
case .class: return "class"
97-
case .enum: return "enum"
98-
case .interface: return "interface"
99-
case .struct: return "struct"
100-
case .typeParameter: return "typeParameter"
101-
case .parameter: return "parameter"
102-
case .variable: return "variable"
103-
case .property: return "property"
104-
case .enumMember: return "enumMember"
105-
case .event: return "event"
106-
case .function: return "function"
107-
case .method: return "method"
108-
case .macro: return "macro"
109-
case .keyword: return "keyword"
110-
case .modifier: return "modifier"
111-
case .comment: return "comment"
112-
case .string: return "string"
113-
case .number: return "number"
114-
case .regexp: return "regexp"
115-
case .operator: return "operator"
116-
case .decorator: return "decorator"
117-
case .identifier: return "identifier"
118-
}
119-
}
120-
121-
/// **Public for testing**
122-
public var _lspName: String {
123-
lspName
124-
}
125-
}
126-
127-
/// Additional metadata about a token.
128-
///
129-
/// Similar to `Kind`, the raw values do not actually have
130-
/// to be stable, do note however that the bit indices should
131-
/// be numbered starting at 0 and that the ordering should
132-
/// correspond to `allModifiers`.
133-
public struct Modifiers: OptionSet, Hashable {
134-
public static let declaration = Self(rawValue: 1 << 0)
135-
public static let definition = Self(rawValue: 1 << 1)
136-
public static let readonly = Self(rawValue: 1 << 2)
137-
public static let `static` = Self(rawValue: 1 << 3)
138-
public static let deprecated = Self(rawValue: 1 << 4)
139-
public static let abstract = Self(rawValue: 1 << 5)
140-
public static let async = Self(rawValue: 1 << 6)
141-
public static let modification = Self(rawValue: 1 << 7)
142-
public static let documentation = Self(rawValue: 1 << 8)
143-
public static let defaultLibrary = Self(rawValue: 1 << 9)
144-
145-
/// All available modifiers, in ascending order of the bit index
146-
/// they are represented with (starting at the rightmost bit).
147-
public static let allModifiers: [Self] = [
148-
.declaration,
149-
.definition,
150-
.readonly,
151-
.static,
152-
.deprecated,
153-
.abstract,
154-
.async,
155-
.modification,
156-
.documentation,
157-
.defaultLibrary,
158-
]
159-
160-
public let rawValue: UInt32
161-
162-
/// The name of the modifier used by LSP, if this
163-
/// is a single modifier. Note that every modifier
164-
/// in `allModifiers` must have an associated `lspName`.
165-
var lspName: String? {
166-
switch self {
167-
case .declaration: return "declaration"
168-
case .definition: return "definition"
169-
case .readonly: return "readonly"
170-
case .static: return "static"
171-
case .deprecated: return "deprecated"
172-
case .abstract: return "abstract"
173-
case .async: return "async"
174-
case .modification: return "modification"
175-
case .documentation: return "documentation"
176-
case .defaultLibrary: return "defaultLibrary"
177-
default: return nil
178-
}
179-
}
180-
181-
/// **Public for testing**
182-
public var _lspName: String? {
183-
lspName
184-
}
185-
186-
public init(rawValue: UInt32) {
187-
self.rawValue = rawValue
188-
}
189-
}
50+
public typealias Kind = SemanticTokenTypes
51+
public typealias Modifiers = SemanticTokenModifiers
19052
}
19153

19254
extension Array where Element == SyntaxHighlightingToken {
@@ -214,7 +76,7 @@ extension Array where Element == SyntaxHighlightingToken {
21476
UInt32(lineDelta),
21577
UInt32(charDelta),
21678
UInt32(token.utf16length),
217-
token.kind.rawValue,
79+
token.kind.tokenType,
21880
token.modifiers.rawValue,
21981
]
22082
}
@@ -230,3 +92,24 @@ extension Array where Element == SyntaxHighlightingToken {
23092
return filter { !otherRanges.contains($0.range) } + other
23193
}
23294
}
95+
96+
extension SemanticTokenTypes {
97+
/// **(LSP Extension)**
98+
public static let identifier = Self("identifier")
99+
100+
// LSP doesn’t know about actors. Display actors as classes.
101+
public static let actor = Self("class")
102+
103+
/// All tokens supported by sourcekit-lsp
104+
public static let all: [Self] = predefined + [.identifier, .actor]
105+
106+
/// Token types are looked up by index
107+
public var tokenType: UInt32 {
108+
UInt32(Self.all.firstIndex(of: self)!)
109+
}
110+
}
111+
112+
extension SemanticTokenModifiers {
113+
/// All tokens supported by sourcekit-lsp
114+
public static let all: [Self] = predefined
115+
}

Tests/SourceKitLSPTests/SemanticTokensTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ final class SemanticTokensTests: XCTestCase {
5353
range: .bool(true),
5454
full: .bool(true)
5555
),
56-
tokenTypes: Token.Kind.allCases.map(\._lspName),
57-
tokenModifiers: Token.Modifiers.allModifiers.map { $0._lspName! },
56+
tokenTypes: Token.Kind.all.map(\.name),
57+
tokenModifiers: Token.Modifiers.all.compactMap(\.name),
5858
formats: [.relative]
5959
)
6060
)
@@ -176,13 +176,13 @@ final class SemanticTokensTests: XCTestCase {
176176
2, // line delta
177177
3, // char delta
178178
5, // length
179-
Token.Kind.string.rawValue, // kind
179+
Token.Kind.string.tokenType, // kind
180180
0, // modifiers
181181

182182
2, // line delta
183183
2, // char delta
184184
1, // length
185-
Token.Kind.interface.rawValue, // kind
185+
Token.Kind.interface.tokenType, // kind
186186
Token.Modifiers.deprecated.rawValue | Token.Modifiers.definition.rawValue, // modifiers
187187
]
188188
)

0 commit comments

Comments
 (0)