diff --git a/Release Notes/601.md b/Release Notes/601.md index 9bf8ee872d9..66f907e2cbf 100644 --- a/Release Notes/601.md +++ b/Release Notes/601.md @@ -7,6 +7,10 @@ - Issue: https://github.com/apple/swift-syntax/issues/405 - Pull Request: https://github.com/apple/swift-syntax/pull/2605 +- `TokenSyntax.identifier` + - Description: Adds an `identifier` property to `TokenSyntax` which returns a canonicalized representation of an identifier that strips away backticks. + - Pull request: https://github.com/apple/swift-syntax/pull/2576 + ## API Behavior Changes ## Deprecations diff --git a/Sources/SwiftSyntax/CMakeLists.txt b/Sources/SwiftSyntax/CMakeLists.txt index 23cdd2fbb59..0f72aed545b 100644 --- a/Sources/SwiftSyntax/CMakeLists.txt +++ b/Sources/SwiftSyntax/CMakeLists.txt @@ -15,6 +15,7 @@ add_swift_syntax_library(SwiftSyntax CommonAncestor.swift Convenience.swift CustomTraits.swift + Identifier.swift MemoryLayout.swift MissingNodeInitializers.swift SourceEdit.swift diff --git a/Sources/SwiftSyntax/Identifier.swift b/Sources/SwiftSyntax/Identifier.swift new file mode 100644 index 00000000000..0864e754744 --- /dev/null +++ b/Sources/SwiftSyntax/Identifier.swift @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +/// A canonicalized representation of an identifier that strips away backticks. +public struct Identifier: Equatable, Hashable, Sendable { + /// The sanitized `text` of a token. + public var name: String { + String(syntaxText: raw.name) + } + + @_spi(RawSyntax) + public let raw: RawIdentifier + + private let arena: SyntaxArenaRef + + public init?(_ token: TokenSyntax) { + guard case .identifier = token.tokenKind else { + return nil + } + + self.raw = RawIdentifier(token.tokenView) + self.arena = token.tokenView.raw.arenaReference + } +} + +@_spi(RawSyntax) +public struct RawIdentifier: Equatable, Hashable, Sendable { + public let name: SyntaxText + + @_spi(RawSyntax) + fileprivate init(_ raw: RawSyntaxTokenView) { + let backtick = SyntaxText("`") + if raw.rawText.count > 2 && raw.rawText.hasPrefix(backtick) && raw.rawText.hasSuffix(backtick) { + let startIndex = raw.rawText.index(after: raw.rawText.startIndex) + let endIndex = raw.rawText.index(before: raw.rawText.endIndex) + self.name = SyntaxText(rebasing: raw.rawText[startIndex..