Java to Kotlin converter: checking that no element prototype assignment forgotten + no memory leaks through singleton Element instances
This commit is contained in:
@@ -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)) {
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
@@ -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('.'))
|
||||||
|
|||||||
Reference in New Issue
Block a user