Skip to content

Commit bb36e7f

Browse files
committed
Add integerValue to IntegerLiteralExprSyntax
Update Convenience.swift Update Convenience.swift
1 parent a7d8cbe commit bb36e7f

File tree

3 files changed

+99
-40
lines changed

3 files changed

+99
-40
lines changed

Sources/SwiftRefactor/IntegerLiteralUtilities.swift

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,46 +17,6 @@ import SwiftSyntax
1717
#endif
1818

1919
extension IntegerLiteralExprSyntax {
20-
public enum Radix {
21-
case binary
22-
case octal
23-
case decimal
24-
case hex
25-
26-
public var size: Int {
27-
switch self {
28-
case .binary: return 2
29-
case .octal: return 8
30-
case .decimal: return 10
31-
case .hex: return 16
32-
}
33-
}
34-
35-
/// The prefix that is used to express an integer literal with this
36-
/// radix in Swift source code, e.g., "0x" for hexadecimal.
37-
public var literalPrefix: String {
38-
switch self {
39-
case .binary: return "0b"
40-
case .octal: return "0o"
41-
case .hex: return "0x"
42-
case .decimal: return ""
43-
}
44-
}
45-
}
46-
47-
public var radix: Radix {
48-
let text = self.literal.text
49-
if text.starts(with: "0b") {
50-
return .binary
51-
} else if text.starts(with: "0o") {
52-
return .octal
53-
} else if text.starts(with: "0x") {
54-
return .hex
55-
} else {
56-
return .decimal
57-
}
58-
}
59-
6020
/// Returns an (arbitrarily) "ideal" number of digits that should constitute
6121
/// a separator-delimited "group" in an integer literal.
6222
var idealGroupSize: Int {

Sources/SwiftSyntax/Convenience.swift

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,75 @@ extension EnumCaseParameterSyntax {
6868
}
6969
}
7070

71+
extension IntegerLiteralExprSyntax {
72+
public enum Radix {
73+
case binary
74+
case octal
75+
case decimal
76+
case hex
77+
78+
public var size: Int {
79+
switch self {
80+
case .binary: return 2
81+
case .octal: return 8
82+
case .decimal: return 10
83+
case .hex: return 16
84+
}
85+
}
86+
87+
/// The prefix that is used to express an integer literal with this
88+
/// radix in Swift source code, e.g., "0x" for hexadecimal.
89+
public var literalPrefix: String {
90+
switch self {
91+
case .binary: return "0b"
92+
case .octal: return "0o"
93+
case .hex: return "0x"
94+
case .decimal: return ""
95+
}
96+
}
97+
98+
fileprivate var offset: Int {
99+
switch self {
100+
case .binary, .hex, .octal:
101+
return 2
102+
case .decimal:
103+
return 0
104+
}
105+
}
106+
}
107+
108+
public var radix: Radix {
109+
let text = self.literal.text
110+
if text.starts(with: "0b") {
111+
return .binary
112+
} else if text.starts(with: "0o") {
113+
return .octal
114+
} else if text.starts(with: "0x") {
115+
return .hex
116+
} else {
117+
return .decimal
118+
}
119+
}
120+
121+
/// A computed property representing the integer value parsed from the associated `literal.text` property, considering the specified radix.
122+
///
123+
/// - Returns: An integer value parsed from the associated `literal.text`, or `nil` if the text cannot be parsed as an integer.
124+
public var representedLiteralValue: Int? {
125+
guard !hasError else { return nil }
126+
127+
let text = literal.text
128+
let radix = self.radix
129+
let digitsStartIndex = text.index(text.startIndex, offsetBy: radix.offset)
130+
let textWithoutPrefix = text.suffix(from: digitsStartIndex)
131+
132+
let textWithoutPrefixOrUnderscores = textWithoutPrefix.filter {
133+
$0 != "_"
134+
}
135+
136+
return Int(textWithoutPrefixOrUnderscores, radix: radix.size)
137+
}
138+
}
139+
71140
extension MemberAccessExprSyntax {
72141
/// Creates a new ``MemberAccessExprSyntax`` where the accessed member is represented by
73142
/// an identifier without specifying argument labels.

Tests/SwiftSyntaxTest/SyntaxTests.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,4 +168,34 @@ class SyntaxTests: XCTestCase {
168168
XCTAssertEqual(funcKeywordInTree2?.as(TokenSyntax.self)?.tokenKind, .keyword(.func))
169169
XCTAssertNotEqual(funcKeywordInTree1.id, funcKeywordInTree2?.id)
170170
}
171+
172+
func testIntegerLiteralExprSyntax() {
173+
let testCases: [UInt: (String, Int?)] = [
174+
#line: ("2", 2),
175+
#line: ("02", 2),
176+
#line: ("020", 20),
177+
#line: ("-02", -2),
178+
#line: ("2_00_0000", 2_00_0000),
179+
#line: ("-2_00_0000", -2_00_0000),
180+
#line: ("foo", nil),
181+
#line: ("999999999999999999999999999999999999999999999999999999999999999999999999999999", nil),
182+
#line: ("0b1010101", 85),
183+
#line: ("0xFF", 255),
184+
#line: ("0o777", 511),
185+
#line: ("0b001100", 0b001100),
186+
#line: ("4_2", 4_2),
187+
#line: ("0o3434", 0o3434),
188+
#line: ("0xba11aD", 0xba11aD),
189+
#line: ("🐋", nil),
190+
#line: ("-0xA", nil),
191+
#line: ("-0o7", nil),
192+
#line: ("-0b1", nil),
193+
]
194+
195+
for (line, testCase) in testCases {
196+
let (value, expected) = testCase
197+
let expr = IntegerLiteralExprSyntax(literal: .integerLiteral(value))
198+
XCTAssertEqual(expr.representedLiteralValue, expected, line: line)
199+
}
200+
}
171201
}

0 commit comments

Comments
 (0)