Skip to content

Commit 85837e7

Browse files
committed
Move SyntaxClassifier to a separate module
rdar://98318240
1 parent 2306b3e commit 85837e7

12 files changed

+97
-62
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/Syntax.swift

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -456,56 +456,6 @@ public extension SyntaxProtocol {
456456
return TokenSequence(_syntaxNode, viewMode: viewMode)
457457
}
458458

459-
/// Sequence of `SyntaxClassifiedRange`s for this syntax node.
460-
///
461-
/// The provided classified ranges are consecutive and cover the full source
462-
/// text of the node. The ranges may also span multiple tokens, if multiple
463-
/// consecutive tokens would have the same classification then a single classified
464-
/// range is provided for all of them.
465-
var classifications: SyntaxClassifications {
466-
let fullRange = ByteSourceRange(offset: 0, length: byteSize)
467-
return SyntaxClassifications(_syntaxNode, in: fullRange)
468-
}
469-
470-
/// Sequence of `SyntaxClassifiedRange`s contained in this syntax node within
471-
/// a relative range.
472-
///
473-
/// The provided classified ranges may extend beyond the provided `range`.
474-
/// Active classifications (non-`none`) will extend the range to include the
475-
/// full classified range (e.g. from the beginning of the comment block), while
476-
/// `none` classified ranges will extend to the beginning or end of the token
477-
/// that the `range` touches.
478-
/// It is guaranteed that no classified range will be provided that doesn't
479-
/// intersect the provided `range`.
480-
///
481-
/// - Parameters:
482-
/// - in: The relative byte range to pull `SyntaxClassifiedRange`s from.
483-
/// - Returns: Sequence of `SyntaxClassifiedRange`s.
484-
func classifications(in range: ByteSourceRange) -> SyntaxClassifications {
485-
return SyntaxClassifications(_syntaxNode, in: range)
486-
}
487-
488-
/// The `SyntaxClassifiedRange` for a relative byte offset.
489-
/// - Parameters:
490-
/// - at: The relative to the node byte offset.
491-
/// - Returns: The `SyntaxClassifiedRange` for the offset or nil if the source text
492-
/// at the given offset is unclassified.
493-
func classification(at offset: Int) -> SyntaxClassifiedRange? {
494-
let classifications = SyntaxClassifications(_syntaxNode, in: ByteSourceRange(offset: offset, length: 1))
495-
var iterator = classifications.makeIterator()
496-
return iterator.next()
497-
}
498-
499-
/// The `SyntaxClassifiedRange` for an absolute position.
500-
/// - Parameters:
501-
/// - at: The absolute position.
502-
/// - Returns: The `SyntaxClassifiedRange` for the position or nil if the source text
503-
/// at the given position is unclassified.
504-
func classification(at position: AbsolutePosition) -> SyntaxClassifiedRange? {
505-
let relativeOffset = position.utf8Offset - self.position.utf8Offset
506-
return self.classification(at: relativeOffset)
507-
}
508-
509459
/// Returns a value representing the unique identity of the node.
510460
var id: SyntaxIdentifier {
511461
return data.nodeId

Sources/SwiftSyntax/SyntaxTreeViewMode.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ public enum SyntaxTreeViewMode {
2828
case all
2929

3030
/// Returns whether this traversal node should visit `node` or ignore it.
31-
func shouldTraverse(node: RawSyntax) -> Bool {
31+
@_spi(RawSyntax)
32+
public func shouldTraverse(node: RawSyntax) -> Bool {
3233
switch self {
3334
case .sourceAccurate:
3435
if let tokenView = node.tokenView {

Sources/lit-test-helper/ClassifiedSyntaxTreePrinter.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
import IDEUtils
1314
import SwiftSyntax
1415
import Foundation
1516

Tests/SwiftParserTest/ClassificationTests.swift renamed to Tests/IDEUtilsTest/ClassificationTests.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
import XCTest
14+
import IDEUtils
1415
import SwiftSyntax
1516
import SwiftParser
17+
import _SwiftSyntaxTestSupport
1618

1719
public class ClassificationTests: XCTestCase {
1820

Tests/PerformanceTest/SyntaxClassifierPerformanceTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
import XCTest
14+
import IDEUtils
1415
import SwiftSyntax
1516
import SwiftSyntaxParser
1617

build-script.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
WORKSPACE_DIR = os.path.dirname(PACKAGE_DIR)
1818
EXAMPLES_DIR = os.path.join(PACKAGE_DIR, "Examples")
1919
SOURCES_DIR = os.path.join(PACKAGE_DIR, "Sources")
20+
IDEUTILS_DIR = os.path.join(SOURCES_DIR, "IDEUtils")
2021
SWIFTSYNTAX_DIR = os.path.join(SOURCES_DIR, "SwiftSyntax")
2122
SWIFTSYNTAX_DOCUMENTATION_DIR = \
2223
os.path.join(SWIFTSYNTAX_DIR, "Documentation.docc")
@@ -300,6 +301,7 @@ def generate_syntax_node_template_gyb_files(
300301
def gyb_dir_mapping(temp_directories: bool) -> Dict[str, str]:
301302
source_dirs = [
302303
SYNTAXSUPPORT_DIR,
304+
IDEUTILS_DIR,
303305
SWIFTSYNTAX_DIR,
304306
os.path.join(SWIFTSYNTAX_DIR, "Raw"),
305307
SWIFTSYNTAXBUILDER_DIR,

0 commit comments

Comments
 (0)