Skip to content

Commit 1cd6c22

Browse files
authored
Merge pull request #1953 from StevenWong12/convert_coloring_lit_test
Convert `lit`-based syntax classification test to XCTest
2 parents c0c1e5e + 462b69b commit 1cd6c22

File tree

6 files changed

+509
-16
lines changed

6 files changed

+509
-16
lines changed

Sources/SwiftIDEUtils/SyntaxClassification.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ public enum SyntaxClassification {
3939
case lineComment
4040
/// The token should not receive syntax coloring.
4141
case none
42-
/// An image, color, etc. literal.
43-
case objectLiteral
4442
/// An identifier referring to an operator.
4543
case operatorIdentifier
4644
/// A `#` token like `#warning`.
@@ -66,7 +64,7 @@ extension SyntaxClassification {
6664
internal static func classify(_ keyPath: AnyKeyPath) -> (SyntaxClassification, Bool)? {
6765
switch keyPath {
6866
case \AttributeSyntax.attributeName:
69-
return (.attribute, false)
67+
return (.attribute, true)
7068
case \PlatformVersionItemSyntax.availabilityVersionRestriction:
7169
return (.keyword, false)
7270
case \AvailabilityVersionRestrictionSyntax.platform:

Sources/SwiftIDEUtils/SyntaxClassifier.swift

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -160,17 +160,24 @@ private struct ClassificationVisitor {
160160
classifications.append(range)
161161
}
162162

163+
/// Classifies `triviaPieces` starting from `offset` and returns the number of bytes the trivia took up in the source
164+
private mutating func classify(triviaPieces: [RawTriviaPiece], at offset: Int) -> Int {
165+
var classifiedBytes = 0
166+
for triviaPiece in triviaPieces {
167+
let range = triviaPiece.classify(offset: offset + classifiedBytes)
168+
report(range: range)
169+
classifiedBytes += triviaPiece.byteLength
170+
}
171+
return classifiedBytes
172+
}
173+
163174
// Report classification ranges in `descriptor.node` that is a token.
164175
private mutating func handleToken(_ descriptor: Descriptor) -> VisitResult {
165176
let tokenView = descriptor.node.tokenView!
166177
var byteOffset = descriptor.byteOffset
167178

168179
// Leading trivia.
169-
for piece in tokenView.leadingRawTriviaPieces {
170-
let range = piece.classify(offset: byteOffset)
171-
report(range: range)
172-
byteOffset += piece.byteLength
173-
}
180+
byteOffset += classify(triviaPieces: tokenView.leadingRawTriviaPieces, at: byteOffset)
174181
// Token text.
175182
do {
176183
let range = TokenKindAndText(kind: tokenView.rawKind, text: tokenView.rawText)
@@ -179,11 +186,7 @@ private struct ClassificationVisitor {
179186
byteOffset += tokenView.rawText.count
180187
}
181188
// Trailing trivia.
182-
for piece in tokenView.trailingRawTriviaPieces {
183-
let range = piece.classify(offset: byteOffset)
184-
report(range: range)
185-
byteOffset += piece.byteLength
186-
}
189+
byteOffset += classify(triviaPieces: tokenView.trailingRawTriviaPieces, at: byteOffset)
187190

188191
precondition(byteOffset == descriptor.byteOffset + descriptor.node.byteLength)
189192
return .continue
@@ -196,12 +199,37 @@ private struct ClassificationVisitor {
196199

197200
for case (let index, let child?) in children.enumerated() {
198201

199-
let classification: (SyntaxClassification, Bool)?
202+
let classification: (classification: SyntaxClassification, force: Bool)?
200203
if case .layout(let layout) = descriptor.node.kind.syntaxNodeType.structure {
201204
classification = SyntaxClassification.classify(layout[index])
202205
} else {
203206
classification = nil
204207
}
208+
209+
if let classification, classification.force {
210+
// Leading trivia.
211+
if let leadingTriviaPieces = child.leadingTriviaPieces {
212+
byteOffset += classify(triviaPieces: leadingTriviaPieces, at: byteOffset)
213+
}
214+
// Layout node text.
215+
let layoutNodeTextLength = child.byteLength - child.leadingTriviaByteLength - child.trailingTriviaByteLength
216+
let range = SyntaxClassifiedRange(
217+
kind: classification.classification,
218+
range: ByteSourceRange(
219+
offset: byteOffset,
220+
length: layoutNodeTextLength
221+
)
222+
)
223+
report(range: range)
224+
byteOffset += layoutNodeTextLength
225+
226+
// Trailing trivia.
227+
if let trailingTriviaPieces = child.trailingTriviaPieces {
228+
byteOffset += classify(triviaPieces: trailingTriviaPieces, at: byteOffset)
229+
}
230+
continue
231+
}
232+
205233
let result = visit(
206234
.init(
207235
node: child,

Sources/SwiftSyntax/Raw/RawSyntax.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,16 @@ extension RawSyntax {
505505
lastToken(viewMode: .sourceAccurate)?.trailingTriviaByteLength ?? 0
506506
}
507507

508+
@_spi(RawSyntax)
509+
public var leadingTriviaPieces: [RawTriviaPiece]? {
510+
firstToken(viewMode: .sourceAccurate)?.leadingRawTriviaPieces
511+
}
512+
513+
@_spi(RawSyntax)
514+
public var trailingTriviaPieces: [RawTriviaPiece]? {
515+
lastToken(viewMode: .sourceAccurate)?.trailingRawTriviaPieces
516+
}
517+
508518
/// The length of this node’s content, without the first leading and the last
509519
/// trailing trivia. Intermediate trivia inside a layout node is included in
510520
/// this.

Sources/lit-test-helper/ClassifiedSyntaxTreePrinter.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ extension SyntaxClassification {
3030
case .poundDirective: return "#kw"
3131
case .buildConfigId: return "#id"
3232
case .attribute: return "attr-builtin"
33-
case .objectLiteral: return "object-literal"
3433
case .editorPlaceholder: return "placeholder"
3534
case .lineComment: return "comment-line"
3635
case .blockComment: return "comment-block"

Tests/SwiftIDEUtilsTest/Assertions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func assertClassification(
7171
line: spec.line
7272
)
7373

74-
lastRangeUpperBound = source.index(source.startIndex, offsetBy: range.endOffset)
74+
lastRangeUpperBound = source.utf8.index(source.utf8.startIndex, offsetBy: range.endOffset)
7575
}
7676
}
7777

0 commit comments

Comments
 (0)