Converter:

Refactor handling of primitive types
Inject converter in places of use
Make Element and Node traits
This commit is contained in:
Pavel Talanov
2013-11-05 15:57:43 +04:00
committed by Pavel V. Talanov
parent ca99db3c47
commit 3edefcf598
26 changed files with 80 additions and 51 deletions
+1 -1
View File
@@ -218,7 +218,7 @@ public open class Converter(val project: Project) {
} }
} }
members.add(Constructor(Identifier.EMPTY_IDENTIFIER, arrayListOf(), Collections.emptySet<Modifier>(), members.add(Constructor(Identifier.EMPTY_IDENTIFIER, arrayListOf(), Collections.emptySet<Modifier>(),
ClassType(name, Collections.emptyList<Element>(), false), ClassType(name, Collections.emptyList<Element>(), false, this),
Collections.emptyList<Element>(), Collections.emptyList<Element>(),
ParameterList(createParametersFromFields(finalOrWithEmptyInitializer)), ParameterList(createParametersFromFields(finalOrWithEmptyInitializer)),
Block(createInitStatementsFromFields(finalOrWithEmptyInitializer)), Block(createInitStatementsFromFields(finalOrWithEmptyInitializer)),
@@ -19,8 +19,10 @@ package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type import org.jetbrains.jet.j2k.ast.types.Type
import org.jetbrains.jet.lang.types.expressions.OperatorConventions import org.jetbrains.jet.lang.types.expressions.OperatorConventions
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.jet.j2k.ast.types.ArrayType
import org.jetbrains.jet.j2k.ast.types.isPrimitive
public open class ArrayInitializerExpression(val `type`: Type, val initializers: List<Expression>) : Expression() { public open class ArrayInitializerExpression(val arrayType: ArrayType, val initializers: List<Expression>) : Expression() {
public override fun toKotlin(): String { public override fun toKotlin(): String {
return createArrayFunction() + "(" + createInitializers() + ")" return createArrayFunction() + "(" + createInitializers() + ")"
} }
@@ -30,16 +32,16 @@ public open class ArrayInitializerExpression(val `type`: Type, val initializers:
} }
private fun createArrayFunction(): String { private fun createArrayFunction(): String {
var sType: String? = innerTypeStr() val elementType = arrayType.elementType
if (Node.PRIMITIVE_TYPES.contains(sType)) { if (elementType.isPrimitive()) {
return sType + "Array" return (elementType.convertedToNotNull().toKotlin() + "Array").decapitalize()
} }
return StringUtil.decapitalize(`type`.convertedToNotNull().toKotlin())!! return arrayType.convertedToNotNull().toKotlin().decapitalize()
} }
private fun innerTypeStr(): String { private fun innerTypeStr(): String {
return `type`.convertedToNotNull().toKotlin().replace("Array", "").toLowerCase() return arrayType.convertedToNotNull().toKotlin().replace("Array", "").toLowerCase()
} }
private fun explicitConvertIfNeeded(i: Expression): String { private fun explicitConvertIfNeeded(i: Expression): String {
@@ -16,7 +16,7 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
public open class CallChainExpression(val expression: Expression, val identifier: Expression) : Expression() { public class CallChainExpression(val expression: Expression, val identifier: Expression) : Expression() {
public override fun isNullable(): Boolean { public override fun isNullable(): Boolean {
if (!expression.isEmpty() && expression.isNullable()) return true if (!expression.isEmpty() && expression.isNullable()) return true
return identifier.isNullable() return identifier.isNullable()
+3 -2
View File
@@ -23,7 +23,7 @@ import org.jetbrains.jet.j2k.ast.types.Type
import java.util.HashSet import java.util.HashSet
import java.util.ArrayList import java.util.ArrayList
public open class Class(converter: Converter, public open class Class(val converter: Converter,
val name: Identifier, val name: Identifier,
val docComments: List<Node>, val docComments: List<Node>,
modifiers: Set<Modifier>, modifiers: Set<Modifier>,
@@ -80,7 +80,8 @@ public open class Class(converter: Converter,
val constructorTypeParameters = ArrayList<Element>() val constructorTypeParameters = ArrayList<Element>()
constructorTypeParameters.addAll(typeParameters) constructorTypeParameters.addAll(typeParameters)
constructorTypeParameters.addAll(f.typeParameters) constructorTypeParameters.addAll(f.typeParameters)
return Function(Identifier("init"), arrayList(), modifiers, ClassType(name, constructorTypeParameters, false), return Function(Identifier("init"), arrayList(), modifiers,
ClassType(name, constructorTypeParameters, false, converter),
constructorTypeParameters, f.params, block) constructorTypeParameters, f.params, block)
} }
+4 -4
View File
@@ -17,17 +17,17 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
public abstract class Element() : Node() { public trait Element : Node {
public open fun isEmpty(): Boolean = false public fun isEmpty(): Boolean = false
class object { class object {
public val EMPTY_ELEMENT: Element = object : Element() { public val EMPTY_ELEMENT: Element = object : Element {
override fun toKotlin() = "" override fun toKotlin() = ""
override fun isEmpty() = true override fun isEmpty() = true
} }
} }
} }
public class Comment(val text: String) : Element() { public class Comment(val text: String) : Element {
override fun toKotlin() = text override fun toKotlin() = text
} }
+1 -1
View File
@@ -19,7 +19,7 @@ package org.jetbrains.jet.j2k.ast
public open class File(val packageName: String, public open class File(val packageName: String,
val imports: MutableList<Import>, val imports: MutableList<Import>,
val body: MutableList<Node>, val body: MutableList<Node>,
val mainFunction: String) : Node() { val mainFunction: String) : Node {
public override fun toKotlin(): String { public override fun toKotlin(): String {
val common: String = imports.toKotlin("\n") + "\n\n" + body.toKotlin("\n") + "\n" + mainFunction val common: String = imports.toKotlin("\n") + "\n\n" + body.toKotlin("\n") + "\n" + mainFunction
+1 -1
View File
@@ -17,6 +17,6 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
public open class Import(val name: String) : Node() { public class Import(val name: String) : Node {
public override fun toKotlin() = "import " + name public override fun toKotlin() = "import " + name
} }
@@ -17,11 +17,13 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type import org.jetbrains.jet.j2k.ast.types.Type
import org.jetbrains.jet.j2k.Converter
public class LocalVariable(val identifier: Identifier, public class LocalVariable(val identifier: Identifier,
val modifiersSet: Set<Modifier>, val modifiersSet: Set<Modifier>,
val javaType: Type, val javaType: Type,
val initializer: Expression) : Expression() { val initializer: Expression,
val converter: Converter) : Expression() {
public fun isImmutable(): Boolean = forceImmutable || modifiersSet.contains(Modifier.FINAL) public fun isImmutable(): Boolean = forceImmutable || modifiersSet.contains(Modifier.FINAL)
+1 -1
View File
@@ -16,7 +16,7 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
public abstract class Member(val modifiers: Set<Modifier>) : Node() { public abstract class Member(val modifiers: Set<Modifier>) : Node {
open fun accessModifier(): Modifier? { open fun accessModifier(): Modifier? {
return modifiers.find { m -> m == Modifier.PUBLIC || m == Modifier.PROTECTED || m == Modifier.PRIVATE } return modifiers.find { m -> m == Modifier.PUBLIC || m == Modifier.PROTECTED || m == Modifier.PRIVATE }
} }
+3 -6
View File
@@ -16,12 +16,9 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.Converter
public abstract class Node() {
public abstract fun toKotlin(): String
class object { public trait Node {
public val PRIMITIVE_TYPES: Set<String> = hashSet( public fun toKotlin(): String
"double", "float", "long", "int", "short", "byte", "boolean", "char")
}
} }
@@ -18,6 +18,6 @@ package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type import org.jetbrains.jet.j2k.ast.types.Type
public open class ReferenceElement(val reference: Identifier, val types: List<Type>) : Element() { public class ReferenceElement(val reference: Identifier, val types: List<Type>) : Element {
public override fun toKotlin() = reference.toKotlin() + types.toKotlin(", ", "<", ">") public override fun toKotlin() = reference.toKotlin() + types.toKotlin(", ", "<", ">")
} }
@@ -17,7 +17,7 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
public abstract class Statement() : Element() { public abstract class Statement() : Element {
class object { class object {
public val EMPTY_STATEMENT: Statement = object : Statement() { public val EMPTY_STATEMENT: Statement = object : Statement() {
public override fun toKotlin() = "" public override fun toKotlin() = ""
@@ -18,7 +18,7 @@ package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type import org.jetbrains.jet.j2k.ast.types.Type
public open class TypeElement(val `type`: Type) : Element() { public open class TypeElement(val `type`: Type) : Element {
override fun toKotlin() = `type`.toKotlin() override fun toKotlin() = `type`.toKotlin()
public fun toKotlinNotNull(): String = `type`.convertedToNotNull().toKotlin() public fun toKotlinNotNull(): String = `type`.convertedToNotNull().toKotlin()
@@ -18,9 +18,9 @@ package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ast.types.Type import org.jetbrains.jet.j2k.ast.types.Type
public open class TypeParameter(val name: Identifier, val extendsTypes: List<Type>) : Element() { public class TypeParameter(val name: Identifier, val extendsTypes: List<Type>) : Element {
public open fun hasWhere(): Boolean = extendsTypes.size() > 1 public fun hasWhere(): Boolean = extendsTypes.size() > 1
public open fun getWhereToKotlin(): String { public fun getWhereToKotlin(): String {
if (hasWhere()) { if (hasWhere()) {
return name.toKotlin() + " : " + extendsTypes.get(1).toKotlin() return name.toKotlin() + " : " + extendsTypes.get(1).toKotlin()
} }
@@ -16,7 +16,10 @@
package org.jetbrains.jet.j2k.ast.types package org.jetbrains.jet.j2k.ast.types
public open class ArrayType(val elementType: Type, nullable: Boolean) : Type(nullable) { import org.jetbrains.jet.j2k.Converter
public class ArrayType(val elementType: Type, nullable: Boolean,
converter: Converter) : MayBeNullableType(nullable, converter) {
public override fun toKotlin(): String { public override fun toKotlin(): String {
if (elementType is PrimitiveType) { if (elementType is PrimitiveType) {
return elementType.toKotlin() + "Array" + isNullableStr() return elementType.toKotlin() + "Array" + isNullableStr()
@@ -25,5 +28,5 @@ public open class ArrayType(val elementType: Type, nullable: Boolean) : Type(nul
return "Array<" + elementType.toKotlin() + ">" + isNullableStr() return "Array<" + elementType.toKotlin() + ">" + isNullableStr()
} }
public override fun convertedToNotNull(): Type = ArrayType(elementType, false) public override fun convertedToNotNull(): Type = ArrayType(elementType, false, converter)
} }
@@ -19,8 +19,11 @@ package org.jetbrains.jet.j2k.ast.types
import org.jetbrains.jet.j2k.ast.Element import org.jetbrains.jet.j2k.ast.Element
import org.jetbrains.jet.j2k.ast.Identifier import org.jetbrains.jet.j2k.ast.Identifier
import java.util.ArrayList import java.util.ArrayList
import org.jetbrains.jet.j2k.Converter
public open class ClassType(val `type`: Identifier, val parameters: List<Element>, nullable: Boolean,
converter: Converter) : MayBeNullableType(nullable, converter) {
public open class ClassType(val `type`: Identifier, val parameters: List<Element>, nullable: Boolean) : Type(nullable) {
public override fun toKotlin(): String { public override fun toKotlin(): String {
// TODO change to map() when KT-2051 is fixed // TODO change to map() when KT-2051 is fixed
val parametersToKotlin = ArrayList<String>() val parametersToKotlin = ArrayList<String>()
@@ -35,5 +38,5 @@ public open class ClassType(val `type`: Identifier, val parameters: List<Element
} }
public override fun convertedToNotNull(): Type = ClassType(`type`, parameters, false) public override fun convertedToNotNull(): Type = ClassType(`type`, parameters, false, converter)
} }
@@ -16,6 +16,6 @@
package org.jetbrains.jet.j2k.ast.types package org.jetbrains.jet.j2k.ast.types
public open class EmptyType() : Type(false) { public open class EmptyType() : NotNullType {
public override fun toKotlin(): String = "UNRESOLVED_TYPE" public override fun toKotlin(): String = "UNRESOLVED_TYPE"
} }
@@ -16,6 +16,6 @@
package org.jetbrains.jet.j2k.ast.types package org.jetbrains.jet.j2k.ast.types
public open class InProjectionType(val bound: Type) : Type(false) { public open class InProjectionType(val bound: Type) : NotNullType {
public override fun toKotlin(): String = "in " + bound.toKotlin() public override fun toKotlin(): String = "in " + bound.toKotlin()
} }
@@ -16,6 +16,6 @@
package org.jetbrains.jet.j2k.ast.types package org.jetbrains.jet.j2k.ast.types
public open class OutProjectionType(val bound: Type) : Type(false) { public open class OutProjectionType(val bound: Type) : NotNullType {
public override fun toKotlin(): String = "out " + bound.toKotlin() public override fun toKotlin(): String = "out " + bound.toKotlin()
} }
@@ -18,6 +18,6 @@ package org.jetbrains.jet.j2k.ast.types
import org.jetbrains.jet.j2k.ast.Identifier import org.jetbrains.jet.j2k.ast.Identifier
public open class PrimitiveType(val `type`: Identifier) : Type(false) { public open class PrimitiveType(val `type`: Identifier) : NotNullType {
public override fun toKotlin(): String = `type`.toKotlin() public override fun toKotlin(): String = `type`.toKotlin()
} }
@@ -16,6 +16,6 @@
package org.jetbrains.jet.j2k.ast.types package org.jetbrains.jet.j2k.ast.types
public open class StarProjectionType() : Type(false) { public open class StarProjectionType() : NotNullType {
public override fun toKotlin(): String = "*" public override fun toKotlin(): String = "*"
} }
@@ -17,14 +17,28 @@
package org.jetbrains.jet.j2k.ast.types package org.jetbrains.jet.j2k.ast.types
import org.jetbrains.jet.j2k.ast.Element import org.jetbrains.jet.j2k.ast.Element
import org.jetbrains.jet.j2k.Converter
public fun Type.isPrimitive(): Boolean = this is PrimitiveType
public abstract class MayBeNullableType(override public val nullable: Boolean, val converter: Converter): Type {
}
public trait NotNullType : Type {
override public val nullable: Boolean
get() = false
}
public trait Type : Element {
public val nullable: Boolean
public abstract class Type(val nullable: Boolean) : Element() {
public open fun convertedToNotNull(): Type { public open fun convertedToNotNull(): Type {
if (nullable) throw UnsupportedOperationException("convertedToNotNull must be defined") if (nullable) throw UnsupportedOperationException("convertedToNotNull must be defined")
return this return this
} }
public open fun isNullableStr(): String? { protected fun isNullableStr(): String? {
return (if (nullable && !forceNotNullTypes) return (if (nullable && !forceNotNullTypes)
"?" "?"
else else
@@ -16,6 +16,6 @@
package org.jetbrains.jet.j2k.ast.types package org.jetbrains.jet.j2k.ast.types
public open class VarArg(val `type`: Type) : Type(false) { public open class VarArg(val `type`: Type) : NotNullType {
public override fun toKotlin(): String = `type`.toKotlin() public override fun toKotlin(): String = `type`.toKotlin()
} }
@@ -43,7 +43,8 @@ public open class ElementVisitor(val myConverter: Converter) : JavaElementVisito
myResult = LocalVariable(Identifier(theVariable.getName()!!), myResult = LocalVariable(Identifier(theVariable.getName()!!),
Converter.modifiersListToModifiersSet(theVariable.getModifierList()), Converter.modifiersListToModifiersSet(theVariable.getModifierList()),
kType, kType,
myConverter.expressionToExpression(theVariable.getInitializer(), theVariable.getType())) myConverter.expressionToExpression(theVariable.getInitializer(), theVariable.getType()),
myConverter)
} }
public override fun visitExpressionList(list: PsiExpressionList?) { public override fun visitExpressionList(list: PsiExpressionList?) {
@@ -28,6 +28,7 @@ import com.intellij.psi.CommonClassNames.*
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.jet.lang.types.lang.PrimitiveType import org.jetbrains.jet.lang.types.lang.PrimitiveType
import org.jetbrains.jet.j2k.isAnnotatedAsNotNull import org.jetbrains.jet.j2k.isAnnotatedAsNotNull
import org.jetbrains.jet.j2k.ast.types.ArrayType
public open class ExpressionVisitor(converter: Converter) : StatementVisitor(converter) { public open class ExpressionVisitor(converter: Converter) : StatementVisitor(converter) {
{ {
@@ -47,7 +48,9 @@ public open class ExpressionVisitor(converter: Converter) : StatementVisitor(con
} }
public override fun visitArrayInitializerExpression(expression: PsiArrayInitializerExpression?) { public override fun visitArrayInitializerExpression(expression: PsiArrayInitializerExpression?) {
myResult = ArrayInitializerExpression(getConverter().typeToType(expression?.getType()), val expressionType = getConverter().typeToType(expression?.getType())
assert(expressionType is ArrayType) { "Array initializer must have array type" }
myResult = ArrayInitializerExpression(expressionType as ArrayType,
getConverter().expressionsToExpressionList(expression?.getInitializers()!!)) getConverter().expressionsToExpressionList(expression?.getInitializers()!!))
} }
@@ -25,6 +25,9 @@ import org.jetbrains.jet.j2k.ast.types.*
import java.util.LinkedList import java.util.LinkedList
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import java.util.ArrayList import java.util.ArrayList
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType
private val PRIMITIVE_TYPES_NAMES = JvmPrimitiveType.values().map { it.getName() }
public open class TypeVisitor(private val myConverter: Converter) : PsiTypeVisitor<Type>() { public open class TypeVisitor(private val myConverter: Converter) : PsiTypeVisitor<Type>() {
private var myResult: Type = EmptyType() private var myResult: Type = EmptyType()
@@ -37,7 +40,7 @@ public open class TypeVisitor(private val myConverter: Converter) : PsiTypeVisit
if (name == "void") { if (name == "void") {
myResult = PrimitiveType(Identifier("Unit")) myResult = PrimitiveType(Identifier("Unit"))
} }
else if (Node.PRIMITIVE_TYPES.contains(name)) { else if (PRIMITIVE_TYPES_NAMES.contains(name)) {
myResult = PrimitiveType(Identifier(StringUtil.capitalize(name))) myResult = PrimitiveType(Identifier(StringUtil.capitalize(name)))
} }
else { else {
@@ -48,7 +51,7 @@ public open class TypeVisitor(private val myConverter: Converter) : PsiTypeVisit
public override fun visitArrayType(arrayType: PsiArrayType?): Type { public override fun visitArrayType(arrayType: PsiArrayType?): Type {
if (myResult is EmptyType) { if (myResult is EmptyType) {
myResult = ArrayType(myConverter.typeToType(arrayType?.getComponentType()), true) myResult = ArrayType(myConverter.typeToType(arrayType?.getComponentType()), true, myConverter)
} }
return myResult return myResult
@@ -63,18 +66,18 @@ public open class TypeVisitor(private val myConverter: Converter) : PsiTypeVisit
if (resolvedClassTypeParams.size() == 1) { if (resolvedClassTypeParams.size() == 1) {
if ((resolvedClassTypeParams.get(0) as ClassType).`type`.name == "Any") { if ((resolvedClassTypeParams.get(0) as ClassType).`type`.name == "Any") {
starParamList.add(StarProjectionType()) starParamList.add(StarProjectionType())
myResult = ClassType(identifier, starParamList, true) myResult = ClassType(identifier, starParamList, true, myConverter)
} }
else { else {
myResult = ClassType(identifier, resolvedClassTypeParams, true) myResult = ClassType(identifier, resolvedClassTypeParams, true, myConverter)
} }
} }
else { else {
myResult = ClassType(identifier, resolvedClassTypeParams, true) myResult = ClassType(identifier, resolvedClassTypeParams, true, myConverter)
} }
} }
else { else {
myResult = ClassType(identifier, myConverter.typesToTypeList(classType.getParameters()), true) myResult = ClassType(identifier, myConverter.typesToTypeList(classType.getParameters()), true, myConverter)
} }
return myResult return myResult
} }
@@ -121,7 +124,7 @@ public open class TypeVisitor(private val myConverter: Converter) : PsiTypeVisit
val boundType: Type = (if (superTypes.size > 0) val boundType: Type = (if (superTypes.size > 0)
ClassType(Identifier(getClassTypeName(superTypes[0])), ClassType(Identifier(getClassTypeName(superTypes[0])),
myConverter.typesToTypeList(superTypes[0].getParameters()), myConverter.typesToTypeList(superTypes[0].getParameters()),
true) true, myConverter)
else else
StarProjectionType()) StarProjectionType())
typeParams.add(boundType) typeParams.add(boundType)