Skip to content

Commit

Permalink
Merge pull request #231 from cashapp/skorulis/knit-naming
Browse files Browse the repository at this point in the history
Add handling for common cases inside TypeNamer
  • Loading branch information
bradfol authored Jan 23, 2025
2 parents d6298ef + abc7ff7 commit 1d7700f
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 5 deletions.
29 changes: 25 additions & 4 deletions Sources/KnitCodeGen/TypeNamer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@ enum TypeNamer {
}
// Drop any annotation
var type = type.replacingOccurrences(of: "any ", with: "")
let removedCharacters = CharacterSet(charactersIn: "?[]():&, ")
let removedCharacters = CharacterSet(charactersIn: "?[]():& ")
type = type.components(separatedBy: removedCharacters).joined(separator: "")
let regex = try! NSRegularExpression(pattern: "<.*>")
let nsString = type as NSString
if let match = regex.firstMatch(in: type, range: .init(location: 0, length: type.count)) {
let range = match.range
let mainType = nsString.replacingCharacters(in: match.range, with: "")
if keepGenerics {
var genericName = nsString.substring(
with: .init(location: range.location + 1, length: range.length - 2)
Expand All @@ -47,18 +48,38 @@ enum TypeNamer {
.replacingOccurrences(of: ",", with: "_")
.replacingOccurrences(of: " ", with: "")
type = nsString.replacingCharacters(in: match.range, with: "_\(genericName)")
} else if let suffix = Self.suffixedGenericTypes.first(where: { mainType.hasSuffix($0)} ) {
let genericName = nsString.substring(
with: .init(location: range.location + 1, length: range.length - 2)
)
if let mainGeneric = genericName.components(separatedBy: .init(charactersIn: ",")).first {
type = mainGeneric + suffix
} else {
type = mainType
}
} else {
type = nsString.replacingCharacters(in: match.range, with: "")
type = mainType
}
} else {
type = type.components(separatedBy: .init(charactersIn: ",")).joined(separator: "")
}
if let dotIndex = type.firstIndex(of: ".") {
if let dotIndex = type.lastIndex(of: ".") {
let nameStart = type.index(after: dotIndex)
type = String(type[nameStart...])
let lastType = String(type[nameStart...])
// Types with a Factory subtype should keep the subject of the factory
if lastType == "Factory" {
let components = type.components(separatedBy: .init(charactersIn: "."))
type = components.suffix(2).joined(separator: "")
} else {
type = lastType
}
}

return type
}

private static let suffixedGenericTypes = ["Publisher", "Subject", "Provider"]

static func isClosure(type: String) -> Bool {
return type.contains("->")
}
Expand Down
41 changes: 40 additions & 1 deletion Tests/KnitCodeGenTests/TypeNamerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ final class TypeNamerTests: XCTestCase {

XCTAssertEqual(
TypeNamer.sanitizeType(type: "Result<String, Error>", keepGenerics: true),
"Result_StringError"
"Result_String_Error"
)

XCTAssertEqual(
Expand Down Expand Up @@ -110,6 +110,45 @@ final class TypeNamerTests: XCTestCase {
)
}

func testFactoryRule() {
assertComputedIdentifier(
type: "MyClass.Factory",
expectedIdentifier: "myClassFactory"
)

assertComputedIdentifier(
type: "Module.MyClass.Factory",
expectedIdentifier: "myClassFactory"
)

assertComputedIdentifier(
type: "Factory",
expectedIdentifier: "factory"
)
}

func testSuffixRule() {
assertComputedIdentifier(
type: "AnyPublisher<String>",
expectedIdentifier: "stringPublisher"
)

assertComputedIdentifier(
type: "AnyPublisher<MyType?, Never>",
expectedIdentifier: "myTypePublisher"
)

assertComputedIdentifier(
type: "CurrentValueSubject<String>",
expectedIdentifier: "stringSubject"
)

assertComputedIdentifier(
type: "ValueProvider<Int>",
expectedIdentifier: "intProvider"
)
}

}

private func assertComputedIdentifier(
Expand Down

0 comments on commit 1d7700f

Please sign in to comment.