Kapt: Support Java 9 in compiler plugin
This commit is contained in:
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.kapt3.AptMode.*
|
||||
import org.jetbrains.kotlin.kapt3.diagnostic.KaptError
|
||||
import org.jetbrains.kotlin.kapt3.stubs.ClassFileToSourceStubConverter
|
||||
import org.jetbrains.kotlin.kapt3.util.KaptLogger
|
||||
import org.jetbrains.kotlin.kapt3.util.getPackageNameJava9Aware
|
||||
import org.jetbrains.kotlin.modules.TargetId
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -271,7 +272,7 @@ abstract class AbstractKapt3Extension(
|
||||
for (stub in stubs) {
|
||||
val className = (stub.defs.first { it is JCTree.JCClassDecl } as JCTree.JCClassDecl).simpleName.toString()
|
||||
|
||||
val packageName = stub.packageName?.toString() ?: ""
|
||||
val packageName = stub.getPackageNameJava9Aware()?.toString() ?: ""
|
||||
val packageDir = if (packageName.isEmpty()) stubsOutputDir else File(stubsOutputDir, packageName.replace('.', '/'))
|
||||
packageDir.mkdirs()
|
||||
File(packageDir, className + ".java").writeText(stub.toString())
|
||||
|
||||
@@ -25,9 +25,12 @@ import com.sun.tools.javac.processing.JavacFiler
|
||||
import com.sun.tools.javac.processing.JavacProcessingEnvironment
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import org.jetbrains.kotlin.kapt3.diagnostic.KaptError
|
||||
import org.jetbrains.kotlin.kapt3.util.isJava9OrLater
|
||||
import org.jetbrains.kotlin.kapt3.util.putJavacOption
|
||||
import java.io.File
|
||||
import javax.annotation.processing.Processor
|
||||
import javax.tools.JavaFileManager
|
||||
import javax.tools.JavaFileObject
|
||||
import com.sun.tools.javac.util.List as JavacList
|
||||
|
||||
fun KaptContext<*>.doAnnotationProcessing(
|
||||
@@ -45,32 +48,55 @@ fun KaptContext<*>.doAnnotationProcessing(
|
||||
put(Option.PROC, "only") // Only process annotations
|
||||
|
||||
if (!withJdk) {
|
||||
put(Option.BOOTCLASSPATH, "") // No boot classpath
|
||||
putJavacOption("BOOTCLASSPATH", "BOOT_CLASS_PATH", "") // No boot classpath
|
||||
}
|
||||
|
||||
put(Option.CLASSPATH, compileClasspath.joinToString(File.pathSeparator) { it.canonicalPath })
|
||||
put(Option.PROCESSORPATH, annotationProcessingClasspath.joinToString(File.pathSeparator) { it.canonicalPath })
|
||||
putJavacOption("CLASSPATH", "CLASS_PATH", compileClasspath.joinToString(File.pathSeparator) { it.canonicalPath })
|
||||
putJavacOption("PROCESSORPATH", "PROCESSOR_PATH", annotationProcessingClasspath.joinToString(File.pathSeparator) { it.canonicalPath })
|
||||
put(Option.PROCESSOR, annotationProcessors)
|
||||
put(Option.S, sourcesOutputDir.canonicalPath)
|
||||
put(Option.D, classesOutputDir.canonicalPath)
|
||||
put(Option.ENCODING, "UTF-8")
|
||||
}
|
||||
|
||||
val fileManager = context.get(JavaFileManager::class.java) as JavacFileManager
|
||||
val processingEnvironment = JavacProcessingEnvironment.instance(context)
|
||||
|
||||
val compilerAfterAP: JavaCompiler
|
||||
try {
|
||||
compiler.initProcessAnnotations(processors)
|
||||
if (isJava9OrLater) {
|
||||
val initProcessAnnotationsMethod = JavaCompiler::class.java.declaredMethods.single { it.name == "initProcessAnnotations" }
|
||||
initProcessAnnotationsMethod.invoke(compiler, processors, emptyList<JavaFileObject>(), emptyList<String>())
|
||||
}
|
||||
else {
|
||||
compiler.initProcessAnnotations(processors)
|
||||
}
|
||||
|
||||
val javaFileObjects = fileManager.getJavaFileObjectsFromFiles(javaSourceFiles)
|
||||
val parsedJavaFiles = compiler.parseFiles(javaFileObjects)
|
||||
var parsedJavaFiles = compiler.stopIfErrorOccurred(
|
||||
CompileStates.CompileState.PARSE, compiler.parseFiles(javaFileObjects))
|
||||
|
||||
if (isJava9OrLater) {
|
||||
val initModulesMethod = compiler.javaClass.getMethod("initModules", JavacList::class.java)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
parsedJavaFiles = compiler.stopIfErrorOccurred(
|
||||
CompileStates.CompileState.PARSE,
|
||||
initModulesMethod.invoke(compiler, parsedJavaFiles) as JavacList<JCTree.JCCompilationUnit>)
|
||||
}
|
||||
|
||||
compilerAfterAP = try {
|
||||
javaLog.interceptorData.files = parsedJavaFiles.map { it.sourceFile to it }.toMap()
|
||||
val analyzedFiles = compiler.stopIfErrorOccurred(
|
||||
CompileStates.CompileState.PARSE, compiler.enterTrees(parsedJavaFiles + additionalSources))
|
||||
compiler.processAnnotations(analyzedFiles)
|
||||
|
||||
if (isJava9OrLater) {
|
||||
val processAnnotationsMethod = compiler.javaClass.getMethod("processAnnotations", JavacList::class.java)
|
||||
processAnnotationsMethod.invoke(compiler, analyzedFiles)
|
||||
compiler
|
||||
}
|
||||
else {
|
||||
compiler.processAnnotations(analyzedFiles)
|
||||
}
|
||||
} catch (e: AnnotationProcessingError) {
|
||||
throw KaptError(KaptError.Kind.EXCEPTION, e.cause ?: e)
|
||||
}
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.kapt3.javac
|
||||
|
||||
import com.sun.tools.javac.file.BaseFileObject
|
||||
import com.sun.tools.javac.file.JavacFileManager
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import java.io.*
|
||||
import org.jetbrains.kotlin.kapt3.util.getPackageNameJava9Aware
|
||||
import java.net.URI
|
||||
import java.net.URL
|
||||
import javax.lang.model.element.Modifier
|
||||
@@ -29,12 +27,9 @@ import javax.tools.JavaFileObject
|
||||
class KaptJavaFileObject(
|
||||
val compilationUnit: JCTree.JCCompilationUnit,
|
||||
val clazz: JCTree.JCClassDecl,
|
||||
fileManager: JavacFileManager,
|
||||
val timestamp: Long = System.currentTimeMillis()
|
||||
) : BaseFileObject(fileManager) {
|
||||
override fun getShortName() = clazz.simpleName.toString()
|
||||
|
||||
override fun inferBinaryName(path: MutableIterable<File>?) = throw UnsupportedOperationException()
|
||||
) : JavaFileObject {
|
||||
override fun toString() = "${javaClass.simpleName}[$name]"
|
||||
|
||||
override fun isNameCompatible(simpleName: String?, kind: JavaFileObject.Kind?): Boolean {
|
||||
if (simpleName == null || kind == null) return false
|
||||
@@ -44,7 +39,7 @@ class KaptJavaFileObject(
|
||||
override fun getKind() = JavaFileObject.Kind.SOURCE
|
||||
|
||||
override fun getName(): String {
|
||||
val packageName = compilationUnit.packageName
|
||||
val packageName = compilationUnit.getPackageNameJava9Aware()
|
||||
if (packageName == null || packageName.toString() == "") {
|
||||
return clazz.name.toString() + ".java"
|
||||
}
|
||||
|
||||
+5
-5
@@ -120,8 +120,9 @@ class ClassFileToSourceStubConverter(
|
||||
JavacList.nil(),
|
||||
JavacList.nil())
|
||||
|
||||
val topLevel = treeMaker.TopLevel(JavacList.nil(), treeMaker.SimpleName("error"), JavacList.of(nonExistentClass))
|
||||
topLevel.sourcefile = KaptJavaFileObject(topLevel, nonExistentClass, fileManager)
|
||||
val topLevel = treeMaker.TopLevelJava9Aware(treeMaker.SimpleName("error"), JavacList.of(nonExistentClass))
|
||||
|
||||
topLevel.sourcefile = KaptJavaFileObject(topLevel, nonExistentClass)
|
||||
|
||||
// We basically don't need to add binding for NonExistentClass
|
||||
return topLevel
|
||||
@@ -135,7 +136,6 @@ class ClassFileToSourceStubConverter(
|
||||
// Nested classes will be processed during the outer classes conversion
|
||||
if ((descriptor as? ClassDescriptor)?.isNested ?: false) return null
|
||||
|
||||
val packageAnnotations = JavacList.nil<JCAnnotation>()
|
||||
val packageName = ktFile.packageFqName.asString()
|
||||
val packageClause = if (packageName.isEmpty()) null else treeMaker.FqName(packageName)
|
||||
|
||||
@@ -144,9 +144,9 @@ class ClassFileToSourceStubConverter(
|
||||
val imports = if (correctErrorTypes) convertImports(ktFile, classDeclaration) else JavacList.nil()
|
||||
val classes = JavacList.of<JCTree>(classDeclaration)
|
||||
|
||||
val topLevel = treeMaker.TopLevel(packageAnnotations, packageClause, imports + classes)
|
||||
val topLevel = treeMaker.TopLevelJava9Aware(packageClause, imports + classes)
|
||||
|
||||
KaptJavaFileObject(topLevel, classDeclaration, fileManager).apply {
|
||||
KaptJavaFileObject(topLevel, classDeclaration).apply {
|
||||
topLevel.sourcefile = this
|
||||
_bindings[clazz.name] = this
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.kapt3.util
|
||||
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.sun.tools.javac.main.Option
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import com.sun.tools.javac.tree.TreeMaker
|
||||
import com.sun.tools.javac.util.Options
|
||||
import com.sun.tools.javac.util.List as JavacList
|
||||
import org.jetbrains.kotlin.kapt3.plus
|
||||
|
||||
internal val isJava9OrLater: Boolean
|
||||
get() = SystemInfo.isJavaVersionAtLeast("9")
|
||||
|
||||
internal fun Options.putJavacOption(jdk8Name: String, jdk9Name: String, value: String) {
|
||||
val option = if (isJava9OrLater) {
|
||||
Option.valueOf(jdk9Name)
|
||||
}
|
||||
else {
|
||||
Option.valueOf(jdk8Name)
|
||||
}
|
||||
|
||||
put(option, value)
|
||||
}
|
||||
|
||||
internal fun TreeMaker.TopLevelJava9Aware(packageClause: JCTree.JCExpression?, declarations: JavacList<JCTree>): JCTree.JCCompilationUnit {
|
||||
return if (isJava9OrLater) {
|
||||
val topLevelMethod = TreeMaker::class.java.declaredMethods.single { it.name == "TopLevel" }
|
||||
val packageDecl: JCTree? = packageClause?.let {
|
||||
val packageDeclMethod = TreeMaker::class.java.methods.single { it.name == "PackageDecl" }
|
||||
packageDeclMethod.invoke(this, JavacList.nil<JCTree>(), packageClause) as JCTree
|
||||
}
|
||||
val allDeclarations = if (packageDecl != null) JavacList.of(packageDecl) + declarations else declarations
|
||||
topLevelMethod.invoke(this, allDeclarations) as JCTree.JCCompilationUnit
|
||||
}
|
||||
else {
|
||||
TopLevel(JavacList.nil(), packageClause, declarations)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun JCTree.JCCompilationUnit.getPackageNameJava9Aware(): JCTree? {
|
||||
return if (isJava9OrLater) {
|
||||
JCTree.JCCompilationUnit::class.java.getDeclaredMethod("getPackageName").invoke(this) as JCTree?
|
||||
}
|
||||
else {
|
||||
this.packageName
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user