Java to Kotlin converter: more cases when field can be declared as val

This commit is contained in:
Valentin Kipyatkov
2014-06-23 20:11:06 +04:00
parent 5a8ab41948
commit e38b1b4fd8
14 changed files with 74 additions and 21 deletions
+25 -2
View File
@@ -285,7 +285,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
else {
val initializer = field.getInitializer()
val convertedType = typeConverter.convertVariableType(field)
val isVal = field.isEffectivelyFinal()
val isVal = isVal(field)
val omitType = !settings.specifyFieldTypeByDefault &&
initializer != null &&
(modifiers.isPrivate && (isVal || convertedType == typeConverter.convertExpressionType(initializer)) ||
@@ -302,6 +302,29 @@ public class Converter private(val project: Project, val settings: ConverterSett
return converted.assignPrototype(field)
}
private 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()
if (constructor != null &&
constructor.getContainingClass() == containingClass &&
parent.getParent() is PsiExpressionStatement &&
parent.getParent()?.getParent() == constructor.getBody()) {
return true
}
}
return false
}
private fun convertMethod(method: PsiMethod, membersToRemove: MutableSet<PsiMember>): Function {
return withMethodReturnType(method.getReturnType()).doConvertMethod(method, membersToRemove).assignPrototype(method)
}
@@ -428,7 +451,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
val (field, `type`) = parameterToField[parameter]!!
Parameter(field.declarationIdentifier(),
`type`,
if (field.hasModifierProperty(PsiModifier.FINAL)) Parameter.VarValModifier.Val else Parameter.VarValModifier.Var,
if (isVal(field)) Parameter.VarValModifier.Val else Parameter.VarValModifier.Var,
convertAnnotations(parameter) + convertAnnotations(field),
convertModifiers(field).filter { it in ACCESS_MODIFIERS }).assignPrototypes(listOf(parameter, field), inheritBlankLinesBefore = false)
}
@@ -263,4 +263,13 @@ class TypeConverter(val settings: ConverterSettings, val conversionScope: Conver
}
return false
}
private fun PsiVariable.isEffectivelyFinal(): Boolean {
if (hasModifierProperty(PsiModifier.FINAL)) return true
return when(this) {
is PsiLocalVariable -> !hasWriteAccesses(getContainingMethod())
is PsiField -> if (hasModifierProperty(PsiModifier.PRIVATE)) !hasWriteAccesses(getContainingClass()) else false
else -> false
}
}
}
-9
View File
@@ -93,12 +93,3 @@ fun PsiElement.isInSingleLine(): Boolean {
}
return true
}
fun PsiVariable.isEffectivelyFinal(): Boolean {
if (hasModifierProperty(PsiModifier.FINAL)) return true
return when(this) {
is PsiLocalVariable -> !hasWriteAccesses(getContainingMethod())
is PsiField -> if (hasModifierProperty(PsiModifier.PRIVATE)) !hasWriteAccesses(getContainingClass()) else false
else -> false
}
}
@@ -1,4 +1,4 @@
public class Identifier<T> private(private val myName: T, private var myHasDollar: Boolean) {
public class Identifier<T> private(private val myName: T, private val myHasDollar: Boolean) {
private var myNullable = true
public fun getName(): T {
@@ -1,4 +1,4 @@
public class Identifier private(private val myName: String, private var myHasDollar: Boolean) {
public class Identifier private(private val myName: String, private val myHasDollar: Boolean) {
private var myNullable = true
public fun getName(): String {
@@ -1,4 +1,4 @@
enum class Color private(private var code: Int) {
enum class Color private(private val code: Int) {
WHITE : Color(21)
BLACK : Color(22)
RED : Color(23)
@@ -1,6 +1,6 @@
package demo
enum class Color private(private var code: Int) {
enum class Color private(private val code: Int) {
public fun getCode(): Int {
return code
@@ -5,6 +5,23 @@ class A {
private int field3 = 0;
final int field4 = 0;
int field5 = 0;
private int field6;
private int field7;
private int field8;
private int field9;
private int field10;
private int field11;
A(int p1, int p2, A a) {
field6 = p1;
field7 = 10;
this.field8 = p2;
this.field9 = 10;
if (p1 > 0) {
this.field10 = 10;
}
a.field11 = 10;
}
void foo() {
field3 = field2;
+14 -1
View File
@@ -1,11 +1,24 @@
class A() {
class A(private val field6: Int, private val field8: Int, a: A) {
private val field1 = 0
private val field2 = 0
private var field3 = 0
val field4 = 0
var field5 = 0
private val field7: Int
private val field9: Int
private var field10: Int = 0
private var field11: Int = 0
fun foo() {
field3 = field2
}
{
field7 = 10
this.field9 = 10
if (field6 > 0) {
this.field10 = 10
}
a.field11 = 10
}
}
@@ -1,3 +1,3 @@
class Base<T>(name: T)
class One<T, K>(name: T, private var mySecond: K) : Base<T>(name)
class One<T, K>(name: T, private val mySecond: K) : Base<T>(name)
@@ -1,3 +1,3 @@
class Base(name: String)
class One(name: String, private var mySecond: String) : Base(name)
class One(name: String, private val mySecond: String) : Base(name)
+1 -1
View File
@@ -1,4 +1,4 @@
public class Identifier<T> private(private val myName: T, private var myHasDollar: Boolean) {
public class Identifier<T> private(private val myName: T, private val myHasDollar: Boolean) {
private var myNullable = true
public fun getName(): T {
@@ -1,4 +1,4 @@
class C(private var s: String?) {
class C(private val s: String?) {
fun foo() {
if (s != null) {
@@ -1,4 +1,4 @@
class C(private var s: String?) {
class C(private val s: String?) {
{
if (s == null) {
System.out.print("null")