diff --git a/plugins/annotation-processing/annotation-processing.iml b/plugins/annotation-processing/annotation-processing.iml
index 81a78835658..e6933c9078a 100644
--- a/plugins/annotation-processing/annotation-processing.iml
+++ b/plugins/annotation-processing/annotation-processing.iml
@@ -14,5 +14,6 @@
+
\ No newline at end of file
diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt
index 000348d1212..f4c6f8aaa62 100644
--- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt
+++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.annotation
import com.intellij.openapi.project.Project
+import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.psi.*
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analyzer.AnalysisResult
@@ -35,8 +36,10 @@ import java.util.*
import javax.annotation.processing.Processor
class AnnotationProcessingExtension(
- val generatedOutputDir: File,
- val annotationProcessingClasspath: List
+ val generatedSourcesOutputDir: File,
+ val classesOutputDir: File,
+ val annotationProcessingClasspath: List,
+ val javaSourceRoots: List
) : AnalysisCompletedHandlerExtension {
private var annotationProcessingComplete = false
@@ -56,12 +59,25 @@ class AnnotationProcessingExtension(
val analysisContext = AnalysisContext(hashMapOf())
analysisContext.analyzeFiles(files)
+ val psiManager = PsiManager.getInstance(project)
+ for (javaSourceRoot in javaSourceRoots) {
+ javaSourceRoot.walk().filter { it.isFile && it.extension == "java" }.forEach {
+ val vFile = StandardFileSystems.local().findFileByPath(it.absolutePath)
+ if (vFile != null) {
+ val javaFile = psiManager.findFile(vFile) as? PsiJavaFile
+ if (javaFile != null) {
+ analysisContext.analyzeFile(javaFile)
+ }
+ }
+ }
+ }
+
val options = emptyMap()
val javaPsiFacade = JavaPsiFacade.getInstance(project)
val projectScope = GlobalSearchScope.projectScope(project)
- val filer = KotlinFiler(generatedOutputDir)
+ val filer = KotlinFiler(generatedSourcesOutputDir, classesOutputDir)
val messages = KotlinMessager()
val types = KotlinTypes(javaPsiFacade, PsiManager.getInstance(project), projectScope)
val elements = KotlinElements(javaPsiFacade, projectScope)
@@ -69,7 +85,6 @@ class AnnotationProcessingExtension(
val processingEnvironment = KotlinProcessingEnvironment(elements, types, messages, options, filer)
processors.forEach { it.init(processingEnvironment) }
-
// Round 1
val round1Environment = KotlinRoundEnvironment(analysisContext)
for (processor in processors) {
@@ -97,7 +112,7 @@ class AnnotationProcessingExtension(
}
annotationProcessingComplete = true
- return AnalysisResult.RetryWithAdditionalJavaRoots(bindingContext, module, listOf(generatedOutputDir))
+ return AnalysisResult.RetryWithAdditionalJavaRoots(bindingContext, module, listOf(generatedSourcesOutputDir))
}
private fun loadAnnotationProcessors(classpath: List): List {
@@ -128,6 +143,10 @@ private fun AnalysisContext.analyzeFile(file: KtFile) {
}
}
+private fun AnalysisContext.analyzeFile(file: PsiJavaFile) {
+ file.classes.forEach { analyzeDeclaration(it) }
+}
+
private fun AnalysisContext.analyzeDeclaration(declaration: PsiElement) {
if (declaration !is PsiModifierListOwner) return
diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt
index 1e25d5486bc..753bffd7d0f 100644
--- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt
+++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt
@@ -18,18 +18,23 @@ package org.jetbrains.kotlin.annotation.processing
import com.intellij.mock.MockProject
import org.jetbrains.kotlin.annotation.AnnotationProcessingExtension
+import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
import org.jetbrains.kotlin.compiler.plugin.CliOption
import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException
import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.CompilerConfigurationKey
+import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension
import java.io.File
object AnnotationProcessingConfigurationKeys {
val GENERATED_OUTPUT_DIR: CompilerConfigurationKey =
CompilerConfigurationKey.create("generated files output directory")
+
+ val CLASS_FILES_OUTPUT_DIR: CompilerConfigurationKey =
+ CompilerConfigurationKey.create("class files output directory")
val ANNOTATION_PROCESSOR_CLASSPATH: CompilerConfigurationKey> =
CompilerConfigurationKey.create>("annotation processor classpath")
@@ -40,7 +45,10 @@ class AnnotationProcessingCommandLineProcessor : CommandLineProcessor {
val ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID: String = "org.jetbrains.kotlin.kapt2"
val GENERATED_OUTPUT_DIR_OPTION: CliOption =
- CliOption("generated", "", "Output path for generated files", required = false)
+ CliOption("generated", "", "Output path for the generated files", required = false)
+
+ val CLASS_FILES_OUTPUT_DIR_OPTION: CliOption =
+ CliOption("classes", "", "Output path for the class files", required = false)
val ANNOTATION_PROCESSOR_CLASSPATH_OPTION: CliOption =
CliOption("apclasspath", "", "Annotation processor classpath",
@@ -60,6 +68,7 @@ class AnnotationProcessingCommandLineProcessor : CommandLineProcessor {
configuration.put(AnnotationProcessingConfigurationKeys.ANNOTATION_PROCESSOR_CLASSPATH, paths)
}
GENERATED_OUTPUT_DIR_OPTION -> configuration.put(AnnotationProcessingConfigurationKeys.GENERATED_OUTPUT_DIR, value)
+ CLASS_FILES_OUTPUT_DIR_OPTION -> configuration.put(AnnotationProcessingConfigurationKeys.CLASS_FILES_OUTPUT_DIR, value)
else -> throw CliOptionProcessingException("Unknown option: ${option.name}")
}
}
@@ -73,7 +82,13 @@ class AnnotationProcessingComponentRegistrar : ComponentRegistrar {
val generatedOutputDirFile = File(generatedOutputDir)
generatedOutputDirFile.mkdirs()
- val annotationProcessingExtension = AnnotationProcessingExtension(generatedOutputDirFile, classpath)
+ val javaRoots = configuration[JVMConfigurationKeys.CONTENT_ROOTS]
+ ?.filterIsInstance()?.map { it.file } ?: emptyList()
+
+ val classesOutputDir = File(configuration.get(AnnotationProcessingConfigurationKeys.CLASS_FILES_OUTPUT_DIR)
+ ?: configuration[JVMConfigurationKeys.MODULES]!!.first().getOutputDirectory())
+
+ val annotationProcessingExtension = AnnotationProcessingExtension(generatedOutputDirFile, classesOutputDir, classpath, javaRoots)
AnalysisCompletedHandlerExtension.registerExtension(project, annotationProcessingExtension)
}
}
\ No newline at end of file
diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinFiler.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinFiler.kt
index 8398785203a..59392f1b1bd 100644
--- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinFiler.kt
+++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinFiler.kt
@@ -22,8 +22,9 @@ import javax.lang.model.element.Element
import javax.tools.FileObject
import javax.tools.JavaFileManager
import javax.tools.JavaFileObject
+import javax.tools.StandardLocation
-class KotlinFiler(val generatedDir: File) : Filer {
+class KotlinFiler(val generatedSourceDir: File, val classesOutputDir: File) : Filer {
private companion object {
val PACKAGE_INFO_SUFFIX = ".packageInfo"
}
@@ -33,7 +34,7 @@ class KotlinFiler(val generatedDir: File) : Filer {
private fun createDotGeneratedIfNeeded() {
if (!dotGeneratedGenerated) {
dotGeneratedGenerated = true
- File(generatedDir, ".generated").writeText("Generated by kapt2")
+ File(generatedSourceDir, ".generated").writeText("Generated by kapt2")
}
}
@@ -46,7 +47,7 @@ class KotlinFiler(val generatedDir: File) : Filer {
val packageName = fqName.substringBeforeLast('.')
- val packageDir = File(generatedDir, packageName.replace('.', '/'))
+ val packageDir = File(generatedSourceDir, packageName.replace('.', '/'))
packageDir.mkdirs()
val fileName = fqName.substringAfterLast('.') + (if (isPackageInfo) PACKAGE_INFO_SUFFIX else extension)
@@ -62,12 +63,23 @@ class KotlinFiler(val generatedDir: File) : Filer {
}
override fun createResource(
- location: JavaFileManager.Location?,
+ location: JavaFileManager.Location,
pkg: CharSequence,
relativeName: CharSequence,
vararg originatingElements: Element?
): FileObject? {
- throw UnsupportedOperationException()
+ val baseDir = when (location) {
+ StandardLocation.CLASS_OUTPUT -> classesOutputDir
+ StandardLocation.SOURCE_OUTPUT -> generatedSourceDir
+ else -> throw IllegalArgumentException("Location is not supported: $location (${location.name})")
+ }
+
+ val targetDir = File(baseDir, pkg.toString().replace('.', '/'))
+ targetDir.mkdirs()
+
+ val targetFile = File(targetDir, relativeName.toString())
+
+ return KotlinFileObject(targetFile)
}
override fun createClassFile(name: CharSequence, vararg originatingElements: Element?): JavaFileObject {
diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinJavaFileObject.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinJavaFileObject.kt
index 962522223d7..b8bcc67f68e 100644
--- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinJavaFileObject.kt
+++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinJavaFileObject.kt
@@ -17,9 +17,30 @@
package org.jetbrains.kotlin.annotation.processing.impl
import java.io.File
+import javax.tools.FileObject
import javax.tools.JavaFileObject
-class KotlinJavaFileObject(val file: File) : JavaFileObject {
+class KotlinJavaFileObject(file: File) : KotlinAbstractFileObject(file), JavaFileObject {
+ //TODO
+ override fun isNameCompatible(simpleName: String, kind: JavaFileObject.Kind) = true
+
+ override fun getKind() = when (file.extension) {
+ "class" -> JavaFileObject.Kind.CLASS
+ "java" -> JavaFileObject.Kind.SOURCE
+ "html" -> JavaFileObject.Kind.HTML
+ else -> JavaFileObject.Kind.OTHER
+ }
+
+ //TODO
+ override fun getAccessLevel() = null
+
+ //TODO
+ override fun getNestingKind() = null
+}
+
+class KotlinFileObject(file: File) : KotlinAbstractFileObject(file)
+
+abstract class KotlinAbstractFileObject(val file: File) : FileObject {
override fun openOutputStream() = file.outputStream()
override fun getName() = file.name
@@ -39,20 +60,4 @@ class KotlinJavaFileObject(val file: File) : JavaFileObject {
override fun openReader(ignoreEncodingErrors: Boolean) = file.reader()
override fun delete() = file.delete()
-
- //TODO
- override fun isNameCompatible(simpleName: String, kind: JavaFileObject.Kind) = true
-
- override fun getKind() = when (file.extension) {
- "class" -> JavaFileObject.Kind.CLASS
- "java" -> JavaFileObject.Kind.SOURCE
- "html" -> JavaFileObject.Kind.HTML
- else -> JavaFileObject.Kind.OTHER
- }
-
- //TODO
- override fun getAccessLevel() = null
-
- //TODO
- override fun getNestingKind() = null
}
\ No newline at end of file