Kapt: add JeElementRenderer
(cherry picked from commit 3eecf78)
This commit is contained in:
committed by
Yan Zhulanow
parent
cd09f2bcb8
commit
0fc92c784b
+1
-1
@@ -71,7 +71,7 @@ class KotlinElements(val javaPsiFacade: JavaPsiFacade, val scope: GlobalSearchSc
|
|||||||
override fun getBinaryName(type: TypeElement) = JeName((type as JeTypeElement).psi.qualifiedName)
|
override fun getBinaryName(type: TypeElement) = JeName((type as JeTypeElement).psi.qualifiedName)
|
||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
override fun getDocComment(e: Element?) = ""
|
override fun getDocComment(e: Element?) = null
|
||||||
|
|
||||||
override fun isDeprecated(e: Element?): Boolean {
|
override fun isDeprecated(e: Element?): Boolean {
|
||||||
return (e as? JeAnnotationOwner)?.annotationOwner?.findAnnotation("java.lang.Deprecated") != null
|
return (e as? JeAnnotationOwner)?.annotationOwner?.findAnnotation("java.lang.Deprecated") != null
|
||||||
|
|||||||
+119
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.java.model.elements
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.java.model.JeElement
|
||||||
|
import org.jetbrains.kotlin.java.model.types.*
|
||||||
|
import javax.lang.model.element.AnnotationMirror
|
||||||
|
import javax.lang.model.element.AnnotationValue
|
||||||
|
import javax.lang.model.element.Element
|
||||||
|
import javax.lang.model.element.ElementKind
|
||||||
|
import javax.lang.model.type.TypeMirror
|
||||||
|
|
||||||
|
class DefaultJeElementRenderer : JeElementRenderer {
|
||||||
|
override fun render(element: JeElement): String {
|
||||||
|
return when (element) {
|
||||||
|
is JePackageElement -> buildString {
|
||||||
|
appendln("package ${element.qualifiedName}").appendln()
|
||||||
|
element.enclosedElements.forEach { appendln(render(it).withMargin()).appendln() }
|
||||||
|
}
|
||||||
|
is JeTypeElement -> buildString {
|
||||||
|
val classType = when (element.kind) {
|
||||||
|
ElementKind.ANNOTATION_TYPE -> "@interface"
|
||||||
|
ElementKind.INTERFACE -> "interface"
|
||||||
|
ElementKind.ENUM -> "enum"
|
||||||
|
ElementKind.CLASS -> "class"
|
||||||
|
else -> throw IllegalStateException("Invalid class type: ${element.kind}")
|
||||||
|
}
|
||||||
|
appendln(renderModifiers(element) + classType + ' ' + element.simpleName + " {")
|
||||||
|
appendln(element.enclosedElements.joinToString(LINE_SEPARATOR.repeat(2)) { render(it).withMargin() })
|
||||||
|
append("}")
|
||||||
|
}
|
||||||
|
is JeVariableElement -> renderModifiers(element) + renderType(element.asType()) + " " + element.simpleName
|
||||||
|
is JeMethodExecutableElement -> buildString {
|
||||||
|
append(renderModifiers(element) + renderType(element.returnType, noneAsVoid = true) + " " + element.simpleName)
|
||||||
|
append(element.parameters.joinToString(prefix = "(", postfix = ")") { renderType(it.asType()) + " " + it.simpleName })
|
||||||
|
}
|
||||||
|
is JeClassInitializerExecutableElement -> renderModifiers(element) + "{}"
|
||||||
|
else -> throw IllegalArgumentException("Unsupported element: $element")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderType(type: TypeMirror, noneAsVoid: Boolean = false): String {
|
||||||
|
return when (type) {
|
||||||
|
is JeNullType -> "null"
|
||||||
|
is JeVoidType -> "void"
|
||||||
|
is JeErrorType -> "<ERROR>"
|
||||||
|
is JeNoneType -> if (noneAsVoid) "void" else throw IllegalArgumentException("Unexpected 'none' type")
|
||||||
|
is JePsiType -> type.psiType.getCanonicalText(false)
|
||||||
|
else -> throw IllegalArgumentException("Unsupported type: $type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderModifiers(element: Element): String {
|
||||||
|
val renderedAnnotations = renderAnnotations(element)
|
||||||
|
val modifiers = element.modifiers
|
||||||
|
|
||||||
|
return if (modifiers.isEmpty())
|
||||||
|
renderedAnnotations
|
||||||
|
else
|
||||||
|
renderedAnnotations + modifiers.map { it.name.toLowerCase() }.joinToString(" ", postfix = " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderAnnotations(element: Element): String {
|
||||||
|
val annotations = element.annotationMirrors
|
||||||
|
if (annotations.isEmpty()) return ""
|
||||||
|
return annotations.joinToString(LINE_SEPARATOR, postfix = LINE_SEPARATOR) { renderAnnotation(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderAnnotation(anno: AnnotationMirror): String {
|
||||||
|
val name = "@" + renderType(anno.annotationType)
|
||||||
|
val args = anno.elementValues
|
||||||
|
if (args.isEmpty()) return name
|
||||||
|
|
||||||
|
return name + args
|
||||||
|
.map { it.key.simpleName.toString() + " = " + renderAnnotationValue(it.value) }
|
||||||
|
.joinToString(prefix = "(", postfix = ")")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderAnnotationValue(value: AnnotationValue): String {
|
||||||
|
return when (value) {
|
||||||
|
is JeAnnotationAnnotationValue -> renderAnnotation(value.value)
|
||||||
|
is JeArrayAnnotationValue -> value.value.joinToString(prefix = "{ ", postfix = " }") { renderAnnotationValue(it) }
|
||||||
|
is JeEnumValueAnnotationValue -> value.value.simpleName.toString()
|
||||||
|
is JeErrorAnnotationValue -> "<ERROR>"
|
||||||
|
is JeExpressionAnnotationValue, is JeLiteralAnnotationValue -> value.value?.let { renderConstantValue(it) } ?: "null"
|
||||||
|
is JeTypeAnnotationValue -> renderType(value.value) + ".class"
|
||||||
|
else -> throw IllegalArgumentException("Unsupported annotation value: $value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderConstantValue(value: Any?): String {
|
||||||
|
return when (value) {
|
||||||
|
null -> "null"
|
||||||
|
is String -> "\"" + value.replace("\"", "\\\"") + "\""
|
||||||
|
else -> value.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun String.withMargin() = lines().map { MARGIN + it }.joinToString(LINE_SEPARATOR)
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
val MARGIN = " "
|
||||||
|
val LINE_SEPARATOR: String = System.getProperty("line.separator")
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-8
@@ -40,22 +40,22 @@ fun JeAnnotationValue(psi: PsiAnnotationMemberValue): AnnotationValue = when (ps
|
|||||||
else -> throw AssertionError("Unsupported annotation element value: $psi")
|
else -> throw AssertionError("Unsupported annotation element value: $psi")
|
||||||
}
|
}
|
||||||
|
|
||||||
private class JeAnnotationAnnotationValue(val psi: PsiAnnotation) : AnnotationValue {
|
internal class JeAnnotationAnnotationValue(val psi: PsiAnnotation) : AnnotationValue {
|
||||||
override fun getValue() = JeAnnotationMirror(psi)
|
override fun getValue() = JeAnnotationMirror(psi)
|
||||||
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitAnnotation(value, p)
|
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitAnnotation(value, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class JeEnumValueAnnotationValue(val psi: PsiEnumConstant) : AnnotationValue {
|
internal class JeEnumValueAnnotationValue(val psi: PsiEnumConstant) : AnnotationValue {
|
||||||
override fun getValue() = JeVariableElement(psi)
|
override fun getValue() = JeVariableElement(psi)
|
||||||
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitEnumConstant(value, p)
|
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitEnumConstant(value, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class JeTypeAnnotationValue(val psi: PsiClassObjectAccessExpression) : AnnotationValue {
|
internal class JeTypeAnnotationValue(val psi: PsiClassObjectAccessExpression) : AnnotationValue {
|
||||||
override fun getValue() = psi.operand.type.toJeType(psi.manager)
|
override fun getValue() = psi.operand.type.toJeType(psi.manager)
|
||||||
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitType(value, p)
|
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitType(value, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class JePrimitiveAnnotationValue : AnnotationValue {
|
internal abstract class JePrimitiveAnnotationValue : AnnotationValue {
|
||||||
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P): R {
|
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P): R {
|
||||||
val value = this.value
|
val value = this.value
|
||||||
return when (value) {
|
return when (value) {
|
||||||
@@ -73,20 +73,20 @@ private abstract class JePrimitiveAnnotationValue : AnnotationValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class JeLiteralAnnotationValue(val psi: PsiLiteral) : JePrimitiveAnnotationValue() {
|
internal class JeLiteralAnnotationValue(val psi: PsiLiteral) : JePrimitiveAnnotationValue() {
|
||||||
override fun getValue() = psi.value
|
override fun getValue() = psi.value
|
||||||
}
|
}
|
||||||
|
|
||||||
private class JeExpressionAnnotationValue(val psi: PsiExpression) : JePrimitiveAnnotationValue() {
|
internal class JeExpressionAnnotationValue(val psi: PsiExpression) : JePrimitiveAnnotationValue() {
|
||||||
override fun getValue() = JavaPsiFacade.getInstance(psi.project).constantEvaluationHelper.computeConstantExpression(psi)
|
override fun getValue() = JavaPsiFacade.getInstance(psi.project).constantEvaluationHelper.computeConstantExpression(psi)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class JeArrayAnnotationValue(val psi: PsiArrayInitializerMemberValue) : AnnotationValue {
|
internal class JeArrayAnnotationValue(val psi: PsiArrayInitializerMemberValue) : AnnotationValue {
|
||||||
override fun getValue() = psi.initializers.map { JeAnnotationValue(it) }
|
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)
|
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitArray(value, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class JeErrorAnnotationValue(val psi: PsiElement) : AnnotationValue {
|
internal 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 <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitString(psi.text, p)
|
||||||
override fun getValue() = null
|
override fun getValue() = null
|
||||||
}
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.java.model.elements
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.java.model.JeElement
|
||||||
|
|
||||||
|
interface JeElementRenderer {
|
||||||
|
fun render(element: JeElement): String
|
||||||
|
}
|
||||||
+2
-2
@@ -55,8 +55,8 @@ class JeTypeElement(override val psi: PsiClass) : JeElement(), TypeElement, JeAn
|
|||||||
else -> NestingKind.LOCAL
|
else -> NestingKind.LOCAL
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getEnclosedElements(): List<Element> {
|
override fun getEnclosedElements(): List<JeElement> {
|
||||||
val declarations = mutableListOf<Element>()
|
val declarations = mutableListOf<JeElement>()
|
||||||
psi.initializers.forEach { declarations += JeClassInitializerExecutableElement(it) }
|
psi.initializers.forEach { declarations += JeClassInitializerExecutableElement(it) }
|
||||||
psi.fields.forEach { declarations += JeVariableElement(it) }
|
psi.fields.forEach { declarations += JeVariableElement(it) }
|
||||||
psi.methods.forEach { declarations += JeMethodExecutableElement(it) }
|
psi.methods.forEach { declarations += JeMethodExecutableElement(it) }
|
||||||
|
|||||||
Reference in New Issue
Block a user