Skip to content

Commit c49eb29

Browse files
authored
Merge pull request swiftlang#109 from akyrtzi/classification-enhancements
Enhancements to classification mechanism
2 parents f650fa3 + 4b7ef21 commit c49eb29

File tree

6 files changed

+286
-104
lines changed

6 files changed

+286
-104
lines changed

Sources/SwiftSyntax/Syntax.swift

+67
Original file line numberDiff line numberDiff line change
@@ -251,20 +251,55 @@ extension _SyntaxBase {
251251
}
252252

253253
/// Sequence of `SyntaxClassifiedRange`s for this syntax node.
254+
///
255+
/// The provided classified ranges are consecutive and cover the full source
256+
/// text of the node. The ranges may also span multiple tokens, if multiple
257+
/// consecutive tokens would have the same classification then a single classified
258+
/// range is provided for all of them.
254259
var classifications: SyntaxClassifications {
255260
let fullRange = ByteSourceRange(offset: 0, length: byteSize)
256261
return SyntaxClassifications(self, in: fullRange)
257262
}
258263

259264
/// Sequence of `SyntaxClassifiedRange`s contained in this syntax node within
260265
/// a relative range.
266+
///
267+
/// The provided classified ranges may extend beyond the provided `range`.
268+
/// Active classifications (non-`none`) will extend the range to include the
269+
/// full classified range (e.g. from the beginning of the comment block), while
270+
/// `none` classified ranges will extend to the beginning or end of the token
271+
/// that the `range` touches.
272+
/// It is guaranteed that no classified range will be provided that doesn't
273+
/// intersect the provided `range`.
274+
///
261275
/// - Parameters:
262276
/// - in: The relative byte range to pull `SyntaxClassifiedRange`s from.
263277
/// - Returns: Sequence of `SyntaxClassifiedRange`s.
264278
func classifications(in range: ByteSourceRange) -> SyntaxClassifications {
265279
return SyntaxClassifications(self, in: range)
266280
}
267281

282+
/// The `SyntaxClassifiedRange` for a relative byte offset.
283+
/// - Parameters:
284+
/// - at: The relative to the node byte offset.
285+
/// - Returns: The `SyntaxClassifiedRange` for the offset or nil if the source text
286+
/// at the given offset is unclassified.
287+
func classification(at offset: Int) -> SyntaxClassifiedRange? {
288+
let classifications = SyntaxClassifications(self, in: ByteSourceRange(offset: offset, length: 1))
289+
var iterator = classifications.makeIterator()
290+
return iterator.next()
291+
}
292+
293+
/// The `SyntaxClassifiedRange` for an absolute position.
294+
/// - Parameters:
295+
/// - at: The absolute position.
296+
/// - Returns: The `SyntaxClassifiedRange` for the position or nil if the source text
297+
/// at the given position is unclassified.
298+
func classification(at position: AbsolutePosition) -> SyntaxClassifiedRange? {
299+
let relativeOffset = position.utf8Offset - self.position.utf8Offset
300+
return self.classification(at: relativeOffset)
301+
}
302+
268303
/// Returns a value representing the unique identity of the node.
269304
var uniqueIdentifier: SyntaxIdentifier {
270305
return data.nodeId
@@ -483,19 +518,51 @@ extension Syntax {
483518
}
484519

485520
/// Sequence of `SyntaxClassifiedRange`s for this syntax node.
521+
///
522+
/// The provided classification ranges are consecutive and cover the full source
523+
/// text of the node. The ranges may also span multiple tokens, if multiple
524+
/// consecutive tokens would have the same classification then a single classified
525+
/// range is provided for all of them.
486526
public var classifications: SyntaxClassifications {
487527
return base.classifications
488528
}
489529

490530
/// Sequence of `SyntaxClassifiedRange`s contained in this syntax node within
491531
/// a relative range.
532+
///
533+
/// The provided classified ranges may extend beyond the provided `range`.
534+
/// Active classifications (non-`none`) will extend the range to include the
535+
/// full classified range (e.g. from the beginning of the comment block), while
536+
/// `none` classified ranges will extend to the beginning or end of the token
537+
/// that the `range` touches.
538+
/// It is guaranteed that no classified range will be provided that doesn't
539+
/// intersect the provided `range`.
540+
///
492541
/// - Parameters:
493542
/// - in: The relative byte range to pull `SyntaxClassifiedRange`s from.
494543
/// - Returns: Sequence of `SyntaxClassifiedRange`s.
495544
public func classifications(in range: ByteSourceRange) -> SyntaxClassifications {
496545
return base.classifications(in: range)
497546
}
498547

548+
/// The `SyntaxClassifiedRange` for a relative byte offset.
549+
/// - Parameters:
550+
/// - at: The relative to the node byte offset.
551+
/// - Returns: The `SyntaxClassifiedRange` for the offset or nil if the source text
552+
/// at the given offset is unclassified.
553+
public func classification(at offset: Int) -> SyntaxClassifiedRange? {
554+
return base.classification(at: offset)
555+
}
556+
557+
/// The `SyntaxClassifiedRange` for an absolute position.
558+
/// - Parameters:
559+
/// - at: The absolute position.
560+
/// - Returns: The `SyntaxClassifiedRange` for the position or nil if the source text
561+
/// at the given position is unclassified.
562+
public func classification(at position: AbsolutePosition) -> SyntaxClassifiedRange? {
563+
return base.classification(at: position)
564+
}
565+
499566
/// Returns a value representing the unique identity of the node.
500567
public var uniqueIdentifier: SyntaxIdentifier {
501568
return base.uniqueIdentifier

Sources/SwiftSyntax/SyntaxClassification.swift.gyb

+5-5
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ extension SyntaxClassification {
5555
/// - Returns: A pair of classification and whether it is "forced", or nil if
5656
/// no classification is attached.
5757
internal static func classify(
58-
parentKind: SyntaxKind, indexInParent: UInt32, childKind: SyntaxKind
58+
parentKind: SyntaxKind, indexInParent: Int, childKind: SyntaxKind
5959
) -> (SyntaxClassification, Bool)? {
6060
// Separate checks for token nodes (most common checks) versus checks for layout nodes.
6161
if childKind == .token {
@@ -83,18 +83,18 @@ extension SyntaxClassification {
8383
}
8484

8585
extension RawTokenKind {
86-
internal var classification: SyntaxClassification? {
86+
internal var classification: SyntaxClassification {
8787
switch (self) {
8888
% for token in SYNTAX_TOKENS:
8989
case .${token.swift_kind()}:
90-
% if token.classification and token.classification.name != 'None':
90+
% if token.classification:
9191
return .${token.classification.swift_name}
9292
% else:
93-
return nil
93+
return .none
9494
% end
9595
% end
9696
case .eof:
97-
return nil
97+
return .none
9898
}
9999
}
100100
}

0 commit comments

Comments
 (0)