Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 21 additions & 10 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,24 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Set up JDK 21
uses: actions/setup-java@v4.5.0
with:
java-version: '21'
distribution: 'adopt'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
- uses: actions/checkout@v2
- name: Set up JDK 21
uses: actions/setup-java@v4.5.0
with:
java-version: '21'
distribution: 'adopt'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build

# upload file:///home/runner/work/ts-generator/ts-generator/build/reports/tests/test/index.html
# Warning: No files were found with the provided path: ts-generator/build/reports/tests/test/. No artifacts will be uploaded.
- name: Upload test report to GitHub Actions
if: always()
uses: actions/upload-artifact@v4
with:
name: 'test-report'
path: 'build/reports/tests/test/'


50 changes: 31 additions & 19 deletions src/main/kotlin/me/ntrrgc/tsGenerator/TypeScriptGenerator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,7 @@ class TypeScriptGenerator(
}

private fun generateDefinition(): String {
return if (klass.java.isEnum) {
generateEnum(klass)
} else {
generateInterface(klass)
}
return generateInterface(klass)
}


Expand All @@ -169,7 +165,11 @@ class TypeScriptGenerator(
)
arrayFromKType(kType)
else if (classifier.isSubclassOf(Map::class))
mapFromKType(kType)
try {
mapFromKType(kType)
} catch (_: Exception) {
nonPrimitiveFromKType(kType)
}
else
nonPrimitiveFromKType(kType)
)
Expand Down Expand Up @@ -244,28 +244,37 @@ class TypeScriptGenerator(
getIterableElementType(kType) ?: kType.arguments.singleOrNull()?.type ?: KotlinAnyOrNull
}
}
return "${formatKType(itemType).formatWithParenthesis()}[]"
// a Path is iterable and it returns Path s for subdirectories
return if (kType == itemType)
"${nonPrimitiveFromKType(kType)}[]" // can it be others like maps?
else
"${formatKType(itemType).formatWithParenthesis()}[]"
}

// https://github.com/ntrrgc/ts-generator/pull/39/files#diff-15868d315697c109f701fa6b29d6b1beaabb6c461122d4cbca76194bba08da6eR194
// GPLv3 does not apply for this function
private fun mapFromKType(kType: KType): String {
// Use native JS associative object

val rawKeyType = kType.arguments[0].type ?: KotlinAnyOrNull
val keyType = formatKType(rawKeyType)
val valueType = formatKType(kType.arguments[1].type ?: KotlinAnyOrNull)
return if ((rawKeyType.classifier as? KClass<*>)?.java?.isEnum == true)
"{ [key in ${keyType.formatWithoutParenthesis()}]: ${valueType.formatWithoutParenthesis()} }"
else
"{ [key: ${keyType.formatWithoutParenthesis()}]: ${valueType.formatWithoutParenthesis()} }"
}

private fun generateEnum(klass: KClass<*>): String {
return "type ${klass.simpleName} = ${
klass.java.enumConstants.joinToString(" | ") { constant: Any ->
constant.toString().toJSString()
}
};"
val isKeyEnum = (rawKeyType.classifier as? KClass<*>)?.java?.isEnum == true

return when {
isKeyEnum ->
"{ [key in ${keyType.formatWithoutParenthesis()}]: ${valueType.formatWithoutParenthesis()} }"

keyType.formatWithoutParenthesis() == "string" || keyType.formatWithoutParenthesis() == "number" ->
"{ [key: ${keyType.formatWithoutParenthesis()}]: ${valueType.formatWithoutParenthesis()} }"

else ->
"Map<${keyType.formatWithoutParenthesis()}, ${valueType.formatWithoutParenthesis()}>"
}

}


private fun generateInterface(klass: KClass<*>): String {
val supertypes = klass.supertypes
.filterNot { it.classifier in ignoredSuperclasses }
Expand Down Expand Up @@ -325,6 +334,9 @@ class TypeScriptGenerator(
} catch (exception: kotlin.reflect.jvm.internal.KotlinReflectionInternalError) {
print(exception.toString())
""
} catch (exception: java.lang.IllegalArgumentException) {
print(exception.toString())
""
}

private fun functionsOf(klass: KClass<*>): String = try {
Expand Down
40 changes: 26 additions & 14 deletions src/test/kotlin/me/ntrrgc/tsGenerator/tests/generatorTests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,27 @@ fun runModuleGenerationWithoutVerification(
ignoreSuperclasses: Set<KClass<*>> = setOf(),
voidType: VoidType = VoidType.NULL
) {
val generator = TypeScriptGenerator(
listOf(klass), mappings, classTransformers,
ignoreSuperclasses, intTypeName = "number", voidType = voidType
)
try {
val generator = TypeScriptGenerator(
listOf(klass), mappings, classTransformers,
ignoreSuperclasses, intTypeName = "number", voidType = voidType
)

val modules = generator.definitionsAsModules

val modules = generator.definitionsAsModules
for (module in modules) {
println("file: ${module.key}")
println()
println("content: ${module.value}")
println()
}

for (module in modules) {
println("file: ${module.key}")
println()
println("content: ${module.value}")
println()
true shouldBe true
} catch (exception: Exception) {
exception.printStackTrace()
throw exception
}

true shouldBe true
}

@Suppress("unused")
Expand Down Expand Up @@ -967,8 +973,14 @@ class ModuleOutput : StringSpec({

class Tests : StringSpec({
"generates NPM package without spitting error" {
TypeScriptGenerator(listOf(ClassWithMethodsThatReturnsOrTakesFunctionalType::class))
.generateNPMPackage("test-generated-package-types")
.writePackageTo(Path("./runs"))
try {
TypeScriptGenerator(listOf(ClassWithMethodsThatReturnsOrTakesFunctionalType::class))
.generateNPMPackage("test-generated-package-types")
.writePackageTo(Path("./runs"))
} catch (exception: Exception) {
exception.printStackTrace()
throw exception
}

}
})
Loading