diff --git a/j2k/src/org/jetbrains/jet/j2k/CodeBuilder.kt b/j2k/src/org/jetbrains/jet/j2k/CodeBuilder.kt index b47da7a9bc8..3927e0725ab 100644 --- a/j2k/src/org/jetbrains/jet/j2k/CodeBuilder.kt +++ b/j2k/src/org/jetbrains/jet/j2k/CodeBuilder.kt @@ -21,6 +21,7 @@ import java.util.HashSet import org.jetbrains.jet.lang.psi.psiUtil.isAncestor import java.util.ArrayList import org.jetbrains.jet.j2k.ast.Element +import org.jetbrains.jet.j2k.ast.Modifiers import kotlin.platform.platformName fun CodeBuilder.append(generators: Collection<() -> T>, separator: String, prefix: String = "", suffix: String = ""): CodeBuilder { @@ -104,6 +105,17 @@ class CodeBuilder(private val topElement: PsiElement?) { element.generateCode(this) + // scan for all comments inside which are not yet used in the text and put them here to not loose any comment from code + for ((prototype, _) in element.prototypes) { + prototype.accept(object : JavaRecursiveElementVisitor(){ + override fun visitComment(comment: PsiComment) { + if (commentsAndSpacesUsed.add(comment)) { + append(comment.getText()!!, comment.isEndOfLineComment()) + } + } + }) + } + postfixElements.forEach { append(it.getText()!!, it.isEndOfLineComment()) } return this diff --git a/j2k/src/org/jetbrains/jet/j2k/Converter.kt b/j2k/src/org/jetbrains/jet/j2k/Converter.kt index e36c812a901..3ba4c87e7f9 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Converter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/Converter.kt @@ -168,7 +168,7 @@ public class Converter private(val project: Project, val settings: ConverterSett private fun convertClass(psiClass: PsiClass): Class { val annotations = convertAnnotations(psiClass) - val modifiers = convertModifiers(psiClass) + var modifiers = convertModifiers(psiClass) val typeParameters = convertTypeParameterList(psiClass.getTypeParameterList()) val implementsTypes = convertToNotNullableTypes(psiClass.getImplementsListTypes()) val extendsTypes = convertToNotNullableTypes(psiClass.getExtendsListTypes()) @@ -198,11 +198,11 @@ public class Converter private(val project: Project, val settings: ConverterSett } if (settings.openByDefault && !psiClass.hasModifierProperty(PsiModifier.FINAL)) { - modifiers.add(Modifier.OPEN) + modifiers = modifiers.with(Modifier.OPEN) } if (psiClass.getContainingClass() != null && !psiClass.hasModifierProperty(PsiModifier.STATIC)) { - modifiers.add(Modifier.INNER) + modifiers = modifiers.with(Modifier.INNER) } Class(name, annotations, modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, classBody) @@ -247,7 +247,7 @@ public class Converter private(val project: Project, val settings: ConverterSett val initializer = MethodCallExpression.buildNotNull(null, className.name, finalOrWithEmptyInitializerFields.map { initializers[it]!! }) val localVar = LocalVariable(SecondaryConstructor.tempValIdentifier, Annotations.Empty, - setOf(), + Modifiers.Empty, { ClassType(className, listOf(), Nullability.NotNull, settings) }, initializer, true, @@ -259,10 +259,10 @@ public class Converter private(val project: Project, val settings: ConverterSett //TODO: comments? val parameters = finalOrWithEmptyInitializerFields.map { field -> val varValModifier = if (field.isVal) Parameter.VarValModifier.Val else Parameter.VarValModifier.Var - Parameter(field.identifier, field.`type`, varValModifier, field.annotations, field.modifiers.filter { ACCESS_MODIFIERS.contains(it) }) + Parameter(field.identifier, field.`type`, varValModifier, field.annotations, field.modifiers.filter { it in ACCESS_MODIFIERS }) } - val primaryConstructor = PrimaryConstructor(this, Annotations.Empty, setOf(Modifier.PRIVATE), ParameterList(parameters), Block.Empty) + val primaryConstructor = PrimaryConstructor(this, Annotations.Empty, Modifiers(listOf(Modifier.PRIVATE)), ParameterList(parameters), Block.Empty) val updatedMembers = classBody.normalMembers.filter { !finalOrWithEmptyInitializerFields.contains(it) } return ClassBody(primaryConstructor, classBody.secondaryConstructors, updatedMembers, classBody.classObjectMembers, classBody.lBrace, classBody.rBrace) } @@ -302,7 +302,7 @@ public class Converter private(val project: Project, val settings: ConverterSett val returnType = typeConverter.convertMethodReturnType(method) val annotations = convertAnnotations(method) + convertThrows(method) - val modifiers = convertModifiers(method) + var modifiers = convertModifiers(method) if (method.isConstructor()) { if (method.isPrimaryConstructor()) { @@ -316,7 +316,7 @@ public class Converter private(val project: Project, val settings: ConverterSett else { val isOverride = isOverride(method) if (isOverride) { - modifiers.add(Modifier.OVERRIDE) + modifiers = modifiers.with(Modifier.OVERRIDE) } val containingClass = method.getContainingClass() @@ -325,7 +325,7 @@ public class Converter private(val project: Project, val settings: ConverterSett val isEffectivelyFinal = method.hasModifierProperty(PsiModifier.FINAL) || containingClass != null && (containingClass.hasModifierProperty(PsiModifier.FINAL) || containingClass.isEnum()) if (!isEffectivelyFinal && !modifiers.contains(Modifier.ABSTRACT) && !modifiers.contains(Modifier.PRIVATE)) { - modifiers.add(Modifier.OPEN) + modifiers = modifiers.with(Modifier.OPEN) } } @@ -342,7 +342,7 @@ public class Converter private(val project: Project, val settings: ConverterSett ClassType(Identifier("Any"), listOf(), Nullability.Nullable, settings), Parameter.VarValModifier.None, params.parameters.single().annotations, - listOf()) + Modifiers.Empty) params = ParameterList(listOf(correctedParameter)) } } @@ -390,7 +390,7 @@ public class Converter private(val project: Project, val settings: ConverterSett private fun convertPrimaryConstructor(constructor: PsiMethod, annotations: Annotations, - modifiers: Set, + modifiers: Modifiers, membersToRemove: MutableSet): PrimaryConstructor { val params = constructor.getParameterList().getParameters() val parameterToField = HashMap>() @@ -439,7 +439,7 @@ public class Converter private(val project: Project, val settings: ConverterSett `type`, if (field.hasModifierProperty(PsiModifier.FINAL)) Parameter.VarValModifier.Val else Parameter.VarValModifier.Var, convertAnnotations(parameter) + convertAnnotations(field), - convertModifiers(field).filter { ACCESS_MODIFIERS.contains(it) }).assignPrototypes(listOf(parameter, field), inheritBlankLinesBefore = false) + convertModifiers(field).filter { it in ACCESS_MODIFIERS }).assignPrototypes(listOf(parameter, field), inheritBlankLinesBefore = false) } }) return PrimaryConstructor(this, annotations, modifiers, parameterList, block).assignPrototype(constructor) @@ -521,9 +521,9 @@ public class Converter private(val project: Project, val settings: ConverterSett = ParameterList(parameterList.getParameters().map { convertParameter(it) }).assignPrototype(parameterList) fun convertParameter(parameter: PsiParameter, - nullability: Nullability = Nullability.Default, - varValModifier: Parameter.VarValModifier = Parameter.VarValModifier.None, - modifiers: List = listOf()): Parameter { + nullability: Nullability = Nullability.Default, + varValModifier: Parameter.VarValModifier = Parameter.VarValModifier.None, + modifiers: Modifiers = Modifiers.Empty): Parameter { var `type` = typeConverter.convertVariableType(parameter) when (nullability) { Nullability.NotNull -> `type` = `type`.toNotNullType() @@ -566,8 +566,8 @@ public class Converter private(val project: Project, val settings: ConverterSett return Identifier(identifier.getText()!!).assignPrototype(identifier) } - fun convertModifiers(owner: PsiModifierListOwner): MutableSet - = HashSet(MODIFIERS_MAP.filter { owner.hasModifierProperty(it.first) }.map { it.second }) + fun convertModifiers(owner: PsiModifierListOwner): Modifiers + = Modifiers(MODIFIERS_MAP.filter { owner.hasModifierProperty(it.first) }.map { it.second }).assignPrototype(owner.getModifierList(), false) private val MODIFIERS_MAP = listOf( PsiModifier.ABSTRACT to Modifier.ABSTRACT, diff --git a/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt b/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt index 48345f04168..e7ed3cba81a 100644 --- a/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt @@ -24,6 +24,7 @@ import java.util.HashMap import java.util.HashSet import org.jetbrains.jet.j2k.ast.Import import org.jetbrains.jet.j2k.ast.ImportList +import org.jetbrains.jet.j2k.ast.assignPrototype class TypeConverter(val settings: ConverterSettings, val conversionScope: ConversionScope) { private val nullabilityCache = HashMap() @@ -56,7 +57,7 @@ class TypeConverter(val settings: ConverterSettings, val conversionScope: Conver = types.map { convertType(it) } public fun convertVariableType(variable: PsiVariable): Type - = convertType(variable.getType(), variableNullability(variable)) + = convertType(variable.getType(), variableNullability(variable)).assignPrototype(variable.getTypeElement()) public fun variableNullability(variable: PsiVariable): Nullability { val cached = nullabilityCache[variable] @@ -119,7 +120,7 @@ class TypeConverter(val settings: ConverterSettings, val conversionScope: Conver } public fun convertMethodReturnType(method: PsiMethod): Type - = convertType(method.getReturnType(), methodNullability(method)) + = convertType(method.getReturnType(), methodNullability(method)).assignPrototype(method.getReturnTypeElement()) public fun methodNullability(method: PsiMethod): Nullability { val cached = nullabilityCache[method] diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/AnonymousClassBody.kt b/j2k/src/org/jetbrains/jet/j2k/ast/AnonymousClassBody.kt index 738c22cc822..0c9d2c3b953 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/AnonymousClassBody.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/AnonymousClassBody.kt @@ -19,7 +19,7 @@ package org.jetbrains.jet.j2k.ast import org.jetbrains.jet.j2k.CodeBuilder class AnonymousClassBody(body: ClassBody, val extendsTrait: Boolean) -: Class(Identifier.Empty, Annotations.Empty, setOf(), TypeParameterList.Empty, listOf(), listOf(), listOf(), body) { +: Class(Identifier.Empty, Annotations.Empty, Modifiers.Empty, TypeParameterList.Empty, listOf(), listOf(), listOf(), body) { override fun generateCode(builder: CodeBuilder) { body.append(builder, null) } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Class.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Class.kt index 2b04dfbe1fd..8c5fe900747 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Class.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Class.kt @@ -16,13 +16,12 @@ package org.jetbrains.jet.j2k.ast -import java.util.ArrayList import org.jetbrains.jet.j2k.* open class Class( val name: Identifier, annotations: Annotations, - modifiers: Set, + modifiers: Modifiers, val typeParameterList: TypeParameterList, val extendsTypes: List, val baseClassParams: List, @@ -32,7 +31,11 @@ open class Class( override fun generateCode(builder: CodeBuilder) { builder.append(annotations) - appendModifiers(builder).append(keyword).append(" ").append(name).append(typeParameterList) + .appendWithSpaceAfter(presentationModifiers()) + .append(keyword) + .append(" ") + .append(name) + .append(typeParameterList) appendPrimaryConstructorSignature(builder) appendBaseTypes(builder) typeParameterList.appendWhere(builder) @@ -61,22 +64,6 @@ open class Class( return extendsTypes.map { { builder.append(it) } } } - protected open fun appendModifiers(builder: CodeBuilder): CodeBuilder { - val modifierList = ArrayList() - - modifiers.accessModifier()?.let { modifierList.add(it) } - - if (modifiers.contains(Modifier.ABSTRACT)) { - modifierList.add(Modifier.ABSTRACT) - } - else if (modifiers.contains(Modifier.OPEN)) { - modifierList.add(Modifier.OPEN) - } - - if (modifiers.contains(Modifier.INNER)) { - modifierList.add(Modifier.INNER) - } - - return builder.append(modifierList) - } + protected open fun presentationModifiers(): Modifiers + = if (modifiers.contains(Modifier.ABSTRACT)) modifiers.without(Modifier.OPEN) else modifiers } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/ClassBody.kt b/j2k/src/org/jetbrains/jet/j2k/ast/ClassBody.kt index 33319fe2640..97b1100ce7f 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/ClassBody.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/ClassBody.kt @@ -18,7 +18,7 @@ package org.jetbrains.jet.j2k.ast import org.jetbrains.jet.j2k.* -abstract class Member(val annotations: Annotations, val modifiers: Set) : Element() +abstract class Member(val annotations: Annotations, val modifiers: Modifiers) : Element() class ClassBody ( val primaryConstructor: PrimaryConstructor?, diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt index 4cb3dc0c8bf..5c29743fb18 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt @@ -16,29 +16,30 @@ package org.jetbrains.jet.j2k.ast -import java.util.HashSet import java.util.ArrayList import org.jetbrains.jet.j2k.* abstract class Constructor( converter: Converter, annotations: Annotations, - modifiers: Set, + modifiers: Modifiers, parameterList: ParameterList, block: Block ) : Function(converter, Identifier.Empty, annotations, modifiers, Type.Empty, TypeParameterList.Empty, parameterList, block, false) class PrimaryConstructor(converter: Converter, annotations: Annotations, - modifiers: Set, + modifiers: Modifiers, parameterList: ParameterList, block: Block) : Constructor(converter, annotations, modifiers, parameterList, block) { public fun appendSignature(builder: CodeBuilder): CodeBuilder { - val accessModifier = modifiers.accessModifier() - val modifiersString = if (accessModifier != null && accessModifier != Modifier.PUBLIC) " " + accessModifier.toKotlin() else "" - return builder.append(modifiersString).append("(").append(parameterList).append(")") + val accessModifier = modifiers.filter { it in ACCESS_MODIFIERS && it != Modifier.PUBLIC } + if (!accessModifier.isEmpty) { + builder append " " append accessModifier + } + return builder append "(" append parameterList append ")" } public fun appendBody(builder: CodeBuilder): CodeBuilder = builder.append(block!!) @@ -46,13 +47,12 @@ class PrimaryConstructor(converter: Converter, class SecondaryConstructor(converter: Converter, annotations: Annotations, - modifiers: Set, + modifiers: Modifiers, parameterList: ParameterList, block: Block) : Constructor(converter, annotations, modifiers, parameterList, block) { public fun toFactoryFunction(containingClass: Class?): Function { - val modifiers = HashSet(modifiers) val statements = ArrayList(block?.statements ?: listOf()) statements.add(ReturnStatement(tempValIdentifier)) val block = Block(statements, block?.lBrace ?: LBrace(), block?.rBrace ?: RBrace()) diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Element.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Element.kt index 3fb80b56a23..2a1b4f526b4 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Element.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Element.kt @@ -19,8 +19,8 @@ package org.jetbrains.jet.j2k.ast import org.jetbrains.jet.j2k.* import com.intellij.psi.PsiElement -fun TElement.assignPrototype(prototype: PsiElement?): TElement { - assignPrototypeInfos(if (prototype != null) listOf(PrototypeInfo(prototype, true)) else listOf()) +fun TElement.assignPrototype(prototype: PsiElement?, inheritBlankLinesBefore: Boolean = true): TElement { + assignPrototypeInfos(if (prototype != null) listOf(PrototypeInfo(prototype, inheritBlankLinesBefore)) else listOf()) return this } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt index 6c5f33edd27..04903876a46 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt @@ -21,7 +21,7 @@ import org.jetbrains.jet.j2k.* class Enum( name: Identifier, annotations: Annotations, - modifiers: Set, + modifiers: Modifiers, typeParameterList: TypeParameterList, extendsTypes: List, baseClassParams: List, @@ -35,8 +35,7 @@ class Enum( } override fun generateCode(builder: CodeBuilder) { - builder append annotations - appendModifiers(builder) append "enum class " append name + builder append annotations appendWithSpaceAfter presentationModifiers() append "enum class " append name appendPrimaryConstructorSignature(builder) builder append typeParameterList appendBaseTypes(builder) diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/EnumConstant.kt b/j2k/src/org/jetbrains/jet/j2k/ast/EnumConstant.kt index 296b7c9282a..cd4417e9502 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/EnumConstant.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/EnumConstant.kt @@ -21,7 +21,7 @@ import org.jetbrains.jet.j2k.* class EnumConstant( identifier: Identifier, annotations: Annotations, - modifiers: Set, + modifiers: Modifiers, `type`: Type, params: Element ) : Field(identifier, annotations, modifiers, `type`.toNotNullType(), params, true, false) { diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt index 495153bf717..ea5338ff058 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt @@ -17,12 +17,11 @@ package org.jetbrains.jet.j2k.ast import org.jetbrains.jet.j2k.* -import java.util.ArrayList open class Field( val identifier: Identifier, annotations: Annotations, - modifiers: Set, + modifiers: Modifiers, val `type`: Type, val initializer: Element, val isVal: Boolean, @@ -31,7 +30,7 @@ open class Field( override fun generateCode(builder: CodeBuilder) { builder.append(annotations) - .appendModifiers() + .appendWithSpaceAfter(modifiers) .append(if (isVal) "val " else "var ") .append(identifier) .append(" : ") @@ -45,15 +44,4 @@ open class Field( builder append "=" append initializerToUse } } - - private fun CodeBuilder.appendModifiers(): CodeBuilder { - val modifierList = ArrayList() - if (modifiers.contains(Modifier.ABSTRACT)) { - modifierList.add(Modifier.ABSTRACT) - } - - modifiers.accessModifier()?.let { modifierList.add(it) } - - return append(modifierList) - } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Function.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Function.kt index e12535a2554..8e2bc8e0f68 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Function.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Function.kt @@ -16,14 +16,13 @@ package org.jetbrains.jet.j2k.ast -import java.util.ArrayList import org.jetbrains.jet.j2k.* open class Function( val converter: Converter, val name: Identifier, annotations: Annotations, - modifiers: Set, + modifiers: Modifiers, val `type`: Type, val typeParameterList: TypeParameterList, val parameterList: ParameterList, @@ -31,33 +30,23 @@ open class Function( val isInTrait: Boolean ) : Member(annotations, modifiers) { - private fun CodeBuilder.appendModifiers(): CodeBuilder { - val resultingModifiers = ArrayList() - val isOverride = modifiers.contains(Modifier.OVERRIDE) - if (isOverride) { - resultingModifiers.add(Modifier.OVERRIDE) + private fun presentationModifiers(): Modifiers { + var modifiers = this.modifiers + if (isInTrait) { + modifiers = modifiers.without(Modifier.ABSTRACT) } - val accessModifier = modifiers.accessModifier() - if (accessModifier != null && !isOverride) { - resultingModifiers.add(accessModifier) + if (modifiers.contains(Modifier.OVERRIDE)) { + modifiers = modifiers.filter { it != Modifier.OPEN && it !in ACCESS_MODIFIERS } } - if (modifiers.contains(Modifier.ABSTRACT) && !isInTrait) { - resultingModifiers.add(Modifier.ABSTRACT) - } - - if (modifiers.contains(Modifier.OPEN) && !isOverride) { - resultingModifiers.add(Modifier.OPEN) - } - - return append(resultingModifiers) + return modifiers } override fun generateCode(builder: CodeBuilder) { builder.append(annotations) - .appendModifiers() - .append(" fun ") + .appendWithSpaceAfter(presentationModifiers()) + .append("fun ") .appendWithSuffix(typeParameterList, " ") .append(name) .append("(") diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Initializer.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Initializer.kt index b2a6a317ad0..4be86f4d9bf 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Initializer.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Initializer.kt @@ -18,7 +18,7 @@ package org.jetbrains.jet.j2k.ast import org.jetbrains.jet.j2k.* -class Initializer(val block: Block, modifiers: Set) : Member(Annotations.Empty, modifiers) { +class Initializer(val block: Block, modifiers: Modifiers) : Member(Annotations.Empty, modifiers) { override fun generateCode(builder: CodeBuilder) { builder.append(block) } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt b/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt index b80f19f9691..9976c2ede32 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt @@ -23,7 +23,7 @@ import org.jetbrains.jet.j2k.append class LocalVariable( private val identifier: Identifier, private val annotations: Annotations, - private val modifiers: Set, + private val modifiers: Modifiers, private val typeCalculator: () -> Type /* we use lazy type calculation for better performance */, private val initializer: Expression, private val isVal: Boolean, diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt index 985b646e510..405c4079e8d 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt @@ -16,7 +16,8 @@ package org.jetbrains.jet.j2k.ast -import org.jetbrains.jet.j2k.CodeBuilder +import org.jetbrains.jet.j2k.* +import java.util.HashSet enum class Modifier(val name: String) { PUBLIC: Modifier("public") @@ -33,16 +34,39 @@ enum class Modifier(val name: String) { val ACCESS_MODIFIERS = setOf(Modifier.PUBLIC, Modifier.PROTECTED, Modifier.PRIVATE) fun Collection.accessModifier(): Modifier? { - return firstOrNull { ACCESS_MODIFIERS.contains(it) } + return firstOrNull { it in ACCESS_MODIFIERS } } -fun CodeBuilder.append(modifiers: List): CodeBuilder { - if (!modifiers.isEmpty()) { - for (modifier in modifiers) { - append(modifier.toKotlin()).append(" ") - } +class Modifiers(val modifiers: Collection) : Element() { + override fun generateCode(builder: CodeBuilder) { + builder.append(modifiers.sortBy { it.ordinal() }.map { it.toKotlin() }.joinToString(" ")) + } + + override val isEmpty: Boolean + get() = modifiers.isEmpty() + + fun with(modifier: Modifier): Modifiers = Modifiers(modifiers + listOf(modifier)).assignPrototypesFrom(this) + + fun without(modifier: Modifier): Modifiers { + val set = HashSet(modifiers) + set.remove(modifier) + return Modifiers(set).assignPrototypesFrom(this) + } + + fun contains(modifier: Modifier): Boolean = modifiers.contains(modifier) + + class object { + val Empty = Modifiers(listOf()) + } +} + +fun Modifiers.filter(predicate: (Modifier) -> Boolean): Modifiers + = Modifiers(modifiers.filter(predicate)).assignPrototypesFrom(this) + +fun CodeBuilder.appendWithSpaceAfter(modifiers: Modifiers): CodeBuilder { + if (!modifiers.isEmpty) { + this append modifiers append " " } return this } - diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Parameter.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Parameter.kt index 103ba544ff8..ca5492bdbb1 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Parameter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Parameter.kt @@ -22,7 +22,7 @@ class Parameter(val identifier: Identifier, val `type`: Type, val varVal: Parameter.VarValModifier, val annotations: Annotations, - val modifiers: List) : Element() { + val modifiers: Modifiers) : Element() { public enum class VarValModifier { None Val @@ -30,7 +30,7 @@ class Parameter(val identifier: Identifier, } override fun generateCode(builder: CodeBuilder) { - builder.append(annotations).append(modifiers) + builder.append(annotations).appendWithSpaceAfter(modifiers) if (`type` is VarArgType) { assert(varVal == 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 f174b7f7c8e..034d5bdc5ad 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Trait.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Trait.kt @@ -16,12 +16,11 @@ package org.jetbrains.jet.j2k.ast -import java.util.ArrayList import org.jetbrains.jet.j2k.CodeBuilder class Trait(name: Identifier, annotations: Annotations, - modifiers: Set, + modifiers: Modifiers, typeParameterList: TypeParameterList, extendsTypes: List, baseClassParams: List, @@ -34,10 +33,6 @@ class Trait(name: Identifier, override fun appendPrimaryConstructorSignature(builder: CodeBuilder) { } - override fun appendModifiers(builder: CodeBuilder): CodeBuilder { - val modifierList = ArrayList() - modifiers.accessModifier()?.let { modifierList.add(it) } - return builder.append(modifierList) - } - + override fun presentationModifiers(): Modifiers + = modifiers.filter { it in ACCESS_MODIFIERS } } diff --git a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java index 3f394093cb3..36dfff85d3a 100644 --- a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java +++ b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java @@ -742,6 +742,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/comments/comments.java"); } + @TestMetadata("comments2.java") + public void testComments2() throws Exception { + doTest("j2k/tests/testData/ast/comments/comments2.java"); + } + @TestMetadata("fieldWithEndOfLineComment.java") public void testFieldWithEndOfLineComment() throws Exception { doTest("j2k/tests/testData/ast/comments/fieldWithEndOfLineComment.java"); diff --git a/j2k/tests/testData/ast/comments/comments2.java b/j2k/tests/testData/ast/comments/comments2.java new file mode 100644 index 00000000000..b9de99b91ed --- /dev/null +++ b/j2k/tests/testData/ast/comments/comments2.java @@ -0,0 +1,20 @@ +//file +package foo; + +class A { + void/* nothing to return */ foo(/* no parameters at all */) { + // let declare a variable + // with 2 comments before + int/*int*/ a /* it's a */ = 2 /* it's 2 */ + 1 /* it's 1 */; // variable a declared + } // end of foo + + int/* we return int*/ foo(int/*int*/ p/* parameter p */) { /* body is empty */ } + + private/*it's private*/ int field = 0; + + public /*it's public*/ char foo() { } + + protected/*it's protected*/ void foo() { } + + public/*it's public*/ static/*and static*/ final/*and final*/ int C = 1; +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/comments/comments2.kt b/j2k/tests/testData/ast/comments/comments2.kt new file mode 100644 index 00000000000..ae870f41377 --- /dev/null +++ b/j2k/tests/testData/ast/comments/comments2.kt @@ -0,0 +1,26 @@ +package foo + +class A() { + fun /* nothing to return */ foo(/* no parameters at all */) { + // let declare a variable + // with 2 comments before + val /*int*/ a /* it's a */ = 2 /* it's 2 */ + 1 /* it's 1 */ // variable a declared + } // end of foo + + fun /* we return int*/ foo(/*int*/ p: Int/* parameter p */): Int { + /* body is empty */ + } + + private /*it's private*/ var field: Int = 0 + + public /*it's public*/ fun foo(): Char { + } + + protected /*it's protected*/ fun foo() { + } + + class object { + + public /*it's public*//*and static*//*and final*/ val C: Int = 1 + } +} \ No newline at end of file