diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt index 5d43a5778fc..d52bec0f407 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt @@ -96,8 +96,8 @@ import java.io.File import java.util.* class KotlinCoreEnvironment private constructor( - parentDisposable: Disposable, - applicationEnvironment: JavaCoreApplicationEnvironment, + parentDisposable: Disposable, + applicationEnvironment: JavaCoreApplicationEnvironment, configuration: CompilerConfiguration ) { @@ -143,7 +143,7 @@ class KotlinCoreEnvironment private constructor( configs.map { KotlinConfigurableScriptDefinition(it, kotlinEnvVars) } } else null - ?: emptyList() + ?: emptyList() }) KotlinScriptExternalImportsProvider.getInstance(project)?.run { @@ -154,7 +154,7 @@ class KotlinCoreEnvironment private constructor( } val initialRoots = configuration.getList(JVMConfigurationKeys.CONTENT_ROOTS).classpathRoots() - + // REPL and kapt2 update classpath dynamically val indexFactory = JvmUpdatableDependenciesIndexFactory() @@ -162,7 +162,7 @@ class KotlinCoreEnvironment private constructor( updateClasspathFromRootsIndex(rootsIndex) (ServiceManager.getService(project, CoreJavaFileManager::class.java) - as KotlinCliJavaFileManagerImpl).initIndex(rootsIndex) + as KotlinCliJavaFileManagerImpl).initIndex(rootsIndex) project.registerService(JvmVirtualFileFinderFactory::class.java, JvmCliVirtualFileFinderFactory(rootsIndex)) @@ -196,8 +196,8 @@ class KotlinCoreEnvironment private constructor( } private fun Iterable.classpathRoots(): List = - filterIsInstance(JvmContentRoot::class.java).mapNotNull { - javaRoot -> contentRootToVirtualFile(javaRoot)?.let { virtualFile -> + filterIsInstance(JvmContentRoot::class.java).mapNotNull { + javaRoot -> contentRootToVirtualFile(javaRoot)?.let { virtualFile -> val prefixPackageFqName = (javaRoot as? JavaSourceRoot)?.packagePrefix?.let { if (isValidJavaFqName(it)) { @@ -217,14 +217,22 @@ class KotlinCoreEnvironment private constructor( JavaRoot(virtualFile, rootType, prefixPackageFqName) } - } + } private fun updateClasspathFromRootsIndex(index: JvmDependenciesIndex) { index.indexedRoots.forEach { projectEnvironment.addSourcesToClasspath(it.file) } } - + + val appendJavaSourceRootsHandler = fun(roots: List) { + updateClasspath(roots.map { JavaSourceRoot(it, null) }) + } + + init { + project.putUserData(APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY, appendJavaSourceRootsHandler) + } + fun updateClasspath(roots: List): List? { return rootsIndex.addNewIndexForRoots(roots.classpathRoots())?.let { updateClasspathFromRootsIndex(it) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt index fde2ccd3b4f..11b6a7e4ab9 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt @@ -136,8 +136,10 @@ object KotlinToJVMBytecodeCompiler { projectConfiguration.addJavaSourceRoots(result.additionalJavaRoots) projectConfiguration.isReadOnly = oldReadOnlyValue - environment.updateClasspath(result.additionalJavaRoots.map { JavaSourceRoot(it, null) }) - + if (result.addToEnvironment) { + environment.updateClasspath(result.additionalJavaRoots.map { JavaSourceRoot(it, null) }) + } + // Clear package caches (see KotlinJavaPsiFacade) (PsiManager.getInstance(environment.project).modificationTracker as? PsiModificationTrackerImpl)?.incCounter() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalysisResult.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalysisResult.kt index 14882d9e416..a0f50cb306e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalysisResult.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalysisResult.kt @@ -63,7 +63,8 @@ open class AnalysisResult protected constructor( class RetryWithAdditionalJavaRoots( bindingContext: BindingContext, moduleDescriptor: ModuleDescriptor, - val additionalJavaRoots: List + val additionalJavaRoots: List, + val addToEnvironment: Boolean = true ) : AnalysisResult(bindingContext, moduleDescriptor) companion object { diff --git a/compiler/util/src/org/jetbrains/kotlin/config/AppendJavaSourceRootsHandlerKey.kt b/compiler/util/src/org/jetbrains/kotlin/config/AppendJavaSourceRootsHandlerKey.kt new file mode 100644 index 00000000000..49de20cd1ef --- /dev/null +++ b/compiler/util/src/org/jetbrains/kotlin/config/AppendJavaSourceRootsHandlerKey.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2016 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.config + +import com.intellij.openapi.util.Key +import java.io.File + +val APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY = Key<(List) -> Unit>("AppendJavaSourceRootsHandlerKey") \ 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 ec44bb0aeef..e13f5a7a00d 100755 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt @@ -19,18 +19,16 @@ 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.impl.PsiModificationTrackerImpl import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.analyzer.AnalysisResult +import org.jetbrains.kotlin.annotation.processing.RoundAnnotations import org.jetbrains.kotlin.annotation.processing.diagnostic.ErrorsAnnotationProcessing import org.jetbrains.kotlin.annotation.processing.impl.* -import org.jetbrains.kotlin.asJava.findFacadeClass -import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.config.APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.java.model.elements.JeTypeElement -import org.jetbrains.kotlin.java.model.internal.getAnnotationsWithInherited -import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension import java.io.File @@ -65,6 +63,8 @@ abstract class AbstractAnnotationProcessingExtension( if (verboseOutput) messager.printMessage(Diagnostic.Kind.OTHER, "Kapt: " + message()) } + private fun Int.count(noun: String) = if (this == 1) "$this $noun" else "$this ${noun}s" + override fun analysisCompleted( project: Project, module: ModuleDescriptor, @@ -80,53 +80,146 @@ abstract class AbstractAnnotationProcessingExtension( log { "No annotation processors detected, exiting" } return null } - - log { "Analysing Kotlin files: " + files.map { it.virtualFile.path } } - - val analysisContext = AnalysisContext(hashMapOf()) - analysisContext.analyzeFiles(files) - - log { "Analysing Java source roots: $javaSourceRoots" } - + + val appendJavaSourceRootsHandler = project.getUserData(APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY) + if (appendJavaSourceRootsHandler == null) { + log { "Java source root handler is not set, exiting" } + return null + } + 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 javaPsiFacade = JavaPsiFacade.getInstance(project) + val projectScope = GlobalSearchScope.projectScope(project) + + val options = emptyMap() + log { "Options: $options" } + + val filer = KotlinFiler(generatedSourcesOutputDir, classesOutputDir) + val types = KotlinTypes(javaPsiFacade, PsiManager.getInstance(project), projectScope) + val elements = KotlinElements(javaPsiFacade, projectScope) + + val processingEnvironment = KotlinProcessingEnvironment( + elements, types, messager, options, filer, processors, + project, psiManager, javaPsiFacade, projectScope, appendJavaSourceRootsHandler) + + val processingResult = processingEnvironment.doAnnotationProcessing(files) + + annotationProcessingComplete = true + log { + "Annotation processing complete, " + + processingResult.errorCount.count("error") + ", " + + processingResult.warningCount.count("warning") + } + + if (processingResult.errorCount != 0) { + val reportFile = files.firstOrNull() + if (reportFile != null) { + bindingTrace.report(ErrorsAnnotationProcessing.ANNOTATION_PROCESSING_ERROR.on(reportFile)) + } + + // Do not restart Kotlin file analysis + return null + } + + if (!processingResult.wasAnythingGenerated) { + // Nothing was generated, do not need to restart analysis + return null + } + + return AnalysisResult.RetryWithAdditionalJavaRoots( + bindingTrace.bindingContext, + module, + listOf(generatedSourcesOutputDir), + addToEnvironment = false) + } + + private fun KotlinProcessingEnvironment.doAnnotationProcessing(files: Collection): ProcessingResult { + run initializeProcessors@ { + processors.forEach { it.init(this) } + log { "Initialized processors: " + processors.joinToString { it.javaClass.name } } + } + + val firstRoundAnnotations = RoundAnnotations() + + run analyzeFilesForFirstRound@ { + log { "Analysing Kotlin files: " + files.map { it.virtualFile.path } } + firstRoundAnnotations.analyzeFiles(files) + + log { "Analysing Java source roots: $javaSourceRoots" } + 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) { + firstRoundAnnotations.analyzeFile(javaFile) + } } } } } - val options = emptyMap() - log { "Options: $options" } + val finalRoundNumber = run annotationProcessing@ { + val firstRoundEnvironment = KotlinRoundEnvironment(firstRoundAnnotations, false, 1) + process(firstRoundEnvironment) + } + 1 - val javaPsiFacade = JavaPsiFacade.getInstance(project) - val projectScope = GlobalSearchScope.projectScope(project) + log { "Starting round $finalRoundNumber (final)" } + val finalRoundEnvironment = KotlinRoundEnvironment(RoundAnnotations(), true, finalRoundNumber) + for (processor in processors) { + processor.process(emptySet(), finalRoundEnvironment) + } + + return ProcessingResult(messager.errorCount, messager.warningCount, filer.wasAnythingGenerated) + } + + private tailrec fun KotlinProcessingEnvironment.process(roundEnvironment: KotlinRoundEnvironment): Int { + val newFiles = doRound(roundEnvironment) + val newJavaFiles = newFiles.filter { it.extension.toLowerCase() == "java" } + if (newJavaFiles.isEmpty() || messager.errorCount != 0) { + return roundEnvironment.roundNumber + } - val filer = KotlinFiler(generatedSourcesOutputDir, classesOutputDir) - val types = KotlinTypes(javaPsiFacade, PsiManager.getInstance(project), projectScope) - val elements = KotlinElements(javaPsiFacade, projectScope) + // Add new Java source roots after the first round + if (roundEnvironment.roundNumber == 1) { + appendJavaSourceRootsHandler(listOf(generatedSourcesOutputDir)) + } - val processingEnvironment = KotlinProcessingEnvironment(elements, types, messager, options, filer) - processors.forEach { it.init(processingEnvironment) } + // Update the platform caches + (PsiManager.getInstance(project).modificationTracker as? PsiModificationTrackerImpl)?.incCounter() - log { "Initialized processors: " + processors.joinToString { it.javaClass.name } } + // Find generated files + val localFileSystem = StandardFileSystems.local() + val psiFiles = newJavaFiles + .map { localFileSystem.findFileByPath(it.absolutePath)?.let { psiManager.findFile(it) } } + .filterIsInstance() + + if (psiFiles.isEmpty()) { + log { "Something is strange, files were generated but not found by PsiManager" } + return roundEnvironment.roundNumber + } - log { "Starting round 1" } - val round1Environment = KotlinRoundEnvironment(analysisContext) + // Start the next round + val nextRoundAnnotations = RoundAnnotations().apply { analyzeFiles(psiFiles) } + val nextRoundEnvironment = KotlinRoundEnvironment(nextRoundAnnotations, false, roundEnvironment.roundNumber + 1) + return process(nextRoundEnvironment) + } + + private fun KotlinProcessingEnvironment.doRound(roundEnvironment: KotlinRoundEnvironment): List { + log { "Starting round ${roundEnvironment.roundNumber}" } + + val newFiles = mutableListOf() + filer.onFileCreatedHandler = { newFiles += it } + for (processor in processors) { val supportedAnnotationNames = processor.supportedAnnotationTypes - val supportsAnyAnnotation = supportedAnnotationNames.contains("*") - - val applicableAnnotationNames = when (supportsAnyAnnotation) { - true -> analysisContext.annotationsMap.keys - false -> processor.supportedAnnotationTypes.filter { it in analysisContext.annotationsMap } + val acceptsAnyAnnotation = supportedAnnotationNames.contains("*") + + val applicableAnnotationNames = when (acceptsAnyAnnotation) { + true -> roundEnvironment.annotationsMap.keys + false -> processor.supportedAnnotationTypes.filter { it in roundEnvironment.annotationsMap } } - + if (applicableAnnotationNames.isEmpty()) { log { "Skipping processor " + processor.javaClass.name + ": no relevant annotations" } continue @@ -135,89 +228,20 @@ abstract class AbstractAnnotationProcessingExtension( val applicableAnnotations = applicableAnnotationNames .map { javaPsiFacade.findClass(it, projectScope)?.let { JeTypeElement(it) } } .filterNotNullTo(hashSetOf()) - + log { val annotationNames = applicableAnnotations.joinToString { it.qualifiedName.toString() } "Processing with " + processor.javaClass.name + " (annotations: " + annotationNames + ")" } - processor.process(applicableAnnotations, round1Environment) - } - - log { "Starting round 2 (final)" } - val round2Environment = KotlinRoundEnvironment(AnalysisContext(hashMapOf()), isProcessingOver = true) - for (processor in processors) { - processor.process(emptySet(), round2Environment) + processor.process(applicableAnnotations, roundEnvironment) } - fun Int.count(noun: String) = if (this == 1) "$this $noun" else "$this ${noun}s" - log { "Annotation processing complete, ${messager.errorCount.count("error")}, ${messager.warningCount.count("warning")}" } - - if (messager.errorCount != 0) { - val reportFile = files.firstOrNull() - if (reportFile != null) { - bindingTrace.report(ErrorsAnnotationProcessing.ANNOTATION_PROCESSING_ERROR.on(reportFile)) - } - - // Do not restart analysis - return null - } - - annotationProcessingComplete = true - return AnalysisResult.RetryWithAdditionalJavaRoots(bindingTrace.bindingContext, module, listOf(generatedSourcesOutputDir)) + log { "Round ${roundEnvironment.roundNumber} finished, ${newFiles.size.count("file")} generated (${newFiles.joinToString()})" } + return newFiles } protected abstract fun loadAnnotationProcessors(): List } -internal class AnalysisContext(annotationsMap: MutableMap>) { - private val mutableAnnotationsMap = annotationsMap - - val annotationsMap: Map> - get() = mutableAnnotationsMap - - fun analyzeFiles(files: Collection) { - for (file in files) { - analyzeFile(file) - } - } - - fun analyzeFile(file: KtFile) { - val lightClass = file.findFacadeClass() - - if (lightClass != null) { - analyzeDeclaration(lightClass) - } - - for (declaration in file.declarations) { - if (declaration !is KtClassOrObject) continue - val clazz = declaration.toLightClass() ?: continue - analyzeDeclaration(clazz) - } - } - - fun analyzeFile(file: PsiJavaFile) { - file.classes.forEach { analyzeDeclaration(it) } - } - - fun analyzeDeclaration(declaration: PsiElement) { - if (declaration !is PsiModifierListOwner) return - - for (annotation in declaration.getAnnotationsWithInherited()) { - val fqName = annotation.qualifiedName ?: return - mutableAnnotationsMap.getOrPut(fqName, { mutableListOf() }).add(declaration) - } - - if (declaration is PsiClass) { - declaration.methods.forEach { analyzeDeclaration(it) } - declaration.fields.forEach { analyzeDeclaration(it) } - declaration.innerClasses.forEach { analyzeDeclaration(it) } - } - - if (declaration is PsiMethod) { - for (parameter in declaration.parameterList.parameters) { - analyzeDeclaration(parameter) - } - } - } -} \ No newline at end of file +private class ProcessingResult(val errorCount: Int, val warningCount: Int, val wasAnythingGenerated: Boolean) \ No newline at end of file diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/RoundAnnotations.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/RoundAnnotations.kt new file mode 100644 index 00000000000..ed6583db2df --- /dev/null +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/RoundAnnotations.kt @@ -0,0 +1,75 @@ +/* + * Copyright 2010-2016 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.annotation.processing + +import com.intellij.psi.* +import org.jetbrains.kotlin.asJava.findFacadeClass +import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.java.model.internal.getAnnotationsWithInherited +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtFile + +internal class RoundAnnotations() { + private val mutableAnnotationsMap = mutableMapOf>() + + val annotationsMap: Map> + get() = mutableAnnotationsMap + + fun analyzeFiles(files: Collection) = files.forEach { analyzeFile(it) } + + @JvmName("analyzePsiJavaFiles") + fun analyzeFiles(files: Collection) = files.forEach { analyzeFile(it) } + + fun analyzeFile(file: KtFile) { + val lightClass = file.findFacadeClass() + + if (lightClass != null) { + analyzeDeclaration(lightClass) + } + + for (declaration in file.declarations) { + if (declaration !is KtClassOrObject) continue + val clazz = declaration.toLightClass() ?: continue + analyzeDeclaration(clazz) + } + } + + fun analyzeFile(file: PsiJavaFile) { + file.classes.forEach { analyzeDeclaration(it) } + } + + fun analyzeDeclaration(declaration: PsiElement) { + if (declaration !is PsiModifierListOwner) return + + for (annotation in declaration.getAnnotationsWithInherited()) { + val fqName = annotation.qualifiedName ?: return + mutableAnnotationsMap.getOrPut(fqName, { mutableListOf() }).add(declaration) + } + + if (declaration is PsiClass) { + declaration.methods.forEach { analyzeDeclaration(it) } + declaration.fields.forEach { analyzeDeclaration(it) } + declaration.innerClasses.forEach { analyzeDeclaration(it) } + } + + if (declaration is PsiMethod) { + for (parameter in declaration.parameterList.parameters) { + analyzeDeclaration(parameter) + } + } + } +} \ 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 9acb7da731c..baba9ba08d7 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 @@ -24,11 +24,18 @@ import javax.tools.JavaFileManager import javax.tools.JavaFileObject import javax.tools.StandardLocation -class KotlinFiler(val generatedSourceDir: File, val classesOutputDir: File) : Filer { +class KotlinFiler( + val generatedSourceDir: File, + val classesOutputDir: File, + internal var onFileCreatedHandler: (File) -> Unit = {} +) : Filer { private companion object { val PACKAGE_INFO_SUFFIX = ".packageInfo" } + internal var wasAnythingGenerated: Boolean = false + private set + private fun getGeneratedFile(nameCharSequence: CharSequence, extension: String): File { val name = nameCharSequence.toString() val isPackageInfo = name.endsWith(PACKAGE_INFO_SUFFIX) @@ -47,8 +54,13 @@ class KotlinFiler(val generatedSourceDir: File, val classesOutputDir: File) : Fi return File(packageDir, fileName) } + private fun File.notifyCreated() = apply { + wasAnythingGenerated = true + onFileCreatedHandler(this) + } + override fun createSourceFile(name: CharSequence, vararg originatingElements: Element?): JavaFileObject { - return KotlinJavaFileObject(getGeneratedFile(name, ".java")) + return KotlinJavaFileObject(getGeneratedFile(name, ".java").notifyCreated()) } override fun getResource(location: JavaFileManager.Location, pkg: CharSequence, relativeName: CharSequence): FileObject? { @@ -63,7 +75,7 @@ class KotlinFiler(val generatedSourceDir: File, val classesOutputDir: File) : Fi ): FileObject? { val resourceFile = getResourceFile(location, pkg, relativeName) resourceFile.parentFile.mkdirs() - return KotlinFileObject(resourceFile) + return KotlinFileObject(resourceFile.notifyCreated()) } private fun getResourceFile(location: JavaFileManager.Location, pkg: CharSequence, relativeName: CharSequence): File { @@ -80,6 +92,6 @@ class KotlinFiler(val generatedSourceDir: File, val classesOutputDir: File) : Fi } override fun createClassFile(name: CharSequence, vararg originatingElements: Element?): JavaFileObject { - return KotlinJavaFileObject(getGeneratedFile(name, ".class")) + return KotlinJavaFileObject(getGeneratedFile(name, ".class").notifyCreated()) } } \ No newline at end of file diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinProcessingEnvironment.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinProcessingEnvironment.kt index 4b3868b5669..78bc30100e5 100644 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinProcessingEnvironment.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinProcessingEnvironment.kt @@ -16,10 +16,14 @@ package org.jetbrains.kotlin.annotation.processing.impl +import com.intellij.openapi.project.Project +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.PsiManager +import com.intellij.psi.search.GlobalSearchScope +import java.io.File import java.util.* -import javax.annotation.processing.Filer -import javax.annotation.processing.Messager import javax.annotation.processing.ProcessingEnvironment +import javax.annotation.processing.Processor import javax.lang.model.SourceVersion import javax.lang.model.util.Elements import javax.lang.model.util.Types @@ -27,9 +31,17 @@ import javax.lang.model.util.Types class KotlinProcessingEnvironment( private val elements: Elements, private val types: Types, - private val messager: Messager, + private val messager: KotlinMessager, options: Map, - private val filer: Filer + private val filer: KotlinFiler, + + internal val processors: List, + + internal val project: Project, + internal val psiManager: PsiManager, + internal val javaPsiFacade: JavaPsiFacade, + internal val projectScope: GlobalSearchScope, + internal val appendJavaSourceRootsHandler: (List) -> Unit ) : ProcessingEnvironment { private val options = Collections.unmodifiableMap(options) diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinRoundEnvironment.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinRoundEnvironment.kt index 705372ac6d4..ddd9a1bfe7a 100644 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinRoundEnvironment.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinRoundEnvironment.kt @@ -16,23 +16,29 @@ package org.jetbrains.kotlin.annotation.processing.impl -import org.jetbrains.kotlin.annotation.AnalysisContext +import com.intellij.psi.PsiModifierListOwner +import org.jetbrains.kotlin.annotation.processing.RoundAnnotations import org.jetbrains.kotlin.java.model.toJeElement import javax.annotation.processing.RoundEnvironment import javax.lang.model.element.Element import javax.lang.model.element.TypeElement internal class KotlinRoundEnvironment( - private val context: AnalysisContext, - private val isProcessingOver: Boolean = false) : RoundEnvironment { + private val roundAnnotations: RoundAnnotations, + private val isProcessingOver: Boolean, + internal val roundNumber: Int +) : RoundEnvironment { private var isError = false + internal val annotationsMap: Map> + get() = roundAnnotations.annotationsMap + override fun getRootElements() = emptySet() override fun processingOver() = isProcessingOver private fun getElementsAnnotatedWith(fqName: String): Set { - val declarations = context.annotationsMap[fqName] ?: return emptySet() + val declarations = roundAnnotations.annotationsMap[fqName] ?: return emptySet() return hashSetOf().apply { for (declaration in declarations) { declaration.toJeElement()?.let { add(it) }