Skip to content

[NFC] Inject asSwiftSafeName as a dependency #148

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 0 additions & 180 deletions Sources/_OpenAPIGeneratorCore/Extensions/String.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,6 @@ import Foundation

extension String {

/// Returns a copy of the string modified to be a valid Swift identifier.
///
/// For sanitization rules, see ``String/sanitizedForSwiftCode``.
var asSwiftSafeName: String {
sanitizedForSwiftCode
}

/// Returns a copy of the string with the first letter uppercased.
var uppercasingFirstLetter: String {
transformingFirstLetter { $0.uppercased() }
Expand All @@ -33,12 +26,6 @@ extension String {
}
}

fileprivate extension Character {

/// A Boolean value that indicates whether the character is an underscore.
var isUnderscore: Bool { self == "_" }
}

fileprivate extension String {

/// Returns a copy of the string with the first letter modified by
Expand All @@ -53,171 +40,4 @@ fileprivate extension String {
with: transformation(self[firstLetterIndex])
)
}

/// Returns a string sanitized to be usable as a Swift identifier.
///
/// For example, the string `$nake` would be returned as `_nake`, because
/// the dollar sign is not a valid character in a Swift identifier.
///
/// In addition to replacing illegal characters with an underscores, also
/// ensures that the identifier starts with a letter and not a number.
var sanitizedForSwiftCode: String {
guard !isEmpty else {
return "_empty"
}

// Only allow [a-zA-Z][a-zA-Z0-9_]*
// This is bad, is there something like percent encoding functionality but for general "allowed chars only"?

let firstCharSet: CharacterSet = .letters
let numbers: CharacterSet = .decimalDigits
let otherCharSet: CharacterSet = .alphanumerics.union(.init(charactersIn: "_"))

var sanitizedScalars: [Unicode.Scalar] = []
for (index, scalar) in unicodeScalars.enumerated() {
let allowedSet = index == 0 ? firstCharSet : otherCharSet
let outScalar: Unicode.Scalar
if allowedSet.contains(scalar) {
outScalar = scalar
} else if index == 0 && numbers.contains(scalar) {
sanitizedScalars.append("_")
outScalar = scalar
} else {
outScalar = "_"
}
sanitizedScalars.append(outScalar)
}

let validString = String(UnicodeScalarView(sanitizedScalars))

guard Self.keywords.contains(validString) else {
return validString
}
return "_\(validString)"
}

/// A list of Swift keywords.
///
/// Copied from SwiftSyntax/TokenKind.swift
private static let keywords: Set<String> = [
"associatedtype",
"class",
"deinit",
"enum",
"extension",
"func",
"import",
"init",
"inout",
"let",
"operator",
"precedencegroup",
"protocol",
"struct",
"subscript",
"typealias",
"var",
"fileprivate",
"internal",
"private",
"public",
"static",
"defer",
"if",
"guard",
"do",
"repeat",
"else",
"for",
"in",
"while",
"return",
"break",
"continue",
"fallthrough",
"switch",
"case",
"default",
"where",
"catch",
"throw",
"as",
"Any",
"false",
"is",
"nil",
"rethrows",
"super",
"self",
"Self",
"true",
"try",
"throws",
"__FILE__",
"__LINE__",
"__COLUMN__",
"__FUNCTION__",
"__DSO_HANDLE__",
"_",
"(",
")",
"{",
"}",
"[",
"]",
"<",
">",
".",
".",
",",
"...",
":",
";",
"=",
"@",
"#",
"&",
"->",
"`",
"\\",
"!",
"?",
"?",
"\"",
"\'",
"\"\"\"",
"#keyPath",
"#line",
"#selector",
"#file",
"#fileID",
"#filePath",
"#column",
"#function",
"#dsohandle",
"#assert",
"#sourceLocation",
"#warning",
"#error",
"#if",
"#else",
"#elseif",
"#endif",
"#available",
"#unavailable",
"#fileLiteral",
"#imageLiteral",
"#colorLiteral",
")",
"yield",
"String",
"Error",
"Int",
"Bool",
"Array",
"Type",
"type",
"Protocol",
"await",
]
}
6 changes: 6 additions & 0 deletions Sources/_OpenAPIGeneratorCore/FeatureFlags.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ public enum FeatureFlag: String, Hashable, Equatable, Codable, CaseIterable {
/// - https://github.com/apple/swift-openapi-generator/issues/6
/// - https://github.com/apple/swift-openapi-generator/issues/7
case multipleContentTypes

/// SOAR-0001 Improved OpenAPI -> Swift name mapping
///
/// Tracking issues:
/// - https://github.com/apple/swift-openapi-generator/pull/95
case proposal0001
}

/// A set of enabled feature flags.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ struct ClientFileTranslator: FileTranslator {

let clientMethodDecls =
try OperationDescription
.all(from: doc.paths, in: components)
.all(
from: doc.paths,
in: components,
asSwiftSafeName: swiftSafeName
)
.map(translateClientMethod(_:))

let clientStructPropertyDecl: Declaration = .commentable(
Expand Down
Loading