From e5d7da81364e36b005528802b4d20907cb5cbe0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kry=C5=A1tof=20Mat=C4=9Bj?= Date: Tue, 26 Sep 2023 08:52:44 +0200 Subject: [PATCH] Add generating parent mock for single protocol inheritance --- .../RubiconApp.xcodeproj/project.pbxproj | 8 +++---- .../Rubicon/Generator/ProtocolGenerator.swift | 12 +++++++++- .../Syntactic analysis/ProtocolParser.swift | 10 +++++++- .../Generator/DummyGeneratorTests.swift | 3 ++- .../Generator/ProtocolGeneratorTests.swift | 22 +++++++++++++++++ .../Integration/SpyIntegrationTests.swift | 4 ++-- .../ProtocolParserTests.swift | 24 +++++++++++++++++++ 7 files changed, 74 insertions(+), 9 deletions(-) diff --git a/Application/RubiconApp.xcodeproj/project.pbxproj b/Application/RubiconApp.xcodeproj/project.pbxproj index 2c2840d..b30b275 100644 --- a/Application/RubiconApp.xcodeproj/project.pbxproj +++ b/Application/RubiconApp.xcodeproj/project.pbxproj @@ -491,7 +491,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 43; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=macosx*]" = 473264X5JK; GENERATE_INFOPLIST_FILE = YES; @@ -505,7 +505,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = com.cleverlance.rubicon; PRODUCT_NAME = "Rubicon for Xcode"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -525,7 +525,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "3rd Party Mac Developer Application"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 43; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=macosx*]" = 473264X5JK; GENERATE_INFOPLIST_FILE = YES; @@ -539,7 +539,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = com.cleverlance.rubicon; PRODUCT_NAME = "Rubicon for Xcode"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/Sources/Rubicon/Generator/ProtocolGenerator.swift b/Sources/Rubicon/Generator/ProtocolGenerator.swift index 2aa5b01..85162f0 100644 --- a/Sources/Rubicon/Generator/ProtocolGenerator.swift +++ b/Sources/Rubicon/Generator/ProtocolGenerator.swift @@ -16,10 +16,20 @@ final class ProtocolGeneratorImpl: ProtocolGenerator { func makeProtocol(from declaration: ProtocolDeclaration, stub: String, content: [String]) -> [String] { let content = content.map(indentationGenerator.indenting) + let parentClause = makeParentClause(from: declaration, stub: stub) + let header = declaration.name + stub + parentClause + declaration.name return [ - "\(accessLevelGenerator.makeClassAccessLevel())final class \(declaration.name)\(stub): \(declaration.name) {" + "\(accessLevelGenerator.makeClassAccessLevel())final class \(header) {" ] + content + [ "}", ] } + + private func makeParentClause(from declaration: ProtocolDeclaration, stub: String) -> String { + if let parent = declaration.parents.first, declaration.parents.count == 1 { + return ": \(parent)\(stub), " + } else { + return ": " + } + } } diff --git a/Sources/Rubicon/Syntactic analysis/ProtocolParser.swift b/Sources/Rubicon/Syntactic analysis/ProtocolParser.swift index bec309b..a3a95c7 100644 --- a/Sources/Rubicon/Syntactic analysis/ProtocolParser.swift +++ b/Sources/Rubicon/Syntactic analysis/ProtocolParser.swift @@ -53,13 +53,21 @@ private class ProtocolVisitor: SyntaxVisitor { result.append( ProtocolDeclaration( name: node.name.text, - parents: [], + parents: node.inheritanceClause?.inheritedTypes.compactMap(parseParent) ?? [], variables: varsVisitor.execute(node: node), functions: functionsVisitor.execute(node: node) ) ) return .visitChildren } + + private func parseParent(from inheridedTypeSyntax: InheritedTypeSyntax) -> String? { + guard let type = inheridedTypeSyntax.type.as(IdentifierTypeSyntax.self) else { + return nil + } + + return type.name.text + } } private class FunctionsVisitor: SyntaxVisitor { diff --git a/Tests/RubiconTests/Generator/DummyGeneratorTests.swift b/Tests/RubiconTests/Generator/DummyGeneratorTests.swift index 2844af7..6c2a9ab 100644 --- a/Tests/RubiconTests/Generator/DummyGeneratorTests.swift +++ b/Tests/RubiconTests/Generator/DummyGeneratorTests.swift @@ -97,12 +97,13 @@ extension TypeDeclaration { extension ProtocolDeclaration { static func makeStub( + parents: [String] = [], variables: [VarDeclaration] = [], functions: [FunctionDeclaration] = [] ) -> ProtocolDeclaration { return ProtocolDeclaration( name: "Name", - parents: [], + parents: parents, variables: variables, functions: functions ) diff --git a/Tests/RubiconTests/Generator/ProtocolGeneratorTests.swift b/Tests/RubiconTests/Generator/ProtocolGeneratorTests.swift index e73ccbe..9701e51 100644 --- a/Tests/RubiconTests/Generator/ProtocolGeneratorTests.swift +++ b/Tests/RubiconTests/Generator/ProtocolGeneratorTests.swift @@ -27,6 +27,28 @@ final class ProtocolGeneratorTests: XCTestCase { ]) XCTAssertEqual(accessLevelGeneratorSpy.makeClassAccessLevelCount, 1) } + + func test_givenProtocolSingleParent_whenGenerate_thenGenerateCode() { + let code = sut.makeProtocol(from: .makeStub(parents: ["Parent"]), stub: "Dummy", content: ["content"]) + + equal(code, rows: [ + "accessLevel final class NameDummy: ParentDummy, Name {", + "-content", + "}", + ]) + XCTAssertEqual(accessLevelGeneratorSpy.makeClassAccessLevelCount, 1) + } + + func test_givenProtocolMultipleParent_whenGenerate_thenGenerateCode() { + let code = sut.makeProtocol(from: .makeStub(parents: ["Parent1", "Parent2"]), stub: "Dummy", content: ["content"]) + + equal(code, rows: [ + "accessLevel final class NameDummy: Name {", + "-content", + "}", + ]) + XCTAssertEqual(accessLevelGeneratorSpy.makeClassAccessLevelCount, 1) + } } func equal(string: String?, rows: [String], line: UInt = #line, file: StaticString = #file) { diff --git a/Tests/RubiconTests/Integration/SpyIntegrationTests.swift b/Tests/RubiconTests/Integration/SpyIntegrationTests.swift index 05b3516..a9813cd 100644 --- a/Tests/RubiconTests/Integration/SpyIntegrationTests.swift +++ b/Tests/RubiconTests/Integration/SpyIntegrationTests.swift @@ -4,7 +4,7 @@ import XCTest final class SpyIntegrationTests: XCTestCase { func test_givenProtocol_whenMakeDummy_thenReturnStub() { let code = """ - protocol Car { + protocol Car: Vehicle { var name: String? { get } var color: Int { get set } @@ -20,7 +20,7 @@ final class SpyIntegrationTests: XCTestCase { let result = sut.makeSpy(code: code, accessLevel: .internal, indentStep: "-") equal(string: result.first ?? "", rows: [ - "final class CarSpy: Car {", + "final class CarSpy: VehicleSpy, Car {", "-struct Load {", "--let stuff: Int", "--let label: String", diff --git a/Tests/RubiconTests/Syntactic analysis/ProtocolParserTests.swift b/Tests/RubiconTests/Syntactic analysis/ProtocolParserTests.swift index b73d80f..53af754 100644 --- a/Tests/RubiconTests/Syntactic analysis/ProtocolParserTests.swift +++ b/Tests/RubiconTests/Syntactic analysis/ProtocolParserTests.swift @@ -80,6 +80,30 @@ final class ProtocolParserTests: XCTestCase { XCTAssertEqual(varParserSpy.parse.count, 2) XCTAssertEqual(varParserSpy.parse.first?.node.description, "\n var a: Int { get set }") } + + func test_givenProtocolWithInheritance_whenParse_thenReturnProtocol() throws { + let text = """ + protocol A: B { + } + """ + + let protocols = try sut.parse(text: text) + + XCTAssertEqual(protocols.first?.name, "A") + XCTAssertEqual(protocols.first?.parents, ["B"]) + } + + func test_givenProtocolWithMultipleInheritance_whenParse_thenReturnProtocol() throws { + let text = """ + protocol A: B, C { + } + """ + + let protocols = try sut.parse(text: text) + + XCTAssertEqual(protocols.first?.name, "A") + XCTAssertEqual(protocols.first?.parents, ["B", "C"]) + } } final class FunctionDeclarationParserSpy: FunctionDeclarationParser {