Skip to content

Commit

Permalink
Merge pull request #116 from outfoxx/fix/nested-names
Browse files Browse the repository at this point in the history
Combined update of SwiftPoet and matching changes to fix generation of nested type names
  • Loading branch information
kdubb authored Oct 29, 2024
2 parents d0f547f + e9b50ec commit 7e8bc9f
Show file tree
Hide file tree
Showing 13 changed files with 203 additions and 47 deletions.
2 changes: 2 additions & 0 deletions generator/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ dependencies {
testRuntimeOnly(libs.junitEngine)

testImplementation(libs.hamcrest)
testImplementation(libs.diffutils)
testImplementation(libs.cliktMarkdown)

testImplementation(libs.dockerJava)
testImplementation(libs.dockerJavaTransport)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -512,8 +512,13 @@ class KotlinTypeRegistry(

private fun processArrayShape(shape: ArrayShape, context: KotlinResolutionContext): TypeName {

val elementType = resolveReferencedTypeName(shape.items!!, context)

val elementType =
shape.items
?.let { itemsShape ->
resolveReferencedTypeName(itemsShape, context)
}
?: ANY

val collectionType =
if (shape.uniqueItems == true) {
SET
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,12 @@ class SwiftTypeRegistry(

private fun processArrayShape(shape: ArrayShape, context: SwiftResolutionContext): TypeName {

val elementType = resolveReferencedTypeName(shape.items!!, context)
val elementType =
shape.items
?.let { itemsShape ->
resolveReferencedTypeName(itemsShape, context)
}
?: ANY

val collectionType =
if (shape.uniqueItems == true) {
Expand Down Expand Up @@ -917,42 +922,54 @@ class SwiftTypeRegistry(
}

val decoderPropertyRef = CodeBlock.of("self.%N", prop.swiftIdentifierName)
var decoderPost = ""
val decoderPost = CodeBlock.builder()

var encoderPropertyRef = CodeBlock.of("self.%N", prop.swiftIdentifierName)
var encoderPre = ""
val encoderPre = CodeBlock.builder()

val isLeaf = context.hasNoInheriting(prop.range)
val (refCollection, refElement) = replaceCollectionValueTypesWithReferenceTypes(propertyTypeName)

if (!isLeaf) {
propertyTypeName = if (isOptional) {
(propertyTypeName.makeNonOptional() as DeclaredTypeName).nestedType(ANY_REF_NAME).makeOptional()
} else {
(propertyTypeName as DeclaredTypeName).nestedType(ANY_REF_NAME)
when {
!isLeaf -> {
propertyTypeName = if (isOptional) {
(propertyTypeName.makeNonOptional() as DeclaredTypeName).nestedType(ANY_REF_NAME).makeOptional()
} else {
(propertyTypeName as DeclaredTypeName).nestedType(ANY_REF_NAME)
}

decoderPost.add("${if (isOptional) "?" else ""}.value")
}

refCollection != propertyTypeName -> {

val mapper = if (refCollection.concreteType() == DICTIONARY) "mapValues" else "map"

propertyTypeName = refCollection
decoderPost.add("${if (isOptional) "?" else ""}.$mapper { $0.value }")
encoderPre.add("${if (isOptional) "?" else ""}.$mapper { %T(value: $0) }", refElement)
}

decoderPost = "${if (isOptional) "?" else ""}.value"
} else if (refCollection != propertyTypeName) {
val mapper = if (refCollection.concreteType() == DICTIONARY) "mapValues" else "map"
propertyTypeName = refCollection
decoderPost = "${if (isOptional) "?" else ""}.$mapper { $0.value }"
encoderPre = "${if (isOptional) "?" else ""}.$mapper { ${refElement.name}(value: $0) }"
} else if (propertyTypeName == DICTIONARY_STRING_ANY || propertyTypeName == DICTIONARY_STRING_ANY_OPTIONAL) {

propertyTypeName = DICTIONARY.parameterizedBy(STRING, ANY_VALUE)
decoderPost = "${if (isOptional) "?" else ""}.mapValues { $0.unwrapped as Any }"
encoderPre = "${if (isOptional) "?" else ""}.mapValues { try AnyValue.wrapped($0) }"
} else if (propertyTypeName == ARRAY_ANY || propertyTypeName == ARRAY_ANY_OPTIONAL) {

propertyTypeName = ARRAY.parameterizedBy(ANY_VALUE)
decoderPost = "${if (isOptional) "?" else ""}.map { $0.unwrapped }"
encoderPre = "${if (isOptional) "?" else ""}.map { try AnyValue.wrapped($0) }"
} else if (propertyTypeName.unwrapOptional() == ANY) {

propertyTypeName = ANY_VALUE
decoderPost = "${if (isOptional) "?" else ""}.unwrapped"
encoderPropertyRef = CodeBlock.of("%T.wrapped(%N)", ANY_VALUE, prop.swiftIdentifierName)
propertyTypeName == DICTIONARY_STRING_ANY || propertyTypeName == DICTIONARY_STRING_ANY_OPTIONAL -> {

propertyTypeName = DICTIONARY.parameterizedBy(STRING, ANY_VALUE)
decoderPost.add("${if (isOptional) "?" else ""}.mapValues { $0.unwrapped }")
encoderPre.add("${if (isOptional) "?" else ""}.mapValues { try %T.wrapped($0) }", ANY_VALUE)
}

propertyTypeName == ARRAY_ANY || propertyTypeName == ARRAY_ANY_OPTIONAL -> {

propertyTypeName = ARRAY.parameterizedBy(ANY_VALUE)
decoderPost.add("${if (isOptional) "?" else ""}.map { $0.unwrapped }")
encoderPre.add("${if (isOptional) "?" else ""}.map { try %T.wrapped($0) }", ANY_VALUE)
}

propertyTypeName.unwrapOptional() == ANY -> {

propertyTypeName = ANY_VALUE
decoderPost.add("${if (isOptional) "?" else ""}.unwrapped")
encoderPropertyRef = CodeBlock.of("%T.wrapped(%N)", ANY_VALUE, prop.swiftIdentifierName)
}
}

decoderInitFunctionBuilder
Expand All @@ -963,15 +980,15 @@ class SwiftTypeRegistry(
coderSuffix,
propertyTypeName,
prop.swiftIdentifierName,
decoderPost,
decoderPost.build(),
)

encoderFunctionBuilder
.addCode("%[try container.encode%L(", coderSuffix)
.addCode(encoderPropertyRef)
.addCode(
"%L, forKey: .%N)%]\n",
encoderPre,
encoderPre.build(),
prop.swiftIdentifierName,
)
}
Expand Down Expand Up @@ -1131,9 +1148,9 @@ class SwiftTypeRegistry(
paramType.makeOptional()
}
paramConsBuilder.addParameter(
ParameterSpec.builder(it.swiftIdentifierName, paramType)
.apply { if (it.optional && paramType.optional) defaultValue("nil") }
.build()
ParameterSpec.builder(it.swiftIdentifierName, paramType)
.apply { if (it.optional && paramType.optional) defaultValue("nil") }
.build(),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,12 @@ class TypeScriptTypeRegistry(

private fun processArrayShape(shape: ArrayShape, context: TypeScriptResolutionContext): TypeName {

val elementType = resolveReferencedTypeName(shape.items!!, context)
val elementType =
shape.items
?.let { itemsShape ->
resolveReferencedTypeName(itemsShape, context)
}
?: UNKNOWN

val collectionType =
if (shape.uniqueItems == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.outfoxx.sunday.generator.kotlin

import io.outfoxx.sunday.test.extensions.DiffingExtension
import io.outfoxx.sunday.test.extensions.ResourceExtension
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.api.parallel.Execution
Expand All @@ -24,5 +25,5 @@ import org.junit.jupiter.api.parallel.ResourceLock

@Execution(ExecutionMode.CONCURRENT)
@ResourceLock("Kotlin")
@ExtendWith(ResourceExtension::class)
@ExtendWith(ResourceExtension::class, DiffingExtension::class)
annotation class KotlinTest
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.outfoxx.sunday.generator.kotlin

import com.github.difflib.text.DiffRowGenerator
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.FileSpec
import io.outfoxx.sunday.generator.GenerationMode
Expand Down Expand Up @@ -51,10 +52,13 @@ class RamlObjectTypesTest {
import kotlin.Any
import kotlin.String
import kotlin.collections.List
import kotlin.collections.Map
public interface Test {
public val map: Map<String, Any>
public val array: List<Any>
}
""".trimIndent(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,33 +51,43 @@ class RamlObjectTypesTest {
public class Test : Codable, CustomDebugStringConvertible {
public var map: [String : Any]
public var array: [Any]
public var debugDescription: String {
return DescriptionBuilder(Test.self)
.add(map, named: "map")
.add(array, named: "array")
.build()
}
public init(map: [String : Any]) {
public init(map: [String : Any], array: [Any]) {
self.map = map
self.array = array
}
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.map = try container.decode([String : AnyValue].self, forKey: .map).mapValues { ${'$'}0.unwrapped as Any }
self.map = try container.decode([String : AnyValue].self, forKey: .map).mapValues { ${'$'}0.unwrapped }
self.array = try container.decode([AnyValue].self, forKey: .array).map { ${'$'}0.unwrapped }
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.map.mapValues { try AnyValue.wrapped(${'$'}0) }, forKey: .map)
try container.encode(self.array.map { try AnyValue.wrapped(${'$'}0) }, forKey: .array)
}
public func withMap(map: [String : Any]) -> Test {
return Test(map: map)
return Test(map: map, array: array)
}
public func withArray(array: [Any]) -> Test {
return Test(map: map, array: array)
}
fileprivate enum CodingKeys : String, CodingKey {
case map = "map"
case array = "array"
}
Expand Down Expand Up @@ -184,8 +194,8 @@ class RamlObjectTypesTest {
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.optionalObject = try container.decodeIfPresent([String : AnyValue].self, forKey: .optionalObject)?.mapValues { ${'$'}0.unwrapped as Any }
self.nillableObject = try container.decodeIfPresent([String : AnyValue].self, forKey: .nillableObject)?.mapValues { ${'$'}0.unwrapped as Any }
self.optionalObject = try container.decodeIfPresent([String : AnyValue].self, forKey: .optionalObject)?.mapValues { ${'$'}0.unwrapped }
self.nillableObject = try container.decodeIfPresent([String : AnyValue].self, forKey: .nillableObject)?.mapValues { ${'$'}0.unwrapped }
}
public func encode(to encoder: Encoder) throws {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.outfoxx.sunday.generator.swift

import io.outfoxx.sunday.test.extensions.DiffingExtension
import io.outfoxx.sunday.test.extensions.ResourceExtension
import io.outfoxx.sunday.test.extensions.SwiftCompilerExtension
import org.junit.jupiter.api.extension.ExtendWith
Expand All @@ -25,5 +26,5 @@ import org.junit.jupiter.api.parallel.ResourceLock

@Execution(ExecutionMode.CONCURRENT)
@ResourceLock("Swift")
@ExtendWith(ResourceExtension::class, SwiftCompilerExtension::class)
@ExtendWith(ResourceExtension::class, SwiftCompilerExtension::class, DiffingExtension::class)
annotation class SwiftTest
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,27 @@ class RamlObjectTypesTest {
map: Record<string, unknown>;
array: Array<unknown>;
}
export class Test implements TestSpec {
map: Record<string, unknown>;
array: Array<unknown>;
constructor(init: TestSpec) {
this.map = init.map;
this.array = init.array;
}
copy(changes: Partial<TestSpec>): Test {
return new Test(Object.assign({}, this, changes));
}
toString(): string {
return `Test(map='${'$'}{this.map}')`;
return `Test(map='${'$'}{this.map}', array='${'$'}{this.array}')`;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.outfoxx.sunday.generator.typescript

import io.outfoxx.sunday.test.extensions.DiffingExtension
import io.outfoxx.sunday.test.extensions.ResourceExtension
import io.outfoxx.sunday.test.extensions.TypeScriptCompilerExtension
import org.junit.jupiter.api.extension.ExtendWith
Expand All @@ -25,5 +26,5 @@ import org.junit.jupiter.api.parallel.ResourceLock

@Execution(CONCURRENT)
@ResourceLock("TypeScript")
@ExtendWith(ResourceExtension::class, TypeScriptCompilerExtension::class)
@ExtendWith(ResourceExtension::class, TypeScriptCompilerExtension::class, DiffingExtension::class)
annotation class TypeScriptTest
Loading

0 comments on commit 7e8bc9f

Please sign in to comment.