Skip to content

Commit a288ebb

Browse files
y9vad9y9neon
and
y9neon
authored
1.0.2 (#7)
* refactor: `DSLImpl` renamed to `DSLBuilderImpl` * refactor: `DSLImpl` renamed to `DSLBuilderImpl` * chore: version updated to `1.0.2` * refactor: codegen refactoring (MutableImpl, ImmutableImpl, FactoryFunctionImpl) & little changes * refactor: removed file with old codegen * refactor: codegen rewriting Co-authored-by: y9neon <justneon33@gmail.com>
1 parent 83580cd commit a288ebb

20 files changed

+381
-247
lines changed

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@
22

33
# implier
44

5-
Kotlin Symbol Processor library for creating [**Mutable**](https://github.com/y9vad9/implier/blob/fb5cba3c62defe23ce5773287fc9f37367d800fd/src/main/kotlin/com/y9vad9/implier/annotations.kt#L10), [**Immutable**](https://github.com/y9vad9/implier/blob/fb5cba3c62defe23ce5773287fc9f37367d800fd/src/main/kotlin/com/y9vad9/implier/annotations.kt#L18), [**Builders**](https://github.com/y9vad9/implier/blob/fb5cba3c62defe23ce5773287fc9f37367d800fd/src/main/kotlin/com/y9vad9/implier/annotations.kt#L35), [**DSL Builders**](https://github.com/y9vad9/implier/blob/1.0.1/src/main/kotlin/com/y9vad9/implier/annotations.kt#L50) from interfaces & abstract classes with properties.
5+
Kotlin Symbol Processor library for creating [**
6+
Mutable**](https://github.com/y9vad9/implier/blob/fb5cba3c62defe23ce5773287fc9f37367d800fd/src/main/kotlin/com/y9vad9/implier/annotations.kt#L10)
7+
, [**
8+
Immutable**](https://github.com/y9vad9/implier/blob/fb5cba3c62defe23ce5773287fc9f37367d800fd/src/main/kotlin/com/y9vad9/implier/annotations.kt#L18)
9+
, [**
10+
Builders**](https://github.com/y9vad9/implier/blob/fb5cba3c62defe23ce5773287fc9f37367d800fd/src/main/kotlin/com/y9vad9/implier/annotations.kt#L35)
11+
, [**DSL Builders**](https://github.com/y9vad9/implier/blob/1.0.1/src/main/kotlin/com/y9vad9/implier/annotations.kt#L50)
12+
from interfaces & abstract classes with properties.
613

714
## Examples
815

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
object AppInfo {
22
const val PACKAGE = "com.y9vad9.implier"
3-
const val VERSION = "1.0.0"
3+
const val VERSION = "1.0.2"
44
}

build-logic/dependencies/src/main/kotlin/Deps.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ object Deps {
4646
const val JUnit = "org.jetbrains.kotlin:kotlin-test-junit5:$kotlinVersion"
4747
}
4848

49-
const val KotlinPoet = "com.squareup:kotlinpoet:1.10.2"
49+
object KotlinPoet {
50+
const val KotlinPoet = "com.squareup:kotlinpoet:1.10.2"
51+
const val KSP = "com.squareup:kotlinpoet-ksp:1.10.2"
52+
}
5053

5154
object KotlinGang {
5255
object KDS {

ksp/build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ kotlin {
99
val jvmMain by getting {
1010
dependencies {
1111
implementation(Deps.Libs.KSP.Api)
12-
implementation(Deps.Libs.KotlinPoet)
12+
implementation(Deps.Libs.KotlinPoet.KotlinPoet)
13+
implementation(Deps.Libs.KotlinPoet.KSP)
1314
implementation(Deps.Libs.Kotlin.Reflection)
1415
implementation(project(":"))
1516
}

ksp/src/main/kotlin/com/y9vad9/implier/AnnotationsVisitor.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ class AnnotationsVisitor(private val codeGenerator: CodeGenerator) : KSVisitorVo
3838
classDeclaration
3939
)
4040
}
41-
if (classDeclaration.isAnnotationPresent(DSLImpl::class)) {
41+
if (classDeclaration.isAnnotationPresent(DSLBuilderImpl::class)) {
4242
DSLImplAnnotatedClassProcessor.process(
43-
classDeclaration.getAnnotationsByType(DSLImpl::class).first(),
43+
classDeclaration.getAnnotationsByType(DSLBuilderImpl::class).first(),
4444
codeGenerator,
4545
classDeclaration
4646
)

ksp/src/main/kotlin/com/y9vad9/implier/ImplierAnnotationProcessor.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ class ImplierAnnotationProcessor(private val codeGenerator: CodeGenerator) : Sym
1717
resolver.getAllFiles().flatMap { it.declarations }.filter {
1818
it.isAnnotationPresent(MutableImpl::class)
1919
|| it.isAnnotationPresent(ImmutableImpl::class)
20-
|| it.isAnnotationPresent(FactoryFunctionImpl::class
20+
|| it.isAnnotationPresent(
21+
FactoryFunctionImpl::class
2122
)
2223
}
2324

ksp/src/main/kotlin/com/y9vad9/implier/annotations/processor/BuilderImplAnnotatedClassProcessor.kt

Lines changed: 4 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import com.squareup.kotlinpoet.*
99
import com.y9vad9.implier.BuilderImpl
1010
import com.y9vad9.implier.ImmutableImpl
1111
import com.y9vad9.implier.MutableImpl
12+
import com.y9vad9.implier.codegen.BuilderFileCodeGeneration
13+
import com.y9vad9.implier.codegen.BuilderFileCodeGeneration.generate
1214
import java.io.OutputStreamWriter
1315
import java.util.*
1416

@@ -25,76 +27,14 @@ object BuilderImplAnnotatedClassProcessor : AnnotatedClassProcessor<BuilderImpl>
2527
classDeclaration.simpleName.asString().plus("Builder")
2628
).use { output ->
2729
OutputStreamWriter(output).use { writer ->
28-
generateBuilderImplementation(
30+
BuilderFileCodeGeneration.Data(
2931
type = annotation.type,
3032
initVariantCode = (if (!(classDeclaration.isAnnotationPresent(ImmutableImpl::class))) "Immutable" else "Mutable").plus(
3133
classDeclaration.simpleName.asString()
3234
),
3335
classDeclaration
34-
).writeTo(writer)
36+
).generate().writeTo(writer)
3537
}
3638
}
3739
}
38-
}
39-
40-
private fun generateBuilderImplementation(
41-
type: BuilderImpl.Type,
42-
initVariantCode: String,
43-
declaration: KSClassDeclaration
44-
): FileSpec {
45-
val file = FileSpec.builder(
46-
declaration.packageName.asString(),
47-
declaration.simpleName.asString().plus("Builder")
48-
)
49-
val builderClassName = ClassName(declaration.packageName.asString(), declaration.simpleName.asString().plus("Builder"))
50-
val builderClass = TypeSpec.classBuilder(file.name)
51-
for (member in declaration.getAllProperties()) {
52-
val resolvedMember = member.type.resolve()
53-
val memberType = ClassName(
54-
resolvedMember.declaration.packageName.asString(),
55-
resolvedMember.declaration.simpleName.asString()
56-
)
57-
builderClass.addProperty(
58-
PropertySpec.builder(member.simpleName.asString(), memberType)
59-
.mutable(true)
60-
.delegate("kotlin.properties.Delegates.notNull()")
61-
.addModifiers(KModifier.PRIVATE)
62-
.build()
63-
)
64-
builderClass.addFunction(
65-
FunSpec.builder(
66-
if (type == BuilderImpl.Type.WITHOUT_ACCESSORS) member.simpleName.asString() else "set${
67-
member.simpleName.asString()
68-
.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
69-
}"
70-
).addParameter(
71-
"value",
72-
ClassName(
73-
resolvedMember.declaration.packageName.asString(),
74-
resolvedMember.declaration.simpleName.asString()
75-
)
76-
)
77-
.returns(builderClassName)
78-
.addCode("${member.simpleName.asString()} = value\n")
79-
.addCode("return this")
80-
.build()
81-
)
82-
}
83-
builderClass.addFunction(
84-
FunSpec.builder("build")
85-
.addCode(
86-
"return $initVariantCode(${
87-
declaration.getAllProperties().joinToString(",") { it.simpleName.asString() }
88-
})"
89-
)
90-
.returns(
91-
ClassName(
92-
declaration.packageName.asString(),
93-
declaration.simpleName.asString()
94-
)
95-
)
96-
.build()
97-
)
98-
file.addType(builderClass.build())
99-
return file.build()
10040
}

ksp/src/main/kotlin/com/y9vad9/implier/annotations/processor/DSLImplAnnotatedClassProcessor.kt

Lines changed: 11 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,21 @@ import com.google.devtools.ksp.processing.CodeGenerator
66
import com.google.devtools.ksp.processing.Dependencies
77
import com.google.devtools.ksp.symbol.KSClassDeclaration
88
import com.squareup.kotlinpoet.*
9-
import com.y9vad9.implier.DSLImpl
9+
import com.y9vad9.implier.DSLBuilderImpl
1010
import com.y9vad9.implier.ImmutableImpl
1111
import com.y9vad9.implier.MutableImpl
12+
import com.y9vad9.implier.codegen.DSLFileCodeGeneration
13+
import com.y9vad9.implier.codegen.DSLFileCodeGeneration.generate
1214
import java.io.OutputStreamWriter
1315
import java.util.*
1416

15-
object DSLImplAnnotatedClassProcessor : AnnotatedClassProcessor<DSLImpl> {
17+
object DSLImplAnnotatedClassProcessor : AnnotatedClassProcessor<DSLBuilderImpl> {
1618
@OptIn(KspExperimental::class)
17-
override fun process(annotation: DSLImpl, codeGenerator: CodeGenerator, classDeclaration: KSClassDeclaration) {
19+
override fun process(
20+
annotation: DSLBuilderImpl,
21+
codeGenerator: CodeGenerator,
22+
classDeclaration: KSClassDeclaration
23+
) {
1824
if (!(classDeclaration.isAnnotationPresent(ImmutableImpl::class)
1925
&& classDeclaration.isAnnotationPresent(MutableImpl::class))
2026
)
@@ -25,97 +31,15 @@ object DSLImplAnnotatedClassProcessor : AnnotatedClassProcessor<DSLImpl> {
2531
classDeclaration.simpleName.asString().plus("BuilderScope")
2632
).use { output ->
2733
OutputStreamWriter(output).use { writer ->
28-
generateDSLImplementation(
34+
DSLFileCodeGeneration.Data(
2935
type = annotation.type,
3036
initVariantCode = (if (!(classDeclaration.isAnnotationPresent(ImmutableImpl::class))) "Immutable" else "Mutable").plus(
3137
classDeclaration.simpleName.asString()
3238
),
3339
functionName = annotation.functionName,
3440
declaration = classDeclaration
35-
).writeTo(writer)
41+
).generate().writeTo(writer)
3642
}
3743
}
3844
}
3945
}
40-
41-
private fun generateDSLImplementation(
42-
type: DSLImpl.Type,
43-
functionName: String,
44-
initVariantCode: String,
45-
declaration: KSClassDeclaration
46-
): FileSpec {
47-
val name = declaration.simpleName.asString().plus("BuilderScope")
48-
val file = FileSpec.builder(
49-
declaration.packageName.asString(),
50-
name
51-
)
52-
val builderClassName = ClassName(declaration.packageName.asString(), name)
53-
val builderClass = TypeSpec.classBuilder(file.name)
54-
for (member in declaration.getAllProperties()) {
55-
val resolvedMember = member.type.resolve()
56-
val memberType = ClassName(
57-
resolvedMember.declaration.packageName.asString(),
58-
resolvedMember.declaration.simpleName.asString()
59-
)
60-
when (type) {
61-
DSLImpl.Type.PROPERTY_ACCESS -> builderClass.addProperty(
62-
PropertySpec.builder(member.simpleName.asString(), memberType)
63-
.mutable(true)
64-
.delegate("kotlin.properties.Delegates.notNull()")
65-
.build()
66-
)
67-
else -> {
68-
builderClass.addProperty(
69-
PropertySpec.builder(member.simpleName.asString(), memberType)
70-
.mutable(true)
71-
.delegate("kotlin.properties.Delegates.notNull()")
72-
.addModifiers(KModifier.PUBLIC)
73-
.build()
74-
)
75-
builderClass.addFunction(
76-
FunSpec.builder(
77-
if (type == DSLImpl.Type.WITHOUT_ACCESSORS) member.simpleName.asString() else "set${
78-
member.simpleName.asString()
79-
.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
80-
}"
81-
).addParameter(
82-
"value",
83-
ClassName(
84-
resolvedMember.declaration.packageName.asString(),
85-
resolvedMember.declaration.simpleName.asString()
86-
)
87-
)
88-
.returns(builderClassName)
89-
.addCode("${member.simpleName.asString()} = value\n")
90-
.addCode("return this")
91-
.build()
92-
)
93-
}
94-
}
95-
}
96-
file.addFunction(
97-
FunSpec.builder(functionName)
98-
.addParameter(
99-
"block",
100-
LambdaTypeName.get(receiver = builderClassName, returnType = Unit::class.asTypeName())
101-
)
102-
.addCode(
103-
"""
104-
val dslBuilder = $name()
105-
dslBuilder.apply(block)
106-
return $initVariantCode(${
107-
declaration.getAllProperties().joinToString(",") { "dslBuilder." + it.simpleName.asString() }
108-
})
109-
""".trimIndent()
110-
)
111-
.returns(
112-
ClassName(
113-
declaration.packageName.asString(),
114-
declaration.simpleName.asString()
115-
)
116-
)
117-
.build()
118-
)
119-
file.addType(builderClass.build())
120-
return file.build()
121-
}

ksp/src/main/kotlin/com/y9vad9/implier/annotations/processor/FactoryFunctionAnnotatedClassProcessor.kt

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,37 @@ import com.google.devtools.ksp.isAnnotationPresent
55
import com.google.devtools.ksp.processing.CodeGenerator
66
import com.google.devtools.ksp.processing.Dependencies
77
import com.google.devtools.ksp.symbol.KSClassDeclaration
8-
import com.y9vad9.implier.*
9-
import com.y9vad9.implier.generateFactory
8+
import com.y9vad9.implier.FactoryFunctionImpl
9+
import com.y9vad9.implier.ImmutableImpl
10+
import com.y9vad9.implier.MutableImpl
11+
import com.y9vad9.implier.codegen.FunctionFactoryFileCodeGeneration
12+
import com.y9vad9.implier.codegen.FunctionFactoryFileCodeGeneration.generate
1013
import java.io.OutputStreamWriter
1114

1215
object FactoryFunctionAnnotatedClassProcessor : AnnotatedClassProcessor<FactoryFunctionImpl> {
1316
@OptIn(KspExperimental::class)
14-
override fun process(annotation: FactoryFunctionImpl, codeGenerator: CodeGenerator, classDeclaration: KSClassDeclaration) {
15-
val variantName = if(classDeclaration.isAnnotationPresent(ImmutableImpl::class))
17+
override fun process(
18+
annotation: FactoryFunctionImpl,
19+
codeGenerator: CodeGenerator,
20+
classDeclaration: KSClassDeclaration
21+
) {
22+
val variantName = if (classDeclaration.isAnnotationPresent(ImmutableImpl::class))
1623
"Immutable"
17-
else if(classDeclaration.isAnnotationPresent(MutableImpl::class))
24+
else if (classDeclaration.isAnnotationPresent(MutableImpl::class))
1825
"Mutable"
1926
else throw IllegalStateException(
20-
"Unable to create factory function for interface that does not have Mutable or Immutable realization"
27+
"Unable to create factory function for interface / class that does not have Mutable or Immutable realization"
2128
)
22-
if(classDeclaration.isAnnotationPresent(ImmutableImpl::class)) {
29+
if (classDeclaration.isAnnotationPresent(ImmutableImpl::class)) {
2330
codeGenerator.createNewFile(
2431
Dependencies(false),
2532
classDeclaration.packageName.asString(),
2633
classDeclaration.simpleName.asString().plus("Factory")
2734
).use { output ->
2835
OutputStreamWriter(output).use { writer ->
29-
generateFactory(variantName, classDeclaration).writeTo(writer)
36+
FunctionFactoryFileCodeGeneration.Data(variantName, classDeclaration)
37+
.generate()
38+
.writeTo(writer)
3039
}
3140
}
3241
}

ksp/src/main/kotlin/com/y9vad9/implier/annotations/processor/ImmutableAnnotatedClassProcessor.kt

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,35 @@ package com.y9vad9.implier.annotations.processor
22

33
import com.google.devtools.ksp.processing.CodeGenerator
44
import com.google.devtools.ksp.processing.Dependencies
5+
import com.google.devtools.ksp.symbol.ClassKind
56
import com.google.devtools.ksp.symbol.KSClassDeclaration
7+
import com.google.devtools.ksp.symbol.Modifier
68
import com.y9vad9.implier.ImmutableImpl
7-
import com.y9vad9.implier.generateVariant
9+
import com.y9vad9.implier.codegen.ImplementationFileCodeGeneration
10+
import com.y9vad9.implier.codegen.ImplementationFileCodeGeneration.generate
811
import java.io.OutputStreamWriter
912

1013
object ImmutableAnnotatedClassProcessor : AnnotatedClassProcessor<ImmutableImpl> {
11-
override fun process(annotation: ImmutableImpl, codeGenerator: CodeGenerator, classDeclaration: KSClassDeclaration) {
14+
override fun process(
15+
annotation: ImmutableImpl,
16+
codeGenerator: CodeGenerator,
17+
classDeclaration: KSClassDeclaration
18+
) {
19+
if (classDeclaration.classKind == ClassKind.CLASS && Modifier.ABSTRACT !in classDeclaration.modifiers)
20+
throw IllegalStateException("Unable to create realization from non-abstract class")
21+
else if (classDeclaration.classKind != ClassKind.INTERFACE)
22+
throw IllegalStateException("Unable to create realization from ${classDeclaration.classKind}.")
23+
1224
codeGenerator.createNewFile(
1325
Dependencies(false),
1426
classDeclaration.packageName.asString(),
1527
"Immutable${classDeclaration.simpleName.asString()}"
1628
).use { output ->
1729
OutputStreamWriter(output).use { writer ->
18-
generateVariant("Immutable", false, classDeclaration).writeTo(writer)
30+
ImplementationFileCodeGeneration.Data(
31+
mutable = false,
32+
declaration = classDeclaration
33+
).generate().writeTo(writer)
1934
}
2035
}
2136
}

ksp/src/main/kotlin/com/y9vad9/implier/annotations/processor/MutableAnnotatedClassProcessor.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,29 @@ package com.y9vad9.implier.annotations.processor
22

33
import com.google.devtools.ksp.processing.CodeGenerator
44
import com.google.devtools.ksp.processing.Dependencies
5+
import com.google.devtools.ksp.symbol.ClassKind
56
import com.google.devtools.ksp.symbol.KSClassDeclaration
7+
import com.google.devtools.ksp.symbol.Modifier
68
import com.y9vad9.implier.MutableImpl
7-
import com.y9vad9.implier.generateVariant
9+
import com.y9vad9.implier.codegen.ImplementationFileCodeGeneration
10+
import com.y9vad9.implier.codegen.ImplementationFileCodeGeneration.generate
811
import java.io.OutputStreamWriter
912

1013
object MutableAnnotatedClassProcessor : AnnotatedClassProcessor<MutableImpl> {
1114
override fun process(annotation: MutableImpl, codeGenerator: CodeGenerator, classDeclaration: KSClassDeclaration) {
15+
if (classDeclaration.classKind == ClassKind.CLASS && Modifier.ABSTRACT !in classDeclaration.modifiers)
16+
throw IllegalStateException("Unable to create realization from non-abstract class")
17+
else if (classDeclaration.classKind != ClassKind.INTERFACE)
18+
throw IllegalStateException("Unable to create realization from ${classDeclaration.classKind}.")
19+
1220
codeGenerator.createNewFile(
1321
Dependencies(false),
1422
classDeclaration.packageName.asString(),
1523
"Mutable${classDeclaration.simpleName.asString()}"
1624
).use { output ->
1725
OutputStreamWriter(output).use { writer ->
18-
generateVariant("Mutable", true, classDeclaration).writeTo(writer)
26+
ImplementationFileCodeGeneration.Data(true, classDeclaration).generate()
27+
.writeTo(writer)
1928
}
2029
}
2130
}

0 commit comments

Comments
 (0)