Skip to content

Commit a2a871f

Browse files
authored
Merge pull request #999 from ahoppen/ahoppen/move-syntax-classifier-to-separate-package
Move SyntaxClassifier to a separate module
2 parents 41dafda + 19e9f7f commit a2a871f

21 files changed

+830
-430
lines changed

Package.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ let package = Package(
4545
.macCatalyst(.v13),
4646
],
4747
products: [
48+
.library(name: "IDEUtils", type: .static, targets: ["IDEUtils"]),
4849
.library(name: "SwiftDiagnostics", type: .static, targets: ["SwiftDiagnostics"]),
4950
.library(name: "SwiftOperators", type: .static, targets: ["SwiftOperators"]),
5051
.library(name: "SwiftParser", type: .static, targets: ["SwiftParser"]),
@@ -79,7 +80,6 @@ let package = Package(
7980
"Raw/RawSyntaxValidation.swift.gyb",
8081
"SyntaxAnyVisitor.swift.gyb",
8182
"SyntaxBaseNodes.swift.gyb",
82-
"SyntaxClassification.swift.gyb",
8383
"SyntaxCollections.swift.gyb",
8484
"SyntaxEnum.swift.gyb",
8585
"SyntaxFactory.swift.gyb",
@@ -116,6 +116,13 @@ let package = Package(
116116
name: "_SwiftSyntaxTestSupport",
117117
dependencies: ["SwiftBasicFormat", "SwiftSyntax", "SwiftSyntaxBuilder"]
118118
),
119+
.target(
120+
name: "IDEUtils",
121+
dependencies: ["SwiftSyntax"],
122+
exclude: [
123+
"SyntaxClassification.swift.gyb",
124+
]
125+
),
119126
.target(
120127
name: "SwiftParser",
121128
dependencies: ["SwiftDiagnostics", "SwiftSyntax"],
@@ -160,13 +167,14 @@ let package = Package(
160167
]),
161168
.executableTarget(
162169
name: "lit-test-helper",
163-
dependencies: ["SwiftSyntax", "SwiftSyntaxParser"]
170+
dependencies: ["IDEUtils", "SwiftSyntax", "SwiftSyntaxParser"]
164171
),
165172
.executableTarget(
166173
name: "swift-parser-cli",
167174
dependencies: ["SwiftDiagnostics", "SwiftSyntax", "SwiftParser", "SwiftParserDiagnostics", "SwiftOperators", "_SwiftSyntaxMacros",
168175
.product(name: "ArgumentParser", package: "swift-argument-parser")]
169176
),
177+
.testTarget(name: "IDEUtilsTest", dependencies: ["_SwiftSyntaxTestSupport", "SwiftParser", "SwiftSyntax", "IDEUtils"]),
170178
.testTarget(
171179
name: "SwiftDiagnosticsTest",
172180
dependencies: ["_SwiftSyntaxTestSupport", "SwiftDiagnostics", "SwiftParser", "SwiftParserDiagnostics"]
@@ -192,7 +200,7 @@ let package = Package(
192200
),
193201
.testTarget(
194202
name: "PerformanceTest",
195-
dependencies: ["SwiftSyntax", "SwiftSyntaxParser", "SwiftParser"],
203+
dependencies: ["IDEUtils", "SwiftSyntax", "SwiftSyntaxParser", "SwiftParser"],
196204
exclude: ["Inputs"]
197205
),
198206
.testTarget(
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 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 SwiftSyntax
14+
15+
public extension SyntaxProtocol {
16+
17+
/// Sequence of `SyntaxClassifiedRange`s for this syntax node.
18+
///
19+
/// The provided classified ranges are consecutive and cover the full source
20+
/// text of the node. The ranges may also span multiple tokens, if multiple
21+
/// consecutive tokens would have the same classification then a single classified
22+
/// range is provided for all of them.
23+
var classifications: SyntaxClassifications {
24+
let fullRange = ByteSourceRange(offset: 0, length: byteSize)
25+
return SyntaxClassifications(_syntaxNode, in: fullRange)
26+
}
27+
28+
/// Sequence of `SyntaxClassifiedRange`s contained in this syntax node within
29+
/// a relative range.
30+
///
31+
/// The provided classified ranges may extend beyond the provided `range`.
32+
/// Active classifications (non-`none`) will extend the range to include the
33+
/// full classified range (e.g. from the beginning of the comment block), while
34+
/// `none` classified ranges will extend to the beginning or end of the token
35+
/// that the `range` touches.
36+
/// It is guaranteed that no classified range will be provided that doesn't
37+
/// intersect the provided `range`.
38+
///
39+
/// - Parameters:
40+
/// - in: The relative byte range to pull `SyntaxClassifiedRange`s from.
41+
/// - Returns: Sequence of `SyntaxClassifiedRange`s.
42+
func classifications(in range: ByteSourceRange) -> SyntaxClassifications {
43+
return SyntaxClassifications(_syntaxNode, in: range)
44+
}
45+
46+
/// The `SyntaxClassifiedRange` for a relative byte offset.
47+
/// - Parameters:
48+
/// - at: The relative to the node byte offset.
49+
/// - Returns: The `SyntaxClassifiedRange` for the offset or nil if the source text
50+
/// at the given offset is unclassified.
51+
func classification(at offset: Int) -> SyntaxClassifiedRange? {
52+
let classifications = SyntaxClassifications(_syntaxNode, in: ByteSourceRange(offset: offset, length: 1))
53+
var iterator = classifications.makeIterator()
54+
return iterator.next()
55+
}
56+
57+
/// The `SyntaxClassifiedRange` for an absolute position.
58+
/// - Parameters:
59+
/// - at: The absolute position.
60+
/// - Returns: The `SyntaxClassifiedRange` for the position or nil if the source text
61+
/// at the given position is unclassified.
62+
func classification(at position: AbsolutePosition) -> SyntaxClassifiedRange? {
63+
let relativeOffset = position.utf8Offset - self.position.utf8Offset
64+
return self.classification(at: relativeOffset)
65+
}
66+
}

Sources/SwiftSyntax/SyntaxClassification.swift.gyb renamed to Sources/IDEUtils/SyntaxClassification.swift.gyb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
//
3636
//===----------------------------------------------------------------------===//
3737

38+
@_spi(RawSyntax) import SwiftSyntax
39+
3840
public enum SyntaxClassification {
3941
% for classification in SYNTAX_CLASSIFICATIONS:
4042
% for line in dedented_lines(classification.description):

Sources/SwiftSyntax/SyntaxClassifier.swift renamed to Sources/IDEUtils/SyntaxClassifier.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
extension SyntaxData {
13+
@_spi(RawSyntax) import SwiftSyntax
14+
15+
fileprivate extension SyntaxProtocol {
1416
var contextualClassification: (SyntaxClassification, Bool)? {
1517
var contextualClassif: (SyntaxClassification, Bool)? = nil
16-
var curData = self
18+
var curData = Syntax(self)
1719
repeat {
1820
guard let parent = curData.parent else { break }
1921
contextualClassif = SyntaxClassification.classify(parentKind: parent.raw.kind,
@@ -27,10 +29,10 @@ extension SyntaxData {
2729
extension TokenSyntax {
2830
/// The `SyntaxClassifiedRange` for the token text, excluding trivia.
2931
public var tokenClassification: SyntaxClassifiedRange {
30-
let contextualClassification = self.data.contextualClassification
31-
let relativeOffset = tokenView.leadingTriviaLength.utf8Length
32+
let contextualClassification = self.contextualClassification
33+
let relativeOffset = leadingTriviaLength.utf8Length
3234
let absoluteOffset = position.utf8Offset + relativeOffset
33-
return TokenKindAndText(kind: tokenView.rawKind, text: tokenView.rawText).classify(
35+
return TokenKindAndText(kind: rawTokenKind, text: tokenView.rawText).classify(
3436
offset: absoluteOffset, contextualClassification: contextualClassification)
3537
}
3638
}
@@ -122,7 +124,7 @@ private struct ClassificationVisitor {
122124
_ = self.visit(Descriptor(
123125
node: node.raw,
124126
byteOffset: node.position.utf8Offset,
125-
contextualClassification: node.data.contextualClassification))
127+
contextualClassification: node.contextualClassification))
126128
}
127129
}
128130

Sources/SwiftSyntax/gyb_generated/SyntaxClassification.swift renamed to Sources/IDEUtils/gyb_generated/SyntaxClassification.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15+
@_spi(RawSyntax) import SwiftSyntax
16+
1517
public enum SyntaxClassification {
1618
/// The token should not receive syntax coloring.
1719
case none

Sources/SwiftSyntax/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ add_library(SwiftSyntax STATIC
1818
Syntax.swift
1919
SyntaxArena.swift
2020
SyntaxChildren.swift
21-
SyntaxClassifier.swift
2221
SyntaxData.swift
2322
SyntaxOtherNodes.swift
2423
SyntaxText.swift
@@ -37,7 +36,6 @@ add_library(SwiftSyntax STATIC
3736
gyb_generated/Misc.swift
3837
gyb_generated/SyntaxAnyVisitor.swift
3938
gyb_generated/SyntaxBaseNodes.swift
40-
gyb_generated/SyntaxClassification.swift
4139
gyb_generated/SyntaxCollections.swift
4240
gyb_generated/SyntaxEnum.swift
4341
gyb_generated/SyntaxFactory.swift

Sources/SwiftSyntax/Raw/RawSyntax.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
typealias RawSyntaxBuffer = UnsafeBufferPointer<RawSyntax?>
13+
@_spi(RawSyntax) public typealias RawSyntaxBuffer = UnsafeBufferPointer<RawSyntax?>
1414
typealias RawTriviaPieceBuffer = UnsafeBufferPointer<RawTriviaPiece>
1515

1616
fileprivate extension SyntaxKind {
@@ -148,7 +148,8 @@ extension RawSyntax {
148148
}
149149

150150
/// Whether or not this node is a token one.
151-
var isToken: Bool {
151+
@_spi(RawSyntax)
152+
public var isToken: Bool {
152153
kind == .token
153154
}
154155

@@ -171,7 +172,7 @@ extension RawSyntax {
171172
}
172173
return recursiveFlags
173174
case .layout(let layoutView):
174-
return layoutView.layoutData.recursiveFlags
175+
return layoutView.recursiveFlags
175176
}
176177
}
177178

Sources/SwiftSyntax/Raw/RawSyntaxLayoutView.swift

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
extension RawSyntax {
1414
/// A view into the `RawSyntax` that exposes functionality that's specific to layout nodes.
1515
/// The token's payload must be a layout, otherwise this traps.
16-
var layoutView: RawSyntaxLayoutView? {
16+
@_spi(RawSyntax)
17+
public var layoutView: RawSyntaxLayoutView? {
1718
switch raw.payload {
1819
case .parsedToken, .materializedToken:
1920
return nil
@@ -24,7 +25,8 @@ extension RawSyntax {
2425
}
2526

2627
/// A view into `RawSyntax` that exposes functionality that only applies to layout nodes.
27-
struct RawSyntaxLayoutView {
28+
@_spi(RawSyntax)
29+
public struct RawSyntaxLayoutView {
2830
private let raw: RawSyntax
2931

3032
fileprivate init(raw: RawSyntax) {
@@ -37,7 +39,7 @@ struct RawSyntaxLayoutView {
3739
}
3840
}
3941

40-
var layoutData: RawSyntaxData.Layout {
42+
private var layoutData: RawSyntaxData.Layout {
4143
switch raw.rawData.payload {
4244
case .parsedToken(_),
4345
.materializedToken(_):
@@ -47,8 +49,13 @@ struct RawSyntaxLayoutView {
4749
}
4850
}
4951

52+
var recursiveFlags: RecursiveRawSyntaxFlags {
53+
return layoutData.recursiveFlags
54+
}
55+
5056
/// Creates a new node of the same kind but with children replaced by `elements`.
51-
func replacingLayout<C: Collection>(
57+
@_spi(RawSyntax)
58+
public func replacingLayout<C: Collection>(
5259
with elements: C,
5360
arena: SyntaxArena
5461
) -> RawSyntax where C.Element == RawSyntax? {
@@ -60,7 +67,8 @@ struct RawSyntaxLayoutView {
6067
}
6168
}
6269

63-
func insertingChild(
70+
@_spi(RawSyntax)
71+
public func insertingChild(
6472
_ newChild: RawSyntax?,
6573
at index: Int,
6674
arena: SyntaxArena
@@ -78,7 +86,8 @@ struct RawSyntaxLayoutView {
7886
}
7987
}
8088

81-
func removingChild(
89+
@_spi(RawSyntax)
90+
public func removingChild(
8291
at index: Int,
8392
arena: SyntaxArena
8493
) -> RawSyntax {
@@ -101,11 +110,13 @@ struct RawSyntaxLayoutView {
101110
}
102111
}
103112

104-
func appending(_ newChild: RawSyntax?, arena: SyntaxArena) -> RawSyntax {
113+
@_spi(RawSyntax)
114+
public func appending(_ newChild: RawSyntax?, arena: SyntaxArena) -> RawSyntax {
105115
insertingChild(newChild, at: children.count, arena: arena)
106116
}
107117

108-
func replacingChildSubrange<C: Collection>(
118+
@_spi(RawSyntax)
119+
public func replacingChildSubrange<C: Collection>(
109120
_ range: Range<Int>,
110121
with elements: C,
111122
arena: SyntaxArena
@@ -130,7 +141,8 @@ struct RawSyntaxLayoutView {
130141
}
131142
}
132143

133-
func replacingChild(
144+
@_spi(RawSyntax)
145+
public func replacingChild(
134146
at index: Int,
135147
with newChild: RawSyntax?,
136148
arena: SyntaxArena
@@ -144,17 +156,20 @@ struct RawSyntaxLayoutView {
144156
}
145157
}
146158

147-
func formLayoutArray() -> [RawSyntax?] {
159+
@_spi(RawSyntax)
160+
public func formLayoutArray() -> [RawSyntax?] {
148161
Array(children)
149162
}
150163

151164
/// Child nodes.
152-
var children: RawSyntaxBuffer {
165+
@_spi(RawSyntax)
166+
public var children: RawSyntaxBuffer {
153167
layoutData.layout
154168
}
155169

156170
/// The number of children, `present` or `missing`, in this node.
157-
var numberOfChildren: Int {
171+
@_spi(RawSyntax)
172+
public var numberOfChildren: Int {
158173
return children.count
159174
}
160175
}

Sources/SwiftSyntax/Raw/RawSyntaxNodeProtocol.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ extension RawSyntax: RawSyntaxNodeProtocol {
6868
public struct RawTokenSyntax: RawSyntaxToSyntax, RawSyntaxNodeProtocol {
6969
public typealias SyntaxType = TokenSyntax
7070

71-
var tokenView: RawSyntaxTokenView {
71+
@_spi(RawSyntax)
72+
public var tokenView: RawSyntaxTokenView {
7273
return raw.tokenView!
7374
}
7475

Sources/SwiftSyntax/Raw/RawSyntaxNodes.swift.gyb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ public protocol Raw${node.name}NodeProtocol: Raw${node.base_type}NodeProtocol {}
3131
public struct Raw${node.name}: Raw${node.name if node.is_base() else node.base_type}NodeProtocol, RawSyntaxToSyntax {
3232
public typealias SyntaxType = ${node.name}
3333

34-
var layoutView: RawSyntaxLayoutView {
34+
@_spi(RawSyntax)
35+
public var layoutView: RawSyntaxLayoutView {
3536
return raw.layoutView!
3637
}
3738

0 commit comments

Comments
 (0)