Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix invalid enum generation when specific conditions are present #84

Merged
merged 2 commits into from
Jan 24, 2024
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
69 changes: 40 additions & 29 deletions src/main/kotlin/net/theevilreaper/dartpoet/clazz/ClassSpec.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
package net.theevilreaper.dartpoet.clazz

import net.theevilreaper.dartpoet.DartModifier.*
import net.theevilreaper.dartpoet.DartModifier
import net.theevilreaper.dartpoet.DartModifier.CLASS
import net.theevilreaper.dartpoet.DartModifier.WITH
import net.theevilreaper.dartpoet.InheritKeyword
import net.theevilreaper.dartpoet.annotation.AnnotationSpec
import net.theevilreaper.dartpoet.code.CodeWriter
import net.theevilreaper.dartpoet.code.buildCodeString
import net.theevilreaper.dartpoet.code.writer.ClassWriter
import net.theevilreaper.dartpoet.enum.EnumPropertySpec
import net.theevilreaper.dartpoet.function.FunctionSpec
import net.theevilreaper.dartpoet.function.constructor.ConstructorSpec
import net.theevilreaper.dartpoet.function.typedef.TypeDefSpec
import net.theevilreaper.dartpoet.property.PropertySpec
import net.theevilreaper.dartpoet.type.TypeName
import net.theevilreaper.dartpoet.util.toImmutableList
import net.theevilreaper.dartpoet.util.toImmutableSet

Expand All @@ -16,27 +26,26 @@ import net.theevilreaper.dartpoet.util.toImmutableSet
* @author theEvilReaper
*/
class ClassSpec internal constructor(
builder: ClassBuilder
builder: ClassBuilder,
) {
internal val name = builder.name
internal val classType = builder.classType
internal val modifiers = builder.classMetaData.modifiers.toImmutableSet()
internal val annotations = builder.classMetaData.annotations.toImmutableSet()
internal val endsWithNewLine = builder.endWithNewLine
internal val isEnum = builder.isEnumClass
internal val isAbstract = builder.isAbstract
internal val isMixin = builder.isMixinClass
internal val isAnonymous = builder.isAnonymousClass
internal val isLibrary = builder.isLibrary

internal val superClass = builder.superClass
internal val inheritKeyWord = builder.inheritKeyWord
internal val classModifiers = modifiers.filter { it != WITH }.toImmutableSet()
internal val typeDefs = builder.typedefs.toImmutableList()
internal val functions = builder.functionStack.toImmutableSet()
internal val properties = builder.propertyStack.toImmutableSet()
internal val constructors = builder.constructorStack.toImmutableSet()
internal val enumPropertyStack = builder.enumPropertyStack.toImmutableList()
internal val name: String = builder.name.orEmpty()
internal val classType: ClassType = builder.classType
internal val modifiers: Set<DartModifier> = builder.classMetaData.modifiers.toImmutableSet()
internal val annotations: Set<AnnotationSpec> = builder.classMetaData.annotations.toImmutableSet()
internal val endsWithNewLine: Boolean = builder.endWithNewLine
internal val isEnum: Boolean = builder.isEnumClass
internal val isAbstract: Boolean = builder.isAbstract
internal val isMixin: Boolean = builder.isMixinClass
internal val isAnonymous: Boolean = builder.isAnonymousClass
internal val isLibrary: Boolean = builder.isLibrary
internal val superClass: TypeName? = builder.superClass
internal val inheritKeyWord: InheritKeyword? = builder.inheritKeyWord
internal val classModifiers: Set<DartModifier> = modifiers.filter { it != WITH }.toImmutableSet()
internal val typeDefs: List<TypeDefSpec> = builder.typedefs.toImmutableList()
internal val functions: Set<FunctionSpec> = builder.functionStack.toImmutableSet()
internal val properties: Set<PropertySpec> = builder.propertyStack.toImmutableSet()
internal val constructors: Set<ConstructorSpec> = builder.constructorStack.toImmutableSet()
internal val enumPropertyStack: List<EnumPropertySpec> = builder.enumPropertyStack.toImmutableList()
internal var constantStack = builder.constantStack.toImmutableSet()

/**
Expand All @@ -46,17 +55,19 @@ class ClassSpec internal constructor(
get() = functions.isEmpty() && properties.isEmpty() && constructors.isEmpty() && constantStack.isEmpty() && enumPropertyStack.isEmpty()

init {
if (name != null) {
check(name.trim().isNotEmpty()) { "The name can't be empty" }
if (!isLibrary) {
check(name.isNotEmpty()) { "The name of a class can't be empty" }
}

/*check(isEnum && !this.modifiers.containsAnyOf(ABSTRACT, MIXIN)) {
"An enum class can't have [${ABSTRACT.identifier}, ${MIXIN.identifier} as modifiers"
}
if (isEnum) {
check(enumPropertyStack.isNotEmpty()) { "A enum requires at least one enum property" }

val propertiesSize: Int = properties.size

check (isAbstract && !this.modifiers.containsAnyOf(MIXIN, ENUM)) {
"An abstract class can't have [${ABSTRACT.identifier}, ${ENUM.identifier} as modifiers"
}*/
enumPropertyStack.forEach {
check(it.parameters.size == propertiesSize) { "The entries from the enum property must have the same size" }
}
}
}

