Kapt: Fixes on review

(cherry picked from commit be31262)
This commit is contained in:
Yan Zhulanow
2016-07-15 19:36:16 +03:00
committed by Yan Zhulanow
parent 5b8e6abdeb
commit f61367df28
28 changed files with 273 additions and 193 deletions
@@ -121,51 +121,59 @@ class AnnotationProcessingExtension(
}
}
internal class AnalysisContext(val annotationsMap: MutableMap<String, MutableList<PsiModifierListOwner>>)
private fun AnalysisContext.analyzeFiles(files: Collection<KtFile>) {
for (file in files) {
analyzeFile(file)
}
}
private fun AnalysisContext.analyzeFile(file: KtFile) {
val lightClass = file.findFacadeClass()
internal class AnalysisContext(annotationsMap: MutableMap<String, MutableList<PsiModifierListOwner>>) {
private val mutableAnnotationsMap = annotationsMap
if (lightClass != null) {
analyzeDeclaration(lightClass)
}
val annotationsMap: Map<String, List<PsiModifierListOwner>>
get() = mutableAnnotationsMap
for (declaration in file.declarations) {
if (declaration !is KtClassOrObject) continue
val clazz = declaration.toLightClass() ?: continue
analyzeDeclaration(clazz)
}
}
private fun AnalysisContext.analyzeFile(file: PsiJavaFile) {
file.classes.forEach { analyzeDeclaration(it) }
}
private fun AnalysisContext.analyzeDeclaration(declaration: PsiElement) {
if (declaration !is PsiModifierListOwner) return
val annotations = declaration.modifierList?.annotations
if (annotations != null) {
for (annotation in annotations) {
val fqName = annotation.qualifiedName ?: continue
annotationsMap.getOrPut(fqName, { mutableListOf() }).add(declaration)
fun analyzeFiles(files: Collection<KtFile>) {
for (file in files) {
analyzeFile(file)
}
}
if (declaration is PsiClass) {
declaration.methods.forEach { analyzeDeclaration(it) }
declaration.fields.forEach { analyzeDeclaration(it) }
declaration.innerClasses.forEach { analyzeDeclaration(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)
}
}
when (declaration) {
is KtClassOrObject -> declaration.declarations.forEach { analyzeDeclaration(it) }
fun analyzeFile(file: PsiJavaFile) {
file.classes.forEach { analyzeDeclaration(it) }
}
fun analyzeDeclaration(declaration: PsiElement) {
if (declaration !is PsiModifierListOwner) return
//TODO support inherited annotations
val annotations = declaration.modifierList?.annotations
if (annotations != null) {
for (annotation in annotations) {
val fqName = annotation.qualifiedName ?: continue
mutableAnnotationsMap.getOrPut(fqName, { mutableListOf() }).add(declaration)
}
}
if (declaration is PsiClass) {
declaration.methods.forEach { analyzeDeclaration(it) }
declaration.fields.forEach { analyzeDeclaration(it) }
declaration.innerClasses.forEach { analyzeDeclaration(it) }
}
if (declaration is PsiMethod) {
for (parameter in declaration.parameterList.parameters) {
analyzeDeclaration(parameter)
}
}
}
}
@@ -58,7 +58,7 @@ class AnnotationProcessingCommandLineProcessor : CommandLineProcessor {
override val pluginId: String = ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID
override val pluginOptions: Collection<CliOption> =
listOf(GENERATED_OUTPUT_DIR_OPTION, ANNOTATION_PROCESSOR_CLASSPATH_OPTION)
listOf(GENERATED_OUTPUT_DIR_OPTION, ANNOTATION_PROCESSOR_CLASSPATH_OPTION, CLASS_FILES_OUTPUT_DIR_OPTION)
override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) {
when (option) {
@@ -69,7 +69,8 @@ class KotlinElements(val javaPsiFacade: JavaPsiFacade, val scope: GlobalSearchSc
}
override fun getBinaryName(type: TypeElement) = JeName((type as JeTypeElement).psi.qualifiedName)
//TODO
override fun getDocComment(e: Element?) = ""
override fun isDeprecated(e: Element?): Boolean {
@@ -104,7 +105,7 @@ class KotlinElements(val javaPsiFacade: JavaPsiFacade, val scope: GlobalSearchSc
}
override fun getAllAnnotationMirrors(e: Element): List<AnnotationMirror> {
val annotations = (e as? JeElement)?.annotationMirrors?.toMutableList() ?: return emptyList()
val annotations = (e as? JeElement)?.annotationMirrors?.toMutableList() ?: mutableListOf()
if (e is JeTypeElement) {
var parent = e.psi.superClass
@@ -29,18 +29,7 @@ class KotlinFiler(val generatedSourceDir: File, val classesOutputDir: File) : Fi
val PACKAGE_INFO_SUFFIX = ".packageInfo"
}
private var dotGeneratedGenerated = false
private fun createDotGeneratedIfNeeded() {
if (!dotGeneratedGenerated) {
dotGeneratedGenerated = true
File(generatedSourceDir, ".generated").writeText("Generated by kapt2")
}
}
private fun getGeneratedFile(nameCharSequence: CharSequence, extension: String): File {
createDotGeneratedIfNeeded()
val name = nameCharSequence.toString()
val isPackageInfo = name.endsWith(PACKAGE_INFO_SUFFIX)
val fqName = if (isPackageInfo) name.substring(0, PACKAGE_INFO_SUFFIX.length) else name
@@ -59,7 +48,7 @@ class KotlinFiler(val generatedSourceDir: File, val classesOutputDir: File) : Fi
}
override fun getResource(location: JavaFileManager.Location, pkg: CharSequence, relativeName: CharSequence): FileObject? {
throw UnsupportedOperationException()
return KotlinFileObject(getResourceFile(location, pkg, relativeName))
}
override fun createResource(
@@ -68,18 +57,22 @@ class KotlinFiler(val generatedSourceDir: File, val classesOutputDir: File) : Fi
relativeName: CharSequence,
vararg originatingElements: Element?
): FileObject? {
val resourceFile = getResourceFile(location, pkg, relativeName)
resourceFile.parentFile.mkdirs()
return KotlinFileObject(resourceFile)
}
private fun getResourceFile(location: JavaFileManager.Location, pkg: CharSequence, relativeName: CharSequence): File {
val baseDir = when (location) {
StandardLocation.CLASS_OUTPUT -> classesOutputDir
StandardLocation.SOURCE_OUTPUT -> generatedSourceDir
else -> throw IllegalArgumentException("Location is not supported: $location (${location.name})")
}
val targetDir = File(baseDir, pkg.toString().replace('.', '/'))
targetDir.mkdirs()
val targetFile = File(targetDir, relativeName.toString())
return KotlinFileObject(targetFile)
return File(targetDir, relativeName.toString())
}
override fun createClassFile(name: CharSequence, vararg originatingElements: Element?): JavaFileObject {
@@ -49,9 +49,7 @@ abstract class KotlinAbstractFileObject(val file: File) : FileObject {
override fun openInputStream() = file.inputStream()
override fun getCharContent(ignoreEncodingErrors: Boolean): CharSequence? {
TODO()
}
override fun getCharContent(ignoreEncodingErrors: Boolean) = file.readText()
override fun getLastModified() = file.lastModified()
@@ -21,6 +21,7 @@ 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 : Messager {
override fun printMessage(kind: Diagnostic.Kind, msg: CharSequence) = printMessage(kind, msg, null)
@@ -32,6 +33,10 @@ class KotlinMessager : Messager {
}
override fun printMessage(kind: Diagnostic.Kind, msg: CharSequence, e: Element?, a: AnnotationMirror?, v: AnnotationValue?) {
println(msg)
val output = when (kind) {
Kind.ERROR, Kind.WARNING, Kind.MANDATORY_WARNING -> System.err
else -> System.out
}
output.println(msg)
}
}
@@ -33,7 +33,7 @@ class KotlinProcessingEnvironment(
override fun getTypeUtils() = types
override fun getMessager() = messager
override fun getLocale() = Locale.getDefault()
override fun getSourceVersion() = SourceVersion.RELEASE_6
override fun getSourceVersion() = SourceVersion.RELEASE_8
override fun getOptions() = options
override fun getFiler() = filer
}
@@ -17,7 +17,7 @@
package org.jetbrains.kotlin.annotation.processing.impl
import org.jetbrains.kotlin.annotation.AnalysisContext
import org.jetbrains.kotlin.java.model.JeConverter
import org.jetbrains.kotlin.java.model.toJeElement
import javax.annotation.processing.RoundEnvironment
import javax.lang.model.element.Element
import javax.lang.model.element.TypeElement
@@ -35,7 +35,7 @@ internal class KotlinRoundEnvironment(
val declarations = context.annotationsMap[fqName] ?: return emptySet()
return hashSetOf<Element>().apply {
for (declaration in declarations) {
JeConverter.convert(declaration)?.let { add(it) }
declaration.toJeElement()?.let { add(it) }
}
}
}
@@ -139,8 +139,12 @@ class KotlinTypes(val javaPsiFacade: JavaPsiFacade, val psiManager: PsiManager,
}
override fun isSameType(t1: TypeMirror, t2: TypeMirror) = t1 == t2
override fun getNoType(kind: TypeKind) = CustomJeNoneType(kind)
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
@@ -165,7 +169,7 @@ class KotlinTypes(val javaPsiFacade: JavaPsiFacade, val psiManager: PsiManager,
val psiType = createDeclaredType(psiClass, typeArgs) ?:
throw IllegalStateException("Can't create declared type ($psiClass, $typeArgs)")
return JeDeclaredType(psiType, psiClass, typeArgumentMirrors = typeArgMirrors.toList())
return JeDeclaredType(psiType, psiClass)
}
override fun getDeclaredType(
@@ -197,7 +201,7 @@ class KotlinTypes(val javaPsiFacade: JavaPsiFacade, val psiManager: PsiManager,
val psiType = createDeclaredType(psiClass, typeArgs) ?:
throw IllegalStateException("Can't create declared type ($psiClass, $typeArgs)")
return JeDeclaredType(psiType, psiClass, containing, typeArgMirrors.toList())
return JeDeclaredType(psiType, psiClass, containing)
}
override fun asMemberOf(containing: DeclaredType, element: Element): TypeMirror {
@@ -258,9 +262,9 @@ private fun illegalArg(text: String? = null): Nothing {
}
private fun assertKindNot(typeMirror: TypeMirror, vararg kinds: TypeKind): Unit {
if (typeMirror.kind in kinds) illegalArg("type must not be kind of " + typeMirror.kind.name + ", got ${typeMirror.kind}")
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) {
illegalArg("Must be a subclass of JePsiType, got ${type.javaClass.canonicalName}")
illegalArg("Must be a subclass of JePsiType, got ${type.javaClass.name}")
}
@@ -30,23 +30,40 @@ interface JeAnnotationOwner : Element {
override fun getAnnotationMirrors() = annotationOwner?.annotations?.map { JeAnnotationMirror(it) } ?: emptyList()
override fun <A : Annotation> getAnnotation(annotationClass: Class<A>): A? {
if (!annotationClass.isAnnotation) {
throw IllegalArgumentException("Not an annotation class: " + annotationClass)
}
val annotationFqName = annotationClass.canonicalName
val annotation = annotationOwner?.annotations
?.firstOrNull { it.qualifiedName == annotationFqName } ?: return null
val annotationDeclaration = annotation.nameReferenceElement?.resolve() as? PsiClass ?: return null
@Suppress("UNCHECKED_CAST")
return KotlinAnnotationProxyMaker(annotation, annotationDeclaration, annotationClass).generate() as? A
return getAnnotationsByType(annotationClass, onlyFirst = true).firstOrNull()
}
@Suppress("UNCHECKED_CAST")
override fun <A : Annotation?> getAnnotationsByType(annotationType: Class<A>): Array<A> {
return RArray.newInstance(annotationType, 0) as Array<A>
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 = annotationOwner?.annotations?.filter { it.qualifiedName == annotationFqName } ?: return emptyList()
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>
}
}
@@ -19,14 +19,13 @@ package org.jetbrains.kotlin.java.model
import com.intellij.psi.*
import org.jetbrains.kotlin.java.model.elements.*
object JeConverter {
fun convert(psi: PsiElement?): JeElement? = when (psi) {
null -> null
is PsiPackage -> JePackageElement(psi)
is PsiClass -> JeTypeElement(psi)
is PsiVariable -> JeVariableElement(psi)
is PsiMethod -> JeMethodExecutableElement(psi)
is PsiClassInitializer -> JeClassInitializerExecutableElement(psi)
else -> null
}
// 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
}
@@ -17,8 +17,8 @@
package org.jetbrains.kotlin.java.model.elements
import com.intellij.psi.PsiClassInitializer
import com.intellij.psi.PsiModifier
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.*
@@ -27,7 +27,7 @@ import javax.lang.model.type.TypeMirror
class JeClassInitializerExecutableElement(override val psi: PsiClassInitializer) : JeElement(),
ExecutableElement, JeNoAnnotations, JeModifierListOwner
{
val isStaticInitializer = psi.hasModifierProperty(PsiModifier.STATIC)
val isStaticInitializer = psi.isStatic
override fun getEnclosingElement() = psi.containingClass?.let { JeTypeElement(it) }
@@ -22,6 +22,7 @@ import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiModifier
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.kotlin.java.model.*
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
@@ -83,11 +84,11 @@ class JeMethodExecutableElement(override val psi: PsiMethod) : JeElement(), Exec
}
fun PsiMethod.getReceiverTypeMirror(): TypeMirror {
if (hasModifierProperty(PsiModifier.STATIC)) return JeNoneType
if (isStatic) return JeNoneType
if (isConstructor) {
val containingClass = containingClass
if (containingClass != null && !containingClass.hasModifierProperty(PsiModifier.STATIC)) {
if (containingClass != null && !containingClass.isStatic) {
containingClass.containingClass?.let {
return PsiTypesUtil.getClassType(it).toJeType(manager)
}
@@ -35,14 +35,15 @@ class JePackageElement(override val psi: PsiPackage) : JeElement(), PackageEleme
override fun <R : Any?, P : Any?> accept(v: ElementVisitor<R, P>, p: P) = v.visitPackage(this, p)
override fun isUnnamed() = false
override fun isUnnamed() = psi.name.isNullOrEmpty()
override fun getQualifiedName() = JeName(psi.qualifiedName)
override fun getEnclosedElements() = psi.classes.map { JeTypeElement(it) }
override fun asType() = JePackageTypeMirror
override fun equals(other: Any?): Boolean{
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
@@ -66,9 +66,13 @@ class JeTypeElement(override val psi: PsiClass) : JeElement(), TypeElement, JeAn
fun getAllMembers(): List<Element> {
val declarations = mutableListOf<Element>()
psi.constructors.forEach { declarations += JeMethodExecutableElement(it) }
psi.fields.forEach { declarations += JeVariableElement(it) }
psi.methods.forEach { declarations += JeMethodExecutableElement(it) }
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
}
@@ -92,5 +96,5 @@ class JeTypeElement(override val psi: PsiClass) : JeElement(), TypeElement, JeAn
override fun hashCode() = psi.hashCode()
override fun toString() = psi.qualifiedName ?: psi.superClass?.qualifiedName ?: "<unnamed>"
override fun toString() = psi.qualifiedName ?: "<anonymous> extends " + psi.superClass?.qualifiedName ?: "<unnamed>"
}
@@ -28,7 +28,11 @@ import javax.lang.model.element.VariableElement
class JeVariableElement(override val psi: PsiVariable) : JeElement(), VariableElement, JeModifierListOwner, JeAnnotationOwner {
override fun getSimpleName() = JeName(psi.name)
override fun getEnclosingElement(): JeTypeElement? {
override fun getEnclosingElement(): JeElement? {
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(it) }
}
@@ -50,6 +54,7 @@ class JeVariableElement(override val psi: PsiVariable) : JeElement(), VariableEl
override fun <R : Any?, P : Any?> accept(v: ElementVisitor<R, P>, p: P) = v.visitVariable(this, p)
override fun getEnclosedElements() = emptyList<Element>()
override val annotationOwner: PsiAnnotationOwner?
get() = psi.modifierList
@@ -62,5 +67,5 @@ class JeVariableElement(override val psi: PsiVariable) : JeElement(), VariableEl
override fun hashCode() = psi.hashCode()
override fun toString() = psi.name ?: "<unnamed>"
override fun toString() = psi.name ?: "<unnamed variable>"
}
@@ -30,24 +30,30 @@ 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(): Any {
fun generate(): Annotation {
return AnnotationParser.annotationForMap(annotationType, getAllValuesForParser(getAllPsiValues()))
}
private fun getAllPsiValues(): List<Triple<PsiAnnotationMethod, PsiAnnotationMemberValue, Method>> {
val values = mutableListOf<Triple<PsiAnnotationMethod, PsiAnnotationMemberValue, Method>>()
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) {
val jMethod = try { annotationType.getMethod(method.name) } catch (e : NoSuchMethodException) { continue }
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 += Triple(method, value, jMethod)
values += AnnotationParameterData(method, value, jMethod)
}
return values
}
private fun getAllValuesForParser(values: List<Triple<PsiAnnotationMethod, PsiAnnotationMemberValue, Method>>): Map<String, Any?> {
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) {
@@ -70,7 +76,7 @@ private fun getConstantValue(
returnType == PsiType.NULL || returnType == PsiType.VOID -> unexpectedType("void")
jReturnType == String::class.java -> return calculateConstantValue(psiValue, evaluator)
jReturnType == Class::class.java -> {
val type = (psiValue as PsiClassObjectAccessExpression).operand.type.toJeType(manager)
val type = getObjectType(psiValue).toJeType(manager)
return MirroredTypeExceptionProxy(type)
}
jReturnType.isArray -> {
@@ -83,7 +89,7 @@ private fun getConstantValue(
}
if (jComponentType == Class::class.java) {
val typeMirrors = arrayValues.map { (it as PsiClassObjectAccessExpression).operand.type.toJeType(manager) }
val typeMirrors = arrayValues.map { getObjectType(it).toJeType(manager) }
return MirroredTypesExceptionProxy(Collections.unmodifiableList(typeMirrors))
} else {
val arr = Array.newInstance(jComponentType, arrayValues.size)
@@ -103,7 +109,24 @@ private fun getConstantValue(
}
}
private fun castPrimitiveValue(type: PsiType, value: Any?): Any? = when (type) {
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.javaClass}")
}
private fun castPrimitiveValue(type: PsiType, value: Any?): Any = when (type) {
PsiType.BYTE -> byteValue(value)
PsiType.SHORT -> shortValue(value)
PsiType.INT -> intValue(value)
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.java.model.internal
import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiModifier.*
import com.intellij.psi.PsiModifierList
import com.intellij.psi.PsiModifierListOwner
@@ -49,4 +50,10 @@ private fun PsiModifierList.getJavaModifiers(): Set<Modifier> {
}
}
internal val PsiModifierListOwner.isStatic: Boolean
get() = hasModifierProperty(PsiModifier.STATIC)
internal val PsiModifierListOwner.isFinal: Boolean
get() = hasModifierProperty(PsiModifier.FINAL)
fun PsiModifierListOwner.getJavaModifiers() = modifierList?.getJavaModifiers() ?: emptySet()
@@ -27,19 +27,13 @@ class JeArrayType(override val psiType: PsiArrayType, override val psiManager: P
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitArray(this, p)
override fun getComponentType() = psiType.componentType.toJeType(psiManager)
override fun equals(other: Any?): Boolean {
override fun toString() = psiType.getCanonicalText(false)
override fun equals(other: Any?): Boolean{
if (this === other) return true
if (other?.javaClass != javaClass) return false
if (!super.equals(other)) return false
return psiType == (other as JeArrayType).psiType
return psiType == (other as? JeArrayType)?.psiType
}
override fun hashCode(): Int{
var result = super.hashCode()
result = 31 * result + psiType.hashCode()
return result
}
override fun toString() = psiType.getCanonicalText(false)
override fun hashCode() = psiType.hashCode()
}
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.java.model.types
import com.intellij.psi.PsiClassInitializer
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiModifier
import org.jetbrains.kotlin.java.model.internal.isStatic
import javax.lang.model.type.*
class JeClassInitializerExecutableTypeMirror(val initializer: PsiClassInitializer) : JeTypeMirror, JeTypeWithManager, ExecutableType {
@@ -29,7 +29,7 @@ class JeClassInitializerExecutableTypeMirror(val initializer: PsiClassInitialize
override val psiManager: PsiManager
get() = initializer.manager
override fun getReturnType() = CustomJeNoneType(TypeKind.VOID)
override fun getReturnType() = JeVoidType
override fun getReceiverType() = JeNoneType
@@ -40,7 +40,7 @@ class JeClassInitializerExecutableTypeMirror(val initializer: PsiClassInitialize
override fun getTypeVariables() = emptyList<TypeVariable>()
override fun toString() = (initializer.containingClass?.qualifiedName?.let { it + "." } ?: "") +
(if (initializer.hasModifierProperty(PsiModifier.STATIC)) "<clinit>" else "<init>")
(if (initializer.isStatic) "<clinit>" else "<instinit>")
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -17,45 +17,61 @@
package org.jetbrains.kotlin.java.model.types
import com.intellij.pom.java.LanguageLevel
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiClassType
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiType
import com.intellij.psi.*
import com.intellij.psi.impl.light.LightClassReferenceExpression
import com.intellij.psi.impl.source.PsiClassReferenceType
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.kotlin.java.model.elements.JeTypeElement
import org.jetbrains.kotlin.java.model.internal.isStatic
import javax.lang.model.type.DeclaredType
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeMirror
import javax.lang.model.type.TypeVisitor
fun createDeclaredType(psiClass: PsiClass, typeArgs: List<PsiType>): PsiClassReferenceType? {
val params = typeArgs.toTypedArray()
val text = (psiClass.name ?: return null) + typeArgs.joinToString(prefix = "<", postfix = ">")
val args = typeArgs.toTypedArray()
val text = (psiClass.name ?: return null) + typeArgs.joinToString(prefix = "<", postfix = ">") { it.canonicalText }
return PsiClassReferenceType(object : LightClassReferenceExpression(psiClass.manager, text, psiClass) {
override fun getTypeParameters() = params
override fun getTypeParameters() = args
}, LanguageLevel.JDK_1_8)
}
class JeDeclaredType(
override val psiType: PsiClassType,
override val psiType: PsiClassType,
val psiClass: PsiClass,
val enclosingDeclaredType: DeclaredType? = null,
val typeArgumentMirrors: List<TypeMirror>? = null
val enclosingDeclaredType: DeclaredType? = null
) : JePsiType(), JeTypeWithManager, DeclaredType {
override fun getKind() = TypeKind.DECLARED
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitDeclared(this, p)
override val psiManager: PsiManager
get() = psiClass.manager
override fun getTypeArguments() = typeArgumentMirrors ?: psiType.parameters.map { it.toJeType(psiManager) }
override fun getTypeArguments(): List<TypeMirror> {
if (psiType.isRaw) return emptyList()
return when (psiType) {
is PsiClassReferenceType -> {
val substitutor = psiType.resolveGenerics().substitutor
if (substitutor.isValid) {
substitutor.substitutionMap.map { it.value.toJeType(psiManager) }
}
else {
emptyList()
}
}
else -> emptyList()
}
}
override fun asElement() = JeTypeElement(psiClass)
override fun getEnclosingType(): TypeMirror {
if (!psiClass.isStatic) return JeNoneType
if (enclosingDeclaredType != null) return enclosingDeclaredType
val psiClass = psiClass.containingClass ?: return JeNoneType
return PsiTypesUtil.getClassType(psiClass).toJeType(psiManager)
}
@@ -63,16 +79,10 @@ class JeDeclaredType(
override fun equals(other: Any?): Boolean{
if (this === other) return true
if (other?.javaClass != javaClass) return false
if (!super.equals(other)) return false
return psiType == (other as JeDeclaredType).psiType
return psiType == (other as? JeDeclaredType)?.psiType
}
override fun hashCode(): Int {
var result = super.hashCode()
result = 31 * result + psiType.hashCode()
return result
}
override fun toString(): String = psiType.getCanonicalText(false)
override fun hashCode() = psiType.hashCode()
override fun toString() = psiType.getCanonicalText(false)
}
@@ -28,5 +28,14 @@ class JeIntersectionType(
) : JePsiType(), JeTypeWithManager, IntersectionType {
override fun getKind() = TypeKind.INTERSECTION
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitIntersection(this, p)
override fun getBounds() = psiType.superTypes.map { it.toJeType(psiManager) }
override fun equals(other: Any?): Boolean{
if (this === other) return true
if (other?.javaClass != javaClass) return false
return psiType == (other as? JeIntersectionType)?.psiType
}
override fun hashCode() = psiType.hashCode()
}
@@ -36,7 +36,7 @@ class JeMethodExecutableTypeMirror(
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitExecutable(this, p)
override fun getReturnType() = (returnType ?: psi.returnType)?.let { it.toJeType(psi.manager) } ?: CustomJeNoneType(TypeKind.VOID)
override fun getReturnType() = (returnType ?: psi.returnType)?.let { it.toJeType(psi.manager) } ?: JeVoidType
override fun getReceiverType() = psi.getReceiverTypeMirror()
@@ -40,17 +40,11 @@ class JePrimitiveType(override val psiType: PsiPrimitiveType) : JePsiType(), Pri
override fun toString() = psiType.canonicalText
override fun equals(other: Any?): Boolean {
override fun equals(other: Any?): Boolean{
if (this === other) return true
if (other?.javaClass != javaClass) return false
if (!super.equals(other)) return false
return psiType === (other as JePrimitiveType).psiType
return psiType == (other as? JePrimitiveType)?.psiType
}
override fun hashCode(): Int{
var result = super.hashCode()
result = 31 * result + psiType.hashCode()
return result
}
override fun hashCode() = psiType.hashCode()
}
@@ -20,22 +20,4 @@ import com.intellij.psi.PsiType
abstract class JePsiType : JeTypeMirror {
abstract val psiType: PsiType
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
other as JePsiType
if (kind != other.kind) return false
if (psiType != other.psiType) return false
return true
}
override fun hashCode(): Int{
var result = kind.hashCode()
result = 31 * result + psiType.hashCode()
return result
}
}
@@ -16,9 +16,9 @@
package org.jetbrains.kotlin.java.model.types
import org.jetbrains.kotlin.java.model.JeConverter
import org.jetbrains.kotlin.java.model.elements.JeTypeParameterElement
import com.intellij.psi.*
import org.jetbrains.kotlin.java.model.toJeElement
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeMirror
import javax.lang.model.type.TypeVariable
@@ -29,6 +29,7 @@ class JeTypeVariableType(
val parameter: PsiTypeParameter
) : JePsiType(), JeTypeWithManager, TypeVariable {
override fun getKind() = TypeKind.TYPEVAR
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitTypeVariable(this, p)
override val psiManager: PsiManager
@@ -48,5 +49,13 @@ class JeTypeVariableType(
}
}
override fun asElement() = JeTypeParameterElement(parameter, JeConverter.convert(parameter.owner))
override fun asElement() = JeTypeParameterElement(parameter, parameter.owner.toJeElement())
override fun equals(other: Any?): Boolean{
if (this === other) return true
if (other?.javaClass != javaClass) return false
return psiType == (other as? JeTypeVariableType)?.psiType
}
override fun hashCode() = psiType.hashCode()
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.java.model.types
import com.intellij.psi.PsiCapturedWildcardType
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiWildcardType
import javax.lang.model.type.TypeKind
@@ -32,17 +33,30 @@ class JeWildcardType(override val psiType: PsiWildcardType) : JePsiType(), JeTyp
override val psiManager: PsiManager
get() = psiType.manager
override fun equals(other: Any?): Boolean{
if (this === other) return true
if (other?.javaClass != javaClass) return false
return psiType == (other as? JeWildcardType)?.psiType
}
override fun hashCode() = psiType.hashCode()
}
class JeCapturedWildcardType(
override val psiType: PsiCapturedWildcardType,
override val psiManager: PsiManager
) : JePsiType(), JeTypeWithManager, WildcardType {
override fun getKind() = TypeKind.WILDCARD
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitWildcard(this, p)
override fun getSuperBound() = psiType.lowerBound.toJeType(psiManager)
override fun getExtendsBound() = psiType.upperBound.toJeType(psiManager)
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
if (!super.equals(other)) return false
return psiType == (other as JeWildcardType).psiType
return psiType == (other as? JeWildcardType)?.psiType
}
override fun hashCode(): Int {
var result = super.hashCode()
result = 31 * result + psiType.hashCode()
return result
}
override fun hashCode() = psiType.hashCode()
}
@@ -25,7 +25,8 @@ import java.lang.reflect.Array as RArray
private val PSI_PRIMITIVES_MAP = listOf(
PsiType.BYTE, PsiType.CHAR, PsiType.DOUBLE,
PsiType.FLOAT, PsiType.INT, PsiType.LONG,
PsiType.SHORT, PsiType.BOOLEAN).associate { it to JePrimitiveType(it) }
PsiType.SHORT, PsiType.BOOLEAN
).associate { it to JePrimitiveType(it) }
private val TYPE_KIND_TO_PSI_PRIMITIVE_MAP = mapOf(
TypeKind.BYTE to PsiType.BYTE,
@@ -47,6 +48,7 @@ fun PsiType.toJeType(manager: PsiManager): TypeMirror = when (this) {
is PsiPrimitiveType -> PSI_PRIMITIVES_MAP[this] ?: JeErrorType
is PsiArrayType -> JeArrayType(this, manager)
is PsiWildcardType -> JeWildcardType(this)
is PsiCapturedWildcardType -> JeCapturedWildcardType(this, manager)
is PsiClassType -> {
val resolvedClass = this.resolve()
when (resolvedClass) {