Skip to content

Commit

Permalink
[imp-AddKotlinDynamicCompiler] add kotlin compiler (#4544)
Browse files Browse the repository at this point in the history
  • Loading branch information
nekkiy authored and wing328 committed Nov 21, 2019
1 parent b0d6110 commit f434b5f
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 0 deletions.
19 changes: 19 additions & 0 deletions modules/openapi-generator/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@
<generex-version>1.0.2</generex-version>
<jackson-version>2.9.10</jackson-version>
<jackson-threetenbp-version>2.9.10</jackson-threetenbp-version>
<kotlin-version>1.3.41</kotlin-version>
</properties>
<dependencies>
<dependency>
Expand Down Expand Up @@ -328,6 +329,24 @@
<artifactId>openapi-generator-core</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>${kotlin-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-compiler-embeddable</artifactId>
<version>${kotlin-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-script-util</artifactId>
<version>${kotlin-version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package org.openapitools.codegen.kotlin;

import kotlin.script.experimental.jvm.util.KotlinJars;
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys;
import org.jetbrains.kotlin.cli.common.config.ContentRootsKt;
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer;
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector;
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler;
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.com.intellij.openapi.Disposable;
import org.jetbrains.kotlin.config.CommonConfigurationKeys;
import org.jetbrains.kotlin.config.CompilerConfiguration;
import org.jetbrains.kotlin.config.JVMConfigurationKeys;
import org.jetbrains.kotlin.config.JvmTarget;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.*;

import static kotlin.script.experimental.jvm.util.JvmClasspathUtilKt.classpathFromClassloader;

public class KotlinTestUtils {

public static ClassLoader buildModule(List<String> sourcePath, ClassLoader classLoader) {

String moduleName = UUID.randomUUID().toString().replaceAll("-", "");
File saveClassesDir;
try {
saveClassesDir = Files.createTempDirectory("kotlin" + moduleName).toFile();
} catch (IOException e) {
throw new RuntimeException(e);
}
compileModule(moduleName, sourcePath, saveClassesDir, classLoader, true);

try {
return new URLClassLoader(new URL[]{saveClassesDir.toURI().toURL()}, classLoader);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}

}

private static GenerationState compileModule(String moduleName, List<String> sourcePath, File saveClassesDir, ClassLoader classLoader, boolean forcedAddKotlinStd) {
Disposable stubDisposable = new StubDisposable();
CompilerConfiguration configuration = new CompilerConfiguration();
configuration.put(CommonConfigurationKeys.MODULE_NAME, moduleName);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = null;
try {
ps = new PrintStream(baos, true, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, new PrintingMessageCollector(ps, MessageRenderer.PLAIN_FULL_PATHS, true));
configuration.put(JVMConfigurationKeys.OUTPUT_DIRECTORY, saveClassesDir);
// configuration.put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true)
configuration.put(JVMConfigurationKeys.JVM_TARGET, JvmTarget.JVM_1_8);
Set<File> classPath = new HashSet<>();
if (classLoader != null) {
classPath.addAll(classpathFromClassloader(classLoader, false));
}
if (forcedAddKotlinStd) {
classPath.add(KotlinJars.INSTANCE.getStdlib());
}
JvmContentRootsKt.addJvmClasspathRoots(configuration, new ArrayList<>(classPath));
ContentRootsKt.addKotlinSourceRoots(configuration, sourcePath);

KotlinCoreEnvironment env = KotlinCoreEnvironment.createForProduction(stubDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
GenerationState result = KotlinToJVMBytecodeCompiler.INSTANCE.analyzeAndGenerate(env);
ps.flush();
if (result != null) {
return result;
} else {
String s;
try {
s = new String(baos.toByteArray(), "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
throw new IllegalStateException("Compilation error. Details:\n" + s);
}
}

static class StubDisposable implements Disposable {

volatile boolean isDisposed = false;

@Override
public void dispose() {
isDisposed = true;
}

public boolean isDisposed() {
return isDisposed;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.openapitools.codegen.kotlin;

import org.testng.Assert;
import org.testng.annotations.Test;

import java.lang.reflect.Constructor;
import java.util.Collections;

public class KotlinTestUtilsTest {

@Test
public void testNormalCompile() throws Exception {
ClassLoader classLoader = KotlinTestUtils.buildModule(Collections.singletonList(getClass().getResource("KotlinTestUtilsTest/normalPack").getFile()), Thread.currentThread().getContextClassLoader());
Class<?> clazz = classLoader.loadClass("com.example.SimpleClass");
Constructor<?>[] constructors = clazz.getConstructors();
Assert.assertEquals(1, constructors.length);
Constructor<?> constr = constructors[0];
Object testObj = constr.newInstance("test");
}

@Test(expectedExceptions = Exception.class)
public void testBadCompile() {
KotlinTestUtils.buildModule(Collections.singletonList(getClass().getResource("KotlinTestUtilsTest/badPack").getFile()), Thread.currentThread().getContextClassLoader());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example


class SimpleClass {
fun void testFun(){

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example

class SimpleClass (val someStr:String) {
fun testFun(str: String) {

}
}

0 comments on commit f434b5f

Please sign in to comment.