diff --git a/j2k/src/org/jetbrains/jet/j2k/ConstructorConverter.kt b/j2k/src/org/jetbrains/jet/j2k/ConstructorConverter.kt index 2ead40e1d2a..6c0580a20b4 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ConstructorConverter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ConstructorConverter.kt @@ -116,7 +116,7 @@ class ConstructorConverter(private val converter: Converter) { val (field, `type`) = parameterToField[parameter]!! Parameter(field.declarationIdentifier(), `type`, - if (converter.isVal(field)) Parameter.VarValModifier.Val else Parameter.VarValModifier.Var, + if (isVal(field)) Parameter.VarValModifier.Val else Parameter.VarValModifier.Var, converter.convertAnnotations(parameter) + converter.convertAnnotations(field), converter.convertModifiers(field).filter { it in ACCESS_MODIFIERS }).assignPrototypes(listOf(parameter, field), CommentsAndSpacesInheritance(blankLinesBefore = false)) } diff --git a/j2k/src/org/jetbrains/jet/j2k/Converter.kt b/j2k/src/org/jetbrains/jet/j2k/Converter.kt index 1441ef44c85..686c1a14daf 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Converter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/Converter.kt @@ -23,7 +23,6 @@ import java.util.* import com.intellij.psi.CommonClassNames.* import org.jetbrains.jet.lang.types.expressions.OperatorConventions.* import com.intellij.openapi.project.Project -import com.intellij.psi.util.PsiUtil public trait ConversionScope { public fun contains(element: PsiElement): Boolean @@ -235,14 +234,15 @@ public class Converter private(val project: Project, val settings: ConverterSett val typeToDeclare = variableTypeToDeclare(field, settings.specifyFieldTypeByDefault || modifiers.isPublic || modifiers.isProtected, isVal && modifiers.isPrivate) + val initializer = convertExpression(field.getInitializer(), field.getType()) Field(name, annotations, modifiers, typeToDeclare ?: typeConverter.convertVariableType(field), - convertExpression(field.getInitializer(), field.getType()), + initializer, isVal, typeToDeclare != null, - field.hasWriteAccesses(field.getContainingClass())) + initializer.isEmpty && shouldGenerateDefaultInitializer(field)) } return converted.assignPrototype(field) } @@ -264,27 +264,6 @@ public class Converter private(val project: Project, val settings: ConverterSett return if (convertedType == initializerType) null else convertedType } - fun isVal(field: PsiField): Boolean { - if (field.hasModifierProperty(PsiModifier.FINAL)) return true - if (!field.hasModifierProperty(PsiModifier.PRIVATE)) return false - val containingClass = field.getContainingClass() ?: return false - val writes = findVariableUsages(field, containingClass).filter { PsiUtil.isAccessedForWriting(it) } - if (writes.size == 0) return true - if (writes.size > 1) return false - val write = writes.single() - val parent = write.getParent() - if (parent is PsiAssignmentExpression && - parent.getOperationSign().getTokenType() == JavaTokenType.EQ && - isQualifierEmptyOrThis(write)) { - val constructor = write.getContainingConstructor() - return constructor != null && - constructor.getContainingClass() == containingClass && - parent.getParent() is PsiExpressionStatement && - parent.getParent()?.getParent() == constructor.getBody() - } - return false - } - private fun convertMethod(method: PsiMethod, membersToRemove: MutableSet): Member { return withMethodReturnType(method.getReturnType()).doConvertMethod(method, membersToRemove).assignPrototype(method) } diff --git a/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt b/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt index 5e96c897512..546e54442ad 100644 --- a/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt @@ -120,6 +120,12 @@ class TypeConverter(val settings: ConverterSettings, val conversionScope: Conver return nullability } + if (nullability == Nullability.Default) { + if (variable is PsiField && variable.hasModifierProperty(PsiModifier.PRIVATE) && shouldGenerateDefaultInitializer(variable)) { + return Nullability.Nullable + } + } + if (nullability == Nullability.Default) { val scope = searchScope(variable) if (scope != null) { diff --git a/j2k/src/org/jetbrains/jet/j2k/Utils.kt b/j2k/src/org/jetbrains/jet/j2k/Utils.kt index 322e6998ca5..ed18f606af5 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Utils.kt +++ b/j2k/src/org/jetbrains/jet/j2k/Utils.kt @@ -69,6 +69,30 @@ fun getDefaultInitializer(field: Field): Expression { return result.assignNoPrototype() } +fun isVal(field: PsiField): Boolean { + if (field.hasModifierProperty(PsiModifier.FINAL)) return true + if (!field.hasModifierProperty(PsiModifier.PRIVATE)) return false + val containingClass = field.getContainingClass() ?: return false + val writes = findVariableUsages(field, containingClass).filter { PsiUtil.isAccessedForWriting(it) } + if (writes.size == 0) return true + if (writes.size > 1) return false + val write = writes.single() + val parent = write.getParent() + if (parent is PsiAssignmentExpression && + parent.getOperationSign().getTokenType() == JavaTokenType.EQ && + isQualifierEmptyOrThis(write)) { + val constructor = write.getContainingConstructor() + return constructor != null && + constructor.getContainingClass() == containingClass && + parent.getParent() is PsiExpressionStatement && + parent.getParent()?.getParent() == constructor.getBody() + } + return false +} + +fun shouldGenerateDefaultInitializer(field: PsiField) + = field.getInitializer() == null && !(isVal(field) && field.hasWriteAccesses(field.getContainingClass())) + fun isQualifierEmptyOrThis(ref: PsiReferenceExpression): Boolean { val qualifier = ref.getQualifierExpression() return qualifier == null || (qualifier is PsiThisExpression && qualifier.getQualifier() == null) diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt index d0aaa657411..e3e5acecca2 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt @@ -26,7 +26,7 @@ class Field( val initializer: Element, val isVal: Boolean, val explicitType: Boolean, - private val hasWriteAccesses: Boolean + private val defaultInitializer: Boolean ) : Member(annotations, modifiers) { override fun generateCode(builder: CodeBuilder) { @@ -40,7 +40,7 @@ class Field( } var initializerToUse = initializer - if (initializerToUse.isEmpty && !(isVal && hasWriteAccesses)) { + if (initializerToUse.isEmpty && defaultInitializer) { initializerToUse = getDefaultInitializer(this) } if (!initializerToUse.isEmpty) { diff --git a/j2k/tests/testData/ast/enum/enumWithNameField.kt b/j2k/tests/testData/ast/enum/enumWithNameField.kt index 578630d8058..c8d58143b78 100644 --- a/j2k/tests/testData/ast/enum/enumWithNameField.kt +++ b/j2k/tests/testData/ast/enum/enumWithNameField.kt @@ -1,4 +1,4 @@ enum class E { I - private val name: String = 0 + private val name: String? = null } \ No newline at end of file diff --git a/j2k/tests/testData/ast/field/classChildExtendsBase.kt b/j2k/tests/testData/ast/field/classChildExtendsBase.kt index ffd36b6e8ce..c1c9c604157 100644 --- a/j2k/tests/testData/ast/field/classChildExtendsBase.kt +++ b/j2k/tests/testData/ast/field/classChildExtendsBase.kt @@ -1,7 +1,7 @@ class Base { - private val myFirst: String = 0 + private val myFirst: String? = null } class Child : Base() { - private val mySecond: String = 0 + private val mySecond: String? = null } \ No newline at end of file diff --git a/j2k/tests/testData/ast/field/privateField.kt b/j2k/tests/testData/ast/field/privateField.kt index 1aa80e98ddb..5010ae79807 100644 --- a/j2k/tests/testData/ast/field/privateField.kt +++ b/j2k/tests/testData/ast/field/privateField.kt @@ -1,3 +1,3 @@ class C { - private val f: Foo = 0 -} \ No newline at end of file + private val f: Foo? = null +}