diff --git a/README.md b/README.md index 246a976..b34ed14 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ buildscript { gradlePluginPortal() } dependencies { - classpath("dev.icerock.moko:kswift-gradle-plugin:0.6.0") + classpath("dev.icerock.moko:kswift-gradle-plugin:0.6.1") } } ``` @@ -95,7 +95,7 @@ project where framework compiles `build.gradle` ```groovy plugins { - id("dev.icerock.moko.kswift") version "0.6.0" + id("dev.icerock.moko.kswift") version "0.6.1" } ``` @@ -115,7 +115,7 @@ project `build.gradle` ```groovy dependencies { - commonMainApi("dev.icerock.moko:kswift-runtime:0.6.0") // if you want use annotations + commonMainApi("dev.icerock.moko:kswift-runtime:0.6.1") // if you want use annotations } ``` diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 80a3575..44f9be8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ androidLifecycleVersion = "2.1.0" androidCoreTestingVersion = "2.1.0" coroutinesVersion = "1.6.0-native-mt" mokoTestVersion = "0.4.0" -mokoKSwiftVersion = "0.6.0" +mokoKSwiftVersion = "0.6.1" mokoMvvmVersion = "0.11.0" mokoResourcesVersion = "0.16.2" diff --git a/kswift-gradle-plugin/src/main/kotlin/dev/icerock/moko/kswift/plugin/feature/SealedToSwiftEnumFeature.kt b/kswift-gradle-plugin/src/main/kotlin/dev/icerock/moko/kswift/plugin/feature/SealedToSwiftEnumFeature.kt index d089925..7994873 100644 --- a/kswift-gradle-plugin/src/main/kotlin/dev/icerock/moko/kswift/plugin/feature/SealedToSwiftEnumFeature.kt +++ b/kswift-gradle-plugin/src/main/kotlin/dev/icerock/moko/kswift/plugin/feature/SealedToSwiftEnumFeature.kt @@ -146,7 +146,7 @@ class SealedToSwiftEnumFeature( val kmClass = featureContext.clazz val name: String = if (subclassName.startsWith(kmClass.name)) { subclassName.removePrefix(kmClass.name).removePrefix(".") - } else subclassName + } else subclassName.removePrefix(kmClass.name.substringBeforeLast("/")).removePrefix("/") val decapitalizedName: String = name.decapitalize(Locale.ROOT) val isObject: Boolean = Flag.Class.IS_OBJECT(sealedCaseClass.flags) diff --git a/sample/ios-app/Tests/ExternalGenericSealedClassesToSwiftEnumTests.swift b/sample/ios-app/Tests/ExternalGenericSealedClassesToSwiftEnumTests.swift new file mode 100644 index 0000000..6972302 --- /dev/null +++ b/sample/ios-app/Tests/ExternalGenericSealedClassesToSwiftEnumTests.swift @@ -0,0 +1,63 @@ +/* + * Copyright 2022 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +import XCTest +@testable import MultiPlatformLibrary +@testable import MultiPlatformLibrarySwift + +// ===> NEED TO GENERATE +extension TestExternalGenericSealedClass { + var withoutPropertyKs: ExternalGenericSealedClassKs { + get { + return ExternalGenericSealedClassKs(self.withoutProperty) + } + } + var withOnePropertyTKs: ExternalGenericSealedClassKs { + get { + return ExternalGenericSealedClassKs(self.withOnePropertyT) + } + } + var withOnePropertyUKs: ExternalGenericSealedClassKs { + get { + return ExternalGenericSealedClassKs(self.withOnePropertyU) + } + } + var withTwoPropertiesKs: ExternalGenericSealedClassKs { + get { + return ExternalGenericSealedClassKs(self.withTwoProperties) + } + } +} +// <=== NEED TO GENERATE + +class ExternalGenericSealedClassToSwiftEnumTests: XCTestCase { + private let testSource = TestExternalGenericSealedClass() + + func testWithoutProperty() throws { + if case .externalGenericWithoutProperty = testSource.withoutPropertyKs { } else { XCTFail() } + XCTAssertEqual(testSource.withoutPropertyKs.sealed, ExternalGenericWithoutProperty()) + } + + func testWithOnePropertyT() throws { + if case .externalGenericWithOnePropertyT(let data) = testSource.withOnePropertyTKs { + XCTAssertEqual(data.value, "test") + } else { XCTFail() } + XCTAssertEqual(testSource.withOnePropertyTKs.sealed, ExternalGenericWithOnePropertyT(value: "test")) + } + + func testWithOnePropertyU() throws { + if case .externalGenericWithOnePropertyU(let data) = testSource.withOnePropertyUKs { + XCTAssertEqual(data.value, "test") + } else { XCTFail() } + XCTAssertEqual(testSource.withOnePropertyUKs.sealed, ExternalGenericWithOnePropertyU(value: "test")) + } + + func testWithTwoProperties() throws { + if case .externalGenericWithTwoProperties(let data) = testSource.withTwoPropertiesKs { + XCTAssertEqual(data.value1, "test1") + XCTAssertEqual(data.value2, "test2") + } else { XCTFail() } + XCTAssertEqual(testSource.withTwoPropertiesKs.sealed, ExternalGenericWithTwoProperties(value1: "test1", value2: "test2")) + } +} diff --git a/sample/ios-app/Tests/ExternalNonGenericSealedClassesToSwiftEnumTests.swift b/sample/ios-app/Tests/ExternalNonGenericSealedClassesToSwiftEnumTests.swift new file mode 100644 index 0000000..8cf0279 --- /dev/null +++ b/sample/ios-app/Tests/ExternalNonGenericSealedClassesToSwiftEnumTests.swift @@ -0,0 +1,38 @@ +/* + * Copyright 2022 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +import XCTest +@testable import MultiPlatformLibrary +@testable import MultiPlatformLibrarySwift + +// ===> NEED TO GENERATE +extension ExternalNonGenericSealedClass { + var withoutPropertyKs: ExternalNonGenericSealedClassKs { + get { + return ExternalNonGenericSealedClassKs(ExternalNonGenericWithoutProperty()) + } + } + var withPropertyKs: ExternalNonGenericSealedClassKs { + get { + return ExternalNonGenericSealedClassKs(ExternalNonGenericWithProperty(value: "test")) + } + } +} +// <=== NEED TO GENERATE + +class ExternalNonGenericSealedClassToSwiftEnumTests: XCTestCase { + private let testSource = ExternalNonGenericSealedClass() + + func testWithoutProperty() throws { + if case .externalNonGenericWithoutProperty = testSource.withoutPropertyKs { } else { XCTFail() } + XCTAssertEqual(testSource.withoutPropertyKs.sealed, ExternalNonGenericWithoutProperty()) + } + + func testWithProperty() throws { + if case .externalNonGenericWithProperty(let data) = testSource.withPropertyKs { + XCTAssertEqual(data.value, "test") + } else { XCTFail() } + XCTAssertEqual(testSource.withPropertyKs.sealed, ExternalNonGenericWithProperty(value: "test")) + } +} diff --git a/sample/ios-app/ios-app.xcodeproj/project.pbxproj b/sample/ios-app/ios-app.xcodeproj/project.pbxproj index 19b82a9..31575ea 100644 --- a/sample/ios-app/ios-app.xcodeproj/project.pbxproj +++ b/sample/ios-app/ios-app.xcodeproj/project.pbxproj @@ -25,6 +25,8 @@ 45F9E7F226D3E87A00233CAD /* AnyObjectSealedClassToEnum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45F9E7F126D3E87A00233CAD /* AnyObjectSealedClassToEnum.swift */; }; 65373AE744DF99D6120E6CD0 /* Pods_pods_test.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 170EAFB0A847A7E3A3CC557E /* Pods_pods_test.framework */; }; 696500490BA3A16CF420DC2F /* Pods_ios_app_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D801D62C89CE2E003D435252 /* Pods_ios_app_Tests.framework */; }; + A80C51F228FEF18A00D9629E /* ExternalNonGenericSealedClassesToSwiftEnumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80C51F128FEF18A00D9629E /* ExternalNonGenericSealedClassesToSwiftEnumTests.swift */; }; + A80C51F428FEF2DB00D9629E /* ExternalGenericSealedClassesToSwiftEnumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80C51F328FEF2DB00D9629E /* ExternalGenericSealedClassesToSwiftEnumTests.swift */; }; D867A9A4284852F40078FE14 /* NonGenericSealedClassesToSwiftEnumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D867A9A3284852F40078FE14 /* NonGenericSealedClassesToSwiftEnumTests.swift */; }; D867A9A628490D5F0078FE14 /* GenericSealedClassesToSwiftEnumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D867A9A528490D5F0078FE14 /* GenericSealedClassesToSwiftEnumTests.swift */; }; /* End PBXBuildFile section */ @@ -68,6 +70,8 @@ 939B4E57FF3D22263AC6E0F6 /* Pods-ios-app-Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios-app-Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ios-app-Tests/Pods-ios-app-Tests.debug.xcconfig"; sourceTree = ""; }; 9AACFD2445FE7D02ED352AD0 /* Pods-pods-test.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-pods-test.release.xcconfig"; path = "Pods/Target Support Files/Pods-pods-test/Pods-pods-test.release.xcconfig"; sourceTree = ""; }; A644D2F1C5377C40A53FCD6A /* Pods-ios-app.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios-app.release.xcconfig"; path = "Pods/Target Support Files/Pods-ios-app/Pods-ios-app.release.xcconfig"; sourceTree = ""; }; + A80C51F128FEF18A00D9629E /* ExternalNonGenericSealedClassesToSwiftEnumTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalNonGenericSealedClassesToSwiftEnumTests.swift; sourceTree = ""; }; + A80C51F328FEF2DB00D9629E /* ExternalGenericSealedClassesToSwiftEnumTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalGenericSealedClassesToSwiftEnumTests.swift; sourceTree = ""; }; D801D62C89CE2E003D435252 /* Pods_ios_app_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ios_app_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D867A9A3284852F40078FE14 /* NonGenericSealedClassesToSwiftEnumTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonGenericSealedClassesToSwiftEnumTests.swift; sourceTree = ""; }; D867A9A528490D5F0078FE14 /* GenericSealedClassesToSwiftEnumTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericSealedClassesToSwiftEnumTests.swift; sourceTree = ""; }; @@ -152,6 +156,8 @@ 45F9E7F126D3E87A00233CAD /* AnyObjectSealedClassToEnum.swift */, D867A9A3284852F40078FE14 /* NonGenericSealedClassesToSwiftEnumTests.swift */, D867A9A528490D5F0078FE14 /* GenericSealedClassesToSwiftEnumTests.swift */, + A80C51F128FEF18A00D9629E /* ExternalNonGenericSealedClassesToSwiftEnumTests.swift */, + A80C51F328FEF2DB00D9629E /* ExternalGenericSealedClassesToSwiftEnumTests.swift */, ); path = Tests; sourceTree = ""; @@ -448,6 +454,8 @@ buildActionMask = 2147483647; files = ( 4531D9A226BCF698006F6A8A /* SealedClassToSwiftEnumTests.swift in Sources */, + A80C51F428FEF2DB00D9629E /* ExternalGenericSealedClassesToSwiftEnumTests.swift in Sources */, + A80C51F228FEF18A00D9629E /* ExternalNonGenericSealedClassesToSwiftEnumTests.swift in Sources */, D867A9A4284852F40078FE14 /* NonGenericSealedClassesToSwiftEnumTests.swift in Sources */, D867A9A628490D5F0078FE14 /* GenericSealedClassesToSwiftEnumTests.swift in Sources */, 4531D99626BAF83F006F6A8A /* PlatformExtensionsTests.swift in Sources */, diff --git a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/ExternalGenericSealedClass.kt b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/ExternalGenericSealedClass.kt new file mode 100644 index 0000000..9603e61 --- /dev/null +++ b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/ExternalGenericSealedClass.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2022 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package com.icerockdev.library + +/** + * This sealed class was created to test alongside the [ExternalNonGenericSealedClass] type to ensure that kswift + * creates the correct enum types for generic sealed classes with multiple type parameters. + * Here, subclasses are defined out of the body of the parent class. + * See [GenericSealedClass] to see an example of nested subclasses + */ +sealed class ExternalGenericSealedClass + +/** A test `object` with no parameters and hard-coded types. */ +object ExternalGenericWithoutProperty : ExternalGenericSealedClass() + +/** + * A test `data class` with one parameter, one generic type, and one hard-coded type. Hard-codes + * the second type parameter (U). + */ +data class ExternalGenericWithOnePropertyT(val value: T) : + ExternalGenericSealedClass() + +/** + * A test `data class` with one parameter, one generic type, and one hard-coded type. Hard-codes + * the first type parameter (T). + */ +data class ExternalGenericWithOnePropertyU(val value: U) : + ExternalGenericSealedClass() + +/** A test `data class` with two parameters and two generic types. */ +data class ExternalGenericWithTwoProperties(val value1: T, val value2: U) : + ExternalGenericSealedClass() + +class TestExternalGenericSealedClass { + val withoutProperty: ExternalGenericSealedClass = ExternalGenericWithoutProperty + val withOnePropertyT: ExternalGenericSealedClass = + ExternalGenericWithOnePropertyT("test") + val withOnePropertyU: ExternalGenericSealedClass = + ExternalGenericWithOnePropertyU("test") + val withTwoProperties: ExternalGenericSealedClass = + ExternalGenericWithTwoProperties("test1", "test2") +} diff --git a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/ExternalNonGenericSealedClass.kt b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/ExternalNonGenericSealedClass.kt new file mode 100644 index 0000000..6d7142c --- /dev/null +++ b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/ExternalNonGenericSealedClass.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2022 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package com.icerockdev.library + +/** + * This sealed class was created to test alongside the [ExternalGenericSealedClass] type to ensure that + * kswift creates the correct enum types for both generic and non-generic sealed classes. + * Here, subclasses are defined out of the body of the parent class. + * See [NonGenericSealedClass] to see an example of nested subclasses + */ +sealed class ExternalNonGenericSealedClass + +/** A test `object` that has no property. */ +object ExternalNonGenericWithoutProperty : ExternalNonGenericSealedClass() + +/** A test `data class` with an associated value. */ +data class ExternalNonGenericWithProperty(val value: String) : ExternalNonGenericSealedClass()