Skip to content

Commit 0fc97c5

Browse files
authored
[NFC] Inject asSwiftSafeName as a dependency (apple#148)
[NFC] Inject asSwiftSafeName as a dependency ### Motivation Arguably, we should have done this before, but here we go. In order to allow dynamically customizing the logic for converting OpenAPI to Swift identifiers (in support of staging SOAR-0001 gradually), we need to dependency-inject the `(String) -> String` function to all the places that need to do this conversion. ### Modifications This PR doesn't change any behavior (NFC - no functional change), it just refactors the code to have a single funnel point through which all the conversion goes, which has access to the `Config` and can inspect feature flags. Right now, the default behavior is still the same, but this PR creates room for adding the alternative logic from SOAR-0001. ### Result NFC, prepares room for a subsequent PR. Now it's possible to conditionalize the Swift name computing logic based on feature flags. ### Test Plan All tests are passing, adapted as needed, created conveniences in tests for getting a default `Config`, but also made it possible to test the logic by explicitly passing the feature flag. Reviewed by: simonjbeaumont Builds: ✔︎ pull request validation (5.8) - Build finished. ✔︎ pull request validation (5.9) - Build finished. ✔︎ pull request validation (docc test) - Build finished. ✔︎ pull request validation (integration test) - Build finished. ✔︎ pull request validation (nightly) - Build finished. ✔︎ pull request validation (soundness) - Build finished. apple#148
1 parent 8a007c7 commit 0fc97c5

38 files changed

+421
-309
lines changed

Sources/_OpenAPIGeneratorCore/Extensions/String.swift

Lines changed: 0 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,6 @@ import Foundation
1515

1616
extension String {
1717

18-
/// Returns a copy of the string modified to be a valid Swift identifier.
19-
///
20-
/// For sanitization rules, see ``String/sanitizedForSwiftCode``.
21-
var asSwiftSafeName: String {
22-
sanitizedForSwiftCode
23-
}
24-
2518
/// Returns a copy of the string with the first letter uppercased.
2619
var uppercasingFirstLetter: String {
2720
transformingFirstLetter { $0.uppercased() }
@@ -33,12 +26,6 @@ extension String {
3326
}
3427
}
3528

36-
fileprivate extension Character {
37-
38-
/// A Boolean value that indicates whether the character is an underscore.
39-
var isUnderscore: Bool { self == "_" }
40-
}
41-
4229
fileprivate extension String {
4330

4431
/// Returns a copy of the string with the first letter modified by
@@ -53,171 +40,4 @@ fileprivate extension String {
5340
with: transformation(self[firstLetterIndex])
5441
)
5542
}
56-
57-
/// Returns a string sanitized to be usable as a Swift identifier.
58-
///
59-
/// For example, the string `$nake` would be returned as `_nake`, because
60-
/// the dollar sign is not a valid character in a Swift identifier.
61-
///
62-
/// In addition to replacing illegal characters with an underscores, also
63-
/// ensures that the identifier starts with a letter and not a number.
64-
var sanitizedForSwiftCode: String {
65-
guard !isEmpty else {
66-
return "_empty"
67-
}
68-
69-
// Only allow [a-zA-Z][a-zA-Z0-9_]*
70-
// This is bad, is there something like percent encoding functionality but for general "allowed chars only"?
71-
72-
let firstCharSet: CharacterSet = .letters
73-
let numbers: CharacterSet = .decimalDigits
74-
let otherCharSet: CharacterSet = .alphanumerics.union(.init(charactersIn: "_"))
75-
76-
var sanitizedScalars: [Unicode.Scalar] = []
77-
for (index, scalar) in unicodeScalars.enumerated() {
78-
let allowedSet = index == 0 ? firstCharSet : otherCharSet
79-
let outScalar: Unicode.Scalar
80-
if allowedSet.contains(scalar) {
81-
outScalar = scalar
82-
} else if index == 0 && numbers.contains(scalar) {
83-
sanitizedScalars.append("_")
84-
outScalar = scalar
85-
} else {
86-
outScalar = "_"
87-
}
88-
sanitizedScalars.append(outScalar)
89-
}
90-
91-
let validString = String(UnicodeScalarView(sanitizedScalars))
92-
93-
guard Self.keywords.contains(validString) else {
94-
return validString
95-
}
96-
return "_\(validString)"
97-
}
98-
99-
/// A list of Swift keywords.
100-
///
101-
/// Copied from SwiftSyntax/TokenKind.swift
102-
private static let keywords: Set<String> = [
103-
"associatedtype",
104-
"class",
105-
"deinit",
106-
"enum",
107-
"extension",
108-
"func",
109-
"import",
110-
"init",
111-
"inout",
112-
"let",
113-
"operator",
114-
"precedencegroup",
115-
"protocol",
116-
"struct",
117-
"subscript",
118-
"typealias",
119-
"var",
120-
"fileprivate",
121-
"internal",
122-
"private",
123-
"public",
124-
"static",
125-
"defer",
126-
"if",
127-
"guard",
128-
"do",
129-
"repeat",
130-
"else",
131-
"for",
132-
"in",
133-
"while",
134-
"return",
135-
"break",
136-
"continue",
137-
"fallthrough",
138-
"switch",
139-
"case",
140-
"default",
141-
"where",
142-
"catch",
143-
"throw",
144-
"as",
145-
"Any",
146-
"false",
147-
"is",
148-
"nil",
149-
"rethrows",
150-
"super",
151-
"self",
152-
"Self",
153-
"true",
154-
"try",
155-
"throws",
156-
"__FILE__",
157-
"__LINE__",
158-
"__COLUMN__",
159-
"__FUNCTION__",
160-
"__DSO_HANDLE__",
161-
"_",
162-
"(",
163-
")",
164-
"{",
165-
"}",
166-
"[",
167-
"]",
168-
"<",
169-
">",
170-
".",
171-
".",
172-
",",
173-
"...",
174-
":",
175-
";",
176-
"=",
177-
"@",
178-
"#",
179-
"&",
180-
"->",
181-
"`",
182-
"\\",
183-
"!",
184-
"?",
185-
"?",
186-
"\"",
187-
"\'",
188-
"\"\"\"",
189-
"#keyPath",
190-
"#line",
191-
"#selector",
192-
"#file",
193-
"#fileID",
194-
"#filePath",
195-
"#column",
196-
"#function",
197-
"#dsohandle",
198-
"#assert",
199-
"#sourceLocation",
200-
"#warning",
201-
"#error",
202-
"#if",
203-
"#else",
204-
"#elseif",
205-
"#endif",
206-
"#available",
207-
"#unavailable",
208-
"#fileLiteral",
209-
"#imageLiteral",
210-
"#colorLiteral",
211-
")",
212-
"yield",
213-
"String",
214-
"Error",
215-
"Int",
216-
"Bool",
217-
"Array",
218-
"Type",
219-
"type",
220-
"Protocol",
221-
"await",
222-
]
22343
}

Sources/_OpenAPIGeneratorCore/FeatureFlags.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ public enum FeatureFlag: String, Hashable, Equatable, Codable, CaseIterable {
3333
/// - https://github.com/apple/swift-openapi-generator/issues/6
3434
/// - https://github.com/apple/swift-openapi-generator/issues/7
3535
case multipleContentTypes
36+
37+
/// SOAR-0001 Improved OpenAPI -> Swift name mapping
38+
///
39+
/// Tracking issues:
40+
/// - https://github.com/apple/swift-openapi-generator/pull/95
41+
case proposal0001
3642
}
3743

3844
/// A set of enabled feature flags.

Sources/_OpenAPIGeneratorCore/Translator/ClientTranslator/ClientTranslator.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@ struct ClientFileTranslator: FileTranslator {
4343

4444
let clientMethodDecls =
4545
try OperationDescription
46-
.all(from: doc.paths, in: components)
46+
.all(
47+
from: doc.paths,
48+
in: components,
49+
asSwiftSafeName: swiftSafeName
50+
)
4751
.map(translateClientMethod(_:))
4852

4953
let clientStructPropertyDecl: Declaration = .commentable(

0 commit comments

Comments
 (0)