From cc12a6c228e127414a95752754004e537c3107b7 Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Tue, 21 Jun 2016 21:07:07 +0300 Subject: [PATCH] Kapt: Add APT wrappers for PSI elements (cherry picked from commit 1214513) --- .../java-model-wrappers.iml | 17 ++ .../kotlin/java/model/JeAnnotationOwner.kt | 60 ++++ .../kotlin/java/model/JeConverter.kt | 32 +++ .../jetbrains/kotlin/java/model/JeElement.kt | 24 ++ .../kotlin/java/model/JeModifierListOwner.kt | 26 ++ .../org/jetbrains/kotlin/java/model/JeName.kt | 33 +++ .../java/model/elements/JeAnnotationMirror.kt | 63 ++++ .../java/model/elements/JeAnnotationValue.kt | 92 ++++++ .../JeClassInitializerExecutableElement.kt | 71 +++++ .../elements/JeMethodExecutableElement.kt | 102 +++++++ .../java/model/elements/JePackageElement.kt | 55 ++++ .../java/model/elements/JeTypeElement.kt | 96 +++++++ .../model/elements/JeTypeParameterElement.kt | 65 +++++ .../java/model/elements/JeVariableElement.kt | 66 +++++ .../model/internal/annotationStubFactory.kt | 272 ++++++++++++++++++ .../java/model/internal/internalUtil.kt | 45 +++ .../kotlin/java/model/types/JeAbstractType.kt | 41 +++ .../kotlin/java/model/types/JeArrayType.kt | 44 +++ .../JeClassInitializerExecutableTypeMirror.kt | 48 ++++ .../model/types/JeCompoundDeclaredType.kt | 64 +++++ .../kotlin/java/model/types/JeDeclaredType.kt | 56 ++++ .../java/model/types/JeIntersectionType.kt | 28 ++ .../types/JeMethodExecutableTypeMirror.kt | 63 ++++ .../kotlin/java/model/types/JeNullType.kt | 29 ++ .../java/model/types/JePrimitiveType.kt | 56 ++++ .../kotlin/java/model/types/JeTypeBase.kt | 32 +++ .../java/model/types/JeTypeVariableType.kt | 46 +++ .../kotlin/java/model/types/JeWildcardType.kt | 50 ++++ .../kotlin/java/model/types/noTypes.kt | 53 ++++ .../kotlin/java/model/types/types.kt | 61 ++++ 30 files changed, 1790 insertions(+) create mode 100755 plugins/java-model-wrappers/java-model-wrappers.iml create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeAnnotationOwner.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeConverter.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeElement.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeModifierListOwner.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeName.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationMirror.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationValue.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeClassInitializerExecutableElement.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeMethodExecutableElement.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JePackageElement.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeTypeElement.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeTypeParameterElement.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeVariableElement.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/annotationStubFactory.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/internalUtil.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeAbstractType.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeArrayType.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeClassInitializerExecutableTypeMirror.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeCompoundDeclaredType.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeDeclaredType.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeIntersectionType.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeMethodExecutableTypeMirror.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeNullType.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JePrimitiveType.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeTypeBase.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeTypeVariableType.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeWildcardType.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/noTypes.kt create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/types.kt diff --git a/plugins/java-model-wrappers/java-model-wrappers.iml b/plugins/java-model-wrappers/java-model-wrappers.iml new file mode 100755 index 00000000000..3ebc8d39248 --- /dev/null +++ b/plugins/java-model-wrappers/java-model-wrappers.iml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeAnnotationOwner.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeAnnotationOwner.kt new file mode 100644 index 00000000000..7adb4e02233 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeAnnotationOwner.kt @@ -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 getAnnotation(annotationClass: Class): 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 getAnnotationsByType(annotationType: Class): Array { + return RArray.newInstance(annotationType, 0) as Array + } +} + +interface JeNoAnnotations : Element { + override fun getAnnotationMirrors() = emptyList() + + override fun getAnnotation(annotationClass: Class?): Nothing? { + return null + } + + @Suppress("UNCHECKED_CAST") + override fun getAnnotationsByType(annotationType: Class): Array { + return RArray.newInstance(annotationType, 0) as Array + } +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeConverter.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeConverter.kt new file mode 100644 index 00000000000..3f236dc54c8 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeConverter.kt @@ -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 + } +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeElement.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeElement.kt new file mode 100644 index 00000000000..8ddcbac797f --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeElement.kt @@ -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 +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeModifierListOwner.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeModifierListOwner.kt new file mode 100644 index 00000000000..22b24c52436 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeModifierListOwner.kt @@ -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() +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeName.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeName.kt new file mode 100644 index 00000000000..472675535cb --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeName.kt @@ -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("") + val CLINIT = JeName("") + } +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationMirror.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationMirror.kt new file mode 100644 index 00000000000..76c9b8f69cf --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationMirror.kt @@ -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 { + val annotationClass = resolveAnnotationClass() ?: return emptyMap() + + return mutableMapOf().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 { + val annotationClass = resolveAnnotationClass() ?: return emptyMap() + + return mutableMapOf().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 +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationValue.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationValue.kt new file mode 100644 index 00000000000..dd3e7d19d12 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationValue.kt @@ -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 accept(v: AnnotationValueVisitor, p: P) = v.visitAnnotation(value, p) +} + +private class JeEnumValueAnnotationValue(val psi: PsiEnumConstant) : AnnotationValue { + override fun getValue() = JeVariableElement(psi) + override fun accept(v: AnnotationValueVisitor, p: P) = v.visitEnumConstant(value, p) +} + +private class JeTypeAnnotationValue(val psi: PsiClassObjectAccessExpression) : AnnotationValue { + override fun getValue() = psi.operand.type.toJeType() + override fun accept(v: AnnotationValueVisitor, p: P) = v.visitType(value, p) +} + +private abstract class JePrimitiveAnnotationValue : AnnotationValue { + override fun accept(v: AnnotationValueVisitor, 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 accept(v: AnnotationValueVisitor, p: P) = v.visitArray(value, p) +} + +private class JeErrorAnnotationValue(val psi: PsiElement) : AnnotationValue { + override fun accept(v: AnnotationValueVisitor, p: P) = v.visitString(psi.text, p) + override fun getValue() = null +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeClassInitializerExecutableElement.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeClassInitializerExecutableElement.kt new file mode 100644 index 00000000000..720498b9899 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeClassInitializerExecutableElement.kt @@ -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() + + override fun getTypeParameters() = emptyList() + + override fun getParameters() = emptyList() + + 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 accept(v: ElementVisitor, p: P) = v.visitExecutable(this, p) + + override fun getEnclosedElements() = emptyList() + + 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) "." else "." } ?: "" +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeMethodExecutableElement.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeMethodExecutableElement.kt new file mode 100644 index 00000000000..ca6220d14e6 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeMethodExecutableElement.kt @@ -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 accept(v: ElementVisitor, p: P) = v.visitExecutable(this, p) + + override fun getEnclosedElements() = emptyList() + + 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() + +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JePackageElement.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JePackageElement.kt new file mode 100644 index 00000000000..31b79e09cf4 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JePackageElement.kt @@ -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 accept(v: ElementVisitor, 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 +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeTypeElement.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeTypeElement.kt new file mode 100644 index 00000000000..d03f1a867a0 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeTypeElement.kt @@ -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 { + val declarations = mutableListOf() + 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 { + val declarations = mutableListOf() + 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 accept(v: ElementVisitor, 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 ?: "" +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeTypeParameterElement.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeTypeParameterElement.kt new file mode 100644 index 00000000000..b4556b7805a --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeTypeParameterElement.kt @@ -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 accept(v: ElementVisitor, p: P) = v.visitTypeParameter(this, p) + + override fun getEnclosedElements() = emptyList() + + 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" +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeVariableElement.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeVariableElement.kt new file mode 100644 index 00000000000..8aa287b81e8 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeVariableElement.kt @@ -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 accept(v: ElementVisitor, p: P) = v.visitVariable(this, p) + + override fun getEnclosedElements() = emptyList() + 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 ?: "" +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/annotationStubFactory.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/annotationStubFactory.kt new file mode 100644 index 00000000000..e712b450525 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/annotationStubFactory.kt @@ -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, "", "()V", null, null)) { + visitCode() + visitVarInsn(ALOAD, 0) + visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()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?, + parent: ClassLoader?, + val extraClasses: MutableMap, + predefinedClasses: List> + ) : 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) \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/internalUtil.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/internalUtil.kt new file mode 100644 index 00000000000..42386072568 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/internalUtil.kt @@ -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 { + fun MutableSet.check(modifier: String, javaModifier: Modifier) { + if (hasModifierProperty(modifier)) this += javaModifier + } + + return mutableSetOf().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() \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeAbstractType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeAbstractType.kt new file mode 100644 index 00000000000..06d5d810dbf --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeAbstractType.kt @@ -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 + } +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeArrayType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeArrayType.kt new file mode 100644 index 00000000000..1b9fe40614c --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeArrayType.kt @@ -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 accept(v: TypeVisitor, 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) +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeClassInitializerExecutableTypeMirror.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeClassInitializerExecutableTypeMirror.kt new file mode 100644 index 00000000000..1be14a4b091 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeClassInitializerExecutableTypeMirror.kt @@ -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 accept(v: TypeVisitor, p: P) = v.visitExecutable(this, p) + + override fun getReturnType() = CustomJeNoneType(TypeKind.VOID) + + override fun getReceiverType() = JeNoneType + + override fun getThrownTypes() = emptyList() + + override fun getParameterTypes() = emptyList() + + override fun getTypeVariables() = emptyList() + + override fun toString() = (initializer.containingClass?.qualifiedName?.let { it + "." } ?: "") + + (if (initializer.hasModifierProperty(PsiModifier.STATIC)) "" else "") + + 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() +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeCompoundDeclaredType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeCompoundDeclaredType.kt new file mode 100644 index 00000000000..35ba98f5bdb --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeCompoundDeclaredType.kt @@ -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, + val typeArgMirrors: List +) : JeTypeBase(), DeclaredType { + override fun getKind() = TypeKind.DECLARED + override fun accept(v: TypeVisitor, 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 = ">") + } +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeDeclaredType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeDeclaredType.kt new file mode 100644 index 00000000000..41895661d01 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeDeclaredType.kt @@ -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 accept(v: TypeVisitor, 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) +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeIntersectionType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeIntersectionType.kt new file mode 100644 index 00000000000..bf4cc7270e2 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeIntersectionType.kt @@ -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 accept(v: TypeVisitor, p: P) = v.visitIntersection(this, p) + override fun getBounds() = psiType.superTypes.map { it.toJeType() } +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeMethodExecutableTypeMirror.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeMethodExecutableTypeMirror.kt new file mode 100644 index 00000000000..6e9c90a7fbb --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeMethodExecutableTypeMirror.kt @@ -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 accept(v: TypeVisitor, 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 { + signature?.parameterTypes?.let { types -> return types.map { it.toJeType() } } + return method.parameterList.parameters.map { it.type.toJeType() } + } + + override fun getTypeVariables(): List { + 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() +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeNullType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeNullType.kt new file mode 100644 index 00000000000..d1e7ccce2d7 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeNullType.kt @@ -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 accept(v: TypeVisitor, p: P) = v.visitNull(this, p) + override val psiType = PsiType.NULL + override fun toString() = "null" +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JePrimitiveType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JePrimitiveType.kt new file mode 100644 index 00000000000..c40d4d13a64 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JePrimitiveType.kt @@ -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 accept(v: TypeVisitor, 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 + } +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeTypeBase.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeTypeBase.kt new file mode 100644 index 00000000000..e9aa8fd2456 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeTypeBase.kt @@ -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() + + override fun getAnnotation(annotationClass: Class?) = null + + @Suppress("UNCHECKED_CAST") + override fun getAnnotationsByType(annotationType: Class): Array { + return java.lang.reflect.Array.newInstance(annotationType, 0) as Array + } +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeTypeVariableType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeTypeVariableType.kt new file mode 100644 index 00000000000..2a5e14a7b52 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeTypeVariableType.kt @@ -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 accept(v: TypeVisitor, 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)) +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeWildcardType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeWildcardType.kt new file mode 100644 index 00000000000..711197c2f97 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeWildcardType.kt @@ -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 accept(v: TypeVisitor, 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 accept(v: TypeVisitor, p: P) = v.visitWildcard(this, p) + override fun getSuperBound() = superType + override fun getExtendsBound() = extendsType +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/noTypes.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/noTypes.kt new file mode 100644 index 00000000000..f67227112ba --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/noTypes.kt @@ -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 accept(v: TypeVisitor, p: P) = v.visitNoType(this, p) +} + +object JeNoneType : JeTypeBase(), NoType { + override fun getKind() = TypeKind.NONE + override fun accept(v: TypeVisitor, p: P) = v.visitNoType(this, p) +} + +object JeVoidType : JeTypeBase(), NoType { + override fun getKind() = TypeKind.VOID + override fun accept(v: TypeVisitor, p: P) = v.visitNoType(this, p) +} + +class CustomJeNoneType(private val _kind: TypeKind) : JeTypeBase(), NoType { + override fun getKind() = _kind + override fun accept(v: TypeVisitor, p: P) = v.visitNoType(this, p) +} + +object JeErrorType : JeTypeBase(), NoType { + override fun getKind() = TypeKind.ERROR + override fun accept(v: TypeVisitor, p: P) = v.visitNoType(this, p) +} + +object JeDeclaredErrorType : JeTypeBase(), DeclaredType, NoType { + override fun getKind() = TypeKind.ERROR + override fun accept(v: TypeVisitor, p: P) = v.visitNoType(this, p) + + override fun getTypeArguments() = emptyList() + override fun asElement() = null + override fun getEnclosingType() = JeNoneType +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/types.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/types.kt new file mode 100644 index 00000000000..ace1e4ada1f --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/types.kt @@ -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 +} +