Skip to content

Commit

Permalink
Merge pull request #219 from cashapp/skorulis/getter-error
Browse files Browse the repository at this point in the history
Throw an error if getter-named is redundant
  • Loading branch information
skorulis-ap authored Dec 13, 2024
2 parents 4bd2a6c + 1e0544c commit 7ee3dde
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 2 deletions.
13 changes: 12 additions & 1 deletion Sources/KnitCodeGen/FunctionCallRegistrationParsing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ extension FunctionCallExprSyntax {
return ([], [])
}

if primaryRegistration.hasRedundantGetter {
throw RegistrationParsingError.redundantGetter(syntax: self)
}

let implementsCalledMethods = calledMethods.filter { method in
method.calledExpression.declName.baseName.text == Registration.FunctionName.implements.rawValue
}
Expand All @@ -109,6 +113,9 @@ extension FunctionCallExprSyntax {
leadingTrivia: leadingTrivia,
functionName: .implements
) {
if forwardedRegistration.hasRedundantGetter {
throw RegistrationParsingError.redundantGetter(syntax: implementsCalledMethod.calledExpression)
}
forwardedRegistrations.append(forwardedRegistration)
}
}
Expand Down Expand Up @@ -331,6 +338,7 @@ enum RegistrationParsingError: LocalizedError, SyntaxError {
case invalidIfConfig(syntax: SyntaxProtocol, text: String)
case nestedIfConfig(syntax: SyntaxProtocol)
case nonAbstract(syntax: SyntaxProtocol)
case redundantGetter(syntax: SyntaxProtocol)

var errorDescription: String? {
switch self {
Expand All @@ -348,6 +356,8 @@ enum RegistrationParsingError: LocalizedError, SyntaxError {
return "Nested #if statements are not supported"
case .nonAbstract:
return "AbstractAssemblys may only contain Abstract registrations"
case .redundantGetter:
return "getter-named matches the default accessor name and can be removed"
}
}

Expand All @@ -359,7 +369,8 @@ enum RegistrationParsingError: LocalizedError, SyntaxError {
let .unwrappedClosureParams(syntax),
let .invalidIfConfig(syntax, _),
let .nestedIfConfig(syntax),
let .nonAbstract(syntax):
let .nonAbstract(syntax),
let .redundantGetter(syntax):
return syntax
}
}
Expand Down
11 changes: 11 additions & 0 deletions Sources/KnitCodeGen/Registration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ public struct Registration: Equatable, Codable, Sendable {
case service, name, accessLevel, arguments, getterConfig, functionName, concurrencyModifier, spi
}

var namedGetterConfig: GetterConfig? {
getterConfig.first(where: { $0.isNamed })
}

var hasRedundantGetter: Bool {
guard let namedGetterConfig, case let GetterConfig.identifiedGetter(name) = namedGetterConfig else {
return false
}
return TypeNamer.computedIdentifierName(type: service) == name
}

}

extension Registration {
Expand Down
2 changes: 1 addition & 1 deletion Sources/KnitCodeGen/TypeSafetySourceFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public enum TypeSafetySourceFile {
if registration.getterConfig.contains(.callAsFunction) {
try makeResolver(registration: registration, getterType: .callAsFunction)
}
if let namedGetter = registration.getterConfig.first(where: { $0.isNamed }) {
if let namedGetter = registration.namedGetterConfig {
try makeResolver(registration: registration, getterType: namedGetter)
}
}
Expand Down
47 changes: 47 additions & 0 deletions Tests/KnitCodeGenTests/AssemblyParsingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,53 @@ final class AssemblyParsingTests: XCTestCase {
)
}

func testRedundantGetterName() throws {
let sourceFile: SourceFileSyntax = """
class TestAssembly: ModuleAssembly {
typealias TargetResolver = TestResolver
typealias ReplacedAssembly = RealAssembly
func assemble(container: Container) {
// @knit getter-named("a")
container.register(A.self) { }
}
}
"""

_ = try assertParsesSyntaxTree(sourceFile, assertErrorsToPrint: { errors in
XCTAssertEqual(errors.count, 1)
if case RegistrationParsingError.redundantGetter = errors[0] {
// Correct
} else {
XCTFail("Incorrect error case")
}
})
}

func testRedundantForwardedGetterName() throws {
let sourceFile: SourceFileSyntax = """
class TestAssembly: ModuleAssembly {
typealias TargetResolver = TestResolver
typealias ReplacedAssembly = RealAssembly
func assemble(container: Container) {
container.register(A.self) { }
// @knit getter-named("b")
.implements(B.self)
}
}
"""

_ = try assertParsesSyntaxTree(sourceFile, assertErrorsToPrint: { errors in
XCTAssertEqual(errors.count, 1)
if case RegistrationParsingError.redundantGetter = errors[0] {
// Correct
} else {
XCTFail("Incorrect error case")
}
})
}

}

private func assertParsesSyntaxTree(
Expand Down

0 comments on commit 7ee3dde

Please sign in to comment.