Skip to content

Commit 8b2f1c5

Browse files
committed
README, fixes
1 parent 06997af commit 8b2f1c5

File tree

3 files changed

+112
-77
lines changed

3 files changed

+112
-77
lines changed

README.md

Lines changed: 97 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ And you will have to include the required dependencies:
2828

2929
```groovy
3030
dependencies {
31-
implementation 'com.github.tobrun.kotlin-data-compat:annotation:0.1.0'
32-
ksp 'com.github.tobrun.kotlin-data-compat:processor:0.1.0'
31+
implementation 'com.github.tobrun.kotlin-data-compat:annotation:0.3.0'
32+
ksp 'com.github.tobrun.kotlin-data-compat:processor:0.3.0'
3333
}
3434
```
3535

@@ -39,7 +39,10 @@ dependencies {
3939
Given an exisiting data class:
4040
- add `@DataCompat` annotation
4141
- mark class private
42-
- Append `Data` to the class name
42+
- append `Data` to the class name
43+
- support default parameters by using `@Default` annotation
44+
- retain existing class annotations (but not parameters for them)
45+
- retain existing interfaces
4346

4447
For example:
4548

@@ -57,101 +60,120 @@ private data class PersonData(val name: String, val nickname: String? = null, va
5760
After compilation, the following class will be generated:
5861

5962
```kotlin
63+
package com.tobrun.`data`.compat.example
64+
65+
import java.util.Objects
66+
import kotlin.Any
67+
import kotlin.Boolean
68+
import kotlin.Int
69+
import kotlin.String
70+
import kotlin.Unit
71+
import kotlin.jvm.JvmSynthetic
72+
6073
/**
6174
* Represents a person.
6275
* @property name The full name.
6376
* @property nickname The nickname.
6477
* @property age The age.
6578
*/
79+
@SampleAnnotation
6680
public class Person private constructor(
67-
public val name: String,
68-
public val nickname: String?,
69-
public val age: Int
70-
) {
71-
public override fun toString() = "Person(name=$name, nickname=$nickname, age=$age)"
72-
73-
public override fun equals(other: Any?): Boolean = other is Person
74-
&& name == other.name
75-
&& nickname == other.nickname
76-
&& age == other.age
77-
78-
public override fun hashCode(): Int = Objects.hash(name, nickname, age)
79-
80-
/**
81-
* Composes and builds a [Person] object.
82-
*
83-
* This is a concrete implementation of the builder design pattern.
84-
*
85-
* @property name The full name.
86-
* @property nickname The nickname.
87-
* @property age The age.
88-
*/
89-
public class Builder {
90-
@set:JvmSynthetic
91-
public var name: String? = null
92-
93-
@set:JvmSynthetic
94-
public var nickname: String? = null
95-
96-
@set:JvmSynthetic
97-
public var age: Int? = null
98-
99-
/**
100-
* Set the full name.
101-
*
102-
* @param name the full name.
103-
* @return Builder
104-
*/
105-
public fun setName(name: String?): Builder {
106-
this.name = name
107-
return this
81+
public val name: String,
82+
public val nickname: String?,
83+
public val age: Int
84+
) : SampleInterface {
85+
public override fun toString() = """Person(name=$name, nickname=$nickname,
86+
age=$age)""".trimIndent()
87+
88+
public override fun equals(other: Any?): Boolean {
89+
if (this === other) return true
90+
if (javaClass != other?.javaClass) return false
91+
other as Person
92+
return name == other.name && nickname == other.nickname && age == other.age
10893
}
10994

110-
/**
111-
* Set the nickname.
112-
*
113-
* @param nickname the nickname.
114-
* @return Builder
115-
*/
116-
public fun setNickname(nickname: String?): Builder {
117-
this.nickname = nickname
118-
return this
119-
}
95+
public override fun hashCode(): Int = Objects.hash(name, nickname, age)
12096

12197
/**
122-
* Set the age.
123-
*
124-
* @param age the age.
125-
* @return Builder
98+
* Convert to Builder allowing to change class properties.
12699
*/
127-
public fun setAge(age: Int?): Builder {
128-
this.age = age
129-
return this
130-
}
100+
public fun toBuilder(): Builder = Builder() .setName(name) .setNickname(nickname) .setAge(age)
131101

132102
/**
133-
* Returns a [Person] reference to the object being constructed by the builder.
103+
* Composes and builds a [Person] object.
134104
*
135-
* Throws an [IllegalArgumentException] when a non-null property wasn't initialised.
105+
* This is a concrete implementation of the builder design pattern.
136106
*
137-
* @return Person
107+
* @property name The full name.
108+
* @property nickname The nickname.
109+
* @property age The age.
138110
*/
139-
public fun build(): Person {
140-
if (name==null) {
141-
throw IllegalArgumentException("Null name found when building Person.")
142-
}
143-
if (age==null) {
144-
throw IllegalArgumentException("Null age found when building Person.")
145-
}
146-
return Person(name!!, nickname, age!!)
111+
public class Builder {
112+
@set:JvmSynthetic
113+
public var name: String? = "John"
114+
115+
@set:JvmSynthetic
116+
public var nickname: String? = null
117+
118+
@set:JvmSynthetic
119+
public var age: Int? = 42
120+
121+
/**
122+
* Set the full name.
123+
*
124+
* @param name the full name.
125+
* @return Builder
126+
*/
127+
public fun setName(name: String?): Builder {
128+
this.name = name
129+
return this
130+
}
131+
132+
/**
133+
* Set the nickname.
134+
*
135+
* @param nickname the nickname.
136+
* @return Builder
137+
*/
138+
public fun setNickname(nickname: String?): Builder {
139+
this.nickname = nickname
140+
return this
141+
}
142+
143+
/**
144+
* Set the age.
145+
*
146+
* @param age the age.
147+
* @return Builder
148+
*/
149+
public fun setAge(age: Int?): Builder {
150+
this.age = age
151+
return this
152+
}
153+
154+
/**
155+
* Returns a [Person] reference to the object being constructed by the builder.
156+
*
157+
* Throws an [IllegalArgumentException] when a non-null property wasn't initialised.
158+
*
159+
* @return Person
160+
*/
161+
public fun build(): Person {
162+
if (name==null) {
163+
throw IllegalArgumentException("Null name found when building Person.")
164+
}
165+
if (age==null) {
166+
throw IllegalArgumentException("Null age found when building Person.")
167+
}
168+
return Person(name!!, nickname, age!!)
169+
}
147170
}
148-
}
149171
}
150172

151173
/**
152174
* Creates a [Person] through a DSL-style builder.
153175
*
154-
* @param initializer the intialisation block
176+
* @param initializer the initialisation block
155177
* @return Person
156178
*/
157179
@JvmSynthetic

annotation/src/main/kotlin/com/tobrun/datacompat/annotation/Default.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ package com.tobrun.datacompat.annotation
55
* Workaround for KSP not supporting class default parameters:
66
* https://github.com/google/ksp/issues/642
77
*
8+
* Could be applied only for passing default values in the [DataCompat] class.
9+
*
810
* @param valueAsString exact representation of the default value. E.g. if default [String] is used,
911
* it should be passed here as "\"STRING_VALUE\""; if default [Int] is used, it should be passed
1012
* as "INT_VALUE".
1113
*/
1214
@Retention(AnnotationRetention.RUNTIME)
13-
@Target(AnnotationTarget.CLASS)
15+
@Target(AnnotationTarget.VALUE_PARAMETER)
1416
annotation class Default(val valueAsString: String)
Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package com.tobrun.data.compat.example
22

33
import com.tobrun.datacompat.annotation.DataCompat
4+
import com.tobrun.datacompat.annotation.Default
5+
6+
interface SampleInterface
7+
annotation class SampleAnnotation
48

59
/**
610
* Represents a person.
@@ -9,4 +13,11 @@ import com.tobrun.datacompat.annotation.DataCompat
913
* @property age The age.
1014
*/
1115
@DataCompat
12-
private data class PersonData(val name: String, val nickname: String? = null, val age: Int)
16+
@SampleAnnotation
17+
private data class PersonData(
18+
@Default("\"John\"")
19+
val name: String,
20+
val nickname: String?,
21+
@Default("42")
22+
val age: Int
23+
) : SampleInterface

0 commit comments

Comments
 (0)