Kapt: Add APT wrappers for PSI elements

(cherry picked from commit 1214513)
This commit is contained in:
Yan Zhulanow
2016-06-21 21:07:07 +03:00
committed by Yan Zhulanow
parent 89c39b9762
commit cc12a6c228
30 changed files with 1790 additions and 0 deletions
+17
View File
@@ -0,0 +1,17 @@
<?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="library" name="intellij-core" level="project" />
<orderEntry type="library" name="asm" level="project" />
<orderEntry type="module" module-name="light-classes" />
<orderEntry type="module" module-name="frontend" />
<orderEntry type="module" module-name="annotation-processing" />
<orderEntry type="library" name="kotlin-runtime" level="project" />
</component>
</module>
@@ -0,0 +1,60 @@
/*
* 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.PsiAnnotationOwner
import com.intellij.psi.PsiClass
import org.jetbrains.kotlin.java.model.elements.JeAnnotationMirror
import org.jetbrains.kotlin.java.model.internal.createAnnotation
import javax.lang.model.element.AnnotationMirror
import javax.lang.model.element.Element
import java.lang.reflect.Array as RArray
interface JeAnnotationOwner : Element {
val annotationOwner: PsiAnnotationOwner?
override fun getAnnotationMirrors() = annotationOwner?.annotations?.map { JeAnnotationMirror(it) } ?: emptyList()
override fun <A : Annotation> getAnnotation(annotationClass: Class<A>): A? {
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 createAnnotation(annotation, annotationDeclaration, annotationClass) as? A
}
@Suppress("UNCHECKED_CAST")
override fun <A : Annotation?> getAnnotationsByType(annotationType: Class<A>): Array<A> {
return RArray.newInstance(annotationType, 0) as Array<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>
}
}
@@ -0,0 +1,32 @@
/*
* 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.*
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
}
}
@@ -0,0 +1,24 @@
/*
* 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.PsiElement
import javax.lang.model.element.Element
abstract class JeElement : Element {
abstract val psi: PsiElement
}
@@ -0,0 +1,26 @@
/*
* 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()
}
@@ -0,0 +1,33 @@
/*
* 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(it) } ?: 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>")
}
}
@@ -0,0 +1,63 @@
/*
* 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.PsiAnnotation
import com.intellij.psi.PsiAnnotationMethod
import com.intellij.psi.PsiClass
import com.intellij.psi.util.PsiTypesUtil
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(val psi: PsiAnnotation) : AnnotationMirror {
override fun getAnnotationType(): DeclaredType? {
val psiClass = resolveAnnotationClass() ?: return JeDeclaredErrorType
return JeDeclaredType(PsiTypesUtil.getClassType(psiClass), psiClass)
}
override fun getElementValues(): Map<out ExecutableElement, AnnotationValue> {
val annotationClass = resolveAnnotationClass() ?: return emptyMap()
return mutableMapOf<ExecutableElement, AnnotationValue>().apply {
for (attribute in psi.parameterList.attributes) {
val attributeValue = attribute.value ?: continue
val method = annotationClass.methods.firstOrNull {
it is PsiAnnotationMethod && it.name == attribute.name
} ?: return emptyMap()
put(JeMethodExecutableElement(method), JeAnnotationValue(attributeValue))
}
}
}
fun getAllElementValues(): Map<out ExecutableElement, AnnotationValue> {
val annotationClass = resolveAnnotationClass() ?: return emptyMap()
return mutableMapOf<ExecutableElement, AnnotationValue>().apply {
for (method in annotationClass.methods) {
method as? PsiAnnotationMethod ?: continue
val attributeValue = psi.findAttributeValue(method.name) ?: method.defaultValue ?: continue
put(JeMethodExecutableElement(method), JeAnnotationValue(attributeValue))
}
}
}
private fun resolveAnnotationClass() = psi.nameReferenceElement?.resolve() as? PsiClass
}
@@ -0,0 +1,92 @@
/*
* 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.types.toJeType
import javax.lang.model.element.AnnotationValue
import javax.lang.model.element.AnnotationValueVisitor
fun JeAnnotationValue(psi: PsiAnnotationMemberValue): AnnotationValue = when (psi) {
is PsiLiteral -> JeLiteralAnnotationValue(psi)
is PsiAnnotation -> JeAnnotationAnnotationValue(psi)
is PsiArrayInitializerMemberValue -> JeArrayAnnotationValue(psi)
is PsiClassObjectAccessExpression -> JeTypeAnnotationValue(psi)
is PsiReferenceExpression -> {
// TODO check static final field -> primitive, reference to enum value
val element = psi.resolve()
if (element is PsiEnumConstant) {
JeEnumValueAnnotationValue(element)
}
else {
JeErrorAnnotationValue(psi)
}
}
is PsiExpression -> JeExpressionAnnotationValue(psi)
else -> throw AssertionError("Unsupported annotation element value: $psi")
}
private class JeAnnotationAnnotationValue(val psi: PsiAnnotation) : AnnotationValue {
override fun getValue() = JeAnnotationMirror(psi)
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitAnnotation(value, p)
}
private class JeEnumValueAnnotationValue(val psi: PsiEnumConstant) : AnnotationValue {
override fun getValue() = JeVariableElement(psi)
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitEnumConstant(value, p)
}
private class JeTypeAnnotationValue(val psi: PsiClassObjectAccessExpression) : AnnotationValue {
override fun getValue() = psi.operand.type.toJeType()
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitType(value, p)
}
private abstract class JePrimitiveAnnotationValue : 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")
}
}
}
private class JeLiteralAnnotationValue(val psi: PsiLiteral) : JePrimitiveAnnotationValue() {
override fun getValue() = psi.value
}
private class JeExpressionAnnotationValue(val psi: PsiExpression) : JePrimitiveAnnotationValue() {
override fun getValue() = JavaPsiFacade.getInstance(psi.project).constantEvaluationHelper.computeConstantExpression(psi)
}
private class JeArrayAnnotationValue(val psi: PsiArrayInitializerMemberValue) : AnnotationValue {
override fun getValue() = psi.initializers.map { JeAnnotationValue(it) }
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitArray(value, p)
}
private class JeErrorAnnotationValue(val psi: PsiElement) : AnnotationValue {
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitString(psi.text, p)
override fun getValue() = null
}
@@ -0,0 +1,71 @@
/*
* 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 com.intellij.psi.PsiModifier
import org.jetbrains.kotlin.java.model.*
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(override val psi: PsiClassInitializer) : JeElement(),
ExecutableElement, JeNoAnnotations, JeModifierListOwner
{
val isStaticInitializer = psi.hasModifierProperty(PsiModifier.STATIC)
override fun getEnclosingElement() = psi.containingClass?.let { JeTypeElement(it) }
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?.javaClass != javaClass) 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>"
}
@@ -0,0 +1,102 @@
/*
* 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.PsiAnnotationMethod
import com.intellij.psi.PsiAnnotationOwner
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.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(override val psi: PsiMethod) : JeElement(), ExecutableElement, JeModifierListOwner, JeAnnotationOwner {
override fun getEnclosingElement() = psi.containingClass?.let { JeTypeElement(it) }
override fun getSimpleName(): JeName {
if (psi.isConstructor) return JeName.INIT
return JeName(psi.name)
}
override fun getThrownTypes() = psi.throwsList.referencedTypes.map { it.toJeType() }
override fun getTypeParameters() = psi.typeParameters.map { JeTypeParameterElement(it, this) }
override fun getParameters() = psi.parameterList.parameters.map { JeVariableElement(it) }
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() } ?: 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 val annotationOwner: PsiAnnotationOwner?
get() = psi.modifierList
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
return psi == (other as JeMethodExecutableElement).psi
}
override fun hashCode() = psi.hashCode()
override fun toString() = psi.name
}
fun PsiMethod.getReceiverTypeMirror(): TypeMirror {
if (hasModifierProperty(PsiModifier.STATIC)) return JeNoneType
if (isConstructor) {
val containingClass = containingClass
if (containingClass != null && !containingClass.hasModifierProperty(PsiModifier.STATIC)) {
containingClass.containingClass?.let {
return PsiTypesUtil.getClassType(it).toJeType()
}
}
return JeNoneType
}
val containingClass = containingClass ?: return JeNoneType
return PsiTypesUtil.getClassType(containingClass).toJeType()
}
@@ -0,0 +1,55 @@
/*
* 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.JeElement
import org.jetbrains.kotlin.java.model.JeModifierListOwner
import org.jetbrains.kotlin.java.model.JeName
import org.jetbrains.kotlin.java.model.JeNoAnnotations
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(override val psi: PsiPackage) : JeElement(), 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() = false
override fun getQualifiedName() = JeName(psi.qualifiedName)
override fun getEnclosedElements() = psi.classes.map { JeTypeElement(it) }
override fun asType() = JePackageTypeMirror
override fun equals(other: Any?): Boolean{
if (this === other) return true
if (other?.javaClass != javaClass) return false
return psi == (other as JePackageElement).psi
}
override fun hashCode() = psi.hashCode()
override fun toString() = psi.qualifiedName
}
@@ -0,0 +1,96 @@
/*
* 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.ClassUtil
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.kotlin.java.model.*
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(override val psi: PsiClass) : JeElement(), 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(it) }
}
override val annotationOwner: PsiAnnotationOwner?
get() = psi.modifierList
override fun getSimpleName() = JeName(psi.name)
override fun getQualifiedName() = JeName(psi.qualifiedName)
override fun getSuperclass(): TypeMirror {
val superClass = psi.superClass ?: return JeNoneType
return PsiTypesUtil.getClassType(superClass).toJeType()
}
override fun getInterfaces() = psi.interfaces.map { PsiTypesUtil.getClassType(it).toJeType() }
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<Element> {
val declarations = mutableListOf<Element>()
psi.initializers.forEach { declarations += JeClassInitializerExecutableElement(it) }
psi.fields.forEach { declarations += JeVariableElement(it) }
psi.methods.forEach { declarations += JeMethodExecutableElement(it) }
psi.innerClasses.forEach { declarations += JeTypeElement(it) }
return declarations
}
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) }
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() = PsiTypesUtil.getClassType(psi).toJeType()
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?.javaClass != javaClass) return false
return psi == (other as JeTypeElement).psi
}
override fun hashCode() = psi.hashCode()
override fun toString() = psi.qualifiedName ?: psi.superClass?.qualifiedName ?: "<unnamed>"
}
@@ -0,0 +1,65 @@
/*
* 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.PsiAnnotationOwner
import com.intellij.psi.PsiTypeParameter
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.kotlin.java.model.JeAnnotationOwner
import org.jetbrains.kotlin.java.model.JeElement
import org.jetbrains.kotlin.java.model.JeModifierListOwner
import org.jetbrains.kotlin.java.model.JeName
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(
override val psi: PsiTypeParameter,
val parent: JeElement?
) : JeElement(), TypeParameterElement, JeAnnotationOwner, JeModifierListOwner {
override fun getSimpleName() = JeName(psi.name)
override fun getEnclosingElement() = parent
override fun getKind() = ElementKind.TYPE_PARAMETER
override fun asType() = PsiTypesUtil.getClassType(psi).toJeType()
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() }
override fun getGenericElement() = parent
override val annotationOwner: PsiAnnotationOwner?
get() = psi.modifierList
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
return psi == (other as JeTypeParameterElement).psi
}
override fun hashCode() = psi.hashCode()
override fun toString() = psi.name ?: "T"
}
@@ -0,0 +1,66 @@
/*
* 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.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(override val psi: PsiVariable) : JeElement(), VariableElement, JeModifierListOwner, JeAnnotationOwner {
override fun getSimpleName() = JeName(psi.name)
override fun getEnclosingElement(): JeTypeElement? {
val containingClass = (psi as? PsiMember)?.containingClass ?: PsiTreeUtil.getParentOfType(psi, PsiClass::class.java)
return containingClass?.let { JeTypeElement(it) }
}
override fun getConstantValue(): Any? {
val initializer = psi.initializer ?: return null
val evaluationHelper = JavaPsiFacade.getInstance(psi.project).constantEvaluationHelper
return evaluationHelper.computeConstantExpression(initializer)
}
override fun getKind() = when (psi) {
is PsiField -> ElementKind.FIELD
is PsiParameter -> ElementKind.PARAMETER
else -> ElementKind.LOCAL_VARIABLE
}
override fun asType() = psi.type.toJeType()
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
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
return psi == (other as JeVariableElement).psi
}
override fun hashCode() = psi.hashCode()
override fun toString() = psi.name ?: "<unnamed>"
}
@@ -0,0 +1,272 @@
/*
* 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 org.jetbrains.kotlin.asJava.KtLightAnnotation
import org.jetbrains.org.objectweb.asm.ClassWriter
import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.net.URL
import java.net.URLClassLoader
internal fun createAnnotation(
annotation: PsiAnnotation,
annotationDeclaration: PsiClass,
annotationClass: Class<*>
): Annotation? {
val qualifiedName = annotationDeclaration.qualifiedName ?: return null
val implQualifiedName = "stub." + qualifiedName + ".Impl" + Integer.toHexString(annotation.text.hashCode())
val annotationInternalName = annotationDeclaration.getInternalName()
val implInternalName = implQualifiedName.replace('.', '/')
val bytes = createAnnotationImplementationClass(annotation, annotationDeclaration, annotationInternalName, implInternalName)
return loadClass(implQualifiedName, bytes, annotationClass)?.newInstance() as? Annotation
}
private fun createAnnotationImplementationClass(
annotation: PsiAnnotation,
annotationDeclaration: PsiClass,
annotationInternalName: String,
implInternalName: String
): ByteArray {
return ClassWriter(ClassWriter.COMPUTE_FRAMES or ClassWriter.COMPUTE_MAXS).apply {
visit(V1_6, ACC_SUPER or ACC_PUBLIC, implInternalName, null, "java/lang/Object", arrayOf(annotationInternalName))
with(visitMethod(ACC_PUBLIC, "<init>", "()V", null, null)) {
visitCode()
visitVarInsn(ALOAD, 0)
visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false)
visitInsn(RETURN)
visitMaxs(-1, -1)
visitEnd()
}
with(visitMethod(ACC_PUBLIC, "annotationType", "()Ljava/lang/Class;",
"()Ljava/lang/Class<+Ljava/lang/annotation/Annotation;>;", null)) {
visitCode()
visitLdcInsn(Type.getType("L$annotationInternalName;"))
visitInsn(ARETURN)
visitMaxs(-1, -1)
visitEnd()
}
if (annotationDeclaration.allMethods.isNotEmpty()) {
val evaluator = JavaPsiFacade.getInstance(annotation.project).constantEvaluationHelper
for (method in annotationDeclaration.methods) {
if (method !is PsiAnnotationMethod) continue
if (method.returnType == null) continue
val returnType = method.returnType!!
val value = annotation.findAttributeValue(method.name) ?: method.defaultValue
when (returnType) {
PsiType.VOID -> unexpectedType("void")
PsiType.NULL -> unexpectedType("null")
is PsiClassType -> {
val resolvedClass = returnType.resolve()
val resolvedQualifiedName = resolvedClass?.qualifiedName
if (resolvedQualifiedName == "java.lang.String") {
writeStringMethod(method, calculateConstantValue(value, evaluator))
}
else if (resolvedClass != null && resolvedClass.isEnum) {
writeEnumMethod(method, resolvedClass, value)
}
else {
unexpectedType("$resolvedQualifiedName")
}
}
is PsiPrimitiveType -> writeLiteralMethod(method, calculateConstantValue(value, evaluator))
is PsiArrayType -> writeArrayMethod(method, value, evaluator)
else -> unexpectedType(returnType)
}
}
}
visitEnd()
}.toByteArray()
}
private fun ClassWriter.writeEnumMethod(method: PsiAnnotationMethod, enumClass: PsiClass, value: PsiAnnotationMemberValue?) {
val enumInternalName = enumClass.getInternalName()
val enumConstant = (value?.originalElement as? PsiReference)?.resolve() as? PsiEnumConstant ?: return
val mv = visitMethod(ACC_PUBLIC, method.name, "()L$enumInternalName;", null, null)
with (InstructionAdapter(mv)) {
visitCode()
getstatic(enumInternalName, enumConstant.name!!, "L$enumInternalName;")
visitInsn(ARETURN)
visitMaxs(-1 ,-1)
visitEnd()
}
}
private fun ClassWriter.writeStringMethod(method: PsiAnnotationMethod, value: Any?) {
val stringValue = (value as? String) ?: null
val mv = visitMethod(ACC_PUBLIC, method.name, "()Ljava/lang/String;", null, null)
with (InstructionAdapter(mv)) {
visitCode()
if (stringValue != null) {
visitLdcInsn(stringValue)
} else {
visitInsn(ACONST_NULL)
}
visitInsn(ARETURN)
visitMaxs(-1 ,-1)
visitEnd()
}
}
private fun ClassWriter.writeArrayMethod(
method: PsiAnnotationMethod,
value: PsiAnnotationMemberValue?,
evaluator: PsiConstantEvaluationHelper
) {
val componentType = (method.returnType as? PsiArrayType)?.componentType ?: return
val componentAsmType = componentType.toAsmType() ?: return
val initializers = (value as? PsiArrayInitializerMemberValue)?.initializers ?: emptyArray()
val mv = visitMethod(ACC_PUBLIC, method.name, "()[" + componentAsmType.descriptor, null, null)
with (InstructionAdapter(mv)) {
visitCode()
iconst(initializers.size)
newarray(componentAsmType)
initializers.forEachIndexed { index, value ->
val valueObject = calculateConstantValue(value, evaluator)
dup()
iconst(index)
putValue(componentAsmType, valueObject)
astore(componentAsmType)
}
visitInsn(ARETURN)
visitMaxs(-1, -1)
visitEnd()
}
}
private fun calculateConstantValue(value: PsiAnnotationMemberValue?, evaluator: PsiConstantEvaluationHelper) = when (value) {
is PsiLiteral -> value.value
is KtLightAnnotation.LightExpressionValue<*> -> value.getConstantValue()
is PsiExpression -> evaluator.computeConstantExpression(value)
else -> null
}
private fun InstructionAdapter.putValue(type: Type, value: Any?) = when (type) {
Type.DOUBLE_TYPE -> dconst(doubleValue(value))
Type.FLOAT_TYPE -> fconst(floatValue(value))
Type.LONG_TYPE -> lconst(longValue(value))
Type.BYTE_TYPE, Type.SHORT_TYPE, Type.INT_TYPE, Type.CHAR_TYPE, Type.BOOLEAN_TYPE -> iconst(type.castValue(value))
else -> aconst(value)
}
private fun ClassWriter.writeLiteralMethod(method: PsiAnnotationMethod, value: Any?) {
val returnType = method.returnType ?: return
val asmType = returnType.toAsmType() ?: return
val mv = visitMethod(ACC_PUBLIC, method.name, "()" + asmType.descriptor, null, null)
with (InstructionAdapter(mv)) {
visitCode()
putValue(asmType, value)
areturn(asmType)
visitMaxs(-1, -1)
visitEnd()
}
}
private fun PsiType.toAsmType(): Type? = when (this) {
PsiType.BYTE -> Type.BYTE_TYPE
PsiType.SHORT -> Type.SHORT_TYPE
PsiType.INT -> Type.INT_TYPE
PsiType.CHAR -> Type.CHAR_TYPE
PsiType.BOOLEAN -> Type.BOOLEAN_TYPE
PsiType.LONG -> Type.LONG_TYPE
PsiType.FLOAT -> Type.FLOAT_TYPE
PsiType.DOUBLE -> Type.DOUBLE_TYPE
is PsiClassType -> resolve()?.let { Type.getObjectType(it.getInternalName()) }
else -> null
}
private fun Type.castValue(value: Any?): Int = when (this) {
Type.BYTE_TYPE -> byteValue(value)
Type.SHORT_TYPE -> shortValue(value)
Type.INT_TYPE -> intValue(value)
Type.CHAR_TYPE -> charValue(value)
Type.BOOLEAN_TYPE -> booleanValue(value)
else -> unexpectedType(this)
}
private fun PsiClass.getInternalName(): String {
val containingClass = this.containingClass
return if (containingClass != null) {
containingClass.getInternalName() + "$" + this.name
} else {
qualifiedName?.replace('.', '/') ?: error("Invalid class name ($this)")
}
}
private fun byteValue(value: Any?): Int = (value as? Number)?.toByte()?.toInt() ?: 0
private fun intValue(value: Any?): Int = (value as? Number)?.toInt() ?: 0
private fun shortValue(value: Any?): Int = (value as? Number)?.toShort()?.toInt() ?: 0
private fun booleanValue(value: Any?): Int = if (value == true) 1 else 0
private fun charValue(value: Any?): Int = (value as? Char)?.toInt() ?: 0.toChar().toInt()
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 loadClass(fqName: String, bytes: ByteArray, annotationClass: Class<*>): Class<*>? {
class ByteClassLoader(
urls: Array<out URL>?,
parent: ClassLoader?,
val extraClasses: MutableMap<String, ByteArray>,
predefinedClasses: List<Class<*>>
) : URLClassLoader(urls, parent) {
private val predefinedClasses = predefinedClasses.associateBy { it.canonicalName }
override fun findClass(name: String): Class<*>? {
return extraClasses.remove(name)?.let {
defineClass(name, it, 0, it.size)
} ?: predefinedClasses[name] ?: super.findClass(name)
}
}
val classLoader = ByteClassLoader(emptyArray(), annotationClass.classLoader, hashMapOf(fqName to bytes), listOf())
return Class.forName(fqName, false, classLoader)
}
private fun unexpectedType(type: String): Nothing = error("Unexpected type: $type")
private fun unexpectedType(type: PsiType): Nothing = unexpectedType(type.presentableText)
private fun unexpectedType(type: Type): Nothing = unexpectedType(type.descriptor)
@@ -0,0 +1,45 @@
/*
* 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.PsiModifier.*
import com.intellij.psi.PsiModifierList
import com.intellij.psi.PsiModifierListOwner
import javax.lang.model.element.Modifier
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)
check(DEFAULT, Modifier.DEFAULT)
}
}
fun PsiModifierListOwner.getJavaModifiers() = modifierList?.getJavaModifiers() ?: emptySet()
@@ -0,0 +1,41 @@
/*
* 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.PsiType
abstract class JeAbstractType : JeTypeBase() {
abstract val psiType: PsiType
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
other as JeAbstractType
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
}
}
@@ -0,0 +1,44 @@
/*
* 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 javax.lang.model.type.ArrayType
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeVisitor
class JeArrayType(override val psiType: PsiArrayType) : JeAbstractType(), 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()
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
}
override fun hashCode(): Int{
var result = super.hashCode()
result = 31 * result + psiType.hashCode()
return result
}
override fun toString() = psiType.getCanonicalText(false)
}
@@ -0,0 +1,48 @@
/*
* 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 com.intellij.psi.PsiModifier
import javax.lang.model.type.*
class JeClassInitializerExecutableTypeMirror(val initializer: PsiClassInitializer) : JeTypeBase(), 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() = CustomJeNoneType(TypeKind.VOID)
override fun getReceiverType() = JeNoneType
override fun getThrownTypes() = emptyList<TypeMirror>()
override fun getParameterTypes() = emptyList<TypeMirror>()
override fun getTypeVariables() = emptyList<TypeVariable>()
override fun toString() = (initializer.containingClass?.qualifiedName?.let { it + "." } ?: "") +
(if (initializer.hasModifierProperty(PsiModifier.STATIC)) "<clinit>" else "<init>")
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
return initializer == (other as JeClassInitializerExecutableTypeMirror).initializer
}
override fun hashCode() = initializer.hashCode()
}
@@ -0,0 +1,64 @@
/*
* 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.PsiClass
import com.intellij.psi.PsiType
import javax.lang.model.element.TypeElement
import javax.lang.model.type.DeclaredType
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeMirror
import javax.lang.model.type.TypeVisitor
class JeCompoundDeclaredType(
val psiClass: PsiClass,
val baseType: TypeElement,
val enclosingTypeMirror: TypeMirror?,
val typeArgs: List<PsiType>,
val typeArgMirrors: List<TypeMirror>
) : JeTypeBase(), DeclaredType {
override fun getKind() = TypeKind.DECLARED
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitDeclared(this, p)
override fun getTypeArguments() = typeArgMirrors
override fun asElement() = baseType
override fun getEnclosingType() = enclosingTypeMirror ?: JeNoneType
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
other as JeCompoundDeclaredType
if (baseType != other.baseType) return false
if (enclosingTypeMirror != other.enclosingTypeMirror) return false
if (typeArgs != other.typeArgs) return false
return true
}
override fun hashCode(): Int{
var result = baseType.hashCode()
result = 31 * result + (enclosingTypeMirror?.hashCode() ?: 0)
result = 31 * result + typeArgs.hashCode()
return result
}
override fun toString(): String {
return baseType.toString() + typeArgs.joinToString(prefix = "<", postfix = ">")
}
}
@@ -0,0 +1,56 @@
/*
* 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.PsiClass
import com.intellij.psi.PsiClassType
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.kotlin.java.model.elements.JeTypeElement
import javax.lang.model.type.DeclaredType
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeMirror
import javax.lang.model.type.TypeVisitor
class JeDeclaredType(override val psiType: PsiClassType, val psiClass: PsiClass) : JeAbstractType(), DeclaredType {
override fun getKind() = TypeKind.DECLARED
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitDeclared(this, p)
override fun getTypeArguments() = psiType.parameters.map { it.toJeType() }
override fun asElement() = JeTypeElement(psiClass)
override fun getEnclosingType(): TypeMirror {
val psiClass = psiClass.containingClass ?: return JeNoneType
return PsiTypesUtil.getClassType(psiClass).toJeType()
}
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
}
override fun hashCode(): Int {
var result = super.hashCode()
result = 31 * result + psiType.hashCode()
return result
}
override fun toString(): String = psiType.getCanonicalText(false)
}
@@ -0,0 +1,28 @@
/*
* 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.PsiIntersectionType
import javax.lang.model.type.IntersectionType
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeVisitor
class JeIntersectionType(override val psiType: PsiIntersectionType) : JeAbstractType(), 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() }
}
@@ -0,0 +1,63 @@
/*
* 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.PsiMethod
import com.intellij.psi.PsiType
import com.intellij.psi.util.MethodSignature
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.kotlin.java.model.elements.getReceiverTypeMirror
import javax.lang.model.type.ExecutableType
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeMirror
import javax.lang.model.type.TypeVisitor
class JeMethodExecutableTypeMirror(
val method: PsiMethod,
val signature: MethodSignature? = null,
val returnType: PsiType? = null
) : JeTypeBase(), 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() = (returnType ?: method.returnType)?.let { it.toJeType() } ?: CustomJeNoneType(TypeKind.VOID)
override fun getReceiverType() = method.getReceiverTypeMirror()
override fun getThrownTypes() = method.throwsList.referencedTypes.map { it.toJeType() }
override fun getParameterTypes(): List<TypeMirror> {
signature?.parameterTypes?.let { types -> return types.map { it.toJeType() } }
return method.parameterList.parameters.map { it.type.toJeType() }
}
override fun getTypeVariables(): List<JeTypeVariableType> {
val typeParameters = signature?.typeParameters ?: method.typeParameters
return typeParameters.map { JeTypeVariableType(PsiTypesUtil.getClassType(it), it) }
}
override fun toString() = (method.containingClass?.qualifiedName?.let { it + "." } ?: "") + method.name
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
return method == (other as JeMethodExecutableTypeMirror).method
}
override fun hashCode() = method.hashCode()
}
@@ -0,0 +1,29 @@
/*
* 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.PsiType
import javax.lang.model.type.NullType
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeVisitor
object JeNullType : JeAbstractType(), NullType {
override fun getKind() = TypeKind.NULL
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitNull(this, p)
override val psiType = PsiType.NULL
override fun toString() = "null"
}
@@ -0,0 +1,56 @@
/*
* 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.PsiPrimitiveType
import com.intellij.psi.PsiType
import javax.lang.model.type.PrimitiveType
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeVisitor
class JePrimitiveType(override val psiType: PsiPrimitiveType) : JeAbstractType(), PrimitiveType {
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitPrimitive(this, p)
override fun getKind() = when (psiType) {
PsiType.BYTE -> TypeKind.BYTE
PsiType.CHAR -> TypeKind.CHAR
PsiType.DOUBLE -> TypeKind.DOUBLE
PsiType.FLOAT -> TypeKind.FLOAT
PsiType.INT -> TypeKind.INT
PsiType.LONG -> TypeKind.LONG
PsiType.SHORT -> TypeKind.SHORT
PsiType.BOOLEAN -> TypeKind.BOOLEAN
PsiType.VOID -> TypeKind.VOID
else -> TypeKind.ERROR
}
override fun toString() = psiType.canonicalText
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
}
override fun hashCode(): Int{
var result = super.hashCode()
result = 31 * result + psiType.hashCode()
return result
}
}
@@ -0,0 +1,32 @@
/*
* 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 javax.lang.model.element.AnnotationMirror
import javax.lang.model.type.TypeMirror
//TODO support type annotations
abstract class JeTypeBase : TypeMirror {
override fun getAnnotationMirrors() = emptyList<AnnotationMirror>()
override fun <A : Annotation> getAnnotation(annotationClass: Class<A>?) = null
@Suppress("UNCHECKED_CAST")
override fun <A : Annotation?> getAnnotationsByType(annotationType: Class<A>): Array<A> {
return java.lang.reflect.Array.newInstance(annotationType, 0) as Array<A>
}
}
@@ -0,0 +1,46 @@
/*
* 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 org.jetbrains.kotlin.java.model.JeConverter
import org.jetbrains.kotlin.java.model.elements.JeTypeParameterElement
import com.intellij.psi.*
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeMirror
import javax.lang.model.type.TypeVariable
import javax.lang.model.type.TypeVisitor
class JeTypeVariableType(override val psiType: PsiClassType, val parameter: PsiTypeParameter) : JeAbstractType(), TypeVariable {
override fun getKind() = TypeKind.TYPEVAR
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitTypeVariable(this, p)
override fun getLowerBound(): TypeMirror? {
//TODO support captured lower bounds
return JeNullType
}
override fun getUpperBound(): TypeMirror? {
val superTypes = parameter.superTypes
return if (superTypes.size == 1) {
superTypes.first().toJeType(psiManager)
} else {
PsiIntersectionType.createIntersection(*superTypes).toJeType(psiManager)
}
}
override fun asElement() = JeTypeParameterElement(parameter, JeConverter.convert(parameter.owner))
}
@@ -0,0 +1,50 @@
/*
* 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.PsiWildcardType
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeMirror
import javax.lang.model.type.TypeVisitor
import javax.lang.model.type.WildcardType
class JeWildcardType(override val psiType: PsiWildcardType) : JeAbstractType(), 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.superBound.toJeType()
override fun getExtendsBound() = psiType.extendsBound.toJeType()
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
}
override fun hashCode(): Int {
var result = super.hashCode()
result = 31 * result + psiType.hashCode()
return result
}
}
class JeWildcardTypeWithBounds(private val extendsType: TypeMirror, private val superType: TypeMirror) : JeTypeBase(), 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() = superType
override fun getExtendsBound() = extendsType
}
@@ -0,0 +1,53 @@
/*
* 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 javax.lang.model.type.*
object JePackageTypeMirror : JeTypeBase(), NoType {
override fun getKind() = TypeKind.PACKAGE
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitNoType(this, p)
}
object JeNoneType : JeTypeBase(), NoType {
override fun getKind() = TypeKind.NONE
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitNoType(this, p)
}
object JeVoidType : JeTypeBase(), NoType {
override fun getKind() = TypeKind.VOID
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitNoType(this, p)
}
class CustomJeNoneType(private val _kind: TypeKind) : JeTypeBase(), NoType {
override fun getKind() = _kind
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitNoType(this, p)
}
object JeErrorType : JeTypeBase(), NoType {
override fun getKind() = TypeKind.ERROR
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitNoType(this, p)
}
object JeDeclaredErrorType : JeTypeBase(), DeclaredType, NoType {
override fun getKind() = TypeKind.ERROR
override fun <R : Any?, P : Any?> accept(v: TypeVisitor<R, P>, p: P) = v.visitNoType(this, p)
override fun getTypeArguments() = emptyList<TypeMirror>()
override fun asElement() = null
override fun getEnclosingType() = JeNoneType
}
@@ -0,0 +1,61 @@
/*
* 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.
*/
@file:JvmName("JeTypeUtils")
package org.jetbrains.kotlin.java.model.types
import com.intellij.psi.*
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeMirror
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) }
private val TYPE_KIND_TO_PSI_PRIMITIVE_MAP = mapOf(
TypeKind.BYTE to PsiType.BYTE,
TypeKind.CHAR to PsiType.CHAR,
TypeKind.DOUBLE to PsiType.DOUBLE,
TypeKind.FLOAT to PsiType.FLOAT,
TypeKind.INT to PsiType.INT,
TypeKind.LONG to PsiType.LONG,
TypeKind.SHORT to PsiType.SHORT,
TypeKind.BOOLEAN to PsiType.BOOLEAN)
fun TypeKind?.toJePrimitiveType() = PSI_PRIMITIVES_MAP[TYPE_KIND_TO_PSI_PRIMITIVE_MAP[this]]
fun PsiType.toJePrimitiveType() = PSI_PRIMITIVES_MAP[this]
fun PsiType.toJeType(): TypeMirror = when (this) {
PsiType.VOID -> JeVoidType
PsiType.NULL -> JeNullType
is PsiPrimitiveType -> PSI_PRIMITIVES_MAP[this] ?: JeErrorType
is PsiArrayType -> JeArrayType(this)
is PsiWildcardType -> JeWildcardType(this)
is PsiClassType -> {
val resolvedClass = this.resolve()
when (resolvedClass) {
is PsiTypeParameter -> JeTypeVariableType(this, resolvedClass)
is PsiClass -> JeDeclaredType(this, resolvedClass)
else -> JeErrorType
}
}
is PsiIntersectionType -> JeIntersectionType(this)
else -> JeErrorType
}