/**
Expand Down
51 changes: 0 additions & 51 deletions src/test/kotlin/net/theevilreaper/dartpoet/DartFileTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -151,57 +151,6 @@ class DartFileTest {
)
}

@Test
fun `test enum class write`() {
val enumClass = DartFile.builder("navigation_entry")
.type(
ClassSpec.enumClass("NavigationEntry")
.properties(
PropertySpec.builder("name", String::class)
.modifier { DartModifier.FINAL }.build(),
PropertySpec.builder("route", String::class)
.modifier { DartModifier.FINAL }.build()

)
.enumProperties(
EnumPropertySpec.builder("dashboard")
.parameter("%C", "Dashboard")
.parameter("%C", "/dashboard")
.build(),
EnumPropertySpec.builder("build")
.parameter("%C", "Build")
.parameter("%C", "/build")
.build()
)
.constructor(
ConstructorSpec.builder("NavigationEntry")
.modifier(DartModifier.CONST)
.parameters(
ParameterSpec.builder("name").build(),
ParameterSpec.builder("route").build()
)
.build()
)
.build()
)
.build()
assertThat(enumClass.toString()).isEqualTo(
"""
enum NavigationEntry {

dashboard('Dashboard', '/dashboard'),
build('Build', '/build');

final String name;
final String route;

const NavigationEntry(name, route);

}
""".trimIndent()
)
}

@Test
fun `test api handler write`() {
val className = "DefectApi"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package net.theevilreaper.dartpoet.classTypes

import com.google.common.truth.Truth.assertThat
import net.theevilreaper.dartpoet.DartFile
import net.theevilreaper.dartpoet.DartModifier
import net.theevilreaper.dartpoet.clazz.ClassSpec
import net.theevilreaper.dartpoet.enum.EnumPropertySpec
import net.theevilreaper.dartpoet.function.constructor.ConstructorSpec
import net.theevilreaper.dartpoet.parameter.ParameterSpec
import net.theevilreaper.dartpoet.property.PropertySpec
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource
import java.util.stream.Stream
import kotlin.test.assertEquals

class EnumClassTest {

companion object {

@JvmStatic
private fun invalidEnums() = Stream.of(
Arguments.of(
{
ClassSpec.enumClass("TestEnum")
.property(
PropertySpec.builder("name", String::class).build()
)
.build()
},
"A enum requires at least one enum property"
),
Arguments.of(
{
ClassSpec.enumClass("TestEnum")
.enumProperties(
EnumPropertySpec.builder("test")
.parameter("%C", "Test")
.parameter("%L", "10")
.build()
)
.property(PropertySpec.builder("name", String::class).build())
.constructor(
ConstructorSpec.builder("TestEnum")
.parameter(ParameterSpec.builder("name").build())
.build()
)
.build()
},
"The entries from the enum property must have the same size"
)
)
}

@ParameterizedTest
@MethodSource("invalidEnums")
fun `test invalid enum creation`(classSpec: () -> Unit, message: String) {
val exception = assertThrows<IllegalStateException> { classSpec() }
assertEquals(IllegalStateException::class, exception::class)
assertEquals(message, exception.message)
}

@Test
fun `test invalid enum creation`() {
val enumClass = ClassSpec.enumClass("TestEnum")
.property(PropertySpec.builder("name", String::class).build())
.constructor(
ConstructorSpec.builder("TestEnum")
.parameter(ParameterSpec.builder("name").build())
.build()
)
val exception = assertThrows<IllegalStateException> { enumClass.build() }
assertEquals(IllegalStateException::class, exception::class)
assertEquals("A enum requires at least one enum property", exception.message)
}

@Test
fun `test enum class write`() {
val enumClass = DartFile.builder("navigation_entry")
.type(
ClassSpec.enumClass("NavigationEntry")
.properties(
PropertySpec.builder("name", String::class)
.modifier { DartModifier.FINAL }.build(),
PropertySpec.builder("route", String::class)
.modifier { DartModifier.FINAL }.build()

)
.enumProperties(
EnumPropertySpec.builder("dashboard")
.parameter("%C", "Dashboard")
.parameter("%C", "/dashboard")
.build(),
EnumPropertySpec.builder("build")
.parameter("%C", "Build")
.parameter("%C", "/build")
.build()
)
.constructor(
ConstructorSpec.builder("NavigationEntry")
.modifier(DartModifier.CONST)
.parameters(
ParameterSpec.builder("name").build(),
ParameterSpec.builder("route").build()
)
.build()
)
.build()
)
.build()
assertThat(enumClass.toString()).isEqualTo(
"""
enum NavigationEntry {

dashboard('Dashboard', '/dashboard'),
build('Build', '/build');

final String name;
final String route;

const NavigationEntry(name, route);

}
""".trimIndent()
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ class ClassWriterTest {
private fun simpleClasses() = Stream.of(
Arguments.of(ClassSpec.builder("Test").build(), "class Test {}"),
Arguments.of(ClassSpec.mixinClass("Test").build(), "mixin Test {}"),
Arguments.of(ClassSpec.enumClass("Test").build(), "enum Test {}"),
Arguments.of(
ClassSpec.builder("Model").endWithNewLine(true).build(),
"""
Expand Down