[lombok] Run compiled code

This commit is contained in:
Andrey Zinovyev
2021-03-28 17:54:41 +03:00
committed by TeamCityServer
parent 411441c332
commit d459cde010
24 changed files with 196 additions and 45 deletions
@@ -439,6 +439,7 @@ public abstract class CodegenTestCase extends KotlinBaseTest<KotlinBaseTest.Test
OutputUtilsKt.writeAllTo(classFileFactory, kotlinOut);
}
javaClassesOutputDirectory = null;
if (compileJavaFiles) {
List<String> javaClasspath = new ArrayList<>();
javaClasspath.add(kotlinOut.getPath());
@@ -463,6 +464,13 @@ public abstract class CodegenTestCase extends KotlinBaseTest<KotlinBaseTest.Test
throw ExceptionUtilsKt.rethrow(e);
}
}
if (kotlinOut != null) {
postCompile(kotlinOut, javaClassesOutputDirectory);
}
}
protected void postCompile(@NotNull File kotlinOut, @Nullable File javaOut) {
}
protected void runJavacTask(@NotNull Collection<File> files, @NotNull List<String> options) throws IOException {
@@ -17,6 +17,7 @@ Features support:
- [ ] Copy annotations
- [ ] Strip defined prefixes - in config and @Accessors
- [ ] Skip generation with AccessLevel.NONE
- [ ] Strip 'is' prefix for boolean fields
[~] [@With](https://projectlombok.org/features/With)
@@ -37,7 +38,7 @@ Features support:
Other todos:
- [x] Generic classes
- [ ] Actually run compiled code
- [x] Actually run compiled code
- [ ] Don't generate members that already exist (if having a duplicate is a problem)
- [ ] Gradle integration (as subplugin or just a way to enable lombok support)
- [ ] Maven integration (as subplugin or just a way to enable lombok support)
@@ -31,11 +31,13 @@ data class Accessors(val fluent: Boolean = false, val chain: Boolean = false) {
override val name: FqName = LombokNames.ACCESSORS
override fun extract(annotation: AnnotationDescriptor): Accessors =
Accessors(
fluent = annotation.getBooleanArgument("fluent"),
chain = annotation.getBooleanArgument("chain")
override fun extract(annotation: AnnotationDescriptor): Accessors {
val fluent = annotation.getBooleanArgument("fluent")
return Accessors(
fluent = fluent,
chain = annotation.getBooleanArgument("chain", default = fluent)
)
}
}
}
@@ -19,8 +19,8 @@ public class ConstructorExample {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val generated = ConstructorExample(12, "sdf", true)
}
}
@@ -24,8 +24,8 @@ public class ConstructorExample {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val existing: ConstructorExample = ConstructorExample("existing")
val generated: ConstructorExample = ConstructorExample.of(45, "234", false)
}
@@ -0,0 +1,111 @@
//FILE: SuperClass.java
import lombok.*;
import java.util.*;
public class SuperClass {
public void setName(String name) {
}
}
//FILE: ClashTest.java
import lombok.*;
import java.util.*;
@Getter
@Setter
public class ClashTest extends SuperClass {
private int age = 10;
private String name;
private boolean human;
private Integer toOverride;
public int getAge() {
return age;
}
public void setAge(String age) {
}
public boolean isHuman(String arg) {
return human;
}
static void test() {
val obj = new ClashTest();
obj.getAge();
// obj.setAge(41);
obj.getName();
obj.setName("Al");
obj.isHuman();
obj.setHuman(true);
obj.isHuman("sdf");
}
}
//FILE: ChildClass.java
import lombok.*;
import java.util.*;
public class ChildClass extends ClashTest{
@Override
public Integer getToOverride() {
return super.getToOverride();
}
}
//FILE: test.kt
class KotlinChildClass : ClashTest() {
override fun getToOverride(): Int = super.getToOverride()
}
class Test {
fun run() {
val obj = ClashTest()
obj.getAge()
//todo thats shouldn't work
obj.setAge(41)
val age = obj.age
obj.age = 12
obj.getName()
obj.setName("Al")
val name = obj.name
obj.name = "sdf"
obj.isHuman()
obj.setHuman(true)
obj.isHuman("sdf")
val isHuman = obj.isHuman
obj.isHuman = false
val childObj = KotlinChildClass()
childObj.getToOverride()
childObj.setToOverride(34)
childObj.toOverride
childObj.toOverride = 412
}
}
@@ -15,8 +15,8 @@ public class GetterTest {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val obj = GetterTest()
obj.primitiveBoolean
@@ -26,13 +26,13 @@ public class GenericsTest<A, B> {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val obj = GenericsTest<String, Boolean>()
val age: Int = obj.getAge();
val a: String = obj.getFieldA();
obj.setFieldA("fooo");
val b: Boolean = obj.getFieldB();
val a: String = obj.getFieldA();
val b: Boolean? = obj.getFieldB();
obj.setFieldC(java.util.HashMap<String, Boolean>());
}
}
@@ -21,8 +21,8 @@ public class ConstructorExample<A, B> {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val generated = ConstructorExample<Long, Boolean>(12, 42L, true)
val generatedReq = ConstructorExample<String, Boolean>("234");
}
@@ -21,8 +21,8 @@ public class ConstructorExample<A, B> {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val generated: ConstructorExample<Long, Boolean> = ConstructorExample.of(12, 42L, true)
val generatedReq: ConstructorExample<String, Boolean> = ConstructorExample.of("234");
}
@@ -22,8 +22,8 @@ public class GetterTest {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val obj = GetterTest()
val getter = obj.getAge()
val property = obj.age
@@ -37,6 +37,8 @@ object Test {
//shouldn't be accesible from here
// obj.getName()
OverridenGetterTest().usage()
}
class OverridenGetterTest : GetterTest() {
@@ -23,8 +23,8 @@ public class ClassLevelGetterTest {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val obj = ClassLevelGetterTest()
val getter = obj.getAge()
val property = obj.age
@@ -36,6 +36,8 @@ object Test {
//shouldn't be accesible from here
// obj.getName()
OverridenGetterTest().usage()
}
class OverridenGetterTest : ClassLevelGetterTest() {
@@ -27,8 +27,8 @@ public class FluentTest {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val obj = FluentTest()
val getter = obj.age()
@@ -38,6 +38,8 @@ object Test {
obj.overrideAnnotation
obj.getOverrideAnnotation()
OverridenGetterTest().usage()
}
class OverridenGetterTest : FluentTest() {
@@ -22,8 +22,8 @@ public class ConstructorExample {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val existing = ConstructorExample("existing")
val generated = ConstructorExample()
}
@@ -22,8 +22,8 @@ public class ConstructorExample {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val existing: ConstructorExample = ConstructorExample("existing")
val generated: ConstructorExample = ConstructorExample.make()
}
@@ -33,8 +33,8 @@ public class ConstructorExample {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val generated = ConstructorExample("foo", true)
}
}
@@ -35,8 +35,8 @@ public class ConstructorExample {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val generated = ConstructorExample.build("foo", true, 12)
}
}
@@ -20,8 +20,8 @@ public class SetterTest {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val obj = SetterTest()
obj.setAge(42)
obj.age = 42
@@ -32,6 +32,8 @@ object Test {
//shouldn't be accesible from here
// obj.setName("abc")
OverridenGetterTest().usage()
}
class OverridenGetterTest : SetterTest() {
@@ -23,8 +23,8 @@ public class SetterTest {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val obj = SetterTest()
obj.setAge(42)
obj.age = 42
@@ -25,10 +25,10 @@ public class SetterTest {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val obj = SetterTest()
obj.fluent(12);
obj.fluent(12)
obj.setChained("zz").getChained()
obj.whyNotBoth("zzz").whyNotBoth()
}
@@ -13,8 +13,8 @@ public class GetterSetterExample {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val obj = GetterSetterExample()
val getter = obj.getAge()
val property = obj.age
@@ -26,8 +26,8 @@ public class WithExample {
//FILE: test.kt
object Test {
fun usage() {
class Test {
fun run() {
val obj: WithExample = WithExample().withAge(16).withName("fooo")
}
}
@@ -13,11 +13,14 @@ import org.jetbrains.kotlin.codegen.CodegenTestCase
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
import java.net.URLClassLoader
abstract class AbstractLombokCompileTest : CodegenTestCase() {
private val commonClassLoader = URLClassLoader(arrayOf(getLombokJar().toURI().toURL()))
override fun doMultiFileTest(wholeFile: File, files: List<TestFile>) {
compile(files)
compile(files, true, true)
}
override fun setupEnvironment(environment: KotlinCoreEnvironment) {
@@ -35,6 +38,19 @@ abstract class AbstractLombokCompileTest : CodegenTestCase() {
}
}
override fun postCompile(kotlinOut: File, javaOut: File?) {
//run compiled code, Test.run() method is expected to be in generated classes
val cp = listOfNotNull(kotlinOut, javaOut).map { it.toURI().toURL() }.toTypedArray()
val classLoader = URLClassLoader(cp, commonClassLoader)
try {
val clazz = classLoader.loadClass("Test")
clazz.getMethod("run").invoke(clazz.newInstance())
} catch (t: Throwable) {
LOG.error("Error running Test.run()", t)
fail("Error running compiled code: $t")
}
}
private fun writeLombokConfig(directory: String, testFiles: List<TestFile>): File? =
testFiles.singleOrNull { it.name == "lombok.config" }?.let {
val file = File(directory, it.name)
@@ -46,6 +46,11 @@ public class LombokCompileTestGenerated extends AbstractLombokCompileTest {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/allArgsConstructorStatic.kt");
}
@TestMetadata("clashAccessors.kt")
public void testClashAccessors() throws Exception {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/clashAccessors.kt");
}
@TestMetadata("gettersClassLevel.kt")
public void testGettersClassLevel() throws Exception {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/gettersClassLevel.kt");