Skip to content

Commit

Permalink
Tests broke on Linux, simplify & fix
Browse files Browse the repository at this point in the history
  • Loading branch information
djbe committed Jul 21, 2022
1 parent a86f6c5 commit 61ecf62
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 100 deletions.
161 changes: 72 additions & 89 deletions Sources/StencilSwiftKit/SwiftIdentifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,98 +8,86 @@ import Foundation

typealias CharRange = CountableClosedRange<Int>

private func mr(_ char: Int) -> CharRange {
char...char
}

// Official list of valid identifier characters
// swiftlint:disable:next line_length
// from: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-ID410
private let kHeadRanges: [CharRange] = [
0x61...0x7a as CharRange,
0x41...0x5a as CharRange,
mr(0x5f), mr(0xa8), mr(0xaa), mr(0xad), mr(0xaf),
0xb2...0xb5 as CharRange,
0xb7...0xba as CharRange,
0xbc...0xbe as CharRange,
0xc0...0xd6 as CharRange,
0xd8...0xf6 as CharRange,
0xf8...0xff as CharRange,
0x100...0x2ff as CharRange,
0x370...0x167f as CharRange,
0x1681...0x180d as CharRange,
0x180f...0x1dbf as CharRange,
0x1e00...0x1fff as CharRange,
0x200b...0x200d as CharRange,
0x202a...0x202e as CharRange,
mr(0x203F), mr(0x2040), mr(0x2054),
0x2060...0x206f as CharRange,
0x2070...0x20cf as CharRange,
0x2100...0x218f as CharRange,
0x2460...0x24ff as CharRange,
0x2776...0x2793 as CharRange,
0x2c00...0x2dff as CharRange,
0x2e80...0x2fff as CharRange,
0x3004...0x3007 as CharRange,
0x3021...0x302f as CharRange,
0x3031...0x303f as CharRange,
0x3040...0xd7ff as CharRange,
0xf900...0xfd3d as CharRange,
0xfd40...0xfdcf as CharRange,
0xfdf0...0xfe1f as CharRange,
0xfe30...0xfe44 as CharRange,
0xfe47...0xfffd as CharRange,
0x10000...0x1fffd as CharRange,
0x20000...0x2fffd as CharRange,
0x30000...0x3fffd as CharRange,
0x40000...0x4fffd as CharRange,
0x50000...0x5fffd as CharRange,
0x60000...0x6fffd as CharRange,
0x70000...0x7fffd as CharRange,
0x80000...0x8fffd as CharRange,
0x90000...0x9fffd as CharRange,
0xa0000...0xafffd as CharRange,
0xb0000...0xbfffd as CharRange,
0xc0000...0xcfffd as CharRange,
0xd0000...0xdfffd as CharRange,
0xe0000...0xefffd as CharRange
]
private extension CharRange {
static func mr(_ char: Int) -> CharRange {
char...char
}

private let kTailRanges: [CharRange] = [
0x30...0x39, 0x300...0x36F, 0x1dc0...0x1dff, 0x20d0...0x20ff, 0xfe20...0xfe2f
]
static let headRanges: [CharRange] = [
0x61...0x7a as CharRange,
0x41...0x5a as CharRange,
mr(0x5f), mr(0xa8), mr(0xaa), mr(0xad), mr(0xaf),
0xb2...0xb5 as CharRange,
0xb7...0xba as CharRange,
0xbc...0xbe as CharRange,
0xc0...0xd6 as CharRange,
0xd8...0xf6 as CharRange,
0xf8...0xff as CharRange,
0x100...0x2ff as CharRange,
0x370...0x167f as CharRange,
0x1681...0x180d as CharRange,
0x180f...0x1dbf as CharRange,
0x1e00...0x1fff as CharRange,
0x200b...0x200d as CharRange,
0x202a...0x202e as CharRange,
mr(0x203F), mr(0x2040), mr(0x2054),
0x2060...0x206f as CharRange,
0x2070...0x20cf as CharRange,
0x2100...0x218f as CharRange,
0x2460...0x24ff as CharRange,
0x2776...0x2793 as CharRange,
0x2c00...0x2dff as CharRange,
0x2e80...0x2fff as CharRange,
0x3004...0x3007 as CharRange,
0x3021...0x302f as CharRange,
0x3031...0x303f as CharRange,
0x3040...0xd7ff as CharRange,
0xf900...0xfd3d as CharRange,
0xfd40...0xfdcf as CharRange,
0xfdf0...0xfe1f as CharRange,
0xfe30...0xfe44 as CharRange,
0xfe47...0xfffd as CharRange,
0x10000...0x1fffd as CharRange,
0x20000...0x2fffd as CharRange,
0x30000...0x3fffd as CharRange,
0x40000...0x4fffd as CharRange,
0x50000...0x5fffd as CharRange,
0x60000...0x6fffd as CharRange,
0x70000...0x7fffd as CharRange,
0x80000...0x8fffd as CharRange,
0x90000...0x9fffd as CharRange,
0xa0000...0xafffd as CharRange,
0xb0000...0xbfffd as CharRange,
0xc0000...0xcfffd as CharRange,
0xd0000...0xdfffd as CharRange,
0xe0000...0xefffd as CharRange
]

private func identifierCharacterSets(exceptions: String) -> (head: NSMutableCharacterSet, tail: NSMutableCharacterSet) {
let addRange: (NSMutableCharacterSet, CharRange) -> Void = { mcs, range in
mcs.addCharacters(in: NSRange(location: range.lowerBound, length: range.count))
}
static let tailRanges: [CharRange] = [
0x30...0x39, 0x300...0x36F, 0x1dc0...0x1dff, 0x20d0...0x20ff, 0xfe20...0xfe2f
]
}

let head = NSMutableCharacterSet()
for range in kHeadRanges {
addRange(head, range)
}
head.removeCharacters(in: exceptions)
private extension CharacterSet {
static let illegalIdentifierHead = setFromRanges(CharRange.headRanges)
static let illegalIdentifierTail = setFromRanges(CharRange.headRanges + CharRange.tailRanges)

guard let tail = head.mutableCopy() as? NSMutableCharacterSet else {
fatalError("Internal error: mutableCopy() should have returned a valid NSMutableCharacterSet")
}
for range in kTailRanges {
addRange(tail, range)
static func setFromRanges(_ ranges: [CharRange]) -> CharacterSet {
var result = CharacterSet()
for range in ranges {
guard let lower = Unicode.Scalar(range.lowerBound), let upper = Unicode.Scalar(range.upperBound) else { continue }
result.insert(charactersIn: lower...upper)
}
return result
}
tail.removeCharacters(in: exceptions)

return (head, tail)
}

enum SwiftIdentifier {
static func identifier(
from string: String,
forbiddenChars exceptions: String = "",
replaceWithUnderscores underscores: Bool = false
) -> String {
let (_, tail) = identifierCharacterSets(exceptions: exceptions)

let parts = string.components(separatedBy: tail.inverted)
static func identifier(from string: String, replaceWithUnderscores underscores: Bool = false) -> String {
let parts = string.components(separatedBy: CharacterSet.illegalIdentifierTail.inverted)
let replacement = underscores ? "_" : ""
let mappedParts = parts.map { (string: String) -> String in
// Can't use capitalizedString here because it will lowercase all letters after the first
Expand All @@ -109,17 +97,12 @@ enum SwiftIdentifier {
}

let result = mappedParts.joined(separator: replacement)
return prefixWithUnderscoreIfNeeded(string: result, forbiddenChars: exceptions)
return prefixWithUnderscoreIfNeeded(string: result)
}

static func prefixWithUnderscoreIfNeeded(
string: String,
forbiddenChars exceptions: String = ""
) -> String {
static func prefixWithUnderscoreIfNeeded(string: String) -> String {
guard let firstChar = string.unicodeScalars.first else { return "" }

let (head, _) = identifierCharacterSets(exceptions: exceptions)
let prefix = !head.longCharacterIsMember(firstChar.value) ? "_" : ""
let prefix = !CharacterSet.illegalIdentifierHead.contains(firstChar) ? "_" : ""

return prefix + string
}
Expand Down
11 changes: 0 additions & 11 deletions Tests/StencilSwiftKitTests/SwiftIdentifierTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,6 @@ final class SwiftIdentifierTests: XCTestCase {
XCTAssertEqual(SwiftIdentifier.identifier(from: "Hello"), "Hello")
}

func testBasicStringWithForbiddenChars() {
XCTAssertEqual(SwiftIdentifier.identifier(from: "Hello", forbiddenChars: "l"), "HeO")
}

func testBasicStringWithForbiddenCharsAndUnderscores() {
XCTAssertEqual(
SwiftIdentifier.identifier(from: "Hello", forbiddenChars: "l", replaceWithUnderscores: true),
"He__O"
)
}

func testSpecialChars() {
XCTAssertEqual(SwiftIdentifier.identifier(from: "This-is-42$hello@world"), "ThisIs42HelloWorld")
}
Expand Down

0 comments on commit 61ecf62

Please sign in to comment.