Java to Kotlin converter: checking that no element prototype assignment forgotten + no memory leaks through singleton Element instances

This commit is contained in:
Valentin Kipyatkov
2014-06-24 13:59:11 +04:00
parent 4f27dd63b5
commit f8fef59654
16 changed files with 190 additions and 134 deletions
+10 -4
View File
@@ -21,7 +21,6 @@ import java.util.HashSet
import org.jetbrains.jet.lang.psi.psiUtil.isAncestor import org.jetbrains.jet.lang.psi.psiUtil.isAncestor
import java.util.ArrayList import java.util.ArrayList
import org.jetbrains.jet.j2k.ast.Element import org.jetbrains.jet.j2k.ast.Element
import org.jetbrains.jet.j2k.ast.Modifiers
import kotlin.platform.platformName import kotlin.platform.platformName
fun<T> CodeBuilder.append(generators: Collection<() -> T>, separator: String, prefix: String = "", suffix: String = ""): CodeBuilder { fun<T> CodeBuilder.append(generators: Collection<() -> T>, separator: String, prefix: String = "", suffix: String = ""): CodeBuilder {
@@ -79,14 +78,21 @@ class CodeBuilder(private val topElement: PsiElement?) {
public fun append(element: Element): CodeBuilder { public fun append(element: Element): CodeBuilder {
if (element.isEmpty) return this // do not insert comment and spaces for empty elements to avoid multiple blank lines if (element.isEmpty) return this // do not insert comment and spaces for empty elements to avoid multiple blank lines
if (element.prototypes.isEmpty() || topElement == null) { if (element.prototypes == null && topElement != null) {
val s = "Element $element has no prototypes assigned.\n" +
"Use Element.assignPrototype() or Element.assignNoPrototype().\n" +
"Element created at:\n${element.createdAt}"
throw RuntimeException(s)
}
if (topElement == null || element.prototypes!!.isEmpty()) {
element.generateCode(this) element.generateCode(this)
return this return this
} }
val prefixElements = ArrayList<PsiElement>(1) val prefixElements = ArrayList<PsiElement>(1)
val postfixElements = ArrayList<PsiElement>(1) val postfixElements = ArrayList<PsiElement>(1)
for ((prototype, inheritBlankLinesBefore) in element.prototypes) { for ((prototype, inheritBlankLinesBefore) in element.prototypes!!) {
assert(prototype !is PsiComment) assert(prototype !is PsiComment)
assert(prototype !is PsiWhiteSpace) assert(prototype !is PsiWhiteSpace)
assert(topElement.isAncestor(prototype)) assert(topElement.isAncestor(prototype))
@@ -112,7 +118,7 @@ class CodeBuilder(private val topElement: PsiElement?) {
element.generateCode(this) 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 // 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) { for ((prototype, _) in element.prototypes!!) {
prototype.accept(object : JavaRecursiveElementVisitor(){ prototype.accept(object : JavaRecursiveElementVisitor(){
override fun visitComment(comment: PsiComment) { override fun visitComment(comment: PsiComment) {
if (commentsAndSpacesUsed.add(comment)) { if (commentsAndSpacesUsed.add(comment)) {
+33 -22
View File
@@ -225,7 +225,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
var keepStatement = true var keepStatement = true
if (statement is AssignmentExpression) { if (statement is AssignmentExpression) {
val assignee = statement.left val assignee = statement.left
if (assignee is QualifiedExpression && (assignee.qualifier as? Identifier)?.name == SecondaryConstructor.tempValIdentifier.name) { if (assignee is QualifiedExpression && (assignee.qualifier as? Identifier)?.name == SecondaryConstructor.tempValName) {
val name = (assignee.identifier as Identifier).name val name = (assignee.identifier as Identifier).name
for (field in finalOrWithEmptyInitializerFields) { for (field in finalOrWithEmptyInitializerFields) {
if (name == field.identifier.name) { if (name == field.identifier.name) {
@@ -245,24 +245,27 @@ public class Converter private(val project: Project, val settings: ConverterSett
} }
val initializer = MethodCallExpression.buildNotNull(null, className.name, finalOrWithEmptyInitializerFields.map { initializers[it]!! }) val initializer = MethodCallExpression.buildNotNull(null, className.name, finalOrWithEmptyInitializerFields.map { initializers[it]!! })
val localVar = LocalVariable(SecondaryConstructor.tempValIdentifier, initializer.assignNoPrototype()
val localVar = LocalVariable(SecondaryConstructor.tempValIdentifier(),
Annotations.Empty, Annotations.Empty,
Modifiers.Empty, Modifiers.Empty,
{ ClassType(className, listOf(), Nullability.NotNull, settings) }, { ClassType(className, listOf(), Nullability.NotNull, settings) },
initializer, initializer,
true, true,
settings) settings).assignNoPrototype()
newStatements.add(0, DeclarationStatement(listOf(localVar))) newStatements.add(0, DeclarationStatement(listOf(localVar)).assignNoPrototype())
constructor.block = Block(newStatements, LBrace(), RBrace()) constructor.block = Block(newStatements, LBrace().assignNoPrototype(), RBrace().assignNoPrototype()).assignNoPrototype()
} }
//TODO: comments? //TODO: comments?
val parameters = finalOrWithEmptyInitializerFields.map { field -> val parameters = finalOrWithEmptyInitializerFields.map { field ->
val varValModifier = if (field.isVal) Parameter.VarValModifier.Val else Parameter.VarValModifier.Var val varValModifier = if (field.isVal) Parameter.VarValModifier.Val else Parameter.VarValModifier.Var
Parameter(field.identifier, field.`type`, varValModifier, field.annotations, field.modifiers.filter { it in ACCESS_MODIFIERS }) Parameter(field.identifier, field.`type`, varValModifier, field.annotations, field.modifiers.filter { it in ACCESS_MODIFIERS }).assignPrototypesFrom(field)
} }
val primaryConstructor = PrimaryConstructor(this, Annotations.Empty, Modifiers(listOf(Modifier.PRIVATE)), ParameterList(parameters), Block.Empty) val modifiers = Modifiers(listOf(Modifier.PRIVATE)).assignNoPrototype()
val parameterList = ParameterList(parameters).assignNoPrototype()
val primaryConstructor = PrimaryConstructor(this, Annotations.Empty, modifiers, parameterList, Block.Empty)
val updatedMembers = classBody.normalMembers.filter { !finalOrWithEmptyInitializerFields.contains(it) } val updatedMembers = classBody.normalMembers.filter { !finalOrWithEmptyInitializerFields.contains(it) }
return ClassBody(primaryConstructor, classBody.secondaryConstructors, updatedMembers, classBody.classObjectMembers, classBody.lBrace, classBody.rBrace) return ClassBody(primaryConstructor, classBody.secondaryConstructors, updatedMembers, classBody.classObjectMembers, classBody.lBrace, classBody.rBrace)
} }
@@ -330,7 +333,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
private fun doConvertMethod(method: PsiMethod, membersToRemove: MutableSet<PsiMember>): Function { private fun doConvertMethod(method: PsiMethod, membersToRemove: MutableSet<PsiMember>): Function {
val returnType = typeConverter.convertMethodReturnType(method) val returnType = typeConverter.convertMethodReturnType(method)
val annotations = convertAnnotations(method) + convertThrows(method) val annotations = (convertAnnotations(method) + convertThrows(method)).assignNoPrototype()
var modifiers = convertModifiers(method) var modifiers = convertModifiers(method)
if (method.isConstructor()) { if (method.isConstructor()) {
@@ -453,7 +456,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
convertAnnotations(parameter) + convertAnnotations(field), convertAnnotations(parameter) + convertAnnotations(field),
convertModifiers(field).filter { it in ACCESS_MODIFIERS }).assignPrototypes(listOf(parameter, field), inheritBlankLinesBefore = false) convertModifiers(field).filter { it in ACCESS_MODIFIERS }).assignPrototypes(listOf(parameter, field), inheritBlankLinesBefore = false)
} }
}) }).assignPrototype(constructor.getParameterList())
return PrimaryConstructor(this, annotations, modifiers, parameterList, block).assignPrototype(constructor) return PrimaryConstructor(this, annotations, modifiers, parameterList, block).assignPrototype(constructor)
} }
@@ -524,7 +527,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
} }
fun convertTypeElement(element: PsiTypeElement?): TypeElement fun convertTypeElement(element: PsiTypeElement?): TypeElement
= TypeElement(if (element == null) Type.Empty else typeConverter.convertType(element.getType())).assignPrototype(element) = TypeElement(if (element == null) ErrorType().assignNoPrototype() else typeConverter.convertType(element.getType())).assignPrototype(element)
private fun convertToNotNullableTypes(types: Array<out PsiType?>): List<Type> private fun convertToNotNullableTypes(types: Array<out PsiType?>): List<Type>
= types.map { typeConverter.convertType(it, Nullability.NotNull) } = types.map { typeConverter.convertType(it, Nullability.NotNull) }
@@ -608,13 +611,13 @@ public class Converter private(val project: Project, val settings: ConverterSett
} }
val list = annotations.map { convertAnnotation(it, owner is PsiLocalVariable) }.filterNotNull() //TODO: brackets are also needed for local classes val list = annotations.map { convertAnnotation(it, owner is PsiLocalVariable) }.filterNotNull() //TODO: brackets are also needed for local classes
return Annotations(list, newLines) return Annotations(list, newLines).assignNoPrototype()
} }
private fun convertAnnotation(annotation: PsiAnnotation, brackets: Boolean): Annotation? { private fun convertAnnotation(annotation: PsiAnnotation, brackets: Boolean): Annotation? {
val qualifiedName = annotation.getQualifiedName() val qualifiedName = annotation.getQualifiedName()
if (qualifiedName == CommonClassNames.JAVA_LANG_DEPRECATED && annotation.getParameterList().getAttributes().isEmpty()) { if (qualifiedName == CommonClassNames.JAVA_LANG_DEPRECATED && annotation.getParameterList().getAttributes().isEmpty()) {
return Annotation(Identifier("deprecated"), listOf(null to LiteralExpression("\"\"")), brackets).assignPrototype(annotation) //TODO: insert comment return Annotation(Identifier("deprecated").assignNoPrototype(), listOf(null to LiteralExpression("\"\"").assignNoPrototype()), brackets).assignPrototype(annotation) //TODO: insert comment
} }
val nameRef = annotation.getNameReferenceElement() val nameRef = annotation.getNameReferenceElement()
@@ -625,7 +628,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
val method = annotationClass?.findMethodsByName(it.getName() ?: "value", false)?.firstOrNull() val method = annotationClass?.findMethodsByName(it.getName() ?: "value", false)?.firstOrNull()
val expectedType = method?.getReturnType() val expectedType = method?.getReturnType()
val attrName = it.getName()?.let { Identifier(it) } val attrName = it.getName()?.let { Identifier(it).assignNoPrototype() }
val value = it.getValue() val value = it.getValue()
val isVarArg = method == lastMethod /* converted to vararg in Kotlin */ val isVarArg = method == lastMethod /* converted to vararg in Kotlin */
@@ -638,7 +641,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
private fun convertAttributeValue(value: PsiAnnotationMemberValue?, expectedType: PsiType?, isVararg: Boolean, isUnnamed: Boolean): List<Expression> { private fun convertAttributeValue(value: PsiAnnotationMemberValue?, expectedType: PsiType?, isVararg: Boolean, isUnnamed: Boolean): List<Expression> {
return when (value) { return when (value) {
is PsiExpression -> listOf(convertExpression(value as? PsiExpression, expectedType)) is PsiExpression -> listOf(convertExpression(value as? PsiExpression, expectedType).assignPrototype(value))
is PsiArrayInitializerMemberValue -> { is PsiArrayInitializerMemberValue -> {
val componentType = (expectedType as? PsiArrayType)?.getComponentType() val componentType = (expectedType as? PsiArrayType)?.getComponentType()
@@ -650,27 +653,35 @@ public class Converter private(val project: Project, val settings: ConverterSett
val expectedTypeConverted = typeConverter.convertType(expectedType) val expectedTypeConverted = typeConverter.convertType(expectedType)
if (expectedTypeConverted is ArrayType) { if (expectedTypeConverted is ArrayType) {
val array = createArrayInitializerExpression(expectedTypeConverted, componentsConverted, needExplicitType = false) val array = createArrayInitializerExpression(expectedTypeConverted, componentsConverted, needExplicitType = false)
listOf(if (isVararg) StarExpression(array) else array) if (isVararg) {
listOf(StarExpression(array.assignNoPrototype()).assignPrototype(value))
}
else {
listOf(array.assignPrototype(value))
}
} }
else { else {
listOf(DummyStringExpression(value.getText()!!)) listOf(DummyStringExpression(value.getText()!!).assignPrototype(value))
} }
} }
} }
else -> listOf(DummyStringExpression(value?.getText() ?: "")) else -> listOf(DummyStringExpression(value?.getText() ?: "").assignPrototype(value))
} }
} }
private fun convertThrows(method: PsiMethod): Annotations { private fun convertThrows(method: PsiMethod): Annotations {
val throwsList = method.getThrowsList() val throwsList = method.getThrowsList()
val types = throwsList.getReferencedTypes() val types = throwsList.getReferencedTypes()
val refElements = throwsList.getReferenceElements()
assert(types.size == refElements.size)
if (types.isEmpty()) return Annotations.Empty if (types.isEmpty()) return Annotations.Empty
val annotation = Annotation(Identifier("throws"), val arguments = types.indices.map {
types.map { null to MethodCallExpression.buildNotNull(null, "javaClass", listOf(), listOf(typeConverter.convertType(it, Nullability.NotNull))) }, val convertedType = typeConverter.convertType(types[it], Nullability.NotNull)
false) null to MethodCallExpression.buildNotNull(null, "javaClass", listOf(), listOf(convertedType)).assignPrototype(refElements[it])
return Annotations(listOf(annotation.assignPrototype(throwsList)), }
true) val annotation = Annotation(Identifier("throws").assignNoPrototype(), arguments, false)
return Annotations(listOf(annotation.assignPrototype(throwsList)), true).assignPrototype(throwsList)
} }
private val TYPE_MAP: Map<String, String> = mapOf( private val TYPE_MAP: Map<String, String> = mapOf(
@@ -26,6 +26,8 @@ import org.jetbrains.jet.j2k.ast.Import
import org.jetbrains.jet.j2k.ast.ImportList import org.jetbrains.jet.j2k.ast.ImportList
import org.jetbrains.jet.j2k.ast.assignPrototype import org.jetbrains.jet.j2k.ast.assignPrototype
import com.intellij.psi.CommonClassNames.JAVA_LANG_OBJECT import com.intellij.psi.CommonClassNames.JAVA_LANG_OBJECT
import org.jetbrains.jet.j2k.ast.assignNoPrototype
import org.jetbrains.jet.j2k.ast.ErrorType
class TypeConverter(val settings: ConverterSettings, val conversionScope: ConversionScope) { class TypeConverter(val settings: ConverterSettings, val conversionScope: ConversionScope) {
private val nullabilityCache = HashMap<PsiElement, Nullability>() private val nullabilityCache = HashMap<PsiElement, Nullability>()
@@ -40,12 +42,12 @@ class TypeConverter(val settings: ConverterSettings, val conversionScope: Conver
private var importNames: Set<String> = setOf() private var importNames: Set<String> = setOf()
public val importsToAdd: Collection<Import> public val importsToAdd: Collection<Import>
get() = classesToImport.map { Import(it) } get() = classesToImport.map { Import(it).assignNoPrototype() }
public fun convertType(`type`: PsiType?, nullability: Nullability = Nullability.Default): Type { public fun convertType(`type`: PsiType?, nullability: Nullability = Nullability.Default): Type {
if (`type` == null) return Type.Empty if (`type` == null) return ErrorType().assignNoPrototype()
val result = `type`.accept<Type>(TypeVisitor(this, importNames, classesToImport))!! val result = `type`.accept<Type>(TypeVisitor(this, importNames, classesToImport))!!.assignNoPrototype()
return when (nullability) { return when (nullability) {
Nullability.NotNull -> result.toNotNullType() Nullability.NotNull -> result.toNotNullType()
Nullability.Nullable -> result.toNullableType() Nullability.Nullable -> result.toNullableType()
+13 -11
View File
@@ -59,20 +59,22 @@ fun PsiModifierListOwner.nullabilityFromAnnotations(): Nullability {
fun getDefaultInitializer(field: Field): Expression { fun getDefaultInitializer(field: Field): Expression {
val t = field.`type` val t = field.`type`
if (t.isNullable) { val result = if (t.isNullable) {
return LiteralExpression("null") LiteralExpression("null")
} }
else if (t is PrimitiveType) {
if (t is PrimitiveType) { when (t.name.name) {
when(t.name.name) { "Boolean" -> LiteralExpression("false")
"Boolean" -> return LiteralExpression("false") "Char" -> LiteralExpression("' '")
"Char" -> return LiteralExpression("' '") "Double" -> MethodCallExpression.buildNotNull(LiteralExpression("0").assignNoPrototype(), OperatorConventions.DOUBLE.toString())
"Double" -> return MethodCallExpression.buildNotNull(LiteralExpression("0"), OperatorConventions.DOUBLE.toString()) "Float" -> MethodCallExpression.buildNotNull(LiteralExpression("0").assignNoPrototype(), OperatorConventions.FLOAT.toString())
"Float" -> return MethodCallExpression.buildNotNull(LiteralExpression("0"), OperatorConventions.FLOAT.toString()) else -> LiteralExpression("0")
} }
} }
else {
return LiteralExpression("0") LiteralExpression("0")
}
return result.assignNoPrototype()
} }
fun isQualifierEmptyOrThis(ref: PsiReferenceExpression): Boolean { fun isQualifierEmptyOrThis(ref: PsiReferenceExpression): Boolean {
@@ -58,6 +58,8 @@ class Annotations(val annotations: List<Annotation>, val newLines: Boolean) : El
} }
} }
override val isEmpty: Boolean = annotations.isEmpty()
fun plus(other: Annotations) = Annotations(annotations + other.annotations, newLines || other.newLines) fun plus(other: Annotations) = Annotations(annotations + other.annotations, newLines || other.newLines)
class object { class object {
@@ -25,7 +25,7 @@ abstract class Constructor(
modifiers: Modifiers, modifiers: Modifiers,
parameterList: ParameterList, parameterList: ParameterList,
block: Block block: Block
) : Function(converter, Identifier.Empty, annotations, modifiers, Type.Empty, TypeParameterList.Empty, parameterList, block, false) ) : Function(converter, Identifier.Empty, annotations, modifiers, ErrorType(), TypeParameterList.Empty, parameterList, block, false)
class PrimaryConstructor(converter: Converter, class PrimaryConstructor(converter: Converter,
annotations: Annotations, annotations: Annotations,
@@ -54,18 +54,22 @@ class SecondaryConstructor(converter: Converter,
public fun toFactoryFunction(containingClass: Class?): Function { public fun toFactoryFunction(containingClass: Class?): Function {
val statements = ArrayList(block?.statements ?: listOf()) val statements = ArrayList(block?.statements ?: listOf())
statements.add(ReturnStatement(tempValIdentifier)) statements.add(ReturnStatement(tempValIdentifier()).assignNoPrototype())
val block = Block(statements, block?.lBrace ?: LBrace(), block?.rBrace ?: RBrace()) val newBlock = Block(statements, block?.lBrace ?: LBrace().assignNoPrototype(), block?.rBrace ?: RBrace().assignNoPrototype())
val typeParameters = ArrayList<TypeParameter>() if (this.block != null) {
if (containingClass != null) { newBlock.assignPrototypesFrom(block!!)
typeParameters.addAll(containingClass.typeParameterList.parameters)
} }
return Function(converter, Identifier("create"), annotations, modifiers,
ClassType(containingClass?.name ?: Identifier.Empty, typeParameters, Nullability.NotNull, converter.settings), val typeParameters = if (containingClass != null) containingClass.typeParameterList.parameters else listOf()
TypeParameterList(typeParameters), parameterList, block, false).assignPrototypesFrom(this) val typeParameterList = TypeParameterList(typeParameters).assignNoPrototype()
val returnType = ClassType(containingClass?.name ?: Identifier.Empty, typeParameters, Nullability.NotNull, converter.settings).assignNoPrototype()
return Function(converter, Identifier("create").assignNoPrototype(), annotations, modifiers,
returnType, typeParameterList, parameterList, newBlock, false).assignPrototypesFrom(this)
} }
class object { class object {
public val tempValIdentifier: Identifier = Identifier("__", false) public val tempValName: String = "__"
public fun tempValIdentifier(): Identifier = Identifier(tempValName, false).assignNoPrototype()
} }
} }
+19 -8
View File
@@ -20,17 +20,23 @@ import org.jetbrains.jet.j2k.*
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
fun <TElement: Element> TElement.assignPrototype(prototype: PsiElement?, inheritBlankLinesBefore: Boolean = true): TElement { fun <TElement: Element> TElement.assignPrototype(prototype: PsiElement?, inheritBlankLinesBefore: Boolean = true): TElement {
assignPrototypeInfos(if (prototype != null) listOf(PrototypeInfo(prototype, inheritBlankLinesBefore)) else listOf()) prototypes = if (prototype != null) listOf(PrototypeInfo(prototype, inheritBlankLinesBefore)) else listOf()
return this return this
} }
fun <TElement: Element> TElement.assignPrototypes(prototypes: List<PsiElement>, inheritBlankLinesBefore: Boolean): TElement { fun <TElement: Element> TElement.assignPrototypes(prototypes: List<PsiElement>, inheritBlankLinesBefore: Boolean): TElement {
assignPrototypeInfos(prototypes.map { PrototypeInfo(it, inheritBlankLinesBefore) }) this.prototypes = prototypes.map { PrototypeInfo(it, inheritBlankLinesBefore) }
return this
}
fun <TElement: Element> TElement.assignNoPrototype(): TElement {
prototypes = listOf()
return this return this
} }
fun <TElement: Element> TElement.assignPrototypesFrom(element: Element): TElement { fun <TElement: Element> TElement.assignPrototypesFrom(element: Element): TElement {
assignPrototypeInfos(element.prototypes) prototypes = element.prototypes
createdAt = element.createdAt
return this return this
} }
@@ -43,12 +49,17 @@ fun Element.canonicalCode(): String {
} }
abstract class Element { abstract class Element {
public var prototypes: List<PrototypeInfo> = listOf() public var prototypes: List<PrototypeInfo>? = null
private set set(value) {
// no prototypes assigned to empty elements because they can be singleton instances (and they are not needed anyway)
if (isEmpty) {
$prototypes = listOf()
return
}
$prototypes = value
}
public fun assignPrototypeInfos(prototypes: List<PrototypeInfo>) { public var createdAt: String = "Element creation stacktraces turned off. Uncomment initializer of Element.createdAt." //Exception().getStackTrace().joinToString("\n")
this.prototypes = prototypes
}
/** This method should not be used anywhere except for CodeBuilder! Use CodeBuilder.append instead. */ /** This method should not be used anywhere except for CodeBuilder! Use CodeBuilder.append instead. */
public abstract fun generateCode(builder: CodeBuilder) public abstract fun generateCode(builder: CodeBuilder)
@@ -116,6 +116,10 @@ class PolyadicExpression(val expressions: List<Expression>, val token: String) :
} }
class LambdaExpression(val arguments: String?, val block: Block) : Expression() { class LambdaExpression(val arguments: String?, val block: Block) : Expression() {
{
assignPrototypesFrom(block)
}
override fun generateCode(builder: CodeBuilder) { override fun generateCode(builder: CodeBuilder) {
builder append block.lBrace append " " builder append block.lBrace append " "
@@ -155,7 +159,7 @@ fun createArrayInitializerExpression(arrayType: ArrayType, initializers: List<Ex
if (doubleOrFloatTypes.contains(afterReplace)) { if (doubleOrFloatTypes.contains(afterReplace)) {
if (initializer is LiteralExpression) { if (initializer is LiteralExpression) {
if (!initializer.canonicalCode().contains(".")) { if (!initializer.canonicalCode().contains(".")) {
return LiteralExpression(initializer.literalText + ".0") return LiteralExpression(initializer.literalText + ".0").assignPrototypesFrom(initializer)
} }
} }
else { else {
@@ -165,7 +169,7 @@ fun createArrayInitializerExpression(arrayType: ArrayType, initializers: List<Ex
else -> null else -> null
} }
if (conversionFunction != null) { if (conversionFunction != null) {
return MethodCallExpression.buildNotNull(initializer, conversionFunction) return MethodCallExpression.buildNotNull(initializer, conversionFunction).assignNoPrototype()
} }
} }
} }
@@ -57,8 +57,8 @@ class MethodCallExpression(
typeArguments: List<Type>, typeArguments: List<Type>,
isNullable: Boolean, isNullable: Boolean,
lambdaArgument: LambdaExpression? = null): MethodCallExpression { lambdaArgument: LambdaExpression? = null): MethodCallExpression {
val identifier = Identifier(methodName, false) val identifier = Identifier(methodName, false).assignNoPrototype()
return MethodCallExpression(if (receiver != null) QualifiedExpression(receiver, identifier) else identifier, return MethodCallExpression(if (receiver != null) QualifiedExpression(receiver, identifier).assignNoPrototype() else identifier,
arguments, arguments,
typeArguments, typeArguments,
isNullable, isNullable,
@@ -156,7 +156,10 @@ class SwitchContainer(val expression: Expression, val caseContainers: List<CaseC
} }
class CaseContainer(val caseStatement: List<Element>, statements: List<Statement>) : Statement() { class CaseContainer(val caseStatement: List<Element>, statements: List<Statement>) : Statement() {
private val block = Block(statements.filterNot { it is BreakStatement || it is ContinueStatement }, LBrace(), RBrace(), true) private val block = run {
val filteredStatements = statements.filterNot { it is BreakStatement || it is ContinueStatement }
Block(filteredStatements, LBrace().assignNoPrototype(), RBrace().assignNoPrototype(), true).assignNoPrototype()
}
override fun generateCode(builder: CodeBuilder) { override fun generateCode(builder: CodeBuilder) {
builder.append(caseStatement, ", ").append(" -> ").append(block) builder.append(caseStatement, ", ").append(" -> ").append(block)
@@ -67,7 +67,7 @@ fun Converter.convertTypeParameter(psiTypeParameter: PsiTypeParameter): TypePara
fun Converter.convertTypeParameterList(typeParameterList: PsiTypeParameterList?): TypeParameterList { fun Converter.convertTypeParameterList(typeParameterList: PsiTypeParameterList?): TypeParameterList {
return if (typeParameterList != null) return if (typeParameterList != null)
TypeParameterList(typeParameterList.getTypeParameters()!!.toList().map { convertTypeParameter(it) }) TypeParameterList(typeParameterList.getTypeParameters()!!.toList().map { convertTypeParameter(it) }).assignPrototype(typeParameterList)
else else
TypeParameterList.Empty TypeParameterList.Empty
} }
+25 -25
View File
@@ -18,7 +18,7 @@ package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.* import org.jetbrains.jet.j2k.*
fun Type.isUnit(): Boolean = this == Type.Unit fun Type.isUnit(): Boolean = this is UnitType
enum class Nullability { enum class Nullability {
Nullable Nullable
@@ -51,26 +51,6 @@ abstract class Type() : Element() {
open fun toNullableType(): Type = this open fun toNullableType(): Type = this
object Empty : NotNullType() {
override fun generateCode(builder: CodeBuilder) {
builder.append("UNRESOLVED_TYPE")
}
}
object Unit: NotNullType() {
override fun generateCode(builder: CodeBuilder) {
builder.append("Unit")
}
}
object Null: Type() {
override val isNullable: Boolean = true
override fun generateCode(builder: CodeBuilder) {
builder.append("???")
}
}
override fun equals(other: Any?): Boolean = other is Type && other.canonicalCode() == this.canonicalCode() override fun equals(other: Any?): Boolean = other is Type && other.canonicalCode() == this.canonicalCode()
override fun hashCode(): Int = canonicalCode().hashCode() override fun hashCode(): Int = canonicalCode().hashCode()
@@ -78,6 +58,26 @@ abstract class Type() : Element() {
override fun toString(): String = canonicalCode() override fun toString(): String = canonicalCode()
} }
class UnitType : NotNullType() {
override fun generateCode(builder: CodeBuilder) {
builder.append("Unit")
}
}
class NullType : Type() {
override val isNullable: Boolean = true
override fun generateCode(builder: CodeBuilder) {
builder.append("???")
}
}
class ErrorType : NotNullType() {
override fun generateCode(builder: CodeBuilder) {
builder.append("UNRESOLVED_TYPE")
}
}
class ClassType(val name: Identifier, val typeArgs: List<Element>, nullability: Nullability, settings: ConverterSettings) class ClassType(val name: Identifier, val typeArgs: List<Element>, nullability: Nullability, settings: ConverterSettings)
: MayBeNullableType(nullability, settings) { : MayBeNullableType(nullability, settings) {
@@ -85,8 +85,8 @@ class ClassType(val name: Identifier, val typeArgs: List<Element>, nullability:
builder.append(name).append(typeArgs, ", ", "<", ">").append(isNullableStr) builder.append(name).append(typeArgs, ", ", "<", ">").append(isNullableStr)
} }
override fun toNotNullType(): Type = ClassType(name, typeArgs, Nullability.NotNull, settings) override fun toNotNullType(): Type = ClassType(name, typeArgs, Nullability.NotNull, settings).assignPrototypesFrom(this)
override fun toNullableType(): Type = ClassType(name, typeArgs, Nullability.Nullable, settings) override fun toNullableType(): Type = ClassType(name, typeArgs, Nullability.Nullable, settings).assignPrototypesFrom(this)
} }
class ArrayType(val elementType: Type, nullability: Nullability, settings: ConverterSettings) class ArrayType(val elementType: Type, nullability: Nullability, settings: ConverterSettings)
@@ -101,8 +101,8 @@ class ArrayType(val elementType: Type, nullability: Nullability, settings: Conve
} }
} }
override fun toNotNullType(): Type = ArrayType(elementType, Nullability.NotNull, settings) override fun toNotNullType(): Type = ArrayType(elementType, Nullability.NotNull, settings).assignPrototypesFrom(this)
override fun toNullableType(): Type = ArrayType(elementType, Nullability.Nullable, settings) override fun toNullableType(): Type = ArrayType(elementType, Nullability.Nullable, settings).assignPrototypesFrom(this)
} }
class InProjectionType(val bound: Type) : NotNullType() { class InProjectionType(val bound: Type) : NotNullType() {
@@ -43,7 +43,7 @@ class ElementVisitor(private val converter: Converter) : JavaElementVisitor() {
override fun visitReferenceElement(reference: PsiJavaCodeReferenceElement) { override fun visitReferenceElement(reference: PsiJavaCodeReferenceElement) {
val types = typeConverter.convertTypes(reference.getTypeParameters()) val types = typeConverter.convertTypes(reference.getTypeParameters())
if (!reference.isQualified()) { if (!reference.isQualified()) {
result = ReferenceElement(Identifier(reference.getReferenceName()!!), types) result = ReferenceElement(Identifier(reference.getReferenceName()!!).assignNoPrototype(), types)
} }
else { else {
var code = Identifier.toKotlin(reference.getReferenceName()!!) var code = Identifier.toKotlin(reference.getReferenceName()!!)
@@ -53,7 +53,7 @@ class ElementVisitor(private val converter: Converter) : JavaElementVisitor() {
code = Identifier.toKotlin(p.getReferenceName()!!) + "." + code code = Identifier.toKotlin(p.getReferenceName()!!) + "." + code
qualifier = p.getQualifier() qualifier = p.getQualifier()
} }
result = ReferenceElement(Identifier(code), types) result = ReferenceElement(Identifier(code).assignNoPrototype(), types)
} }
} }
@@ -78,7 +78,7 @@ class ExpressionVisitor(private val converter: Converter,
val lhs = converter.convertExpression(expression.getLExpression()) val lhs = converter.convertExpression(expression.getLExpression())
val rhs = converter.convertExpression(expression.getRExpression()!!, expression.getLExpression().getType()) val rhs = converter.convertExpression(expression.getRExpression()!!, expression.getLExpression().getType())
if (!secondOp.isEmpty()) { if (!secondOp.isEmpty()) {
result = AssignmentExpression(lhs, BinaryExpression(lhs, rhs, secondOp), " = ") result = AssignmentExpression(lhs, BinaryExpression(lhs, rhs, secondOp).assignNoPrototype(), " = ")
} }
else { else {
result = AssignmentExpression(lhs, rhs, expression.getOperationSign().getText()!!) result = AssignmentExpression(lhs, rhs, expression.getOperationSign().getText()!!)
@@ -173,16 +173,16 @@ class ExpressionVisitor(private val converter: Converter,
origin as JetNamedDeclaration origin as JetNamedDeclaration
val parameterCount = target.getParameterList().getParameters().size val parameterCount = target.getParameterList().getParameters().size
if (parameterCount == arguments.size) { if (parameterCount == arguments.size) {
val propertyName = Identifier(property.getName()!!, isNullable) val propertyName = Identifier(property.getName()!!, isNullable).assignNoPrototype()
val isExtension = property.isExtensionDeclaration() val isExtension = property.isExtensionDeclaration()
val propertyAccess = if (isTopLevel) { val propertyAccess = if (isTopLevel) {
if (isExtension) if (isExtension)
QualifiedExpression(converter.convertExpression(arguments.firstOrNull()), propertyName) QualifiedExpression(converter.convertExpression(arguments.firstOrNull()), propertyName).assignNoPrototype()
else else
propertyName propertyName
} }
else { else {
QualifiedExpression(converter.convertExpression(methodExpr.getQualifierExpression()), propertyName) QualifiedExpression(converter.convertExpression(methodExpr.getQualifierExpression()), propertyName).assignNoPrototype()
} }
when(if (isExtension) parameterCount - 1 else parameterCount) { when(if (isExtension) parameterCount - 1 else parameterCount) {
@@ -266,8 +266,8 @@ class ExpressionVisitor(private val converter: Converter,
// non-primary constructor converted to factory method in class object // non-primary constructor converted to factory method in class object
val reference = expression.getClassReference() val reference = expression.getClassReference()
val typeParameters = if (reference != null) typeConverter.convertTypes(reference.getTypeParameters()) else listOf() val typeParameters = if (reference != null) typeConverter.convertTypes(reference.getTypeParameters()) else listOf()
return QualifiedExpression(Identifier(constructor.getName(), false), return QualifiedExpression(Identifier(constructor.getName(), false).assignNoPrototype(),
MethodCallExpression.buildNotNull(null, "create", converter.convertExpressions(arguments), typeParameters)) MethodCallExpression.buildNotNull(null, "create", converter.convertExpressions(arguments), typeParameters).assignNoPrototype())
} }
return NewClassExpression(converter.convertElement(classReference), return NewClassExpression(converter.convertElement(classReference),
@@ -303,20 +303,20 @@ class ExpressionVisitor(private val converter: Converter,
val target = expression.getReference()?.resolve() val target = expression.getReference()?.resolve()
val isNullable = if (target is PsiVariable) typeConverter.variableNullability(target).isNullable(converter.settings) else false val isNullable = if (target is PsiVariable) typeConverter.variableNullability(target).isNullable(converter.settings) else false
val referencedName = expression.getReferenceName()!! val referencedName = expression.getReferenceName()!!
var identifier: Expression = Identifier(referencedName, isNullable) var identifier: Expression = Identifier(referencedName, isNullable).assignNoPrototype()
val qualifier = expression.getQualifierExpression() val qualifier = expression.getQualifierExpression()
val containingConstructor = expression.getContainingConstructor() val containingConstructor = expression.getContainingConstructor()
val insideSecondaryConstructor = containingConstructor != null && !containingConstructor.isPrimaryConstructor() val insideSecondaryConstructor = containingConstructor != null && !containingConstructor.isPrimaryConstructor()
if (insideSecondaryConstructor && (expression.getReference()?.resolve() as? PsiField)?.getContainingClass() == containingConstructor!!.getContainingClass()) { if (insideSecondaryConstructor && (expression.getReference()?.resolve() as? PsiField)?.getContainingClass() == containingConstructor!!.getContainingClass()) {
identifier = QualifiedExpression(SecondaryConstructor.tempValIdentifier, Identifier(referencedName, isNullable)) identifier = QualifiedExpression(SecondaryConstructor.tempValIdentifier(), Identifier(referencedName, isNullable).assignNoPrototype())
} }
else if (insideSecondaryConstructor && expression.isThisConstructorCall()) { else if (insideSecondaryConstructor && expression.isThisConstructorCall()) {
identifier = Identifier("val __ = " + (containingConstructor?.getContainingClass()?.getNameIdentifier()?.getText() ?: "")) identifier = Identifier("val __ = " + (containingConstructor?.getContainingClass()?.getNameIdentifier()?.getText() ?: "")).assignNoPrototype()
} }
else if (qualifier != null && qualifier.getType() is PsiArrayType && referencedName == "length") { else if (qualifier != null && qualifier.getType() is PsiArrayType && referencedName == "length") {
identifier = Identifier("size", isNullable) identifier = Identifier("size", isNullable).assignNoPrototype()
} }
else if (qualifier != null) { else if (qualifier != null) {
if (referencedName == JvmAbi.CLASS_OBJECT_FIELD || referencedName == JvmAbi.INSTANCE_FIELD) { if (referencedName == JvmAbi.CLASS_OBJECT_FIELD || referencedName == JvmAbi.INSTANCE_FIELD) {
@@ -362,13 +362,15 @@ class ExpressionVisitor(private val converter: Converter,
} }
override fun visitSuperExpression(expression: PsiSuperExpression) { override fun visitSuperExpression(expression: PsiSuperExpression) {
val qualifier = expression.getQualifier()?.getReferenceName() val psiQualifier = expression.getQualifier()
result = SuperExpression(if (qualifier != null) Identifier(qualifier) else Identifier.Empty) val qualifier = psiQualifier?.getReferenceName()
result = SuperExpression(if (qualifier != null) Identifier(qualifier).assignPrototype(psiQualifier) else Identifier.Empty)
} }
override fun visitThisExpression(expression: PsiThisExpression) { override fun visitThisExpression(expression: PsiThisExpression) {
val qualifier = expression.getQualifier()?.getReferenceName() val psiQualifier = expression.getQualifier()
result = ThisExpression(if (qualifier != null) Identifier(qualifier) else Identifier.Empty) val qualifier = psiQualifier?.getReferenceName()
result = ThisExpression(if (qualifier != null) Identifier(qualifier).assignPrototype(psiQualifier) else Identifier.Empty)
} }
override fun visitTypeCastExpression(expression: PsiTypeCastExpression) { override fun visitTypeCastExpression(expression: PsiTypeCastExpression) {
@@ -45,14 +45,16 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
result = MethodCallExpression.buildNotNull(null, "assert", listOf(condition, description)) result = MethodCallExpression.buildNotNull(null, "assert", listOf(condition, description))
} }
else { else {
result = MethodCallExpression.build(null, "assert", listOf(condition), listOf(), false, LambdaExpression(null, Block(listOf(description), LBrace(), RBrace()))) val block = Block(listOf(description), LBrace().assignNoPrototype(), RBrace().assignNoPrototype())
val lambda = LambdaExpression(null, block.assignNoPrototype())
result = MethodCallExpression.build(null, "assert", listOf(condition), listOf(), false, lambda)
} }
} }
} }
override fun visitBlockStatement(statement: PsiBlockStatement) { override fun visitBlockStatement(statement: PsiBlockStatement) {
val block = converter.convertBlock(statement.getCodeBlock()) val block = converter.convertBlock(statement.getCodeBlock())
result = MethodCallExpression.build(null, "run", listOf(), listOf(), false, LambdaExpression(null, block)) result = MethodCallExpression.build(null, "run", listOf(), listOf(), false, LambdaExpression(null, block).assignNoPrototype())
} }
override fun visitBreakStatement(statement: PsiBreakStatement) { override fun visitBreakStatement(statement: PsiBreakStatement) {
@@ -118,7 +120,10 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
&& loopVar.getNameIdentifier() != null && loopVar.getNameIdentifier() != null
&& onceWritableIterator) { && onceWritableIterator) {
val end = converter.convertExpression((condition as PsiBinaryExpression).getROperand()) val end = converter.convertExpression((condition as PsiBinaryExpression).getROperand())
val endExpression = if (operationTokenType == JavaTokenType.LT) BinaryExpression(end, LiteralExpression("1"), "-") else end val endExpression = if (operationTokenType == JavaTokenType.LT)
BinaryExpression(end, LiteralExpression("1").assignNoPrototype(), "-").assignNoPrototype()
else
end
result = ForeachWithRangeStatement(loopVar.declarationIdentifier(), result = ForeachWithRangeStatement(loopVar.declarationIdentifier(),
converter.convertExpression(loopVar.getInitializer()), converter.convertExpression(loopVar.getInitializer()),
endExpression, endExpression,
@@ -142,7 +147,8 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
} }
if (nameConflict) { if (nameConflict) {
Block(listOf(converter.convertStatement(body), updateConverted), LBrace(), RBrace(), true) val statements = listOf(converter.convertStatement(body), updateConverted)
Block(statements, LBrace().assignNoPrototype(), RBrace().assignNoPrototype(), true).assignNoPrototype()
} }
else { else {
val block = converter.convertBlock(body.getCodeBlock(), true) val block = converter.convertBlock(body.getCodeBlock(), true)
@@ -150,18 +156,20 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
} }
} }
else { else {
Block(listOf(converter.convertStatement(body), updateConverted), LBrace(), RBrace(), true) val statements = listOf(converter.convertStatement(body), updateConverted)
Block(statements, LBrace().assignNoPrototype(), RBrace().assignNoPrototype(), true).assignNoPrototype()
} }
val whileStatement = WhileStatement( val whileStatement = WhileStatement(
if (condition != null) converter.convertExpression(condition) else LiteralExpression("true"), if (condition != null) converter.convertExpression(condition) else LiteralExpression("true").assignNoPrototype(),
whileBody, whileBody,
statement.isInSingleLine()) statement.isInSingleLine()).assignNoPrototype()
if (initializationConverted.isEmpty) { if (initializationConverted.isEmpty) {
result = whileStatement result = whileStatement
} }
else { else {
val block = Block(listOf(initializationConverted, whileStatement), LBrace(), RBrace()) val statements = listOf(initializationConverted, whileStatement)
val block = Block(statements, LBrace().assignNoPrototype(), RBrace().assignNoPrototype()).assignNoPrototype()
result = MethodCallExpression.build(null, "run", listOf(), listOf(), false, LambdaExpression(null, block)) result = MethodCallExpression.build(null, "run", listOf(), listOf(), false, LambdaExpression(null, block))
} }
} }
@@ -216,7 +224,7 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
val result = ArrayList<CaseContainer>() val result = ArrayList<CaseContainer>()
var pendingLabels = ArrayList<Element>() var pendingLabels = ArrayList<Element>()
var i = 0 var i = 0
var hasDefaultCase: Boolean = false var hasDefaultCase = false
for (ls in cases) { for (ls in cases) {
if (ls.size() > 0) { if (ls.size() > 0) {
var label = ls[0] as PsiSwitchLabelStatement var label = ls[0] as PsiSwitchLabelStatement
@@ -225,21 +233,19 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
// TODO assert("not a right index") {allSwitchStatements?.get(i) == label} // TODO assert("not a right index") {allSwitchStatements?.get(i) == label}
if (ls.size() > 1) { if (ls.size() > 1) {
pendingLabels.add(converter.convertStatement(label)) pendingLabels.add(converter.convertStatement(label))
val slice: List<PsiElement> = ls.subList(1, (ls.size())) val slice = ls.subList(1, (ls.size()))
fun convertStatements(elements: List<PsiElement>): List<Statement> fun convertStatements(elements: List<PsiElement>): List<Statement>
= elements.map { if (it is PsiStatement) converter.convertStatement(it) else null }.filterNotNull() = elements.map { if (it is PsiStatement) converter.convertStatement(it) else null }.filterNotNull()
if (!containsBreak(slice)) { if (!containsBreak(slice)) {
val statements = ArrayList(convertStatements(slice)) val statements = convertStatements(slice) + convertStatements(getAllToNextBreak(allSwitchStatements, i + ls.size()))
statements.addAll(convertStatements(getAllToNextBreak(allSwitchStatements, i + ls.size()))) result.add(CaseContainer(pendingLabels, statements).assignNoPrototype())
result.add(CaseContainer(pendingLabels, statements))
pendingLabels = ArrayList()
} }
else { else {
result.add(CaseContainer(pendingLabels, convertStatements(slice))) result.add(CaseContainer(pendingLabels, convertStatements(slice)).assignNoPrototype())
pendingLabels = ArrayList()
} }
pendingLabels = ArrayList()
} }
else { else {
pendingLabels.add(converter.convertStatement(label)) pendingLabels.add(converter.convertStatement(label))
@@ -247,8 +253,9 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
i += ls.size() i += ls.size()
} }
} }
if (!hasDefaultCase) if (!hasDefaultCase) {
result.add(CaseContainer(listOf(DefaultSwitchLabelStatement()), ArrayList())) result.add(CaseContainer(listOf(DefaultSwitchLabelStatement().assignNoPrototype()), listOf()).assignNoPrototype())
}
return result return result
} }
@@ -268,7 +275,7 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
val catchBlockParameters = tryStatement.getCatchBlockParameters() val catchBlockParameters = tryStatement.getCatchBlockParameters()
catchBlocks.indices.map { catchBlocks.indices.map {
CatchStatement(converter.convertParameter(catchBlockParameters[it], Nullability.NotNull), CatchStatement(converter.convertParameter(catchBlockParameters[it], Nullability.NotNull),
converter.convertBlock(catchBlocks[it])) converter.convertBlock(catchBlocks[it])).assignNoPrototype()
} }
} }
val finallyConverted = converter.convertBlock(tryStatement.getFinallyBlock()) val finallyConverted = converter.convertBlock(tryStatement.getFinallyBlock())
@@ -292,7 +299,7 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
val returns = collectReturns(tryBlock) val returns = collectReturns(tryBlock)
//TODO: support other returns when non-local returns supported by Kotlin //TODO: support other returns when non-local returns supported by Kotlin
if (returns.size == 1 && returns.single() == tryBlock!!.getStatements().last()) { if (returns.size == 1 && returns.single() == tryBlock!!.getStatements().last()) {
wrapResultStatement = { ReturnStatement(it) } wrapResultStatement = { ReturnStatement(it).assignPrototype(returns.single()) }
converterForBody = converter.withStatementVisitor { object : StatementVisitor(it) { converterForBody = converter.withStatementVisitor { object : StatementVisitor(it) {
override fun visitReturnStatement(statement: PsiReturnStatement) { override fun visitReturnStatement(statement: PsiReturnStatement) {
if (statement == returns.single()) { if (statement == returns.single()) {
@@ -310,14 +317,16 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
for (variable in resourceVariables.reverse()) { for (variable in resourceVariables.reverse()) {
val lambda = LambdaExpression(Identifier.toKotlin(variable.getName()!!), block) val lambda = LambdaExpression(Identifier.toKotlin(variable.getName()!!), block)
expression = MethodCallExpression.build(converter.convertExpression(variable.getInitializer()), "use", listOf(), listOf(), false, lambda) expression = MethodCallExpression.build(converter.convertExpression(variable.getInitializer()), "use", listOf(), listOf(), false, lambda)
block = Block(listOf(expression), LBrace(), RBrace()) expression.assignNoPrototype()
block = Block(listOf(expression), LBrace().assignNoPrototype(), RBrace().assignNoPrototype()).assignNoPrototype()
} }
if (catchesConverted.isEmpty() && finallyConverted.isEmpty) { if (catchesConverted.isEmpty() && finallyConverted.isEmpty) {
return wrapResultStatement(expression) return wrapResultStatement(expression)
} }
return TryStatement(Block(listOf(wrapResultStatement(expression)), LBrace(), RBrace(), true), catchesConverted, finallyConverted) block = Block(listOf(wrapResultStatement(expression)), LBrace().assignPrototype(tryBlock?.getLBrace()), RBrace().assignPrototype(tryBlock?.getRBrace()), true)
return TryStatement(block.assignPrototype(tryBlock), catchesConverted, finallyConverted)
} }
private fun collectReturns(block: PsiCodeBlock?): Collection<PsiReturnStatement> { private fun collectReturns(block: PsiCodeBlock?): Collection<PsiReturnStatement> {
@@ -31,16 +31,16 @@ class TypeVisitor(private val converter: TypeConverter, private val importNames:
override fun visitPrimitiveType(primitiveType: PsiPrimitiveType): Type { override fun visitPrimitiveType(primitiveType: PsiPrimitiveType): Type {
val name = primitiveType.getCanonicalText() val name = primitiveType.getCanonicalText()
return if (name == "void") { return if (name == "void") {
Type.Unit UnitType()
} }
else if (PRIMITIVE_TYPES_NAMES.contains(name)) { else if (PRIMITIVE_TYPES_NAMES.contains(name)) {
PrimitiveType(Identifier(StringUtil.capitalize(name))) PrimitiveType(Identifier(StringUtil.capitalize(name)).assignNoPrototype())
} }
else if (name == "null") { else if (name == "null") {
Type.Null NullType()
} }
else { else {
PrimitiveType(Identifier(name)) PrimitiveType(Identifier(name).assignNoPrototype())
} }
} }
@@ -81,7 +81,7 @@ class TypeVisitor(private val converter: TypeConverter, private val importNames:
if (kotlinShortName == getShortName(javaClassName!!) && importNames.contains(getPackageName(javaClassName) + ".*")) { if (kotlinShortName == getShortName(javaClassName!!) && importNames.contains(getPackageName(javaClassName) + ".*")) {
classesToImport.add(kotlinClassName) classesToImport.add(kotlinClassName)
} }
return Identifier(kotlinShortName) return Identifier(kotlinShortName).assignNoPrototype()
} }
} }
@@ -95,11 +95,11 @@ class TypeVisitor(private val converter: TypeConverter, private val importNames:
result = Identifier.toKotlin(codeRefElement.getReferenceName()!!) + "." + result result = Identifier.toKotlin(codeRefElement.getReferenceName()!!) + "." + result
qualifier = codeRefElement.getQualifier() qualifier = codeRefElement.getQualifier()
} }
return Identifier(result) return Identifier(result).assignNoPrototype()
} }
} }
return Identifier(classType.getClassName() ?: "") return Identifier(classType.getClassName() ?: "").assignNoPrototype()
} }
private fun getPackageName(className: String): String = className.substring(0, className.lastIndexOf('.')) private fun getPackageName(className: String): String = className.substring(0, className.lastIndexOf('.'))