From 26b66263585d97e082ef314dd17c6228444cd99a Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Wed, 11 Jun 2014 22:50:48 +0400 Subject: [PATCH] Converter from Java: added proper annotations formatting --- j2k/src/org/jetbrains/jet/j2k/Converter.kt | 36 +++++++++++++------ .../org/jetbrains/jet/j2k/ast/Annotation.kt | 27 ++++++++++---- .../jet/j2k/ast/AnonymousClassBody.kt | 2 +- j2k/src/org/jetbrains/jet/j2k/ast/Class.kt | 2 +- .../org/jetbrains/jet/j2k/ast/Constructors.kt | 6 ++-- j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt | 2 +- .../org/jetbrains/jet/j2k/ast/EnumConstant.kt | 2 +- j2k/src/org/jetbrains/jet/j2k/ast/Field.kt | 2 +- j2k/src/org/jetbrains/jet/j2k/ast/Function.kt | 2 +- .../org/jetbrains/jet/j2k/ast/Initializer.kt | 4 +-- .../jetbrains/jet/j2k/ast/LocalVariable.kt | 2 +- j2k/src/org/jetbrains/jet/j2k/ast/Members.kt | 2 +- .../org/jetbrains/jet/j2k/ast/Parameter.kt | 2 +- j2k/src/org/jetbrains/jet/j2k/ast/Trait.kt | 2 +- .../ast/annotations/annotationUsages.java | 16 +++++++++ .../ast/annotations/annotationUsages.kt | 20 ++++++++++- 16 files changed, 96 insertions(+), 33 deletions(-) diff --git a/j2k/src/org/jetbrains/jet/j2k/Converter.kt b/j2k/src/org/jetbrains/jet/j2k/Converter.kt index 142c9c8f741..dc622babb73 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Converter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/Converter.kt @@ -72,7 +72,7 @@ public class Converter private(val project: Project, val settings: ConverterSett is PsiComment -> Comment(element.getText()!!) is PsiImportList -> convertImportList(element) is PsiImportStatementBase -> convertImport(element, false) - is PsiAnnotation -> convertAnnotation(element) + is PsiAnnotation -> convertAnnotation(element, false) is PsiPackageStatement -> PackageStatement(quoteKeywords(element.getPackageName() ?: "")) is PsiWhiteSpace -> WhiteSpace(element.getText()!!) else -> null @@ -290,7 +290,7 @@ public class Converter private(val project: Project, val settings: ConverterSett Parameter(field.identifier, field.`type`, varValModifier, field.annotations, field.modifiers.filter { ACCESS_MODIFIERS.contains(it) }) } - val primaryConstructor = PrimaryConstructor(this, MemberComments.Empty, listOf(), setOf(Modifier.PRIVATE), ParameterList(parameters), Block.Empty) + val primaryConstructor = PrimaryConstructor(this, MemberComments.Empty, Annotations.Empty, setOf(Modifier.PRIVATE), ParameterList(parameters), Block.Empty) val updatedMembers = MemberList(classBody.normalMembers.elements.filter { !finalOrWithEmptyInitializerFields.contains(it) }) return ClassBody(primaryConstructor, classBody.secondaryConstructors, updatedMembers, classBody.classObjectMembers) } @@ -418,7 +418,7 @@ public class Converter private(val project: Project, val settings: ConverterSett } private fun convertPrimaryConstructor(constructor: PsiMethod, - annotations: List, + annotations: Annotations, modifiers: Set, comments: MemberComments, membersToRemove: MutableSet): PrimaryConstructor { @@ -610,14 +610,30 @@ public class Converter private(val project: Project, val settings: ConverterSett PsiModifier.PRIVATE to Modifier.PRIVATE ) - public fun convertAnnotations(owner: PsiModifierListOwner): List { - return owner.getModifierList()?.getAnnotations() - ?.filter { it.getQualifiedName() !in ANNOTATIONS_TO_REMOVE } - ?.map { convertAnnotation(it) } - ?.filterNotNull() ?: listOf() + public fun convertAnnotations(owner: PsiModifierListOwner): Annotations { + val modifierList = owner.getModifierList() + val annotations = modifierList?.getAnnotations()?.filter { it.getQualifiedName() !in ANNOTATIONS_TO_REMOVE } + if (annotations == null || annotations.isEmpty()) return Annotations.Empty + + val newLines = run { + if (!modifierList!!.isInSingleLine()) { + true + } + else { + var child: PsiElement? = modifierList + while(true) { + child = child!!.getNextSibling() + if (child == null || child!!.getTextLength() != 0) break + } + if (child is PsiWhiteSpace) !child!!.isInSingleLine() else false + } + } + + val list = annotations.map { convertAnnotation(it, owner is PsiLocalVariable) }.filterNotNull() + return Annotations(list, newLines) } - public fun convertAnnotation(annotation: PsiAnnotation): Annotation? { + public fun convertAnnotation(annotation: PsiAnnotation, brackets: Boolean): Annotation? { val name = Identifier((annotation.getNameReferenceElement() ?: return null).getText()!!) val annotationClass = annotation.getNameReferenceElement()?.resolve() as? PsiClass val lastMethod = annotationClass?.getMethods()?.lastOrNull() @@ -653,7 +669,7 @@ public class Converter private(val project: Project, val settings: ConverterSett attrValues.map { attrName to it } } - return Annotation(name, arguments) + return Annotation(name, arguments, brackets) } private val TYPE_MAP: Map = mapOf( diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Annotation.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Annotation.kt index ef656749545..d1632772225 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Annotation.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Annotation.kt @@ -18,17 +18,32 @@ package org.jetbrains.jet.j2k.ast import java.util.HashSet -class Annotation(val name: Identifier, val arguments: List>) : Element { - override fun toKotlin(): String { - if (arguments.isEmpty()) return name.toKotlin() +class Annotation(val name: Identifier, val arguments: List>, val brackets: Boolean) : Element { + private fun surroundWithBrackets(text: String) = if (brackets) "[$text]" else text - return name.toKotlin() + "(" + arguments.map { + override fun toKotlin(): String { + if (arguments.isEmpty()) { + return surroundWithBrackets(name.toKotlin()) + } + + val argsText = arguments.map { if (it.first != null) it.first!!.toKotlin() + " = " + it.second.toKotlin() else it.second.toKotlin() - }.makeString(", ") + ")" + }.makeString(", ") + return surroundWithBrackets(name.toKotlin() + "(" + argsText + ")") } } -fun List.toKotlin(): String = if (isNotEmpty()) map { it.toKotlin() }.makeString("\n") + "\n" else "" +class Annotations(val annotations: List, val newLines: Boolean) { + private val br = if (newLines) "\n" else " " + + fun toKotlin(): String = if (annotations.isNotEmpty()) annotations.map { it.toKotlin() }.makeString(br) + br else "" + + fun plus(other: Annotations) = Annotations(annotations + other.annotations, newLines || other.newLines) + + class object { + val Empty = Annotations(listOf(), false) + } +} diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/AnonymousClassBody.kt b/j2k/src/org/jetbrains/jet/j2k/ast/AnonymousClassBody.kt index 60d2054379f..87535864a53 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/AnonymousClassBody.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/AnonymousClassBody.kt @@ -20,6 +20,6 @@ import org.jetbrains.jet.j2k.Converter import java.util.Collections class AnonymousClassBody(body: ClassBody, val extendsTrait: Boolean) -: Class(Identifier(""), MemberComments.Empty, listOf(), setOf(), TypeParameterList.Empty, listOf(), listOf(), listOf(), body) { +: Class(Identifier(""), MemberComments.Empty, Annotations.Empty, setOf(), TypeParameterList.Empty, listOf(), listOf(), listOf(), body) { override fun toKotlin() = body.toKotlin(null) } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Class.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Class.kt index 544ebf3785b..89341e7f4ba 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Class.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Class.kt @@ -21,7 +21,7 @@ import java.util.ArrayList open class Class( val name: Identifier, comments: MemberComments, - annotations: List, + annotations: Annotations, modifiers: Set, val typeParameterList: TypeParameterList, val extendsTypes: List, diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt index 4169f22f9b5..2fdef678779 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt @@ -23,7 +23,7 @@ import java.util.ArrayList abstract class Constructor( converter: Converter, comments: MemberComments, - annotations: List, + annotations: Annotations, modifiers: Set, parameterList: ParameterList, block: Block @@ -31,7 +31,7 @@ abstract class Constructor( class PrimaryConstructor(converter: Converter, comments: MemberComments, - annotations: List, + annotations: Annotations, modifiers: Set, parameterList: ParameterList, block: Block) @@ -48,7 +48,7 @@ class PrimaryConstructor(converter: Converter, class SecondaryConstructor(converter: Converter, comments: MemberComments, - annotations: List, + annotations: Annotations, modifiers: Set, parameterList: ParameterList, block: Block) diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt index 0f92b411590..f0ab0b3f621 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt @@ -19,7 +19,7 @@ package org.jetbrains.jet.j2k.ast class Enum( name: Identifier, comments: MemberComments, - annotations: List, + annotations: Annotations, modifiers: Set, typeParameterList: TypeParameterList, extendsTypes: List, diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/EnumConstant.kt b/j2k/src/org/jetbrains/jet/j2k/ast/EnumConstant.kt index 60f2c77c072..a3c2b2808b4 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/EnumConstant.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/EnumConstant.kt @@ -19,7 +19,7 @@ package org.jetbrains.jet.j2k.ast class EnumConstant( identifier: Identifier, members: MemberComments, - annotations: List, + annotations: Annotations, modifiers: Set, `type`: Type, params: Element diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt index dece98e1dc3..8e34ece0e49 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt @@ -22,7 +22,7 @@ import java.util.ArrayList open class Field( val identifier: Identifier, comments: MemberComments, - annotations: List, + annotations: Annotations, modifiers: Set, val `type`: Type, val initializer: Element, diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Function.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Function.kt index 9ab8e42149e..0bb87b07cfb 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Function.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Function.kt @@ -23,7 +23,7 @@ open class Function( val converter: Converter, val name: Identifier, comments: MemberComments, - annotations: List, + annotations: Annotations, modifiers: Set, val `type`: Type, val typeParameterList: TypeParameterList, diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Initializer.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Initializer.kt index 0edf00c85c8..6f2adb2cec6 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Initializer.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Initializer.kt @@ -16,9 +16,7 @@ package org.jetbrains.jet.j2k.ast - -//TODO: is a member? -class Initializer(val block: Block, modifiers: Set) : Member(MemberComments.Empty, listOf(), modifiers) { +class Initializer(val block: Block, modifiers: Set) : Member(MemberComments.Empty, Annotations.Empty, modifiers) { override fun toKotlin(): String { return block.toKotlin() } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt b/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt index 8b87543957d..52cf1a7c575 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt @@ -20,7 +20,7 @@ import org.jetbrains.jet.j2k.ConverterSettings class LocalVariable( private val identifier: Identifier, - private val annotations: List, + private val annotations: Annotations, private val modifiers: Set, private val typeCalculator: () -> Type /* we use lazy type calculation for better performance */, private val initializer: Expression, diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Members.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Members.kt index e30440da539..7b74c695e09 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Members.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Members.kt @@ -30,7 +30,7 @@ class MemberComments(elements: List) : WhiteSpaceSeparatedElementList(e } } -abstract class Member(val comments: MemberComments, val annotations: List, val modifiers: Set) : Element { +abstract class Member(val comments: MemberComments, val annotations: Annotations, val modifiers: Set) : Element { fun commentsToKotlin(): String = comments.toKotlin() } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Parameter.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Parameter.kt index 770bfb6f06e..70ce20c83ed 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Parameter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Parameter.kt @@ -19,7 +19,7 @@ package org.jetbrains.jet.j2k.ast class Parameter(val identifier: Identifier, val `type`: Type, val varVal: Parameter.VarValModifier, - val annotations: List, + val annotations: Annotations, val modifiers: Collection) : Element { public enum class VarValModifier { None diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Trait.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Trait.kt index 5f05c2f9f71..f5ff5c77fbc 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Trait.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Trait.kt @@ -21,7 +21,7 @@ import java.util.ArrayList class Trait(name: Identifier, comments: MemberComments, - annotations: List, + annotations: Annotations, modifiers: Set, typeParameterList: TypeParameterList, extendsTypes: List, diff --git a/j2k/tests/testData/ast/annotations/annotationUsages.java b/j2k/tests/testData/ast/annotations/annotationUsages.java index 58ff9a6edaf..7c5577f721c 100644 --- a/j2k/tests/testData/ast/annotations/annotationUsages.java +++ b/j2k/tests/testData/ast/annotations/annotationUsages.java @@ -8,4 +8,20 @@ import javaApi.*; @Anon5(1) @Anon6({"x", "y"}) class C { + @Anon5(1) @Deprecated private int field1 = 0; + + @Anon5(1) + private int field2 = 0; + + @Anon5(1) int field3 = 0; + + @Anon5(1) + int field4 = 0; + + @Anon6({}) + void foo(@Deprecated int p1, @Deprecated @Anon5(2) char p2) { + @Deprecated @Anon5(3) char c = 'a'; + } + + @Anon5(1) void bar(){} } diff --git a/j2k/tests/testData/ast/annotations/annotationUsages.kt b/j2k/tests/testData/ast/annotations/annotationUsages.kt index 8d0d68d9a79..8bad5c3e6bf 100644 --- a/j2k/tests/testData/ast/annotations/annotationUsages.kt +++ b/j2k/tests/testData/ast/annotations/annotationUsages.kt @@ -6,4 +6,22 @@ Anon3(e = E.A, stringArray = array(), value = *array("a", "b")) Anon4("x", "y") Anon5(1) Anon6(array("x", "y")) -class C() \ No newline at end of file +class C() { + Anon5(1) Deprecated private var field1: Int = 0 + + Anon5(1) + private var field2: Int = 0 + + Anon5(1) var field3: Int = 0 + + Anon5(1) + var field4: Int = 0 + + Anon6(array()) + fun foo(Deprecated p1: Int, Deprecated Anon5(2) p2: Char) { + [Deprecated] [Anon5(3)] val c = 'a' + } + + Anon5(1) fun bar() { + } +}