Remove obsolete kapt2 implementation

This commit is contained in:
Yan Zhulanow
2017-06-05 22:49:29 +03:00
parent 423a09e46a
commit 820f914d35
122 changed files with 1 additions and 5983 deletions
-2
View File
@@ -14,7 +14,6 @@
<module fileurl="file://$PROJECT_DIR$/compiler/android-tests/android-tests.iml" filepath="$PROJECT_DIR$/compiler/android-tests/android-tests.iml" group="compiler" />
<module fileurl="file://$PROJECT_DIR$/plugins/annotation-based-compiler-plugins-ide-support/annotation-based-compiler-plugins-ide-support.iml" filepath="$PROJECT_DIR$/plugins/annotation-based-compiler-plugins-ide-support/annotation-based-compiler-plugins-ide-support.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/annotation-collector/annotation-collector.iml" filepath="$PROJECT_DIR$/plugins/annotation-collector/annotation-collector.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/annotation-processing/annotation-processing.iml" filepath="$PROJECT_DIR$/plugins/annotation-processing/annotation-processing.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/ant/ant.iml" filepath="$PROJECT_DIR$/ant/ant.iml" />
<module fileurl="file://$PROJECT_DIR$/compiler/backend/backend.iml" filepath="$PROJECT_DIR$/compiler/backend/backend.iml" group="compiler/java" />
<module fileurl="file://$PROJECT_DIR$/compiler/backend-common/backend-common.iml" filepath="$PROJECT_DIR$/compiler/backend-common/backend-common.iml" group="compiler" />
@@ -64,7 +63,6 @@
<module fileurl="file://$PROJECT_DIR$/compiler/ir/ir.psi2ir/ir.psi2ir.iml" filepath="$PROJECT_DIR$/compiler/ir/ir.psi2ir/ir.psi2ir.iml" group="compiler/ir" />
<module fileurl="file://$PROJECT_DIR$/compiler/ir/ir.tree/ir.tree.iml" filepath="$PROJECT_DIR$/compiler/ir/ir.tree/ir.tree.iml" group="compiler/ir" />
<module fileurl="file://$PROJECT_DIR$/j2k/j2k.iml" filepath="$PROJECT_DIR$/j2k/j2k.iml" group="j2k" />
<module fileurl="file://$PROJECT_DIR$/plugins/java-model-wrappers/java-model-wrappers.iml" filepath="$PROJECT_DIR$/plugins/java-model-wrappers/java-model-wrappers.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/compiler/javac-wrapper/javac-wrapper.iml" filepath="$PROJECT_DIR$/compiler/javac-wrapper/javac-wrapper.iml" group="compiler" />
<module fileurl="file://$PROJECT_DIR$/jps-plugin/jps-plugin.iml" filepath="$PROJECT_DIR$/jps-plugin/jps-plugin.iml" group="ide/jps" />
<module fileurl="file://$PROJECT_DIR$/jps-plugin/jps-tests/jps-tests.iml" filepath="$PROJECT_DIR$/jps-plugin/jps-tests/jps-tests.iml" group="ide/jps" />
@@ -30,9 +30,6 @@ import org.jetbrains.kotlin.android.intention.AbstractAndroidResourceIntentionTe
import org.jetbrains.kotlin.android.lint.AbstractKotlinLintTest
import org.jetbrains.kotlin.android.quickfix.AbstractAndroidLintQuickfixTest
import org.jetbrains.kotlin.android.quickfix.AbstractAndroidQuickFixMultiFileTest
import org.jetbrains.kotlin.annotation.AbstractAnnotationProcessorBoxTest
import org.jetbrains.kotlin.annotation.processing.test.sourceRetention.AbstractBytecodeListingTestForSourceRetention
import org.jetbrains.kotlin.annotation.processing.test.wrappers.AbstractAnnotationProcessingTest
import org.jetbrains.kotlin.asJava.AbstractCompilerLightClassTest
import org.jetbrains.kotlin.cfg.AbstractControlFlowTest
import org.jetbrains.kotlin.cfg.AbstractDataFlowTest
@@ -160,6 +157,7 @@ import org.jetbrains.kotlin.kdoc.AbstractKDocLexerTest
import org.jetbrains.kotlin.android.synthetic.test.AbstractAndroidBoxTest
import org.jetbrains.kotlin.android.synthetic.test.AbstractAndroidBytecodeShapeTest
import org.jetbrains.kotlin.android.synthetic.test.AbstractAndroidSyntheticPropertyDescriptorTest
import org.jetbrains.kotlin.annotation.AbstractAnnotationProcessorBoxTest
import org.jetbrains.kotlin.modules.xml.AbstractModuleXmlParserTest
import org.jetbrains.kotlin.multiplatform.AbstractMultiPlatformIntegrationTest
import org.jetbrains.kotlin.noarg.AbstractBlackBoxCodegenTestForNoArg
@@ -1258,16 +1256,6 @@ fun main(args: Array<String>) {
}
}
testGroup("plugins/plugins-tests/tests", "plugins/annotation-processing/testData") {
testClass<AbstractAnnotationProcessingTest> {
model("wrappers", recursive = true, extension = "kt")
}
testClass<AbstractBytecodeListingTestForSourceRetention> {
model("sourceRetention", extension = "kt")
}
}
testGroup("plugins/kapt3/test", "plugins/kapt3/testData") {
testClass<AbstractClassFileToSourceStubConverterTest> {
model("converter")
@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="java-model-wrappers" />
<orderEntry type="module" module-name="frontend" />
<orderEntry type="module" module-name="plugin-api" />
<orderEntry type="module" module-name="frontend.java" />
<orderEntry type="module" module-name="light-classes" />
<orderEntry type="module" module-name="util" />
<orderEntry type="library" name="kotlin-runtime" level="project" />
<orderEntry type="module" module-name="cli" />
<orderEntry type="module" module-name="backend" />
</component>
</module>
@@ -1 +0,0 @@
org.jetbrains.kotlin.annotation.processing.AnnotationProcessingCommandLineProcessor
@@ -1 +0,0 @@
org.jetbrains.kotlin.annotation.processing.AnnotationProcessingComponentRegistrar
@@ -1,361 +0,0 @@
/*
* 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
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiJavaFile
import com.intellij.psi.PsiManager
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.cli.common.messages.*
import org.jetbrains.kotlin.codegen.ClassBuilderMode
import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
import org.jetbrains.kotlin.java.model.elements.JeTypeElement
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
import java.io.File
import java.io.IOException
import java.io.PrintWriter
import java.io.StringWriter
import java.net.URLClassLoader
import java.util.*
import javax.annotation.processing.Processor
import javax.tools.Diagnostic
class ClasspathBasedAnnotationProcessingExtension(
val annotationProcessingClasspath: List<File>,
override val options: Map<String, String>,
generatedSourcesOutputDir: File,
classesOutputDir: File,
javaSourceRoots: List<File>,
verboseOutput: Boolean,
incrementalDataFile: File?,
messageCollector: MessageCollector?
) : AbstractAnnotationProcessingExtension(generatedSourcesOutputDir,
classesOutputDir, javaSourceRoots, verboseOutput,
incrementalDataFile, messageCollector) {
override fun loadAnnotationProcessors(): List<Processor> {
val classLoader = URLClassLoader(annotationProcessingClasspath.map { it.toURI().toURL() }.toTypedArray())
return ServiceLoader.load(Processor::class.java, classLoader).toList()
}
}
abstract class AbstractAnnotationProcessingExtension(
val generatedSourcesOutputDir: File,
val classesOutputDir: File,
val javaSourceRoots: List<File>,
val verboseOutput: Boolean,
val incrementalDataFile: File? = null,
messageCollector: MessageCollector? = null
) : AnalysisHandlerExtension {
private companion object {
val LINE_SEPARATOR = System.getProperty("line.separator") ?: "\n"
}
private var annotationProcessingComplete = false
private val messager = run {
val collector = messageCollector ?: PrintingMessageCollector(System.err, MessageRenderer.WITHOUT_PATHS, verboseOutput)
KotlinMessager(collector)
}
private inline fun log(message: () -> String) {
if (verboseOutput) {
messager.printMessage(Diagnostic.Kind.OTHER, "Kapt: " + message())
}
}
private fun Int.count(noun: String) = if (this == 1) "$this $noun" else "$this ${noun}s"
private inline fun <T, R> T.runIf(condition: Boolean, block: T.() -> R) {
if (condition) block()
}
override fun analysisCompleted(
project: Project,
module: ModuleDescriptor,
bindingTrace: BindingTrace,
files: Collection<KtFile>
): AnalysisResult? {
if (annotationProcessingComplete) {
return null
}
// Clean the generated source directory even if we don't run any annotation processors
generatedSourcesOutputDir.deleteRecursively()
generatedSourcesOutputDir.mkdirs()
val processors = loadAnnotationProcessors()
if (processors.isEmpty()) {
log { "No annotation processors detected, exiting" }
return null
}
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 startTime = System.currentTimeMillis()
val psiManager = PsiManager.getInstance(project)
val javaPsiFacade = JavaPsiFacade.getInstance(project)
val projectScope = GlobalSearchScope.projectScope(project)
val options = this.options
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, bindingTrace.bindingContext, appendJavaSourceRootsHandler)
var processingResult: ProcessingResult
try {
processingResult = processingEnvironment.doAnnotationProcessing(files)
processingEnvironment.dispose()
}
catch (thr: Throwable) {
messager.printMessage(
Diagnostic.Kind.ERROR,
"An exception occurred during annotation processing. Stacktrace: \n" + thr.getStackTraceAsString())
processingResult = ProcessingResult(errorCount = 1, warningCount = 0, wasAnythingGenerated = false)
}
annotationProcessingComplete = true
log {
"Annotation processing complete in ${System.currentTimeMillis() - startTime} ms, " +
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 Throwable.getStackTraceAsString(): String {
val out = StringWriter(1024)
val printWriter = PrintWriter(out)
try {
printStackTrace(printWriter)
return out.toString().replace("\r", "")
}
finally {
printWriter.close()
}
}
private fun KotlinProcessingEnvironment.createTypeMapper(): KotlinTypeMapper {
return KotlinTypeMapper(bindingContext(), ClassBuilderMode.full(false), NoResolveFileClassesProvider,
IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME, false, false)
}
private fun KotlinProcessingEnvironment.doAnnotationProcessing(files: Collection<KtFile>): ProcessingResult {
run initializeProcessors@ {
processors().forEach { it.init(this) }
log { "Initialized processors: " + processors().joinToString { it::class.java.name } }
}
val firstRoundAnnotations = RoundAnnotations(
bindingContext(),
createTypeMapper())
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)
}
}
}
}
}
runIf(incrementalDataFile != null) processIncrementalData@ {
val incrementalDataFile = incrementalDataFile!!
runIf(incrementalDataFile.exists()) analyzeFilesFromPreviousIncrementalData@ {
val incrementalData = try {
incrementalDataFile.readText()
} catch (e: IOException) {
log { "An exception occurred while processing incremental data file: $incrementalDataFile" }
null
}
if (incrementalData != null) {
val analyzedClasses = mutableListOf<String>()
for (line in incrementalData.lines()) {
if (line.length < 3 || !line.startsWith("i ")) continue
val fqName = line.drop(2)
val psiClass = javaPsiFacade().findClass(fqName, projectScope()) ?: continue
if (firstRoundAnnotations.analyzeDeclaration(psiClass)) {
analyzedClasses += fqName
}
}
log { "Analysing files from incremental data: $analyzedClasses" }
}
}
run saveNewIncrementalData@ {
val analyzedClasses = firstRoundAnnotations.analyzedClasses
log { "Saving incremental data: ${analyzedClasses.size} class names" }
try {
incrementalDataFile.parentFile.mkdirs()
incrementalDataFile.writeText(analyzedClasses.joinToString(LINE_SEPARATOR) { "i $it" })
}
catch (e: IOException) {
log { "Unable to write $incrementalDataFile" }
}
}
}
val finalRoundNumber = run annotationProcessing@ {
val firstRoundEnvironment = KotlinRoundEnvironment(firstRoundAnnotations, false, 1)
process(firstRoundEnvironment) // Dispose for firstRoundEnvironment is called inside process
} + 1
log { "Starting round $finalRoundNumber (final)" }
val finalRoundEnvironment = KotlinRoundEnvironment(firstRoundAnnotations.copy(), true, finalRoundNumber)
for (processor in processors()) {
processor.process(emptySet(), finalRoundEnvironment)
}
finalRoundEnvironment.dispose()
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
}
// Add new Java source roots after the first round
if (roundEnvironment.roundNumber == 1) {
appendJavaSourceRootsHandler()(listOf(generatedSourcesOutputDir))
}
// Update the platform caches
ApplicationManager.getApplication().runWriteAction {
(psiManager().modificationTracker as? PsiModificationTrackerImpl)?.incCounter()
}
// Find generated files
val localFileSystem = StandardFileSystems.local()
val psiFiles = newJavaFiles
.map { localFileSystem.findFileByPath(it.absolutePath)?.let { psiManager().findFile(it) } }
.filterIsInstance<PsiJavaFile>()
if (psiFiles.isEmpty()) {
log { "Something is strange, files were generated but not found by PsiManager" }
return roundEnvironment.roundNumber
}
// Start the next round
val nextRoundAnnotations = roundEnvironment.roundAnnotations().copy().apply { analyzeFiles(psiFiles) }
val nextRoundEnvironment = KotlinRoundEnvironment(nextRoundAnnotations, false, roundEnvironment.roundNumber + 1)
roundEnvironment.dispose()
return process(nextRoundEnvironment)
}
private fun KotlinProcessingEnvironment.doRound(roundEnvironment: KotlinRoundEnvironment): List<File> {
log { "Starting round ${roundEnvironment.roundNumber}" }
val newFiles = mutableListOf<File>()
filer.onFileCreatedHandler = { newFiles += it }
for (processor in processors()) {
val supportedAnnotationNames = processor.supportedAnnotationTypes
val acceptsAnyAnnotation = supportedAnnotationNames.contains("*")
val applicableAnnotationNames = when (acceptsAnyAnnotation) {
true -> roundEnvironment.roundAnnotations().annotationsMap.keys
false -> processor.supportedAnnotationTypes.filter { it in roundEnvironment.roundAnnotations().annotationsMap }
}
if (applicableAnnotationNames.isEmpty()) {
log { "Skipping processor " + processor::class.java.name + ": no relevant annotations" }
continue
}
val applicableAnnotations = applicableAnnotationNames
.map { javaPsiFacade().findClass(it, projectScope())?.let(::JeTypeElement) }
.filterNotNullTo(hashSetOf())
log {
val annotationNames = applicableAnnotations.joinToString { it.qualifiedName.toString() }
"Processing with " + processor::class.java.name + " (annotations: " + annotationNames + ")"
}
processor.process(applicableAnnotations, roundEnvironment)
}
log { "Round ${roundEnvironment.roundNumber} finished, ${newFiles.size.count("file")} generated (${newFiles.joinToString()})" }
return newFiles
}
protected abstract fun loadAnnotationProcessors(): List<Processor>
protected abstract val options: Map<String, String>
}
private class ProcessingResult(val errorCount: Int, val warningCount: Int, val wasAnythingGenerated: Boolean)
@@ -1,150 +0,0 @@
/*
* 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.mock.MockProject
import com.intellij.openapi.extensions.Extensions
import org.jetbrains.kotlin.annotation.ClasspathBasedAnnotationProcessingExtension
import org.jetbrains.kotlin.annotation.processing.diagnostic.DefaultErrorMessagesAnnotationProcessing
import org.jetbrains.kotlin.cli.jvm.config.IS_KAPT2_ENABLED_KEY
import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRoot
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.diagnostics.rendering.DefaultErrorMessages
import org.jetbrains.kotlin.java.model.internal.JeElementRegistry
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
import java.io.File
import org.jetbrains.kotlin.annotation.processing.AnnotationProcessingConfigurationKeys.ANNOTATION_PROCESSOR_CLASSPATH
import org.jetbrains.kotlin.annotation.processing.AnnotationProcessingConfigurationKeys.APT_OPTIONS
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
object AnnotationProcessingConfigurationKeys {
val GENERATED_OUTPUT_DIR: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>("generated files output directory")
val CLASS_FILES_OUTPUT_DIR: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>("class files output directory")
val ANNOTATION_PROCESSOR_CLASSPATH: CompilerConfigurationKey<List<String>> =
CompilerConfigurationKey.create<List<String>>("annotation processor classpath")
val APT_OPTIONS: CompilerConfigurationKey<List<String>> =
CompilerConfigurationKey.create<List<String>>("annotation processing options")
val INCREMENTAL_DATA_FILE: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>("data file for incremental compilation support")
val VERBOSE_MODE: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>("verbose mode")
}
class AnnotationProcessingCommandLineProcessor : CommandLineProcessor {
companion object {
val ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID: String = "org.jetbrains.kotlin.kapt2"
val GENERATED_OUTPUT_DIR_OPTION: CliOption =
CliOption("generated", "<path>", "Output path for the generated files", required = false)
val CLASS_FILES_OUTPUT_DIR_OPTION: CliOption =
CliOption("classes", "<path>", "Output path for the class files", required = false)
val ANNOTATION_PROCESSOR_CLASSPATH_OPTION: CliOption =
CliOption("apclasspath", "<classpath>", "Annotation processor classpath",
required = false, allowMultipleOccurrences = true)
val APT_OPTIONS_OPTION: CliOption =
CliOption("apoption", "<key>:<value>", "Annotation processor option",
required = false, allowMultipleOccurrences = true)
val INCREMENTAL_DATA_FILE_OPTION: CliOption =
CliOption("incrementalData", "<path>", "Location of the incremental data file", required = false)
val VERBOSE_MODE_OPTION: CliOption =
CliOption("verbose", "true | false", "Enable verbose output", required = false)
}
override val pluginId: String = ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID
override val pluginOptions: Collection<CliOption> =
listOf(GENERATED_OUTPUT_DIR_OPTION, ANNOTATION_PROCESSOR_CLASSPATH_OPTION, APT_OPTIONS_OPTION,
CLASS_FILES_OUTPUT_DIR_OPTION, INCREMENTAL_DATA_FILE_OPTION, VERBOSE_MODE_OPTION)
override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) {
when (option) {
ANNOTATION_PROCESSOR_CLASSPATH_OPTION -> configuration.appendList(ANNOTATION_PROCESSOR_CLASSPATH, value)
APT_OPTIONS_OPTION -> configuration.appendList(APT_OPTIONS, value)
GENERATED_OUTPUT_DIR_OPTION -> configuration.put(AnnotationProcessingConfigurationKeys.GENERATED_OUTPUT_DIR, value)
CLASS_FILES_OUTPUT_DIR_OPTION -> configuration.put(AnnotationProcessingConfigurationKeys.CLASS_FILES_OUTPUT_DIR, value)
INCREMENTAL_DATA_FILE_OPTION -> configuration.put(AnnotationProcessingConfigurationKeys.INCREMENTAL_DATA_FILE, value)
VERBOSE_MODE_OPTION -> configuration.put(AnnotationProcessingConfigurationKeys.VERBOSE_MODE, value)
else -> throw CliOptionProcessingException("Unknown option: ${option.name}")
}
}
}
class AnnotationProcessingComponentRegistrar : ComponentRegistrar {
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
val generatedOutputDir = configuration.get(AnnotationProcessingConfigurationKeys.GENERATED_OUTPUT_DIR) ?: return
val apClasspath = configuration.get(ANNOTATION_PROCESSOR_CLASSPATH)?.map(::File) ?: return
val apOptions = (configuration.get(APT_OPTIONS) ?: listOf())
.map { it.split(':') }
.filter { it.size == 2 }
.map { it[0] to it[1] }
.toMap()
val incrementalDataFile = configuration.get(AnnotationProcessingConfigurationKeys.INCREMENTAL_DATA_FILE)?.let(::File)
val generatedOutputDirFile = File(generatedOutputDir)
generatedOutputDirFile.mkdirs()
val contentRoots = configuration[JVMConfigurationKeys.CONTENT_ROOTS] ?: emptyList()
val compileClasspath = contentRoots.filterIsInstance<JvmContentRoot>().map { it.file }
val classpath = apClasspath + compileClasspath
val javaRoots = contentRoots.filterIsInstance<JavaSourceRoot>().map { it.file }
val classesOutputDir = File(configuration.get(AnnotationProcessingConfigurationKeys.CLASS_FILES_OUTPUT_DIR)
?: configuration[JVMConfigurationKeys.MODULES]!!.first().getOutputDirectory())
val verboseOutput = configuration.get(AnnotationProcessingConfigurationKeys.VERBOSE_MODE) == "true"
Extensions.getRootArea().getExtensionPoint(DefaultErrorMessages.Extension.EP_NAME)
.registerExtension(DefaultErrorMessagesAnnotationProcessing())
// Annotations with the "SOURCE" retention will be written to class files
project.putUserData(IS_KAPT2_ENABLED_KEY, true)
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
val annotationProcessingExtension = ClasspathBasedAnnotationProcessingExtension(
classpath, apOptions, generatedOutputDirFile, classesOutputDir, javaRoots, verboseOutput,
incrementalDataFile, messageCollector)
project.registerService(JeElementRegistry::class.java, JeElementRegistry())
AnalysisHandlerExtension.registerExtension(project, annotationProcessingExtension)
}
}
@@ -1,126 +0,0 @@
/*
* 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 com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.asJava.findFacadeClass
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
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
internal class RoundAnnotations(
val bindingContext: BindingContext,
val typeMapper: KotlinTypeMapper
) {
private companion object {
private val BLACKLISTED_ANNOTATATIONS = listOf(
"java.lang.Deprecated", "kotlin.Deprecated", // Deprecated annotations
"java.lang.annotation.", // Java annotations
"org.jetbrains.annotations.", // Nullable/NotNull, ReadOnly, Mutable
"kotlin.jvm.", "kotlin.Metadata" // Kotlin annotations from runtime
)
}
private val mutableAnnotationsMap = mutableMapOf<String, MutableList<PsiModifierListOwner>>()
private val mutableAnalyzedClasses = mutableSetOf<String>()
val annotationsMap: Map<String, List<PsiModifierListOwner>>
get() = mutableAnnotationsMap
val analyzedClasses: Set<String>
get() = mutableAnalyzedClasses
fun copy() = RoundAnnotations(bindingContext, typeMapper)
fun analyzeFiles(files: Collection<KtFile>) = files.forEach { analyzeFile(it) }
@JvmName("analyzePsiJavaFiles")
fun analyzeFiles(files: Collection<PsiJavaFile>) = 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 PsiElement.getTopLevelClassParent(): PsiClass? = when (this) {
is PsiClass -> containingClass?.let { it.getTopLevelClassParent() } ?: this
else -> PsiTreeUtil.getParentOfType(this, PsiClass::class.java, true)?.getTopLevelClassParent()
}
private val PsiAnnotation.hasSourceRetention: Boolean
get() {
val annotationDeclaration = nameReferenceElement?.resolve() as? PsiClass ?: return false
val metaAnnotations = annotationDeclaration.modifierList?.annotations ?: return false
return metaAnnotations.any { anno ->
val declaration = anno.nameReferenceElement?.resolve() as? PsiClass ?: return@any false
if (declaration.qualifiedName != "java.lang.annotation.Retention") return@any false
val value = (anno.findAttributeValue("value") as? PsiReferenceExpression)?.resolve() ?: return@any false
value is PsiEnumConstant && value.name == "SOURCE"
}
}
fun analyzeDeclaration(declaration: PsiElement): Boolean {
if (declaration !is PsiModifierListOwner) return false
// Do not analyze classes twice (for incremental compilation data)
if (declaration is PsiClass && declaration.qualifiedName in analyzedClasses) return false
for (annotation in declaration.getAnnotationsWithInherited()) {
val fqName = annotation.qualifiedName ?: continue
if (BLACKLISTED_ANNOTATATIONS.any { fqName.startsWith(it) }) continue
mutableAnnotationsMap.getOrPut(fqName, { mutableListOf() }).add(declaration)
// Add only top-level classes
val topLevelClassQualifiedName = declaration.getTopLevelClassParent()?.qualifiedName
if (topLevelClassQualifiedName != null) {
mutableAnalyzedClasses += topLevelClassQualifiedName
}
}
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)
}
}
return true
}
}
@@ -1,34 +0,0 @@
/*
* 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.diagnostic
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticFactoryToRendererMap
class DefaultErrorMessagesAnnotationProcessing : DefaultErrorMessages.Extension {
private companion object {
val MAP = DiagnosticFactoryToRendererMap("AnnotationProcessing")
init {
MAP.put(ErrorsAnnotationProcessing.ANNOTATION_PROCESSING_ERROR,
"Some error(s) occurred while processing annotations. Please see the error messages above.")
}
}
override fun getMap() = MAP
}
@@ -1,35 +0,0 @@
/*
* 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.diagnostic;
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0;
import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.psi.KtElement;
import static org.jetbrains.kotlin.diagnostics.Severity.ERROR;
public interface ErrorsAnnotationProcessing {
DiagnosticFactory0<KtElement> ANNOTATION_PROCESSING_ERROR = DiagnosticFactory0.create(ERROR);
@SuppressWarnings("UnusedDeclaration")
Object _initializer = new Object() {
{
Errors.Initializer.initializeFactoryNames(ErrorsAnnotationProcessing.class);
}
};
}
@@ -1,225 +0,0 @@
/*
* 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.impl
import com.intellij.openapi.Disposable
import com.intellij.psi.*
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.PsiSuperMethodUtil
import com.intellij.psi.util.TypeConversionUtil
import org.jetbrains.kotlin.java.model.JeAnnotationOwner
import org.jetbrains.kotlin.java.model.JeElement
import org.jetbrains.kotlin.java.model.JeName
import org.jetbrains.kotlin.java.model.elements.JeAnnotationMirror
import org.jetbrains.kotlin.java.model.elements.JeMethodExecutableElement
import org.jetbrains.kotlin.java.model.elements.JePackageElement
import org.jetbrains.kotlin.java.model.elements.JeTypeElement
import org.jetbrains.kotlin.java.model.internal.getTypeWithTypeParameters
import org.jetbrains.kotlin.java.model.util.disposeAll
import org.jetbrains.kotlin.java.model.util.toDisposable
import java.io.PrintWriter
import java.io.Writer
import javax.lang.model.element.*
import javax.lang.model.util.Elements
class KotlinElements(
javaPsiFacade: JavaPsiFacade,
scope: GlobalSearchScope
) : Elements, Disposable {
internal val javaPsiFacade = javaPsiFacade.toDisposable()
internal val scope = scope.toDisposable()
override fun dispose() = disposeAll(javaPsiFacade, scope)
override fun hides(hider: Element, hidden: Element): Boolean {
val hiderMethod = (hider as? JeMethodExecutableElement)?.psi ?: return false
val hiddenMethod = (hidden as? JeMethodExecutableElement)?.psi ?: return false
val hiderMethodClass = hiderMethod.containingClass ?: return false
val hiddenMethodClass = hiddenMethod.containingClass ?: return false
if (hiddenMethodClass.getTypeWithTypeParameters() !in hiderMethodClass.superTypes) return false
return isSubSignature(hiderMethod, hiddenMethod)
}
override fun overrides(overrider: ExecutableElement, overridden: ExecutableElement, type: TypeElement): Boolean {
overrider as? JeMethodExecutableElement ?: return false
overridden as? JeMethodExecutableElement ?: return false
type as? JeTypeElement ?: return false
if (overrider.psi == overridden.psi) return false
// if 'type' is a subtype of overrider's containing class
if (type.psi.isSubclassOf(overridden.psi.containingClass) && type.psi.isSubclassOf(overrider.psi.containingClass)) {
return isSubSignature(overrider.psi, overridden.psi)
}
return PsiSuperMethodUtil.isSuperMethod(overrider.psi, overridden.psi)
}
override fun getName(cs: CharSequence?) = JeName(cs?.toString())
override fun getElementValuesWithDefaults(a: AnnotationMirror): Map<out ExecutableElement, AnnotationValue> {
a as? JeAnnotationMirror ?: return emptyMap()
return a.getAllElementValues()
}
override fun getBinaryName(type: TypeElement) = JeName((type as JeTypeElement).psi.qualifiedName)
//TODO
override fun getDocComment(e: Element?) = null
override fun isDeprecated(e: Element?): Boolean {
val deprecated = ((e as? JeElement)?.psi as? PsiDocCommentOwner)?.isDeprecated ?: false
if (deprecated) return true
return (e as? JeAnnotationOwner)?.psi?.modifierList?.findAnnotation("java.lang.Deprecated") != null
}
override fun getAllMembers(type: TypeElement) = (type as? JeTypeElement)?.getAllMembers() ?: emptyList()
override fun printElements(w: Writer, vararg elements: Element) {
val printWriter = PrintWriter(w)
for (element in elements) {
printWriter.println(element.simpleName.toString() + " (" + element::class.java.name + ")")
}
}
override fun getPackageElement(name: CharSequence): PackageElement? {
val psiPackage = javaPsiFacade().findPackage(name.toString()) ?: return null
return JePackageElement(psiPackage)
}
override fun getTypeElement(name: CharSequence): TypeElement? {
val psiClass = javaPsiFacade().findClass(name.toString(), scope()) ?: return null
return JeTypeElement(psiClass)
}
override fun getConstantExpression(value: Any?) = Constants.format(value)
override tailrec fun getPackageOf(element: Element): PackageElement? {
if (element is PackageElement) return element
val parent = element.enclosingElement ?: return null
return getPackageOf(parent)
}
override fun getAllAnnotationMirrors(e: Element): List<AnnotationMirror> {
val annotations = (e as? JeElement)?.annotationMirrors?.toMutableList() ?: mutableListOf()
if (e is JeTypeElement) {
var parent = e.psi.superClass
while (parent != null) {
val parentAnnotations = parent.modifierList?.annotations
if (parentAnnotations == null) {
parent = parent.superClass
continue
}
for (parentAnnotation in parentAnnotations) {
val annotationClass = parentAnnotation.nameReferenceElement?.resolve() as? PsiClass ?: continue
annotationClass.modifierList?.findAnnotation("java.lang.annotation.Inherited") ?: continue
annotations += JeAnnotationMirror(parentAnnotation)
}
parent = parent.superClass
}
}
return annotations
}
override fun isFunctionalInterface(type: TypeElement): Boolean {
val jeTypeElement = type as? JeTypeElement ?: return false
if (!jeTypeElement.psi.isInterface) return false
if (jeTypeElement.psi.allMethods.count { it.hasModifierProperty(PsiModifier.ABSTRACT) } != 1) return false
return true
}
}
private fun PsiClass.isSubclassOf(other: PsiClass?): Boolean {
if (other == null) return false
return TypeConversionUtil.isAssignable(other.getTypeWithTypeParameters(), this.getTypeWithTypeParameters(), false)
}
private fun isSubSignature(childMethod: PsiMethod, superMethod: PsiMethod): Boolean {
if (childMethod.name != superMethod.name) return false
if (childMethod.parameterList.parametersCount != superMethod.parameterList.parametersCount) return false
if (childMethod.returnType != superMethod.returnType) return false
for (i in 0..childMethod.parameterList.parametersCount - 1) {
if (childMethod.parameterList.parameters[i].type != superMethod.parameterList.parameters[i].type) return false
}
return true
}
object Constants {
fun format(value: Any?): String {
return when (value) {
is Byte -> formatByte((value as Byte?)!!)
is Short -> formatShort((value as Short?)!!)
is Long -> formatLong((value as Long?)!!)
is Float -> formatFloat((value as Float?)!!)
is Double -> formatDouble((value as Double?)!!)
is Char -> formatChar(value)
is String -> formatString(value)
is Int, is Boolean -> value.toString()
else -> throw IllegalArgumentException(
"Argument is not a primitive type or a string; it " +
(if (value == null) "is a null value." else "has class " + value::class.java.name) + ".")
}
}
private fun formatByte(b: Byte) = String.format("(byte)0x%02x", b)
private fun formatShort(s: Short) = String.format("(short)%d", s)
private fun formatLong(lng: Long) = "${lng}L"
private fun formatChar(c: Char) = '\'' + quote(c) + '\''
private fun formatString(s: String) = '"' + quote(s) + '"'
private fun formatFloat(f: Float): String = when {
java.lang.Float.isNaN(f) -> "0.0f/0.0f"
java.lang.Float.isInfinite(f) -> if (f < 0) "-1.0f/0.0f" else "1.0f/0.0f"
else -> "${f}f"
}
private fun formatDouble(d: Double): String = when {
java.lang.Double.isNaN(d) -> "0.0/0.0"
java.lang.Double.isInfinite(d) -> if (d < 0) "-1.0/0.0" else "1.0/0.0"
else -> d.toString()
}
fun quote(ch: Char): String = when (ch) {
'\b' -> "\\b"
'\n' -> "\\n"
'\r' -> "\\r"
'\t' -> "\\t"
'\'' -> "\\'"
'\"' -> "\\\""
'\\' -> "\\\\"
else -> if (isPrintableAscii(ch)) ch.toString() else String.format("\\u%04x", ch.toInt())
}
fun quote(s: String): String {
val buf = StringBuilder()
for (i in 0..s.length - 1) {
buf.append(quote(s[i]))
}
return buf.toString()
}
private fun isPrintableAscii(ch: Char) = ch >= ' ' && ch <= '~'
}
@@ -1,102 +0,0 @@
/*
* 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.impl
import java.io.File
import javax.annotation.processing.Filer
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 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, baseDir: File = generatedSourceDir): Pair<File, String> {
val name = nameCharSequence.toString()
val isPackageInfo = name.endsWith(PACKAGE_INFO_SUFFIX)
val fqName = if (isPackageInfo) name.substring(0, PACKAGE_INFO_SUFFIX.length) else name
val packageName = fqName.substringBeforeLast('.', "")
val packageDir = if (packageName.isNotEmpty()) {
File(baseDir, packageName.replace('.', '/')).apply { mkdirs() }
}
else {
baseDir
}
val fileName = fqName.substringAfterLast('.') + (if (isPackageInfo) PACKAGE_INFO_SUFFIX else extension)
val file = File(packageDir, fileName)
return Pair(file, file.toRelativeString(baseDir))
}
private fun File.notifyCreated() = apply {
wasAnythingGenerated = true
onFileCreatedHandler(this)
}
override fun createSourceFile(name: CharSequence, vararg originatingElements: Element?): JavaFileObject {
val (file, fileName) = getGeneratedFile(name, ".java")
return KotlinJavaFileObject(file.notifyCreated(), fileName)
}
override fun getResource(location: JavaFileManager.Location, pkg: CharSequence, relativeName: CharSequence): FileObject? {
val (file, fileName) = getResourceFile(location, pkg, relativeName)
return KotlinFileObject(file, fileName)
}
override fun createResource(
location: JavaFileManager.Location,
pkg: CharSequence,
relativeName: CharSequence,
vararg originatingElements: Element?
): FileObject? {
val (resourceFile, fileName) = getResourceFile(location, pkg, relativeName)
resourceFile.parentFile.mkdirs()
return KotlinFileObject(resourceFile.notifyCreated(), fileName)
}
private fun getResourceFile(location: JavaFileManager.Location, pkg: CharSequence, relativeName: CharSequence): Pair<File, String> {
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 resourceFile = File(targetDir, relativeName.toString())
return Pair(resourceFile, resourceFile.toRelativeString(baseDir))
}
override fun createClassFile(name: CharSequence, vararg originatingElements: Element?): JavaFileObject {
val (file, fileName) = getGeneratedFile(name, ".class")
return KotlinJavaFileObject(file.notifyCreated(), fileName)
}
}
@@ -1,61 +0,0 @@
/*
* 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.impl
import java.io.File
import javax.tools.FileObject
import javax.tools.JavaFileObject
class KotlinJavaFileObject(file: File, fileName: String) : KotlinAbstractFileObject(file, fileName), 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, fileName: String) : KotlinAbstractFileObject(file, fileName)
abstract class KotlinAbstractFileObject(val file: File, val fileName: String) : FileObject {
override fun openOutputStream() = file.outputStream()
override fun getName() = fileName
override fun openWriter() = file.writer()
override fun openInputStream() = file.inputStream()
override fun getCharContent(ignoreEncodingErrors: Boolean) = file.readText()
override fun getLastModified() = file.lastModified()
override fun toUri() = file.toURI()
override fun openReader(ignoreEncodingErrors: Boolean) = file.reader()
override fun delete() = file.delete()
}
@@ -1,61 +0,0 @@
/*
* 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.impl
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import javax.annotation.processing.Messager
import javax.lang.model.element.AnnotationMirror
import javax.lang.model.element.AnnotationValue
import javax.lang.model.element.Element
import javax.tools.Diagnostic
import javax.tools.Diagnostic.Kind
class KotlinMessager(private val messageCollector: MessageCollector) : Messager {
var errorCount: Int = 0
private set
var warningCount: Int = 0
private set
override fun printMessage(kind: Diagnostic.Kind, msg: CharSequence) = printMessage(kind, msg, null)
override fun printMessage(kind: Diagnostic.Kind, msg: CharSequence, e: Element?) = printMessage(kind, msg, e, null)
override fun printMessage(kind: Diagnostic.Kind, msg: CharSequence, e: Element?, a: AnnotationMirror?) {
printMessage(kind, msg, e, a, null)
}
override fun printMessage(kind: Diagnostic.Kind, msg: CharSequence, e: Element?, a: AnnotationMirror?, v: AnnotationValue?) {
val severity = when (kind) {
Kind.ERROR -> {
errorCount++
CompilerMessageSeverity.ERROR
}
Kind.WARNING -> {
warningCount++
CompilerMessageSeverity.WARNING
}
Kind.MANDATORY_WARNING -> {
warningCount++
CompilerMessageSeverity.STRONG_WARNING
}
else -> CompilerMessageSeverity.LOGGING
}
messageCollector.report(severity, msg.toString())
}
}
@@ -1,83 +0,0 @@
/*
* 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.impl
import com.intellij.openapi.Disposable
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiManager
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.java.model.internal.JeElementRegistry
import org.jetbrains.kotlin.java.model.util.disposeAll
import org.jetbrains.kotlin.java.model.util.toDisposable
import org.jetbrains.kotlin.resolve.BindingContext
import java.io.File
import java.util.*
import javax.annotation.processing.ProcessingEnvironment
import javax.annotation.processing.Processor
import javax.lang.model.SourceVersion
class KotlinProcessingEnvironment(
elements: KotlinElements,
types: KotlinTypes,
messager: KotlinMessager,
options: Map<String, String>,
filer: KotlinFiler,
processors: List<Processor>,
project: Project,
psiManager: PsiManager,
javaPsiFacade: JavaPsiFacade,
projectScope: GlobalSearchScope,
bindingContext: BindingContext,
appendJavaSourceRootsHandler: (List<File>) -> Unit
) : ProcessingEnvironment, Disposable {
private val elements = elements.toDisposable()
private val types = types.toDisposable()
private val messager = messager.toDisposable()
private val filer = filer.toDisposable()
internal val processors = processors.toDisposable()
internal val project = project.toDisposable()
internal val psiManager = psiManager.toDisposable()
internal val javaPsiFacade = javaPsiFacade.toDisposable()
internal val projectScope = projectScope.toDisposable()
internal val bindingContext = bindingContext.toDisposable()
private val registry = ServiceManager.getService(project, JeElementRegistry::class.java).toDisposable()
internal val appendJavaSourceRootsHandler = appendJavaSourceRootsHandler.toDisposable()
private val options = Collections.unmodifiableMap(options).toDisposable()
override fun dispose() {
types().dispose()
elements().dispose()
registry().dispose()
disposeAll(elements, types, messager, filer, processors,
project, psiManager, javaPsiFacade, projectScope, bindingContext,
appendJavaSourceRootsHandler, options)
}
override fun getElementUtils() = elements()
override fun getTypeUtils() = types()
override fun getMessager() = messager()
override fun getLocale() = Locale.getDefault()
override fun getSourceVersion() = SourceVersion.RELEASE_8
override fun getOptions() = options()
override fun getFiler() = filer()
}
@@ -1,56 +0,0 @@
/*
* 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.impl
import com.intellij.openapi.Disposable
import org.jetbrains.kotlin.annotation.processing.RoundAnnotations
import org.jetbrains.kotlin.java.model.toJeElement
import org.jetbrains.kotlin.java.model.util.disposeAll
import org.jetbrains.kotlin.java.model.util.toDisposable
import javax.annotation.processing.RoundEnvironment
import javax.lang.model.element.Element
import javax.lang.model.element.TypeElement
internal class KotlinRoundEnvironment(
roundAnnotations: RoundAnnotations,
private val isProcessingOver: Boolean,
internal val roundNumber: Int
) : RoundEnvironment, Disposable {
val roundAnnotations = roundAnnotations.toDisposable()
override fun dispose() = disposeAll(roundAnnotations)
private var isError = false
override fun getRootElements() = emptySet<Element>()
override fun processingOver() = isProcessingOver
private fun getElementsAnnotatedWith(fqName: String): Set<Element> {
val declarations = roundAnnotations().annotationsMap[fqName] ?: return emptySet()
return hashSetOf<Element>().apply {
for (declaration in declarations) {
declaration.toJeElement()?.let { add(it) }
}
}
}
override fun getElementsAnnotatedWith(a: TypeElement) = getElementsAnnotatedWith(a.qualifiedName.toString())
override fun getElementsAnnotatedWith(a: Class<out Annotation>) = getElementsAnnotatedWith(a.canonicalName)
override fun errorRaised() = isError
}
@@ -1,315 +0,0 @@
/*
* 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.impl
import com.intellij.openapi.Disposable
import com.intellij.psi.*
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.MethodSignatureUtil
import com.intellij.psi.util.PsiTypesUtil
import com.intellij.psi.util.TypeConversionUtil
import org.jetbrains.kotlin.java.model.JeElement
import org.jetbrains.kotlin.java.model.elements.*
import org.jetbrains.kotlin.java.model.types.*
import org.jetbrains.kotlin.java.model.util.disposeAll
import org.jetbrains.kotlin.java.model.util.toDisposable
import javax.lang.model.element.Element
import javax.lang.model.element.TypeElement
import javax.lang.model.type.*
import javax.lang.model.util.Types
class KotlinTypes(
javaPsiFacade: JavaPsiFacade,
psiManager: PsiManager,
scope: GlobalSearchScope
) : Types, Disposable {
val javaPsiFacade = javaPsiFacade.toDisposable()
val psiManager = psiManager.toDisposable()
val scope = scope.toDisposable()
override fun dispose() = disposeAll(javaPsiFacade, psiManager, scope)
override fun contains(containing: TypeMirror, contained: TypeMirror): Boolean {
assertKindNot(containing, TypeKind.PACKAGE, TypeKind.EXECUTABLE)
assertKindNot(contained, TypeKind.PACKAGE, TypeKind.EXECUTABLE)
assertJeType(containing); containing as JePsiType
assertJeType(contained); contained as JePsiType
fun L(type: PsiType): PsiType = when {
type is PsiWildcardType && type.isSuper -> type.superBound
else -> type
}
fun U(type: PsiType): PsiType = when {
type is PsiWildcardType && type.isExtends -> type.extendsBound
else -> type
}
return when (containing) {
is JeArrayType, is JePrimitiveType -> containing == contained
else -> {
!GenericsUtil.checkNotInBounds(L(contained.psiType), L(containing.psiType), false)
&& !GenericsUtil.checkNotInBounds(U(contained.psiType), U(containing.psiType), false)
}
}
}
override fun getArrayType(componentType: TypeMirror): ArrayType {
if (componentType is ExecutableType || componentType is NoType) error(componentType)
assertJeType(componentType); componentType as JePsiType
return JeArrayType(PsiArrayType(componentType.psiType), psiManager(), isRaw = false)
}
override fun isAssignable(t1: TypeMirror, t2: TypeMirror): Boolean {
assertKindNot(t1, TypeKind.PACKAGE, TypeKind.EXECUTABLE, TypeKind.NONE)
assertKindNot(t2, TypeKind.PACKAGE, TypeKind.EXECUTABLE, TypeKind.NONE)
t1 as? JePsiType ?: return false
t2 as? JePsiType ?: return false
return t2.psiType.isAssignableFrom(t1.psiType)
}
override fun getNullType() = JeNullType
override fun getWildcardType(extendsBound: TypeMirror?, superBound: TypeMirror?): JeWildcardType {
if (extendsBound != null && superBound != null) {
throw IllegalArgumentException("Both extendsBound and superBound should not be specified.")
}
if (extendsBound != null && extendsBound !is JePsiType) illegalArg("extendsBound should have PsiType")
if (superBound != null && superBound !is JePsiType) illegalArg("superBound should have PsiType")
return JeWildcardType(when {
extendsBound != null -> PsiWildcardType.createExtends(psiManager(), (extendsBound as JePsiType).psiType)
superBound != null -> PsiWildcardType.createSuper(psiManager(), (superBound as JePsiType).psiType)
else -> PsiWildcardType.createUnbounded(psiManager())
}, isRaw = false)
}
override fun unboxedType(t: TypeMirror): PrimitiveType? {
fun error(): Nothing = throw IllegalArgumentException("This type could not be unboxed: $t")
t as? JePsiType ?: error()
val unboxedType = PsiPrimitiveType.getUnboxedType(t.psiType) ?: error()
return unboxedType.toJePrimitiveType()
}
override fun getPrimitiveType(kind: TypeKind) = kind.toJePrimitiveType()
override fun erasure(t: TypeMirror): TypeMirror {
if (t.kind == TypeKind.PACKAGE) throw IllegalArgumentException("Invalid type: $t")
return when (t) {
is JeTypeVariableType -> TypeConversionUtil.typeParameterErasure(t.parameter).toJeType(t.psiManager, isRaw = true)
is JePsiType -> TypeConversionUtil.erasure(t.psiType).toJeType(psiManager(), isRaw = true)
is JeMethodExecutableTypeMirror -> {
val oldSignature = t.signature
val parameterTypes = oldSignature?.parameterTypes?.toList() ?: t.psi.parameterList.parameters.map { it.type }
val newSignature = MethodSignatureUtil.createMethodSignature(
oldSignature?.name ?: t.psi.name,
parameterTypes.map { TypeConversionUtil.erasure(it) }.toTypedArray(),
emptyArray(),
PsiSubstitutor.EMPTY,
oldSignature?.isConstructor ?: t.psi.isConstructor)
JeMethodExecutableTypeMirror(
t.psi, newSignature,
TypeConversionUtil.erasure(t.returnType ?: t.psi.returnType), isRaw = true)
}
else -> t
}
}
override fun directSupertypes(t: TypeMirror): List<TypeMirror> {
if (t is NoType || t is ExecutableType) throw IllegalArgumentException("Invalid type: $t")
val psiType = (t as? JePsiType)?.psiType as? PsiClassType ?: return emptyList()
return psiType.superTypes.map { it.toJeType(psiManager()) }
}
override fun boxedClass(p: PrimitiveType): TypeElement? {
p as? JePrimitiveType ?: throw IllegalArgumentException("Unknown type: $p")
val boxedTypeName = p.psiType.boxedTypeName
val boxedClass = javaPsiFacade().findClass(boxedTypeName, scope())
?: throw IllegalStateException("Can't find boxed class $boxedTypeName")
return JeTypeElement(boxedClass)
}
override fun asElement(t: TypeMirror): Element? {
if (t is JeDeclaredType) {
return t.asElement()
} else if (t is JeTypeVariableType) {
return t.asElement()
}
return null
}
override fun isSubtype(t1: TypeMirror, t2: TypeMirror): Boolean {
val psiType1 = (t1 as? JePsiType)?.psiType ?: return false
val psiType2 = (t2 as? JePsiType)?.psiType ?: return false
return TypeConversionUtil.isAssignable(psiType2, psiType1, false)
}
override fun isSameType(t1: TypeMirror, t2: TypeMirror) = t1 == t2
override fun getNoType(kind: TypeKind) = when (kind) {
TypeKind.VOID -> JeVoidType
TypeKind.NONE -> JeNoneType
else -> illegalArg("Must be kind of VOID or NONE, got ${kind.name}")
}
override fun getDeclaredType(typeElem: TypeElement, vararg typeArgMirrors: TypeMirror): DeclaredType {
val psiClass = (typeElem as JeTypeElement).psi
if (!psiClass.hasTypeParameters() && typeArgMirrors.size > 0) {
throw IllegalArgumentException("$typeElem has not type parameters")
}
// Raw type
if (psiClass.hasTypeParameters() && typeArgMirrors.isEmpty()) {
return JeDeclaredType(PsiTypesUtil.getClassType(psiClass).rawType(), psiClass)
}
val typeParameters = psiClass.typeParameters
if (typeArgMirrors.size != typeParameters.size) {
throw IllegalArgumentException("$typeElem type parameters count: " +
"${typeParameters.size}, received ${typeArgMirrors.size} args")
}
val typeArgs = typeArgMirrors.mapIndexed {
i, t -> (t as? JePsiType)?.psiType ?: throw IllegalArgumentException("Invalid type argument #$i: $t")
}
val psiType = createImmediateClassType(psiClass, typeArgs) ?:
throw IllegalStateException("Can't create declared type ($psiClass, $typeArgs)")
return JeDeclaredType(psiType, psiClass)
}
override fun getDeclaredType(
containing: DeclaredType?,
typeElem: TypeElement,
vararg typeArgMirrors: TypeMirror
): DeclaredType? {
if (containing == null) {
return getDeclaredType(typeElem, *typeArgMirrors)
}
val psiClass = (typeElem as JeTypeElement).psi
if (psiClass.containingClass == null) {
throw IllegalArgumentException("$typeElem is a top-level class element")
}
val containingType = (containing as? JePsiType)?.psiType as? PsiClassType
?: throw IllegalArgumentException("Illegal containing type: $containing")
val containingClass = containingType.resolve()
?: throw IllegalArgumentException("Class type can't be resolved: $containing")
if (psiClass.containingClass != containingClass) {
throw IllegalArgumentException("$containing is not an enclosing element for $typeElem")
}
val typeArgs = typeArgMirrors.mapIndexed {
i, t -> (t as? JePsiType)?.psiType ?: throw IllegalArgumentException("Invalid type argument #$i: $t")
}
val psiType = createImmediateClassType(psiClass, typeArgs) ?:
throw IllegalStateException("Can't create declared type ($psiClass, $typeArgs)")
return JeDeclaredType(psiType, psiClass, containing)
}
private fun Array<out PsiType>.findSuperType(superTypeClass: PsiClass): PsiClassType? {
for (supertype in this) {
if (supertype is PsiClassType && supertype.resolve() == superTypeClass) return supertype
supertype.superTypes.findSuperType(superTypeClass)?.let { return it }
}
return null
}
override fun asMemberOf(containing: DeclaredType, element: Element): TypeMirror {
if (containing !is JeDeclaredType || element is JeClassInitializerExecutableElement) return element.asType()
val containingType = containing.psiType
val member = (element as JeElement).psi as? PsiMember ?: return element.asType()
val memberOwnerClass = when (member) {
is PsiTypeParameter -> member.owner as? PsiClass
else -> member.containingClass
} ?: return element.asType()
val relevantSuperType = if (memberOwnerClass == containingType.resolve()) {
containingType
} else {
containingType.superTypes.findSuperType(memberOwnerClass) ?: return element.asType()
}
val resolveResult = relevantSuperType.resolveGenerics()
if (!resolveResult.isValidResult) return element.asType()
val substitutor = resolveResult.substitutor
return when (element) {
is JeMethodExecutableElement -> {
val method = element.psi
val signature = method.getSignature(substitutor)
val returnType = substitutor.substitute(element.psi.returnType)
JeMethodExecutableTypeMirror(method, signature, returnType)
}
is JeVariableElement -> substitutor.substitute(element.psi.type).toJeType(psiManager())
is JeTypeParameterElement -> substitutor.substitute(element.psi)?.toJeType(psiManager()) ?: element.asType()
else -> throw IllegalArgumentException("Invalid element type: ${element::class.java.name} ($element)")
}
}
override fun isSubsignature(t1: ExecutableType, t2: ExecutableType): Boolean {
val m1 = (t1 as JeClassInitializerExecutableTypeMirror).psi
val m2 = (t2 as JeClassInitializerExecutableTypeMirror).psi
// No parameters
if (m1 is PsiClassInitializer && m2 is PsiClassInitializer) return true
if (m1 !is PsiMethod || m2 !is PsiMethod) return false
if (m1.parameterList.parametersCount != m2.parameterList.parametersCount) return false
for (i in 0..(m1.parameterList.parametersCount - 1)) {
val p1 = m1.parameterList.parameters[i].type
val p2 = m2.parameterList.parameters[i].type
if (p1 != p2 && TypeConversionUtil.erasure(p1) != TypeConversionUtil.erasure(p2)) return false
}
return true
}
override fun capture(t: TypeMirror): TypeMirror? {
TODO()
}
}
private fun illegalArg(text: String? = null): Nothing {
val message = if (text != null) ": $text" else ""
throw IllegalArgumentException("Illegal argument" + message)
}
private fun assertKindNot(typeMirror: TypeMirror, vararg kinds: TypeKind): Unit {
if (typeMirror.kind in kinds) illegalArg("type must not be kind of " + kinds.joinToString { it.name } + ", got ${typeMirror.kind.name}")
}
private fun assertJeType(type: TypeMirror) {
if (type !is JeTypeMirror) {
illegalArg("Must be a subclass of JePsiType, got ${type::class.java.name}")
}
}
@@ -1,10 +0,0 @@
annotation class Anno
@Anno
class MyClass {
var myProperty: String = "A"
fun myFunction() = object : java.lang.Runnable {
override fun run() {}
}
}
@@ -1,13 +0,0 @@
annotation class Anno(val name: String = "Mary", val age: Int = 20)
@Anno("Tom", 10)
class A
@Anno(name = "Tom")
class B
@Anno(age = 10)
class C
@Anno
class D
@@ -1,8 +0,0 @@
package test
annotation class Anno
@Anno
class MyClass
interface MyInterface
@@ -1,10 +0,0 @@
annotation class Anno
@Anno
@Deprecated("")
class Depr
class NoDepr
@java.lang.Deprecated
class JavaDepr
@@ -1,25 +0,0 @@
annotation class Anno
@Anno
class A {
interface AA {
fun onClick(o: Any)
}
}
enum class B { RED }
interface C {
fun onClick()
}
interface D {
fun onClick()
fun onDoubleClick()
}
interface E : C
interface F : C {
fun onDoubleClick()
}
@@ -1,18 +0,0 @@
annotation class Anno
@Anno
open class Parent {
open fun a() {}
}
open class Child : Parent() {
override fun a() {}
fun a(name: String) {}
open fun b() = "A"
}
class ChildOfChild : Child() {
override fun a() {}
override fun b() = "B"
fun a(name: CharSequence) {}
}
@@ -1,14 +0,0 @@
annotation class Anno
@Anno
interface Intf {
fun a()
}
open class A {
open fun a() {}
}
class B : A(), Intf {
override fun a() {}
}
@@ -1,17 +0,0 @@
open class Base<T> {
@JvmField
val f: T = null!!
fun m(t: T): T = null!!
}
class Impl<T> : Base<T>() {
fun implM(t: T): T = null!!
}
annotation class Anno
@Anno
class Test {
val f = Impl<String>()
}
@@ -1,10 +0,0 @@
annotation class Anno
@Anno
interface Intf<T>
open class Base<T> : Intf<T> {
fun factory() = Base<CharSequence>()
}
class Impl : Base<String>()
@@ -1,12 +0,0 @@
// Some user annotation is required because annoations from kotlin.jvm are filtered out in kapt
annotation class Anno
@JvmSuppressWildcards
@Anno
class Test
@JvmSuppressWildcards(suppress = true)
class TestTrue
@JvmSuppressWildcards(suppress = false)
class TestFalse
@@ -1 +0,0 @@
class Test
@@ -1,3 +0,0 @@
class Test
annotation class Anno
@@ -1,7 +0,0 @@
package org.jetbrains.kotlin.annotation.processing.test.processor
enum class RGBColors { RED, GREEN, BLUE }
annotation class ColorsAnnotation(val colors: Array<RGBColors>)
@ColorsAnnotation(colors = arrayOf(RGBColors.BLUE, RGBColors.RED))
class Test
@@ -1,23 +0,0 @@
abstract class Base<A> {
fun baseF(): A = null!!
}
annotation class Anno
@Anno
class Test<T> : Base<Int>() {
fun a(): String = ""
fun b(i: String, b: CharSequence) {}
fun c(): Int = 5
fun d(): T = null!!
fun <D : Any> e(item: D): D = item
fun f(items: List<Map<String, Int>>, i: Int) {}
fun <D : String> g(item: D) {}
fun h(): Array<List<String>> = null!!
fun <T> i(): T where T : CharSequence, T : Appendable = null!!
}
class Test2<in A : List<String>, out B : List<String>> {
fun a(items: A) {}
fun b(): B = null!!
}
@@ -1,7 +0,0 @@
annotation class Anno
@Anno
class Test {
fun a(): Int = 5
fun b(): Unit {}
}
@@ -1,44 +0,0 @@
annotation class Anno
@Anno
class Test
@Anno
interface Intf
class Test2 {
@Anno
fun test2Fun() {}
}
class Test3 {
@Anno
class Test3Nested
@Anno
inner class Test3Inner
}
class Test4
class Test5 {
fun test5Fun() {}
}
annotation class Surprise
@Surprise
class Test6
class Test7 {
@Surprise
fun test7Fun(): String = "ABC"
}
class Test8 {
@Anno
fun test8Fun1() {}
@Anno
fun test8Fun2() {}
}
@@ -1,12 +0,0 @@
@java.lang.annotation.Inherited
annotation class Anno
@Anno
open class Base
class Impl : Base()
@Anno
interface Intf
class IntfImpl : Intf
@@ -1,9 +0,0 @@
@Repeatable
@java.lang.annotation.Inherited
annotation class Anno(val name: String)
@Anno("Mary")
open class Base
@Anno("Tom")
class Impl : Base()
@@ -1,25 +0,0 @@
annotation class Anno
@Anno
class AnnoAnnotated
class Test {
@kotlin.jvm.Transient
val f: String = ""
// explicitly
@org.jetbrains.annotations.NotNull
fun a() {}
@kotlin.jvm.Synchronized
fun b() {}
@kotlin.jvm.JvmOverloads
fun c(a: Int = 3, b: String = "") {}
@java.lang.Deprecated
fun d() {}
@kotlin.Deprecated("")
fun e() {}
}
@@ -1,12 +0,0 @@
annotation class Anno
interface Intf
@Anno
class Test {
fun a(map: Map<Int, Intf>) {}
fun b(map: MutableMap<Int, Intf>) {}
fun c(map: Map<Int, Test>) {}
fun d(map: MutableMap<Int, Test>) {}
}
@@ -1,7 +0,0 @@
import kotlin.reflect.KClass
annotation class Anno(val a: Anno2, val b: Array<Anno2>, val c: String, val d: KClass<*>, val e: Array<KClass<*>>)
annotation class Anno2(val name: String)
@Anno(a = Anno2("Tim"), b = arrayOf(Anno2("Kate"), Anno2("Mary")), c = "ABC", d = Anno2::class, e = arrayOf(Anno::class))
class Test
@@ -1,11 +0,0 @@
@Name("Mary")
@Age(18)
class Mary
@Name("Kate")
@Age(22)
class Kate
annotation class Name(val name: String)
annotation class Age(val age: Int)
@@ -1,10 +0,0 @@
annotation class Anno(val name: String)
@Anno("MyClassAnno")
class MyClass {
@Anno("myFuncAnno")
fun myFunc(): String = "Mary"
@field:Anno("myFieldAnno")
val myField: String = "Tom"
}
@@ -1,42 +0,0 @@
@Retention(AnnotationRetention.SOURCE)
annotation class Source1
@Retention(AnnotationRetention.SOURCE)
annotation class Source2
@Retention(AnnotationRetention.SOURCE)
annotation class Source3
@Retention(AnnotationRetention.SOURCE)
annotation class Source4
@Retention(AnnotationRetention.BINARY)
annotation class Binary
@Retention(AnnotationRetention.RUNTIME)
annotation class Runtime
@Source1
class Test
class Test2 {
@Source2
fun t() {}
}
class Test3 {
@field:Source3
val p: String = "A"
}
class Test4 {
fun t(@Source4 a: String) {}
}
class Test5 {
@Retention(AnnotationRetention.SOURCE)
annotation class Source5
@Source5
fun t() {}
}
@@ -1,4 +0,0 @@
@Anno
class MyClass
annotation class Anno
@@ -1,5 +0,0 @@
@Anno2
class MyClass
annotation class Anno
annotation class Anno2
@@ -1,2 +0,0 @@
@Suppress("Tom", "Mary")
class Test
@@ -1,8 +0,0 @@
annotation class Anno
@Anno
class A : B<Int>(), C<Int>
open class B<T>
interface C<T> {}
@@ -1,17 +0,0 @@
interface I<T>
abstract class A<T> : I<T>
annotation class Anno
@Anno
class B : A<String>()
class C<T : CharSequence> : A<T>()
interface I2<X>
open class B2<X>
class A2<T : CharSequence> : B2<T>(), I2<T>
interface I3<T>
class A3<T> : I3<List<T>>
@@ -1,15 +0,0 @@
// Same as withoutSource.kt
@Retention(AnnotationRetention.SOURCE)
annotation class SourceAnno
@Retention(AnnotationRetention.BINARY)
annotation class BinaryAnno
@Retention(AnnotationRetention.RUNTIME)
annotation class RuntimeAnno
@SourceAnno
@BinaryAnno
@RuntimeAnno
class Test
@@ -1,22 +0,0 @@
@kotlin.annotation.Retention
@java.lang.annotation.Retention
@kotlin.Metadata
public annotation class BinaryAnno
@kotlin.annotation.Retention
@java.lang.annotation.Retention
@kotlin.Metadata
public annotation class RuntimeAnno
@kotlin.annotation.Retention
@java.lang.annotation.Retention
@kotlin.Metadata
public annotation class SourceAnno
@RuntimeAnno
@kotlin.Metadata
@SourceAnno
@BinaryAnno
public final class Test {
public method <init>(): void
}
@@ -1,15 +0,0 @@
// Same as withSource.kt
@Retention(AnnotationRetention.SOURCE)
annotation class SourceAnno
@Retention(AnnotationRetention.BINARY)
annotation class BinaryAnno
@Retention(AnnotationRetention.RUNTIME)
annotation class RuntimeAnno
@SourceAnno
@BinaryAnno
@RuntimeAnno
class Test
@@ -1,21 +0,0 @@
@kotlin.annotation.Retention
@java.lang.annotation.Retention
@kotlin.Metadata
public annotation class BinaryAnno
@kotlin.annotation.Retention
@java.lang.annotation.Retention
@kotlin.Metadata
public annotation class RuntimeAnno
@kotlin.annotation.Retention
@java.lang.annotation.Retention
@kotlin.Metadata
public annotation class SourceAnno
@RuntimeAnno
@kotlin.Metadata
@BinaryAnno
public final class Test {
public method <init>(): void
}
@@ -1,9 +0,0 @@
annotation class Inject
class Test {
@Inject
fun myFunc(): String = "Mary"
@field:Inject
val myField: String = "Tom"
}
@@ -1,9 +0,0 @@
annotation class Inject
annotation class Inject2
@Inject2
class Test {
@Inject
@Inject2
fun myFunc(): String = "Mary"
}
@@ -1,4 +0,0 @@
annotation class Inject2
@Inject2
class Test
@@ -1,8 +0,0 @@
annotation class Inject
annotation class Inject2
@Inject
class Test {
@Inject
fun myFunc(): String = "Mary"
}
@@ -1 +0,0 @@
class Test
@@ -1,17 +0,0 @@
// FQNAME: EnumClass
// FILE: EnumClass.java
enum EnumClass {
RED, GREEN, BLUE;
void someMethod() {
System.out.println("Hello, world!")
}
String getStringRepresentation() {
return this.toString();
}
}
// FILE: Anno.kt
annotation class Anno
@@ -1,11 +0,0 @@
final enum EnumClass {
public static final EnumClass RED
public static final EnumClass GREEN
public static final EnumClass BLUE
void someMethod()
java.lang.String getStringRepresentation()
}
@@ -1,17 +0,0 @@
// FQNAME: MetaAnnotation
// FILE: MetaAnnotation.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Deprecated
@Target({ ElementType.CONSTRUCTOR, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface MetaAnnotation {
String strValue();
}
// FILE: Anno.kt
annotation class Anno
@@ -1,6 +0,0 @@
@java.lang.Deprecated
@java.lang.annotation.Target(value = { CONSTRUCTOR, FIELD })
@java.lang.annotation.Retention(value = RUNTIME)
public abstract @interface MetaAnnotation {
public abstract java.lang.String strValue()
}
@@ -1,36 +0,0 @@
// FQNAME: Simple
// FILE: Simple.java
@interface Anno {
String[] numbers();
}
@interface AnnoValue {
String[] value();
}
@KotlinAnnotation(a = "A", b = 5)
@Anno(numbers = { "five", "six" })
@AnnoValue({ "five", "six" })
public abstract class Simple {
@Anno(numbers = "seven")
@AnnoValue("seven")
final String field = "A";
abstract void voidMethod();
static {
System.out.println("A");
}
{
System.out.println("b");
}
protected String strMethod(int param) {
return "A";
}
}
// FILE: KotlinAnnotation.kt
annotation class KotlinAnnotation(val a: String, val b: Int)
@@ -1,18 +0,0 @@
@KotlinAnnotation(a = "A", b = 5)
@Anno(numbers = { "five", "six" })
@AnnoValue(value = { "five", "six" })
public abstract class Simple {
static {}
{}
@Anno(numbers = { "seven" })
@AnnoValue(value = { "seven" })
final java.lang.String field
abstract void voidMethod()
protected java.lang.String strMethod(int param)
public void <init>()
}
@@ -1,25 +0,0 @@
// FQNAME: WithNested
// FILE: WithNested.java
class WithNested {
void myClassFun() {}
static class NestedClass {
void nestedClassFun() {}
}
class InnerClass {
void innerClassFun() {}
class InnerInnerClass {
void innerInnerClassFun() {}
}
}
interface NestedInterface {
void nestedInterfaceFun() {}
}
}
// FILE: Anno.kt
annotation class Anno
@@ -1,27 +0,0 @@
class WithNested {
void myClassFun()
static class NestedClass {
void nestedClassFun()
void <init>()
}
class InnerClass {
void innerClassFun()
class InnerInnerClass {
void innerInnerClassFun()
void <init>(WithNested.InnerClass $instance)
}
void <init>(WithNested $instance)
}
static abstract interface NestedInterface {
public abstract void nestedInterfaceFun()
}
void <init>()
}
@@ -1,33 +0,0 @@
// FQNAME: test.Main
package test
import kotlin.reflect.KClass
@MainAnno("A", 5)
class Main {
@field:XAnno(color = Color.GREEN)
val x: String = ""
@get:YAnno(arrayOf<String>("Mary", "Tom"), intArrayOf(1, 3, 5), arrayOf<Color>(Color.GREEN, Color.RED))
val y: String = ""
@set:ZAnno(String::class, arrayOf(String::class, Long::class, Main::class))
var z: String = ""
// Property annotations are lost here (we don't create Elements (javac API) for the synthetic propertyName$annotations() methods)
@MainAnno("B", 6)
val zz: String = ""
}
enum class Color {
RED, GREEN, BLUE
}
annotation class MainAnno(val a: String, val b: Int)
annotation class XAnno(val color: Color)
annotation class YAnno(val names: Array<String>, val ints: IntArray, val colors: Array<Color>)
annotation class ZAnno(val clazz: KClass<*>, val classes: Array<KClass<*>>)
@@ -1,33 +0,0 @@
@test.MainAnno(a = "A", b = 5)
public final class Main {
@test.XAnno(color = GREEN)
@org.jetbrains.annotations.NotNull
private final java.lang.String x
@org.jetbrains.annotations.NotNull
private final java.lang.String y
@org.jetbrains.annotations.NotNull
private java.lang.String z
@org.jetbrains.annotations.NotNull
private final java.lang.String zz
@org.jetbrains.annotations.NotNull
public final java.lang.String getX()
@test.YAnno(names = { "Mary", "Tom" }, ints = { 1, 3, 5 }, colors = { GREEN, RED })
@org.jetbrains.annotations.NotNull
public final java.lang.String getY()
@org.jetbrains.annotations.NotNull
public final java.lang.String getZ()
@test.ZAnno(clazz = java.lang.String.class, classes = { java.lang.String.class, long.class, test.Main.class })
public final void setZ(java.lang.String p)
@org.jetbrains.annotations.NotNull
public final java.lang.String getZz()
public void <init>()
}
@@ -1,11 +0,0 @@
// FQNAME: EnumClass
enum class EnumClass {
RED, GREEN, BLUE;
fun someFun() {
System.out.println("Hello, world!")
}
fun stringRepresentation() = this.toString()
}
@@ -1,14 +0,0 @@
public enum EnumClass {
public static final EnumClass RED
public static final EnumClass GREEN
public static final EnumClass BLUE
public final void someFun()
@org.jetbrains.annotations.NotNull
public final java.lang.String stringRepresentation()
protected void <init>()
}
@@ -1,22 +0,0 @@
// FQNAME: Test
class Test {
@kotlin.jvm.Transient
val f: String = ""
// explicitly
@org.jetbrains.annotations.NotNull
fun a() {}
@kotlin.jvm.Synchronized
fun b() {}
@kotlin.jvm.JvmOverloads
fun c(a: Int = 3, b: String = "") {}
@java.lang.Deprecated
fun d() {}
@kotlin.Deprecated("")
fun e() {}
}
@@ -1,32 +0,0 @@
public final class Test {
@kotlin.jvm.Transient
@org.jetbrains.annotations.NotNull
private final transient java.lang.String f
@org.jetbrains.annotations.NotNull
public final java.lang.String getF()
@org.jetbrains.annotations.NotNull
@org.jetbrains.annotations.NotNull
public final void a()
@kotlin.jvm.Synchronized
public final synchronized void b()
@kotlin.jvm.JvmOverloads
public final void c(int a, java.lang.String b)
@kotlin.jvm.JvmOverloads
public final void c(int a)
@kotlin.jvm.JvmOverloads
public final void c()
@java.lang.Deprecated
public final void d()
@kotlin.Deprecated(message = "")
public final void e()
public void <init>()
}
@@ -1,7 +0,0 @@
// FQNAME: Anno
@Repeatable
@Deprecated("")
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.EXPRESSION)
annotation class Anno
@@ -1,9 +0,0 @@
@kotlin.annotation.Repeatable
@kotlin.Deprecated(message = "")
@kotlin.annotation.Retention(value = RUNTIME)
@kotlin.annotation.Target(allowedTargets = { CLASS, CONSTRUCTOR, EXPRESSION })
@java.lang.annotation.Retention(value = RUNTIME)
@java.lang.annotation.Target(value = { TYPE, CONSTRUCTOR })
public abstract @interface Anno {
}
@@ -1,30 +0,0 @@
// FQNAME: MyClass
class MyClass {
companion object {
val CONST = 2
}
fun myClassFun() {}
class NestedClass {
companion object A {
val CONSTA = 3
}
fun nestedClassFun() {}
class NestedNestedClass {
fun nestedNestedClassFun() {}
}
}
inner class InnerClass {
fun innerClassFun() {}
}
interface InnerInterface {
fun innerInterfaceFun()
fun innerInterfaceFunWithImpl() = 5
}
}
@@ -1,55 +0,0 @@
public final class MyClass {
private static final int CONST
public static final MyClass.Companion Companion
public final void myClassFun()
public void <init>()
public static final class Companion {
public final int getCONST()
private void <init>()
}
public static final class NestedClass {
private static final int CONSTA
public static final MyClass.NestedClass.A A
public final void nestedClassFun()
public void <init>()
public static final class A {
public final int getCONSTA()
private void <init>()
}
public static final class NestedNestedClass {
public final void nestedNestedClassFun()
public void <init>()
}
}
public final class InnerClass {
public final void innerClassFun()
public void <init>()
}
public static abstract interface InnerInterface {
public abstract void innerInterfaceFun()
public default int innerInterfaceFunWithImpl()
public static final class DefaultImpls {
public static int innerInterfaceFunWithImpl(MyClass.InnerInterface $this)
public void <init>()
}
}
}
@@ -1,9 +0,0 @@
// FQNAME: MyClass
@Retention(AnnotationRetention.SOURCE)
@Repeatable
annotation class Anno(val name: String)
@Anno("Mary")
@Anno("Tom")
class MyClass
@@ -1,5 +0,0 @@
@Anno(name = "Mary")
@Anno(name = "Tom")
public final class MyClass {
public void <init>()
}
@@ -1,10 +0,0 @@
// FQNAME: test.Simple
package test
abstract class Simple(private val prop: String) {
protected val anotherProp: Int = 5
abstract fun strFun(x: Long): String
fun voidFun() {}
}
@@ -1,14 +0,0 @@
public abstract class Simple {
private final int anotherProp
private final java.lang.String prop
protected final int getAnotherProp()
@org.jetbrains.annotations.NotNull
public abstract java.lang.String strFun(long x)
public final void voidFun()
public void <init>(java.lang.String prop)
}
@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="light-classes" />
<orderEntry type="module" module-name="frontend" />
<orderEntry type="library" name="kotlin-runtime" level="project" />
</component>
</module>
@@ -1,82 +0,0 @@
/*
* 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.java.model
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiModifierListOwner
import org.jetbrains.kotlin.java.model.elements.JeAnnotationMirror
import org.jetbrains.kotlin.java.model.internal.KotlinAnnotationProxyMaker
import org.jetbrains.kotlin.java.model.internal.getAnnotationsWithInherited
import javax.lang.model.element.AnnotationMirror
import javax.lang.model.element.Element
import java.lang.reflect.Array as RArray
interface JeAnnotationOwner : JeElement {
override val psi: PsiModifierListOwner
override fun getAnnotationMirrors() = psi.getAnnotationsWithInherited().map(::JeAnnotationMirror)
override fun <A : Annotation> getAnnotation(annotationClass: Class<A>): A? {
return getAnnotationsByType(annotationClass, onlyFirst = true).firstOrNull()
}
@Suppress("UNCHECKED_CAST")
override fun <A : Annotation> getAnnotationsByType(annotationClass: Class<A>): Array<A> {
val annotations = getAnnotationsByType(annotationClass, onlyFirst = false)
return (RArray.newInstance(annotationClass, annotations.size) as Array<A>).apply {
annotations.forEachIndexed { i, annotation -> RArray.set(this, i, annotation) }
}
}
private fun <A : Annotation> getAnnotationsByType(annotationClass: Class<A>, onlyFirst: Boolean): List<A> {
if (!annotationClass.isAnnotation) {
throw IllegalArgumentException("Not an annotation class: " + annotationClass)
}
val annotationFqName = annotationClass.canonicalName
val allAnnotations = psi.getAnnotationsWithInherited().filter { it.qualifiedName == annotationFqName }
if (allAnnotations.isEmpty()) return emptyList()
val annotations = if (onlyFirst) listOf(allAnnotations.first()) else allAnnotations
val annotationDeclarations = annotations.map { it to it.nameReferenceElement?.resolve() as? PsiClass }.filter { it.second != null }
@Suppress("UNCHECKED_CAST")
val annotationProxies = annotationDeclarations.map {
val (annotation, annotationDeclaration) = it
KotlinAnnotationProxyMaker(annotation, annotationDeclaration!!, annotationClass).generate() as? A
}
@Suppress("UNCHECKED_CAST")
return annotationProxies as List<A>
}
}
interface JeNoAnnotations : Element {
override fun getAnnotationMirrors() = emptyList<AnnotationMirror>()
override fun <A : Annotation> getAnnotation(annotationClass: Class<A>?): Nothing? {
return null
}
@Suppress("UNCHECKED_CAST")
override fun <A : Annotation?> getAnnotationsByType(annotationType: Class<A>): Array<A> {
return RArray.newInstance(annotationType, 0) as Array<A>
}
}
@@ -1,31 +0,0 @@
/*
* 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.java.model
import com.intellij.psi.*
import org.jetbrains.kotlin.java.model.elements.*
// to extension function?
fun PsiElement?.toJeElement(): JeElement? = when (this) {
null -> null
is PsiPackage -> JePackageElement(this)
is PsiClass -> JeTypeElement(this)
is PsiVariable -> JeVariableElement(this)
is PsiMethod -> JeMethodExecutableElement(this)
is PsiClassInitializer -> JeClassInitializerExecutableElement(this)
else -> null
}
@@ -1,52 +0,0 @@
/*
* 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.java.model
import com.intellij.openapi.Disposable
import com.intellij.openapi.components.ServiceManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.java.model.internal.JeElementRegistry
import org.jetbrains.kotlin.java.model.util.toDisposable
import javax.lang.model.element.Element
interface JePsiElementOwner {
val psi: PsiElement
}
interface JeElement : Element, JePsiElementOwner
abstract class JeDisposablePsiElementOwner<out T : PsiElement>(element: T) : JePsiElementOwner, Disposable {
private val disposablePsi = element.toDisposable()
init {
@Suppress("LeakingThis")
ServiceManager.getService(element.project, JeElementRegistry::class.java).register(this)
}
override fun dispose() {
disposablePsi.dispose()
}
override val psi: T
get() = disposablePsi()
val psiManager: PsiManager
get() = disposablePsi().manager
}
abstract class JeAbstractElement<out T : PsiElement>(element: T) : JeDisposablePsiElementOwner<T>(element), JeElement, Disposable
@@ -1,26 +0,0 @@
/*
* 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.java.model
import com.intellij.psi.PsiModifierListOwner
import org.jetbrains.kotlin.java.model.internal.getJavaModifiers
import javax.lang.model.element.Element
interface JeModifierListOwner : Element {
val psi: PsiModifierListOwner
override fun getModifiers() = psi.getJavaModifiers()
}
@@ -1,33 +0,0 @@
/*
* 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.java.model
import javax.lang.model.element.Name
fun JeName(name: String?) = name?.let(::JeName) ?: JeName.EMPTY
class JeName(val name: String) : Name, CharSequence by name {
override fun contentEquals(cs: CharSequence?) = cs?.toString() == name
override fun toString() = name
companion object {
val EMPTY = JeName("")
val INIT = JeName("<init>")
val CLINIT = JeName("<clinit>")
}
}
@@ -1,120 +0,0 @@
/*
* 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.java.model.elements
import org.jetbrains.kotlin.java.model.JeElement
import org.jetbrains.kotlin.java.model.types.*
import javax.lang.model.element.AnnotationMirror
import javax.lang.model.element.AnnotationValue
import javax.lang.model.element.Element
import javax.lang.model.element.ElementKind
import javax.lang.model.type.TypeMirror
class DefaultJeElementRenderer : JeElementRenderer {
override fun render(element: JeElement): String {
return when (element) {
is JePackageElement -> buildString {
appendln("package ${element.qualifiedName}").appendln()
element.enclosedElements.forEach { appendln(render(it).withMargin()).appendln() }
}
is JeTypeElement -> buildString {
val classType = when (element.kind) {
ElementKind.ANNOTATION_TYPE -> "@interface"
ElementKind.INTERFACE -> "interface"
ElementKind.ENUM -> "enum"
ElementKind.CLASS -> "class"
else -> throw IllegalStateException("Invalid class type: ${element.kind}")
}
appendln(renderModifiers(element) + classType + ' ' + element.simpleName + " {")
appendln(element.enclosedElements.joinToString(LINE_SEPARATOR.repeat(2)) { render(it).withMargin() })
append("}")
}
is JeVariableElement -> renderModifiers(element) + renderType(element.asType()) + " " + element.simpleName
is JeMethodExecutableElement -> buildString {
append(renderModifiers(element) + renderType(element.returnType, noneAsVoid = true) + " " + element.simpleName)
append(element.parameters.joinToString(prefix = "(", postfix = ")") { renderType(it.asType()) + " " + it.simpleName })
}
is JeClassInitializerExecutableElement -> renderModifiers(element) + "{}"
else -> throw IllegalArgumentException("Unsupported element: $element")
}
}
private fun renderType(type: TypeMirror, noneAsVoid: Boolean = false): String {
return when (type) {
is JeNullType -> "null"
is JeVoidType -> "void"
is JeErrorType -> "<ERROR>"
is JeNoneType -> if (noneAsVoid) "void" else throw IllegalArgumentException("Unexpected 'none' type")
is JePsiType -> type.psiType.getCanonicalText(false)
else -> throw IllegalArgumentException("Unsupported type: $type")
}
}
private fun renderModifiers(element: Element): String {
val renderedAnnotations = renderAnnotations(element)
val modifiers = element.modifiers
return if (modifiers.isEmpty())
renderedAnnotations
else
renderedAnnotations + modifiers.joinToString(" ", postfix = " ") { it.name.toLowerCase() }
}
private fun renderAnnotations(element: Element): String {
val annotations = element.annotationMirrors
if (annotations.isEmpty()) return ""
return annotations.joinToString(LINE_SEPARATOR, postfix = LINE_SEPARATOR) { renderAnnotation(it) }
}
private fun renderAnnotation(anno: AnnotationMirror): String {
val name = "@" + renderType(anno.annotationType)
val args = anno.elementValues
if (args.isEmpty()) return name
return name + args
.map { it.key.simpleName.toString() + " = " + renderAnnotationValue(it.value) }
.joinToString(prefix = "(", postfix = ")")
}
private fun renderAnnotationValue(av: AnnotationValue): String {
return when (av) {
is JeAnnotationAnnotationValue -> renderAnnotation(av.value)
is JeArrayAnnotationValue -> av.value.joinToString(prefix = "{ ", postfix = " }") { renderAnnotationValue(it) }
is JeSingletonArrayAnnotationValue -> av.value.joinToString(prefix = "{ ", postfix = " }") { renderAnnotationValue(it) }
is JeEnumValueAnnotationValue -> av.value.simpleName.toString()
is JeErrorAnnotationValue -> "<ERROR>"
is JeExpressionAnnotationValue, is JeLiteralAnnotationValue -> av.value?.let { renderConstantValue(it) } ?: "null"
is JeTypeAnnotationValue -> renderType(av.value) + ".class"
else -> throw IllegalArgumentException("Unsupported annotation value: $av")
}
}
private fun renderConstantValue(value: Any?): String {
return when (value) {
null -> "null"
is String -> "\"" + value.replace("\"", "\\\"") + "\""
else -> value.toString()
}
}
private fun String.withMargin() = lines().joinToString(LINE_SEPARATOR) { MARGIN + it }
private companion object {
val MARGIN = " "
val LINE_SEPARATOR: String = System.getProperty("line.separator")
}
}
@@ -1,63 +0,0 @@
/*
* 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.java.model.elements
import com.intellij.psi.*
import org.jetbrains.kotlin.java.model.JeDisposablePsiElementOwner
import org.jetbrains.kotlin.java.model.internal.getTypeWithTypeParameters
import org.jetbrains.kotlin.java.model.types.JeDeclaredErrorType
import org.jetbrains.kotlin.java.model.types.JeDeclaredType
import javax.lang.model.element.AnnotationMirror
import javax.lang.model.element.AnnotationValue
import javax.lang.model.element.ExecutableElement
import javax.lang.model.type.DeclaredType
class JeAnnotationMirror(psi: PsiAnnotation) : JeDisposablePsiElementOwner<PsiAnnotation>(psi), AnnotationMirror {
override fun getAnnotationType(): DeclaredType? {
val psiClass = resolveAnnotationClass() ?: return JeDeclaredErrorType
return JeDeclaredType(psiClass.getTypeWithTypeParameters(), psiClass)
}
override fun getElementValues(): Map<out ExecutableElement, AnnotationValue> = getElementValues(false)
fun getAllElementValues(): Map<out ExecutableElement, AnnotationValue> = getElementValues(true)
private fun getElementValues(withDefaults: Boolean): Map<out ExecutableElement, AnnotationValue> {
val annotationClass = resolveAnnotationClass() ?: return emptyMap()
return mutableMapOf<ExecutableElement, AnnotationValue>().apply {
for (method in annotationClass.methods) {
method as? PsiAnnotationMethod ?: continue
val returnType = method.returnType ?: continue
val attributeValue = psi.findDeclaredAttributeValue(method.name)
?: (if (withDefaults) method.defaultValue else null)
?: continue
val annotationValue = when {
returnType is PsiArrayType && attributeValue !is PsiArrayInitializerMemberValue ->
JeSingletonArrayAnnotationValue(attributeValue)
else -> JeAnnotationValue(attributeValue)
}
put(JeMethodExecutableElement(method), annotationValue)
}
}
}
private fun resolveAnnotationClass() = psi.nameReferenceElement?.resolve() as? PsiClass
}
@@ -1,106 +0,0 @@
/*
* 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.java.model.elements
import com.intellij.psi.*
import org.jetbrains.kotlin.java.model.JeDisposablePsiElementOwner
import org.jetbrains.kotlin.java.model.internal.calcConstantValue
import org.jetbrains.kotlin.java.model.types.toJeType
import java.util.*
import javax.lang.model.element.AnnotationValue
import javax.lang.model.element.AnnotationValueVisitor
fun JeAnnotationValue(psi: PsiAnnotationMemberValue): AnnotationValue {
val original = psi.originalElement
val annotationValue = when (original) {
is PsiLiteral -> JeLiteralAnnotationValue(original)
is PsiAnnotation -> JeAnnotationAnnotationValue(original)
is PsiArrayInitializerMemberValue -> JeArrayAnnotationValue(original)
is PsiClassObjectAccessExpression -> JeTypeAnnotationValue(original)
is PsiReferenceExpression -> {
val element = original.resolve()
if (element is PsiEnumConstant) {
JeEnumValueAnnotationValue(element)
}
else if (element is PsiField && element.hasInitializer()) {
JeAnnotationValue(element.initializer ?: error("Field should have an initializer"))
}
else {
JeErrorAnnotationValue(psi)
}
}
is PsiExpression -> JeExpressionAnnotationValue(original)
else -> throw AssertionError("Unsupported annotation element value: $psi (original = $original)")
}
return annotationValue
}
class JeAnnotationAnnotationValue(psi: PsiAnnotation) : JeDisposablePsiElementOwner<PsiAnnotation>(psi), AnnotationValue {
override fun getValue() = JeAnnotationMirror(psi)
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitAnnotation(value, p)
}
class JeEnumValueAnnotationValue(psi: PsiEnumConstant) : JeDisposablePsiElementOwner<PsiEnumConstant>(psi), AnnotationValue {
override fun getValue() = JeVariableElement(psi)
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitEnumConstant(value, p)
}
class JeTypeAnnotationValue(psi: PsiClassObjectAccessExpression) : JeDisposablePsiElementOwner<PsiClassObjectAccessExpression>(psi), AnnotationValue {
override fun getValue() = psi.operand.type.toJeType(psi.manager)
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitType(value, p)
}
abstract class JePrimitiveAnnotationValue<out T : PsiElement>(psi: T) : JeDisposablePsiElementOwner<T>(psi), AnnotationValue {
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P): R {
val value = this.value
return when (value) {
is String -> v.visitString(value, p)
is Int -> v.visitInt(value, p)
is Boolean -> v.visitBoolean(value, p)
is Char -> v.visitChar(value, p)
is Byte -> v.visitByte(value, p)
is Short -> v.visitShort(value, p)
is Long -> v.visitLong(value, p)
is Float -> v.visitFloat(value, p)
is Double -> v.visitDouble(value, p)
else -> throw AssertionError("Bad annotation element value: $value")
}
}
}
class JeLiteralAnnotationValue(psi: PsiLiteral) : JePrimitiveAnnotationValue<PsiLiteral>(psi) {
override fun getValue() = psi.value
}
class JeExpressionAnnotationValue(psi: PsiExpression) : JePrimitiveAnnotationValue<PsiExpression>(psi) {
override fun getValue() = psi.calcConstantValue()
}
class JeArrayAnnotationValue(psi: PsiArrayInitializerMemberValue) : JeDisposablePsiElementOwner<PsiArrayInitializerMemberValue>(psi), AnnotationValue {
override fun getValue() = psi.initializers.map(::JeAnnotationValue)
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitArray(value, p)
}
class JeSingletonArrayAnnotationValue(psi: PsiAnnotationMemberValue) : JeDisposablePsiElementOwner<PsiAnnotationMemberValue>(psi), AnnotationValue {
override fun getValue(): List<AnnotationValue> = Collections.singletonList(JeAnnotationValue(psi))
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitArray(value, p)
}
class JeErrorAnnotationValue(psi: PsiElement) : JeDisposablePsiElementOwner<PsiElement>(psi), AnnotationValue {
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitString(psi.text, p)
override fun getValue() = null
}
@@ -1,71 +0,0 @@
/*
* 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.java.model.elements
import com.intellij.psi.PsiClassInitializer
import org.jetbrains.kotlin.java.model.*
import org.jetbrains.kotlin.java.model.internal.isStatic
import org.jetbrains.kotlin.java.model.types.JeClassInitializerExecutableTypeMirror
import org.jetbrains.kotlin.java.model.types.JeNoneType
import javax.lang.model.element.*
import javax.lang.model.type.TypeMirror
class JeClassInitializerExecutableElement(
psi: PsiClassInitializer
) : JeAbstractElement<PsiClassInitializer>(psi), ExecutableElement, JeNoAnnotations, JeModifierListOwner {
val isStaticInitializer = psi.isStatic
override fun getEnclosingElement() = psi.containingClass?.let(::JeTypeElement)
override fun getSimpleName() = if (isStaticInitializer) JeName.CLINIT else JeName.EMPTY
override fun getThrownTypes() = emptyList<TypeMirror>()
override fun getTypeParameters() = emptyList<TypeParameterElement>()
override fun getParameters() = emptyList<VariableElement>()
override fun getDefaultValue() = null
override fun getReturnType() = JeNoneType
override fun getReceiverType() = JeNoneType
override fun isVarArgs() = false
override fun isDefault() = false
override fun getKind() = if (isStaticInitializer) ElementKind.STATIC_INIT else ElementKind.INSTANCE_INIT
override fun asType() = JeClassInitializerExecutableTypeMirror(psi)
override fun <R : Any?, P : Any?> accept(v: ElementVisitor<R, P>, p: P) = v.visitExecutable(this, p)
override fun getEnclosedElements() = emptyList<Element>()
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || other::class.java != this::class.java) return false
return psi == (other as JeClassInitializerExecutableElement).psi
}
override fun hashCode() = psi.hashCode()
override fun toString() = psi.containingClass?.qualifiedName
?.let { it + if (isStaticInitializer) ".<clinit>" else ".<instinit>" } ?: "<unnamed>"
}
@@ -1,23 +0,0 @@
/*
* 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.java.model.elements
import org.jetbrains.kotlin.java.model.JeElement
interface JeElementRenderer {
fun render(element: JeElement): String
}
@@ -1,97 +0,0 @@
/*
* 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.java.model.elements
import com.intellij.psi.*
import org.jetbrains.kotlin.java.model.*
import org.jetbrains.kotlin.java.model.internal.getTypeWithTypeParameters
import org.jetbrains.kotlin.java.model.internal.isStatic
import org.jetbrains.kotlin.java.model.types.JeMethodExecutableTypeMirror
import org.jetbrains.kotlin.java.model.types.JeNoneType
import org.jetbrains.kotlin.java.model.types.toJeType
import javax.lang.model.element.*
import javax.lang.model.type.TypeMirror
class JeMethodExecutableElement(psi: PsiMethod) : JeAbstractElement<PsiMethod>(psi), ExecutableElement, JeModifierListOwner, JeAnnotationOwner {
override fun getEnclosingElement() = psi.containingClass?.let(::JeTypeElement)
override fun getSimpleName(): JeName {
if (psi.isConstructor) return JeName.INIT
return JeName(psi.name)
}
override fun getThrownTypes() = psi.throwsList.referencedTypes.map { it.toJeType(psi.manager) }
override fun getTypeParameters() = psi.typeParameters.map { JeTypeParameterElement(it, this) }
override fun getParameters() = psi.parameterList.parameters.map(::JeVariableElement)
override fun getDefaultValue(): AnnotationValue? {
val annotationMethod = psi as? PsiAnnotationMethod ?: return null
val defaultValue = annotationMethod.defaultValue ?: return null
return JeAnnotationValue(defaultValue)
}
override fun getReturnType() = psi.returnType?.let { it.toJeType(psi.manager) } ?: JeNoneType
override fun getReceiverType() = psi.getReceiverTypeMirror()
override fun isVarArgs() = psi.isVarArgs
override fun isDefault() = psi.hasModifierProperty(PsiModifier.DEFAULT)
override fun getKind() = when {
psi.isConstructor -> ElementKind.CONSTRUCTOR
else -> ElementKind.METHOD
}
override fun asType() = JeMethodExecutableTypeMirror(psi)
override fun <R : Any?, P : Any?> accept(v: ElementVisitor<R, P>, p: P) = v.visitExecutable(this, p)
override fun getEnclosedElements() = emptyList<Element>()
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || other::class.java != this::class.java) return false
return psi == (other as JeMethodExecutableElement).psi
}
override fun hashCode() = psi.hashCode()
override fun toString() = psi.name
}
fun PsiMethod.getReceiverTypeMirror(): TypeMirror {
if (isStatic) return JeNoneType
if (isConstructor) {
val containingClass = containingClass
if (containingClass != null && !containingClass.isStatic) {
containingClass.containingClass?.let {
return it.getTypeWithTypeParameters().toJeType(manager)
}
}
return JeNoneType
}
val containingClass = containingClass ?: return JeNoneType
return containingClass.getTypeWithTypeParameters().toJeType(manager)
}
@@ -1,53 +0,0 @@
/*
* 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.java.model.elements
import com.intellij.psi.PsiPackage
import org.jetbrains.kotlin.java.model.*
import org.jetbrains.kotlin.java.model.types.JePackageTypeMirror
import javax.lang.model.element.ElementKind
import javax.lang.model.element.ElementVisitor
import javax.lang.model.element.PackageElement
class JePackageElement(psi: PsiPackage) : JeAbstractElement<PsiPackage>(psi), PackageElement, JeModifierListOwner, JeNoAnnotations {
override fun getEnclosingElement() = null
override fun getSimpleName() = JeName(psi.name)
override fun getKind() = ElementKind.PACKAGE
override fun <R : Any?, P : Any?> accept(v: ElementVisitor<R, P>, p: P) = v.visitPackage(this, p)
override fun isUnnamed() = psi.name.isNullOrEmpty()
override fun getQualifiedName() = JeName(psi.qualifiedName)
override fun getEnclosedElements() = psi.classes.map(::JeTypeElement)
override fun asType() = JePackageTypeMirror
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || other::class.java != this::class.java) return false
return psi == (other as JePackageElement).psi
}
override fun hashCode() = psi.hashCode()
override fun toString() = psi.qualifiedName
}
@@ -1,142 +0,0 @@
/*
* 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.java.model.elements
import com.intellij.psi.*
import com.intellij.psi.impl.source.PsiClassReferenceType
import com.intellij.psi.util.ClassUtil
import org.jetbrains.kotlin.asJava.elements.LightParameter
import org.jetbrains.kotlin.java.model.*
import org.jetbrains.kotlin.java.model.internal.DefaultConstructorPsiMethod
import org.jetbrains.kotlin.java.model.internal.getTypeWithTypeParameters
import org.jetbrains.kotlin.java.model.types.JeNoneType
import org.jetbrains.kotlin.java.model.types.toJeType
import javax.lang.model.element.*
import javax.lang.model.type.TypeMirror
class JeTypeElement(psi: PsiClass) : JeAbstractElement<PsiClass>(psi), TypeElement, JeAnnotationOwner, JeModifierListOwner {
override fun getEnclosingElement(): Element? {
psi.containingClass?.let { return JeTypeElement(it) }
val javaFile = psi.containingFile as? PsiJavaFile ?: return null
return JavaPsiFacade.getInstance(psi.project).findPackage(javaFile.packageName)?.let(::JePackageElement)
}
override fun getSimpleName() = JeName(psi.name)
override fun getQualifiedName() = JeName(psi.qualifiedName)
private fun getSuperType(superTypes: Array<PsiClassType>, superClass: PsiClass): PsiClassType {
return superTypes.firstOrNull { it is PsiClassReferenceType && it.resolve() == superClass }
?: superClass.getTypeWithTypeParameters()
}
override fun getSuperclass(): TypeMirror {
val superClass = psi.superClass ?: return JeNoneType
val psiType = getSuperType(psi.superTypes, superClass)
return psiType.toJeType(psi.manager)
}
override fun getInterfaces(): List<TypeMirror> {
val superTypes = psi.superTypes
val interfaces = mutableListOf<TypeMirror>()
for (intf in psi.interfaces) {
val psiType = getSuperType(superTypes, intf)
interfaces += psiType.toJeType(psi.manager)
}
return interfaces
}
override fun getTypeParameters() = psi.typeParameters.map { JeTypeParameterElement(it, this) }
override fun getNestingKind() = when {
ClassUtil.isTopLevelClass(psi) -> NestingKind.TOP_LEVEL
psi.parent is PsiClass -> NestingKind.MEMBER
psi is PsiAnonymousClass -> NestingKind.ANONYMOUS
else -> NestingKind.LOCAL
}
override fun getEnclosedElements(): List<JeElement> {
val declarations = mutableListOf<JeElement>()
psi.initializers.forEach { declarations += JeClassInitializerExecutableElement(it) }
psi.fields.forEach { declarations += JeVariableElement(it) }
psi.methods.forEach { declarations += JeMethodExecutableElement(it) }
psi.innerClasses.forEach { declarations += JeTypeElement(it) }
// Add default constructor if possible
if (!psi.isInterface && !psi.isAnnotationType && psi.constructors.isEmpty()) {
val superClass = psi.superClass
val canHaveDefaultConstructor = superClass == null || run {
val constructors = superClass.constructors
constructors.isEmpty() || constructors.any {
(it.hasModifierProperty(PsiModifier.PUBLIC) || it.hasModifierProperty(PsiModifier.PROTECTED) || run {
it.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) && psi.packageName == superClass.packageName
}) && it.parameterList.parametersCount == 0
}
}
if (canHaveDefaultConstructor) {
declarations += JeMethodExecutableElement(DefaultConstructorPsiMethod(psi, psi.language).apply {
val containingClass = psi.containingClass
if (containingClass != null && !psi.hasModifierProperty(PsiModifier.STATIC)) {
addParameter(LightParameter("\$instance", containingClass.getTypeWithTypeParameters(), this, psi.language))
}
})
}
}
return declarations
}
private val PsiClass.packageName: String
get() = (containingFile as? PsiJavaFile)?.packageName ?: ""
fun getAllMembers(): List<Element> {
val declarations = mutableListOf<Element>()
psi.allFields.forEach { declarations += JeVariableElement(it) }
psi.allMethods.forEach {
if (it.isConstructor && it.containingClass != this@JeTypeElement.psi) return@forEach
declarations += JeMethodExecutableElement(it)
}
psi.allInnerClasses.forEach { declarations += JeTypeElement(it) }
psi.initializers.forEach { declarations += JeClassInitializerExecutableElement(it) }
return declarations
}
override fun getKind() = when {
psi.isEnum -> ElementKind.ENUM
psi.isAnnotationType -> ElementKind.ANNOTATION_TYPE
psi.isInterface -> ElementKind.INTERFACE
else -> ElementKind.CLASS
}
override fun asType() = psi.getTypeWithTypeParameters().toJeType(psi.manager)
override fun <R : Any?, P : Any?> accept(v: ElementVisitor<R, P>, p: P) = v.visitType(this, p)
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || other::class.java != this::class.java) return false
return psi == (other as JeTypeElement).psi
}
override fun hashCode() = psi.hashCode()
override fun toString() = psi.qualifiedName ?: "<anonymous> extends " + psi.superClass?.qualifiedName ?: "<unnamed>"
}
@@ -1,58 +0,0 @@
/*
* 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.java.model.elements
import com.intellij.psi.PsiTypeParameter
import org.jetbrains.kotlin.java.model.*
import org.jetbrains.kotlin.java.model.internal.getTypeWithTypeParameters
import org.jetbrains.kotlin.java.model.types.toJeType
import javax.lang.model.element.Element
import javax.lang.model.element.ElementKind
import javax.lang.model.element.ElementVisitor
import javax.lang.model.element.TypeParameterElement
class JeTypeParameterElement(
psi: PsiTypeParameter,
val parent: JeElement?
) : JeAbstractElement<PsiTypeParameter>(psi), TypeParameterElement, JeAnnotationOwner, JeModifierListOwner {
override fun getSimpleName() = JeName(psi.name)
override fun getEnclosingElement() = parent
override fun getKind() = ElementKind.TYPE_PARAMETER
override fun asType() = psi.getTypeWithTypeParameters().toJeType(psi.manager)
override fun <R : Any?, P : Any?> accept(v: ElementVisitor<R, P>, p: P) = v.visitTypeParameter(this, p)
override fun getEnclosedElements() = emptyList<Element>()
override fun getBounds() = psi.superTypes.map { it.toJeType(psi.manager) }
override fun getGenericElement() = parent
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || other::class.java != this::class.java) return false
return psi == (other as JeTypeParameterElement).psi
}
override fun hashCode() = psi.hashCode()
override fun toString() = psi.name ?: "T"
}
@@ -1,67 +0,0 @@
/*
* 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.java.model.elements
import com.intellij.psi.*
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.java.model.*
import org.jetbrains.kotlin.java.model.internal.calcConstantValue
import org.jetbrains.kotlin.java.model.types.toJeType
import javax.lang.model.element.Element
import javax.lang.model.element.ElementKind
import javax.lang.model.element.ElementVisitor
import javax.lang.model.element.VariableElement
class JeVariableElement(psi: PsiVariable) : JeAbstractElement<PsiVariable>(psi), VariableElement, JeModifierListOwner, JeAnnotationOwner {
override fun getSimpleName() = JeName(psi.name)
override fun getEnclosingElement(): JeElement? {
val psi = psi
if (psi is PsiParameter) {
(psi.declarationScope as? PsiMethod)?.let { return JeMethodExecutableElement(it) }
}
val containingClass = (psi as? PsiMember)?.containingClass ?: PsiTreeUtil.getParentOfType(psi, PsiClass::class.java)
return containingClass?.let(::JeTypeElement)
}
override fun getConstantValue() = psi.initializer?.calcConstantValue()
override fun getKind() = when (psi) {
is PsiField -> ElementKind.FIELD
is PsiParameter -> ElementKind.PARAMETER
else -> ElementKind.LOCAL_VARIABLE
}
override fun asType() = psi.type.toJeType(psi.manager)
override fun <R : Any?, P : Any?> accept(v: ElementVisitor<R, P>, p: P) = v.visitVariable(this, p)
override fun getEnclosedElements() = emptyList<Element>()
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || other::class.java != this::class.java) return false
return psi == (other as JeVariableElement).psi
}
override fun hashCode() = psi.hashCode()
override fun toString() = psi.name ?: "<unnamed variable>"
}
@@ -1,54 +0,0 @@
/*
* 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.java.model.internal;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiType;
import sun.reflect.annotation.EnumConstantNotPresentExceptionProxy;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public final class AnnotationUtil {
public static final Map<PsiType, Class<?>> ARRAY_TYPES_MAP;
static {
Map<PsiType, Class<?>> classes = new HashMap<PsiType, Class<?>>();
classes.put(PsiType.BYTE, byte.class);
classes.put(PsiType.SHORT, short.class);
classes.put(PsiType.INT, int.class);
classes.put(PsiType.CHAR, char.class);
classes.put(PsiType.BOOLEAN, boolean.class);
classes.put(PsiType.LONG, long.class);
classes.put(PsiType.FLOAT, float.class);
classes.put(PsiType.DOUBLE, double.class);
ARRAY_TYPES_MAP = Collections.unmodifiableMap(classes);
}
public static Object createEnumValue(Class<?> enumClass, String name) {
try {
return Enum.valueOf((Class)enumClass, name);
} catch (IllegalArgumentException ex) {
//noinspection unchecked
return new EnumConstantNotPresentExceptionProxy((Class<Enum<?>>) enumClass, name);
}
}
}
@@ -1,38 +0,0 @@
/*
* 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.java.model.internal
import com.intellij.lang.Language
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiModifier.*
import com.intellij.psi.impl.light.LightMethodBuilder
internal class DefaultConstructorPsiMethod(
clazz: PsiClass,
language: Language
) : LightMethodBuilder(clazz, language) {
init {
val modifier = when {
clazz.hasModifierProperty(PUBLIC) -> PUBLIC
clazz.hasModifierProperty(PRIVATE) -> PRIVATE
clazz.hasModifierProperty(PROTECTED) -> PROTECTED
else -> PACKAGE_LOCAL
}
setModifiers(modifier)
isConstructor = true
}
}
@@ -1,42 +0,0 @@
/*
* 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.java.model.internal
import com.intellij.openapi.Disposable
/*
Some annotation processors (I'm looking at you, Data Binding)
have a habit to cache Element or TypeMirror instances into static fields.
Because almost every JeElement or JeTypeMirror is dependent on some PsiElement, and PsiElements are dependent on PsiProject,
the entire project will not be gc'ed normally.
JeElementRegistry allows us to remove all Psi*-references from our wrapper Element and TypeMirror instances.
So this class basically remembers all instances created by kapt, and disposes all of them as the Annotation Processing is complete.
*/
class JeElementRegistry : Disposable {
private val list = mutableListOf<Disposable>()
fun register(obj: Disposable) {
list += obj
}
override fun dispose() {
val list = this.list
list.forEach { it.dispose() }
this.list.clear()
}
}
@@ -1,211 +0,0 @@
/*
* 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.java.model.internal
import com.intellij.psi.*
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.kotlin.java.model.types.toJeType
import sun.reflect.annotation.AnnotationParser
import sun.reflect.annotation.ExceptionProxy
import java.io.ObjectInputStream
import java.lang.reflect.Array
import java.lang.reflect.Method
import java.util.*
import javax.lang.model.type.MirroredTypeException
import javax.lang.model.type.MirroredTypesException
import javax.lang.model.type.TypeMirror
class KotlinAnnotationProxyMaker(val annotation: PsiAnnotation, val annotationClass: PsiClass, val annotationType: Class<out Annotation>) {
fun generate(): Annotation {
return AnnotationParser.annotationForMap(annotationType, getAllValuesForParser(getAllPsiValues()))
}
private data class AnnotationParameterData(
val method: PsiAnnotationMethod,
val value: PsiAnnotationMemberValue,
val jMethod: Method)
private fun getAllPsiValues(): List<AnnotationParameterData> {
val values = mutableListOf<AnnotationParameterData>()
for (method in annotationClass.methods) {
if (method !is PsiAnnotationMethod) continue
if (method.returnType == null) continue
val jMethod = try { annotationType.getMethod(method.name) } catch (e : NoSuchMethodException) { continue }
val value = annotation.findAttributeValue(method.name) ?: method.defaultValue ?: continue
values += AnnotationParameterData(method, value, jMethod)
}
return values
}
private fun getAllValuesForParser(values: List<AnnotationParameterData>): Map<String, Any?> {
val parserValues = mutableMapOf<String, Any?>()
val evaluator = JavaPsiFacade.getInstance(annotation.project).constantEvaluationHelper
for ((method, value, jMethod) in values) {
val jReturnType = jMethod.returnType ?: unexpectedType("no return type for ${jMethod.name}")
parserValues.put(method.name, getConstantValue(value, method.returnType!!, jReturnType, evaluator))
}
return parserValues
}
}
private val JAVA_LANG_STRING = "java.lang.String"
private fun getConstantValue(
psiValue: PsiAnnotationMemberValue,
returnType: PsiType,
jReturnType: Class<*>,
evaluator: PsiConstantEvaluationHelper
): Any? {
val manager = psiValue.manager
when {
returnType == PsiType.NULL || returnType == PsiType.VOID -> unexpectedType("void")
returnType.fqName == JAVA_LANG_STRING -> return (psiValue as? PsiExpression)?.calcConstantValue(evaluator)
jReturnType.isAnnotation -> {
if (psiValue !is PsiAnnotation) error("psiValue is not a PsiAnnotation")
val annotationClass = PsiTypesUtil.getPsiClass(returnType) ?: error("Can't resolve type $returnType")
@Suppress("UNCHECKED_CAST")
val annotation = KotlinAnnotationProxyMaker(psiValue, annotationClass, jReturnType as Class<out Annotation>)
return jReturnType.cast(annotation.generate())
}
jReturnType.isArray -> {
val jComponentType = jReturnType.componentType ?: unexpectedType("no component type for $jReturnType")
if (returnType !is PsiArrayType) unexpectedType(returnType)
val arrayValues = when (psiValue) {
is PsiArrayInitializerMemberValue -> psiValue.initializers.toList()
else -> listOf(psiValue)
}
if (jComponentType.isPrimitive
|| jComponentType.isAnnotation
|| jComponentType.isEnum
|| jComponentType.canonicalName == JAVA_LANG_STRING
) {
val arr = Array.newInstance(jComponentType, arrayValues.size)
arrayValues.forEachIndexed { i, componentPsiValue ->
val componentValue = getConstantValue(componentPsiValue, returnType.componentType, jComponentType, evaluator)
try { Array.set(arr, i, componentValue) } catch (e: IllegalArgumentException) { return null }
}
return arr
} else {
val typeMirrors = arrayValues.map { getObjectType(it).toJeType(manager) }
return MirroredTypesExceptionProxy(Collections.unmodifiableList(typeMirrors))
}
}
jReturnType.isEnum -> {
val enumConstant = (psiValue.originalElement as? PsiReference)?.resolve() as? PsiEnumConstant
?: error("$psiValue can not be resolved to enum constant")
return AnnotationUtil.createEnumValue(jReturnType, enumConstant.name)
}
else -> return if (returnType is PsiClassType) {
val type = getObjectType(psiValue).toJeType(manager)
MirroredTypeExceptionProxy(type)
} else {
castPrimitiveValue(returnType, (psiValue as? PsiExpression)?.calcConstantValue(evaluator))
}
}
}
private val PsiType.fqName: String?
get() = (this as? PsiClassType)?.resolve()?.qualifiedName
private fun getObjectType(value: PsiAnnotationMemberValue): PsiType {
when (value) {
is PsiClassObjectAccessExpression -> return value.operand.type
is PsiReference -> {
val resolvedElement = value.resolve()
if (resolvedElement is PsiField && resolvedElement.isStatic && resolvedElement.isFinal) {
val initializer = resolvedElement.initializer
if (initializer != null) {
return getObjectType(initializer)
}
}
}
}
throw IllegalArgumentException("Illegal value type: ${value::class.java}")
}
private fun castPrimitiveValue(type: PsiType, value: Any?): Any = when (type) {
PsiType.BYTE -> byteValue(value)
PsiType.SHORT -> shortValue(value)
PsiType.INT -> intValue(value)
PsiType.CHAR -> charValue(value)
PsiType.BOOLEAN -> booleanValue(value)
PsiType.LONG -> longValue(value)
PsiType.FLOAT -> floatValue(value)
PsiType.DOUBLE -> doubleValue(value)
else -> unexpectedType(type)
}
private fun byteValue(value: Any?): Byte = (value as? Number)?.toByte() ?: 0
private fun intValue(value: Any?): Int = (value as? Number)?.toInt() ?: 0
private fun shortValue(value: Any?): Short = (value as? Number)?.toShort() ?: 0
private fun booleanValue(value: Any?): Boolean = value == true
private fun charValue(value: Any?): Char = value as? Char ?: 0.toChar()
private fun longValue(value: Any?): Long = (value as? Number)?.toLong() ?: 0
private fun floatValue(value: Any?): Float = (value as? Number)?.toFloat() ?: 0f
private fun doubleValue(value: Any?): Double = (value as? Number)?.toDouble() ?: 0.0
private fun unexpectedType(type: String): Nothing = error("Unexpected type: $type")
private fun unexpectedType(type: PsiType): Nothing = unexpectedType(type.presentableText)
private class MirroredTypeExceptionProxy(@Transient private var type: TypeMirror?) : ExceptionProxy() {
private val typeString = type.toString()
@Suppress("IMPLICIT_CAST_TO_ANY")
override fun hashCode() = (if (type != null) type else typeString)?.hashCode() ?: 0
override fun equals(other: Any?) = type != null && other is MirroredTypeExceptionProxy && type == other.type
override fun toString() = typeString
override fun generateException() = MirroredTypeException(type)
// Explicitly set all transient fields.
private fun readObject(s: ObjectInputStream) {
s.defaultReadObject()
type = null
}
companion object {
private const val serialVersionUID: Long = 269
}
}
private class MirroredTypesExceptionProxy(@Transient private var types: List<TypeMirror>?) : ExceptionProxy() {
private val typeStrings: String = types.toString()
@Suppress("IMPLICIT_CAST_TO_ANY")
override fun hashCode() = (if (types != null) types else typeStrings)?.hashCode() ?: 0
override fun equals(other: Any?) = types != null && other is MirroredTypesExceptionProxy && types == other.types
override fun toString() = typeStrings
override fun generateException() = MirroredTypesException(types)
// Explicitly set all transient fields.
private fun readObject(s: ObjectInputStream) {
s.defaultReadObject()
types = null
}
companion object {
private const val serialVersionUID: Long = 269
}
}
@@ -1,107 +0,0 @@
/*
* 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.java.model.internal
import com.intellij.psi.*
import com.intellij.psi.PsiModifier.*
import com.intellij.psi.impl.PsiSubstitutorImpl
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.kotlin.asJava.elements.KtLightAnnotationForSourceEntry
import javax.lang.model.element.Modifier
private val HAS_DEFAULT by lazy {
Modifier::class.java.declaredFields.any { it.name == "DEFAULT" }
}
private fun PsiModifierList.getJavaModifiers(): Set<Modifier> {
fun MutableSet<Modifier>.check(modifier: String, javaModifier: Modifier) {
if (hasModifierProperty(modifier)) this += javaModifier
}
return mutableSetOf<Modifier>().apply {
check(PUBLIC, Modifier.PUBLIC)
check(PROTECTED, Modifier.PROTECTED)
check(PRIVATE, Modifier.PRIVATE)
check(STATIC, Modifier.STATIC)
check(ABSTRACT, Modifier.ABSTRACT)
check(FINAL, Modifier.FINAL)
check(NATIVE, Modifier.NATIVE)
check(SYNCHRONIZED, Modifier.SYNCHRONIZED)
check(STRICTFP, Modifier.STRICTFP)
check(TRANSIENT, Modifier.TRANSIENT)
check(VOLATILE, Modifier.VOLATILE)
if (HAS_DEFAULT) {
check(DEFAULT, Modifier.DEFAULT)
}
}
}
internal fun PsiExpression.calcConstantValue(evaluator: PsiConstantEvaluationHelper? = null): Any? {
return when (this) {
is PsiLiteral -> value
is KtLightAnnotationForSourceEntry.LightExpressionValue<*> -> getConstantValue() ?: delegate.calcConstantValue(evaluator)
is PsiExpression -> (evaluator ?: getConstantEvaluator(this)).computeConstantExpression(this)
else -> null
}
}
private fun getConstantEvaluator(expression: PsiExpression) = JavaPsiFacade.getInstance(expression.project).constantEvaluationHelper
internal val PsiModifierListOwner.isStatic: Boolean
get() = hasModifierProperty(PsiModifier.STATIC)
internal val PsiModifierListOwner.isFinal: Boolean
get() = hasModifierProperty(PsiModifier.FINAL)
fun PsiModifierListOwner.getJavaModifiers() = modifierList?.getJavaModifiers() ?: emptySet()
fun PsiModifierListOwner.getAnnotationsWithInherited(): List<PsiAnnotation> {
val annotations = modifierList?.annotations?.filter { it.qualifiedName != null }?.toMutableList() ?: mutableListOf()
if (this is PsiClass) {
var superClass = superClass
while (superClass != null) {
superClass.modifierList?.annotations?.let { superClassAnnotations ->
for (annotation in superClassAnnotations) {
// Do not add the inherited annotation from the superclass
// if the current class has an annotation with the same qualified name
if (!annotation.isInherited()
|| annotations.any { it.qualifiedName == annotation.qualifiedName }) continue
annotations += annotation
}
}
superClass = superClass.superClass
}
}
return annotations
}
fun PsiClass.getTypeWithTypeParameters(): PsiClassType {
val elementFactory = JavaPsiFacade.getElementFactory(project)
val params = mutableMapOf<PsiTypeParameter, PsiType>()
typeParameters.forEach { params.put(it, PsiTypesUtil.getClassType(it)) }
return elementFactory.createType(this, PsiSubstitutorImpl.createSubstitutor(params))
}
private fun PsiAnnotation.isInherited(): Boolean {
val annotationClass = nameReferenceElement?.resolve() as? PsiClass ?: return false
val annotations = annotationClass.modifierList?.annotations ?: return false
return annotations.any { it.qualifiedName == "java.lang.annotation.Inherited" }
}
@@ -1,50 +0,0 @@
/*
* 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.java.model.types
import com.intellij.psi.PsiArrayType
import com.intellij.psi.PsiManager
import javax.lang.model.type.ArrayType
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeVisitor
class JeArrayType(
psiType: PsiArrayType,
psiManager: PsiManager,
private val isRaw: Boolean
) : JePsiTypeBase<PsiArrayType>(psiType, psiManager), ArrayType {
override fun getKind() = TypeKind.ARRAY
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitArray(this, p)
override fun getComponentType() = psiType.componentType.toJeType(psiManager, isRaw = isRaw)
override fun toString() = psiType.getCanonicalText(false)
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || other::class.java != this::class.java) return false
other as? JeArrayType ?: return false
return componentType == other.componentType
&& isRaw == other.isRaw
}
override fun hashCode(): Int {
var result = componentType.hashCode()
result = 31 * result + isRaw.hashCode()
return result
}
}
@@ -1,52 +0,0 @@
/*
* 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.java.model.types
import com.intellij.psi.PsiClassInitializer
import org.jetbrains.kotlin.java.model.JeDisposablePsiElementOwner
import org.jetbrains.kotlin.java.model.internal.isStatic
import javax.lang.model.type.*
class JeClassInitializerExecutableTypeMirror(
psi: PsiClassInitializer
) : JeDisposablePsiElementOwner<PsiClassInitializer>(psi), JeTypeMirror, JeTypeWithManager, ExecutableType {
override fun getKind() = TypeKind.EXECUTABLE
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitExecutable(this, p)
override fun getReturnType() = JeVoidType
override fun getReceiverType() = JeNoneType
override fun getThrownTypes() = emptyList<TypeMirror>()
override fun getParameterTypes() = emptyList<TypeMirror>()
override fun getTypeVariables() = emptyList<TypeVariable>()
override fun toString() = (psi.containingClass?.qualifiedName?.let { it + "." } ?: "") +
(if (psi.isStatic) "<clinit>" else "<instinit>")
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || other::class.java != this::class.java) return false
other as? JeClassInitializerExecutableTypeMirror ?: return false
return psi == other.psi
}
override fun hashCode() = psi.hashCode()
}

Some files were not shown because too many files have changed in this diff Show More