From 9eaa961a2ac587ff761e6b48b48409cac35b0529 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Wed, 16 Jan 2019 14:25:24 +0300 Subject: [PATCH] New J2K: Add support of deprecated annotation && fix annotations --- .../kotlin/j2k/JavaToJKTreeBuilder.kt | 28 +++++++++++++++++-- .../jetbrains/kotlin/j2k/NewCodeBuilder.kt | 8 ++++++ .../ClassToObjectPromotionConversion.kt | 1 + .../conversions/JavaModifiersConversion.kt | 8 ++++++ .../StaticsToCompanionExtractConversion.kt | 1 + .../org/jetbrains/kotlin/j2k/expressions.kt | 13 +++++++++ .../org/jetbrains/kotlin/j2k/tree/impl/jk.kt | 2 ++ .../org/jetbrains/kotlin/j2k/tree/jk.kt | 3 +- 8 files changed, 61 insertions(+), 3 deletions(-) diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt index 497e7af6848..86b12b49e89 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt @@ -16,15 +16,18 @@ package org.jetbrains.kotlin.j2k +import com.intellij.lang.jvm.JvmAnnotatedElement import com.intellij.psi.* import com.intellij.psi.JavaTokenType.SUPER_KEYWORD import com.intellij.psi.JavaTokenType.THIS_KEYWORD import com.intellij.psi.impl.source.tree.ChildRole import com.intellij.psi.impl.source.tree.java.* +import com.intellij.psi.javadoc.PsiDocComment import com.intellij.psi.util.InheritanceUtil import com.intellij.psi.util.PsiUtil import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade import org.jetbrains.kotlin.asJava.elements.KtLightMethod +import org.jetbrains.kotlin.idea.j2k.content import org.jetbrains.kotlin.j2k.ast.Nullability import org.jetbrains.kotlin.j2k.tree.* import org.jetbrains.kotlin.j2k.tree.JKLiteralExpression.LiteralType.* @@ -392,6 +395,7 @@ class JavaToJKTreeBuilder( classKind, typeParameterList?.toJK() ?: JKTypeParameterListImpl(), createClassBody(), + annotationList(), modifiers(), visibility(), modality() @@ -512,7 +516,7 @@ class JavaToJKTreeBuilder( with(expressionTreeMapper) { typeElement?.toJK() } ?: JKTypeElementImpl(JKNoTypeImpl), JKNameIdentifierImpl(name), with(expressionTreeMapper) { initializer.toJK() }, - JKAnnotationListImpl(annotations.map { it.toJK() }), + annotationList(), modifiers(), visibility(), modality(), @@ -523,6 +527,16 @@ class JavaToJKTreeBuilder( } } + fun T.annotationList(): JKAnnotationList where T : JvmAnnotatedElement, T: PsiDocCommentOwner { + val plainAnnotations = annotations.map { it.toJK() } + val deprecatedAnnotation = docComment?.deprecatedAnnotation() ?: return JKAnnotationListImpl(plainAnnotations) + return JKAnnotationListImpl( + plainAnnotations.mapNotNull { annotation -> + if (annotation.classSymbol.fqName == "java.lang.Deprecated") null else annotation + } + deprecatedAnnotation + ) + } + fun PsiAnnotation.toJK(): JKAnnotation = JKAnnotationImpl( symbolProvider.provideSymbol(nameReferenceElement!!), @@ -531,6 +545,16 @@ class JavaToJKTreeBuilder( } ) + fun PsiDocComment.deprecatedAnnotation(): JKAnnotation? = + findTagByName("deprecated")?.let { tag -> + JKAnnotationImpl( + symbolProvider.provideByFqName("kotlin.Deprecated"), + JKExpressionListImpl( + stringLiteral(tag.content(), symbolProvider) + ) + ) + } + fun PsiMethod.toJK(): JKJavaMethod { return JKJavaMethodImpl( @@ -543,7 +567,7 @@ class JavaToJKTreeBuilder( parameterList.parameters.map { it.toJK() }, body?.toJK() ?: JKBodyStub, typeParameterList?.toJK() ?: JKTypeParameterListImpl(), - JKAnnotationListImpl(),//TODO get real annotations + annotationList(), throwsList.referencedTypes.map { JKTypeElementImpl(it.toJK(symbolProvider)) }, modifiers(), visibility(), diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt index 34ee3870744..c9259923ffa 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt @@ -173,6 +173,10 @@ class NewCodeBuilder { } override fun visitClass(klass: JKClass) { + klass.annotationList.accept(this) + if (klass.annotationList.annotations.isNotEmpty()) { + printer.println() + } renderModifiersList(klass) builder.append(" ") printer.print(classKindString(klass.classKind)) @@ -688,6 +692,10 @@ class NewCodeBuilder { } override fun visitKtConstructor(ktConstructor: JKKtConstructor) { + ktConstructor.annotationList.accept(this) + if (ktConstructor.annotationList.annotations.isNotEmpty()) { + printer.println() + } renderModifiersList(ktConstructor) printer.print(" constructor") renderParameterList(ktConstructor.parameters) diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ClassToObjectPromotionConversion.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ClassToObjectPromotionConversion.kt index 3814923cb2b..0bfdc92925f 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ClassToObjectPromotionConversion.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ClassToObjectPromotionConversion.kt @@ -38,6 +38,7 @@ class ClassToObjectPromotionConversion(private val context: ConversionContext) : companion.classBody.also { it.handleDeclarationsModifiers() }, + JKAnnotationListImpl(), element.extraModifiers, element.visibility, Modality.FINAL diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/JavaModifiersConversion.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/JavaModifiersConversion.kt index d65ed870a7b..602ded50c68 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/JavaModifiersConversion.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/JavaModifiersConversion.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.j2k.conversions import org.jetbrains.kotlin.j2k.ConversionContext +import org.jetbrains.kotlin.j2k.annotationByFqName import org.jetbrains.kotlin.j2k.jvmAnnotation import org.jetbrains.kotlin.j2k.tree.* @@ -20,6 +21,13 @@ class JavaModifiersConversion(private val context: ConversionContext) : Recursiv } } } + if (element is JKModalityOwner && element is JKAnnotationListOwner) { + val overrideAnnotation = element.annotationList.annotationByFqName("java.lang.Override") + if (overrideAnnotation != null) { + element.annotationList.annotations -= overrideAnnotation + //TODO change modality to OVERRIDE??? + } + } if (element is JKExtraModifiersOwner && element is JKAnnotationListOwner) { if (ExtraModifier.VOLATILE in element.extraModifiers) { element.extraModifiers -= ExtraModifier.VOLATILE diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/StaticsToCompanionExtractConversion.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/StaticsToCompanionExtractConversion.kt index ac267502318..7a47dea6bfe 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/StaticsToCompanionExtractConversion.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/StaticsToCompanionExtractConversion.kt @@ -44,6 +44,7 @@ class StaticsToCompanionExtractConversion : RecursiveApplicableConversionBase() JKClass.ClassKind.COMPANION, JKTypeParameterListImpl(), JKClassBodyImpl(), + JKAnnotationListImpl(), emptyList(), Visibility.PUBLIC, Modality.FINAL diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/expressions.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/expressions.kt index 01fd7442bbe..01f0b2fb1e9 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/expressions.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/expressions.kt @@ -243,6 +243,19 @@ fun throwAnnotation(throws: List, symbolProvider: JKSymbolProvider) = ) ) +fun JKAnnotationList.annotationByFqName(fqName: String): JKAnnotation? = + annotations.firstOrNull { it.classSymbol.fqName == fqName } + +fun stringLiteral(content: String, symbolProvider: JKSymbolProvider): JKExpression { + val lines = content.split('\n') + return lines.mapIndexed { i, line -> + val newlineSeparator = if (i == lines.size - 1) "" else "\\n" + JKKtLiteralExpressionImpl("\"$line$newlineSeparator\"", JKLiteralExpression.LiteralType.STRING) + }.reduce { acc: JKExpression, literalExpression: JKKtLiteralExpression -> + kotlinBinaryExpression(acc, literalExpression, JKKtSingleValueOperatorToken(KtTokens.PLUS), symbolProvider)!! + } +} + fun JKVariable.findUsages(scope: JKTreeElement, context: ConversionContext): List { val symbol = context.symbolProvider.provideUniverseSymbol(this) val usages = mutableListOf() diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt index 270fdc72619..182575f72cd 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt @@ -51,6 +51,7 @@ class JKClassImpl( override var classKind: JKClass.ClassKind, typeParameterList: JKTypeParameterList, classBody: JKClassBody, + annotationList: JKAnnotationList, override var extraModifiers: List, override var visibility: Visibility, override var modality: Modality @@ -61,6 +62,7 @@ class JKClassImpl( override val inheritance by child(inheritance) override var typeParameterList: JKTypeParameterList by child(typeParameterList) override var classBody: JKClassBody by child(classBody) + override var annotationList: JKAnnotationList by child(annotationList) } class JKNameIdentifierImpl(override val value: String) : JKNameIdentifier, JKElementBase(), PsiOwner by PsiOwnerImpl() { diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt index b97c8fa3608..f1da0927709 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt @@ -50,7 +50,8 @@ interface JKFile : JKTreeElement, JKBranchElement { var declarationList: List } -interface JKClass : JKDeclaration, JKVisibilityOwner, JKExtraModifiersOwner, JKModalityOwner, JKTypeParameterListOwner, JKBranchElement { +interface JKClass : JKDeclaration, JKVisibilityOwner, JKExtraModifiersOwner, JKModalityOwner, JKTypeParameterListOwner, JKAnnotationListOwner, + JKBranchElement { val name: JKNameIdentifier val inheritance: JKInheritanceInfo