diff --git a/annotations/com/intellij/openapi/util/text/annotations.xml b/annotations/com/intellij/openapi/util/text/annotations.xml
new file mode 100644
index 00000000000..92e32317eee
--- /dev/null
+++ b/annotations/com/intellij/openapi/util/text/annotations.xml
@@ -0,0 +1,5 @@
+
+ -
+
+
+
diff --git a/j2k/src/org/jetbrains/jet/j2k/ClassBodyConverter.kt b/j2k/src/org/jetbrains/jet/j2k/ClassBodyConverter.kt
index efc27184492..8f9741175e2 100644
--- a/j2k/src/org/jetbrains/jet/j2k/ClassBodyConverter.kt
+++ b/j2k/src/org/jetbrains/jet/j2k/ClassBodyConverter.kt
@@ -24,21 +24,43 @@ import com.intellij.psi.PsiAnnotationMethod
import java.util.ArrayList
import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiMethod
-import com.intellij.psi.PsiField
-import com.intellij.psi.PsiClassInitializer
import org.jetbrains.jet.j2k.ast.*
+import com.intellij.psi.PsiField
+import com.intellij.psi.PsiReturnStatement
+import com.intellij.psi.PsiReferenceExpression
+import com.intellij.openapi.util.text.StringUtil
+import java.util.HashMap
+import com.intellij.psi.PsiClassInitializer
+import com.intellij.psi.PsiExpressionStatement
+import com.intellij.psi.PsiAssignmentExpression
+import com.intellij.psi.PsiExpression
+import com.intellij.psi.JavaTokenType
+import org.jetbrains.jet.j2k.visitors.ExpressionConverter
+import com.intellij.psi.PsiElementFactory
+
+class FieldCorrectionInfo(val name: Identifier, val access: Modifier?, val setterAccess: Modifier?)
class ClassBodyConverter(private val psiClass: PsiClass,
- private val converter: Converter,
- private val constructorConverter: ConstructorConverter?) {
+ private val converter: Converter) {
+ private val membersToRemove = HashSet()
+ private val fieldCorrections = HashMap()
+
public fun convertBody(): ClassBody {
- val membersToRemove = HashSet()
+ processAccessorsToDrop()
+
+ val correctedConverter = buildConverterWithCorrectedFieldNames()
+
+ val constructorConverter = if (psiClass.getName() != null)
+ ConstructorConverter(psiClass, correctedConverter, fieldCorrections)
+ else
+ null
+
val convertedMembers = LinkedHashMap()
for (element in psiClass.getChildren()) {
if (element is PsiMember) {
if (element is PsiAnnotationMethod) continue // converted in convertAnnotationType()
- val converted = converter.convertMember(element, membersToRemove, constructorConverter)
+ val converted = correctedConverter.convertMember(element, membersToRemove, constructorConverter)
if (converted != null && !converted.isEmpty) {
convertedMembers.put(element, converted)
}
@@ -78,7 +100,21 @@ class ClassBodyConverter(private val psiClass: PsiClass,
val lBrace = LBrace().assignPrototype(psiClass.getLBrace())
val rBrace = RBrace().assignPrototype(psiClass.getRBrace())
- return ClassBody(primaryConstructorSignature, members, classObjectMembers, factoryFunctions, lBrace, rBrace)
+ val classBody = ClassBody(primaryConstructorSignature, constructorConverter?.baseClassParams ?: listOf(), members, classObjectMembers, factoryFunctions, lBrace, rBrace)
+
+ return if (constructorConverter != null) constructorConverter.postProcessConstructors(classBody) else classBody
+ }
+
+ private fun Converter.convertMember(member: PsiMember,
+ membersToRemove: MutableSet,
+ constructorConverter: ConstructorConverter?): Member? {
+ return when (member) {
+ is PsiMethod -> convertMethod(member, membersToRemove, constructorConverter)
+ is PsiField -> convertField(member, fieldCorrections[member])
+ is PsiClass -> convertClass(member)
+ is PsiClassInitializer -> convertInitializer(member)
+ else -> throw IllegalArgumentException("Unknown member: $member")
+ }
}
// do not convert private static methods into class object if possible
@@ -101,4 +137,115 @@ class ClassBodyConverter(private val psiClass: PsiClass,
// we generate nested classes with factory functions into class object as a workaround until secondary constructors supported by Kotlin
private fun shouldGenerateIntoClassObject(nestedClass: Class)
= !nestedClass.modifiers.contains(Modifier.INNER) && nestedClass.body.factoryFunctions.isNotEmpty()
+
+ private fun processAccessorsToDrop() {
+ val fieldToGetterInfo = HashMap()
+ val fieldToSetterInfo = HashMap()
+ val fieldsWithConflict = HashSet()
+ for (method in psiClass.getMethods()) {
+ val info = getAccessorInfo(method) ?: continue
+ val map = if (info.kind == AccessorKind.GETTER) fieldToGetterInfo else fieldToSetterInfo
+
+ val prevInfo = map[info.field]
+ if (prevInfo != null) {
+ fieldsWithConflict.add(info.field)
+ continue
+ }
+
+ map[info.field] = info
+ }
+
+ for ((field, getterInfo) in fieldToGetterInfo) {
+ val setterInfo = run {
+ val info = fieldToSetterInfo[field]
+ if (info?.propertyName == getterInfo.propertyName) info else null
+ }
+
+ membersToRemove.add(getterInfo.method)
+ if (setterInfo != null) {
+ membersToRemove.add(setterInfo.method)
+ }
+
+ val getterAccess = converter.convertModifiers(getterInfo.method).accessModifier()
+ val setterAccess = if (setterInfo != null)
+ converter.convertModifiers(setterInfo.method).accessModifier()
+ else
+ converter.convertModifiers(field).accessModifier()
+ //TODO: check that setter access is not bigger
+ fieldCorrections[field] = FieldCorrectionInfo(Identifier(getterInfo.propertyName).assignNoPrototype(),
+ getterAccess,
+ setterAccess)
+ }
+ }
+
+ private enum class AccessorKind {
+ GETTER
+ SETTER
+ }
+
+ private class AccessorInfo(val method: PsiMethod, val field: PsiField, val kind: AccessorKind, val propertyName: String)
+
+ private fun getAccessorInfo(method: PsiMethod): AccessorInfo? {
+ val name = method.getName()
+ if (name.startsWith("get") && method.getParameterList().getParametersCount() == 0) {
+ val body = method.getBody() ?: return null
+ val returnStatement = (body.getStatements().singleOrNull() as? PsiReturnStatement) ?: return null
+ val field = fieldByExpression(returnStatement.getReturnValue()) ?: return null
+ val propertyName = StringUtil.decapitalize(name.substring("get".length))
+ return AccessorInfo(method, field, AccessorKind.GETTER, propertyName)
+ }
+ else if (name.startsWith("set") && method.getParameterList().getParametersCount() == 1) {
+ val body = method.getBody() ?: return null
+ val statement = (body.getStatements().singleOrNull() as? PsiExpressionStatement) ?: return null
+ val assignment = statement.getExpression() as? PsiAssignmentExpression ?: return null
+ if (assignment.getOperationTokenType() != JavaTokenType.EQ) return null
+ val field = fieldByExpression(assignment.getLExpression()) ?: return null
+ if ((assignment.getRExpression() as? PsiReferenceExpression)?.resolve() != method.getParameterList().getParameters().single()) return null
+ val propertyName = StringUtil.decapitalize(name.substring("set".length))
+ return AccessorInfo(method, field, AccessorKind.SETTER, propertyName)
+ }
+ else {
+ return null
+ }
+ }
+
+ private fun fieldByExpression(expression: PsiExpression?): PsiField? {
+ val refExpr = expression as? PsiReferenceExpression ?: return null
+ if (!refExpr.isQualifierEmptyOrThis()) return null
+ val field = refExpr.resolve() as? PsiField ?: return null
+ if (field.getContainingClass() != psiClass || field.hasModifierProperty(PsiModifier.STATIC)) return null
+ return field
+ }
+
+ //TODO: correct usages to accessors (and field too) across all code being converted + all other Kotlin code in the project
+ private fun buildConverterWithCorrectedFieldNames(): Converter {
+ if (fieldCorrections.isEmpty()) return converter
+ return converter.withExpressionConverter { prevExpressionConverter ->
+ object : ExpressionConverter {
+ override fun convertExpression(expression: PsiExpression, converter: Converter): Expression {
+ val result = prevExpressionConverter.convertExpression(expression, converter)
+ if (expression !is PsiReferenceExpression) return result
+
+ val field = expression.resolve() as? PsiField ?: return result
+ val correction = fieldCorrections[field] ?: return result
+ if (correction.name.name == field.getName()) return result
+
+ val qualifier = expression.getQualifierExpression()
+ return if (qualifier != null) {
+ QualifiedExpression(converter.convertExpression(qualifier), correction.name)
+ }
+ else {
+ // check if field name is shadowed
+ val elementFactory = PsiElementFactory.SERVICE.getInstance(expression.getProject())
+ val refExpr = elementFactory.createExpressionFromText(correction.name.name, expression) as PsiReferenceExpression
+ if (refExpr.resolve() == null)
+ correction.name
+ else
+ QualifiedExpression(ThisExpression(Identifier.Empty).assignNoPrototype(), correction.name) //TODO: this is not correct in case of nested/anonymous classes
+ }
+
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/j2k/src/org/jetbrains/jet/j2k/ConstructorConverter.kt b/j2k/src/org/jetbrains/jet/j2k/ConstructorConverter.kt
index f6309743320..89ee5e25154 100644
--- a/j2k/src/org/jetbrains/jet/j2k/ConstructorConverter.kt
+++ b/j2k/src/org/jetbrains/jet/j2k/ConstructorConverter.kt
@@ -18,13 +18,15 @@ package org.jetbrains.jet.j2k
import com.intellij.psi.*
import org.jetbrains.jet.j2k.ast.*
-import org.jetbrains.jet.j2k.visitors.ExpressionVisitor
import com.intellij.psi.util.PsiUtil
import java.util.HashMap
import java.util.ArrayList
import java.util.HashSet
+import org.jetbrains.jet.j2k.visitors.ExpressionConverter
-class ConstructorConverter(private val psiClass: PsiClass, private val converter: Converter) {
+class ConstructorConverter(private val psiClass: PsiClass,
+ private val converter: Converter,
+ private val fieldCorrections: Map) {
private val typeConverter = converter.typeConverter
private val tempValName: String = "__"
@@ -163,23 +165,25 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
if (constructor in constructorsToDrop) return null
val params = converter.convertParameterList(constructor.getParameterList())
- val bodyConverter = converter.withExpressionVisitor { object : ExpressionVisitor(it) {
- override fun visitReferenceExpression(expression: PsiReferenceExpression) {
- if (isQualifierEmptyOrThis(expression)) {
- val member = expression.getReference()?.resolve() as? PsiMember
- if (member != null &&
+ val bodyConverter = converter.withExpressionConverter { prevExpressionConverter ->
+ object : ExpressionConverter {
+ override fun convertExpression(expression: PsiExpression, converter: Converter): Expression {
+ if (expression is PsiReferenceExpression && expression.isQualifierEmptyOrThis()) {
+ val member = expression.getReference()?.resolve() as? PsiMember
+ if (member != null &&
!member.isConstructor() &&
member.getContainingClass() == constructor.getContainingClass()) {
- val isNullable = member is PsiField && typeConverter.variableNullability(member).isNullable(converter.settings)
- val qualifier = if (member.hasModifierProperty(PsiModifier.STATIC)) constructor.declarationIdentifier() else tempValIdentifier()
- result = QualifiedExpression(qualifier, Identifier(expression.getReferenceName()!!, isNullable).assignNoPrototype())
- return
+ val isNullable = member is PsiField && typeConverter.variableNullability(member).isNullable(converter.settings)
+ val qualifier = if (member.hasModifierProperty(PsiModifier.STATIC)) constructor.declarationIdentifier() else tempValIdentifier()
+ val name = fieldCorrections[member]?.name ?: Identifier(expression.getReferenceName()!!, isNullable).assignNoPrototype()
+ return QualifiedExpression(qualifier, name)
+ }
}
- }
- super.visitReferenceExpression(expression)
+ return prevExpressionConverter.convertExpression(expression, converter)
+ }
}
- }}
+ }
var body = postProcessBody(bodyConverter.convertBlock(constructor.getBody()))
val containingClass = constructor.getContainingClass()
val typeParameterList = converter.convertTypeParameterList(containingClass?.getTypeParameterList())
@@ -219,20 +223,27 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
continue
}
+ val fieldCorrection = fieldCorrections[field]
+ // we cannot specify different setter access for constructor parameter
+ if (fieldCorrection != null && !isVal(converter.referenceSearcher, field) && fieldCorrection.access != fieldCorrection.setterAccess) continue
+
parameterToField.put(parameter, field to type)
statementsToRemove.add(initializationStatement)
membersToRemove.add(field)
- if (field.getName() != parameter.getName()) {
- parameterUsageReplacementMap.put(parameter.getName()!!, field.getName()!!)
+ val fieldName = fieldCorrection?.name?.name ?: field.getName()!!
+ if (fieldName != parameter.getName()) {
+ parameterUsageReplacementMap.put(parameter.getName()!!, fieldName)
}
}
- val bodyConverter = converter.withExpressionVisitor {
- object : ReplacingExpressionVisitor(this, parameterUsageReplacementMap, it) {
- override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
- if (expression.isSuperConstructorCall()) return // skip it
- super.visitMethodCallExpression(expression)
+ val bodyConverter = converter.withExpressionConverter { prevExpressionConverter ->
+ object : ReplacingExpressionConverter(this, parameterUsageReplacementMap, prevExpressionConverter) {
+ override fun convertExpression(expression: PsiExpression, converter: Converter): Expression {
+ if (expression is PsiMethodCallExpression && expression.isSuperConstructorCall()) {
+ return Expression.Empty // skip it
+ }
+ return super.convertExpression(expression, converter)
}
}
}
@@ -243,7 +254,7 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
}
// we need to replace renamed parameter usages in base class constructor arguments and in default values
- val correctedConverter = converter.withExpressionVisitor { ReplacingExpressionVisitor(this, parameterUsageReplacementMap, it) }
+ val correctedConverter = converter.withExpressionConverter { prevExpressionConverter -> ReplacingExpressionConverter(this, parameterUsageReplacementMap, prevExpressionConverter) }
.withSpecialContext(psiClass) /* to correct nested class references */
val statement = primaryConstructor.getBody()?.getStatements()?.firstOrNull()
@@ -264,11 +275,17 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
}
else {
val (field, type) = parameterToField[parameter]!!
- Parameter(field.declarationIdentifier(),
+ val fieldCorrection = fieldCorrections[field]
+ val name = fieldCorrection?.name ?: field.declarationIdentifier()
+ val accessModifiers = if (fieldCorrection != null)
+ Modifiers(listOf()).with(fieldCorrection.access).assignNoPrototype()
+ else
+ converter.convertModifiers(field).filter { it in ACCESS_MODIFIERS }
+ Parameter(name,
type,
if (isVal(converter.referenceSearcher, field)) Parameter.VarValModifier.Val else Parameter.VarValModifier.Var,
converter.convertAnnotations(parameter) + converter.convertAnnotations(field),
- converter.convertModifiers(field).filter { it in ACCESS_MODIFIERS },
+ accessModifiers,
defaultValue).assignPrototypes(listOf(parameter, field), CommentsAndSpacesInheritance(blankLinesBefore = false))
}
}).assignPrototype(primaryConstructor.getParameterList())
@@ -286,7 +303,7 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
val assignment = ref.getParent() as? PsiAssignmentExpression ?: continue
if (assignment.getOperationSign().getTokenType() != JavaTokenType.EQ) continue
val assignee = assignment.getLExpression() as? PsiReferenceExpression ?: continue
- if (!isQualifierEmptyOrThis(assignee)) continue
+ if (!assignee.isQualifierEmptyOrThis()) continue
val field = assignee.resolve() as? PsiField ?: continue
if (field.getContainingClass() != constructor.getContainingClass()) continue
if (field.hasModifierProperty(PsiModifier.STATIC)) continue
@@ -297,7 +314,7 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
if (statement.getParent() != body) continue
// and no other assignments to field should exist in the constructor
- if (converter.referenceSearcher.findVariableUsages(field, body).any { it != assignee && PsiUtil.isAccessedForWriting(it) && isQualifierEmptyOrThis(it) }) continue
+ if (converter.referenceSearcher.findVariableUsages(field, body).any { it != assignee && PsiUtil.isAccessedForWriting(it) && it.isQualifierEmptyOrThis() }) continue
//TODO: check access to field before assignment
return field to statement
@@ -312,7 +329,7 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
}
else {
val updatedFunctions = processFactoryFunctionsWithConstructorCall(classBody.factoryFunctions)
- return ClassBody(classBody.primaryConstructorSignature, classBody.members, classBody.classObjectMembers, updatedFunctions, classBody.lBrace, classBody.rBrace)
+ return ClassBody(classBody.primaryConstructorSignature, classBody.baseClassParams, classBody.members, classBody.classObjectMembers, updatedFunctions, classBody.lBrace, classBody.rBrace)
}
}
@@ -341,7 +358,7 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
val parameterList = ParameterList(parameters).assignNoPrototype()
val constructorSignature = PrimaryConstructorSignature(Annotations.Empty, modifiers, parameterList).assignNoPrototype()
val updatedMembers = classBody.members.filter { !fieldsToInitialize.contains(it) }
- return ClassBody(constructorSignature, updatedMembers, classBody.classObjectMembers, updatedFactoryFunctions, classBody.lBrace, classBody.rBrace)
+ return ClassBody(constructorSignature, classBody.baseClassParams, updatedMembers, classBody.classObjectMembers, updatedFactoryFunctions, classBody.lBrace, classBody.rBrace)
}
private fun processFactoryFunctionsWithConstructorCall(functions: List): List {
@@ -443,11 +460,11 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
return ref.getCanonicalText() == "super" && ref.resolve()?.isConstructor() ?: false
}
- private /*inner*//*TODO:KT-5343*/ open class ReplacingExpressionVisitor(
- val owner: ConstructorConverter,
- val parameterUsageReplacementMap: Map, converter: Converter) : ExpressionVisitor(converter) {
- override fun visitReferenceExpression(expression: PsiReferenceExpression) {
- if (expression.getQualifier() == null) {
+ private /*inner*//*TODO: see KT-5343*/ open class ReplacingExpressionConverter(val owner: ConstructorConverter,
+ val parameterUsageReplacementMap: Map,
+ val prevExpressionConverter: ExpressionConverter) : ExpressionConverter {
+ override fun convertExpression(expression: PsiExpression, converter: Converter): Expression {
+ if (expression is PsiReferenceExpression && expression.getQualifier() == null) {
val replacement = parameterUsageReplacementMap[expression.getReferenceName()]
if (replacement != null) {
val target = expression.getReference()?.resolve()
@@ -455,14 +472,13 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
val scope = target.getDeclarationScope()
// we do not check for exactly this constructor because default values reference parameters in other constructors
if (scope.isConstructor() && scope.getParent() == owner.psiClass) {
- result = Identifier(replacement, owner.typeConverter.variableNullability(target).isNullable(owner.converter.settings))
- return
+ return Identifier(replacement, converter.typeConverter.variableNullability(target).isNullable(converter.settings))
}
}
}
}
- super.visitReferenceExpression(expression)
+ return prevExpressionConverter.convertExpression(expression, converter)
}
}
}
\ No newline at end of file
diff --git a/j2k/src/org/jetbrains/jet/j2k/Converter.kt b/j2k/src/org/jetbrains/jet/j2k/Converter.kt
index 5ee0915d671..09ff3452a70 100644
--- a/j2k/src/org/jetbrains/jet/j2k/Converter.kt
+++ b/j2k/src/org/jetbrains/jet/j2k/Converter.kt
@@ -51,7 +51,7 @@ public class Converter private(val project: Project,
private val postProcessor: PostProcessor?,
private val state: Converter.State) {
private class State(val methodReturnType: PsiType?,
- val expressionVisitorFactory: (Converter) -> ExpressionVisitor,
+ val expressionConverter: ExpressionConverter,
val statementVisitorFactory: (Converter) -> StatementVisitor,
val specialContext: PsiElement?,
val importList: ImportList?,
@@ -64,7 +64,6 @@ public class Converter private(val project: Project,
val importNames: Set = state.importList?.imports?.mapTo(HashSet()) { it.name } ?: setOf()
val importsToAdd: MutableCollection? = state.importsToAdd
- private val expressionVisitor = state.expressionVisitorFactory(this)
private val statementVisitor = state.statementVisitorFactory(this)
val annotationConverter = AnnotationConverter(this)
@@ -74,34 +73,34 @@ public class Converter private(val project: Project,
public fun create(project: Project, settings: ConverterSettings, conversionScope: ConversionScope,
referenceSearcher: ReferenceSearcher, postProcessor: PostProcessor?): Converter {
- val state = State(null, { ExpressionVisitor(it) }, { StatementVisitor(it) }, null, null, null)
+ val state = State(null, ExpressionVisitor(), { StatementVisitor(it) }, null, null, null)
return Converter(project, settings, conversionScope, referenceSearcher, postProcessor, state)
}
}
fun withMethodReturnType(methodReturnType: PsiType?): Converter
= Converter(project, settings, conversionScope, referenceSearcher, postProcessor,
- State(methodReturnType, state.expressionVisitorFactory, state.statementVisitorFactory, state.specialContext, state.importList, state.importsToAdd))
+ State(methodReturnType, state.expressionConverter, state.statementVisitorFactory, state.specialContext, state.importList, state.importsToAdd))
- fun withExpressionVisitor(factory: (Converter) -> ExpressionVisitor): Converter
+ fun withExpressionConverter(factory: (prevConverter: ExpressionConverter) -> ExpressionConverter): Converter
= Converter(project, settings, conversionScope, referenceSearcher, postProcessor,
- State(state.methodReturnType, factory, state.statementVisitorFactory, state.specialContext, state.importList, state.importsToAdd))
+ State(state.methodReturnType, factory(state.expressionConverter), state.statementVisitorFactory, state.specialContext, state.importList, state.importsToAdd))
fun withStatementVisitor(factory: (Converter) -> StatementVisitor): Converter
= Converter(project, settings, conversionScope, referenceSearcher, postProcessor,
- State(state.methodReturnType, state.expressionVisitorFactory, factory, state.specialContext, state.importList, state.importsToAdd))
+ State(state.methodReturnType, state.expressionConverter, factory, state.specialContext, state.importList, state.importsToAdd))
fun withSpecialContext(context: PsiElement): Converter
= Converter(project, settings, conversionScope, referenceSearcher, postProcessor,
- State(state.methodReturnType, state.expressionVisitorFactory, state.statementVisitorFactory, context, state.importList, state.importsToAdd))
+ State(state.methodReturnType, state.expressionConverter, state.statementVisitorFactory, context, state.importList, state.importsToAdd))
private fun withImportList(importList: ImportList): Converter
= Converter(project, settings, conversionScope, referenceSearcher, postProcessor,
- State(state.methodReturnType, state.expressionVisitorFactory, state.statementVisitorFactory, state.specialContext, importList, state.importsToAdd))
+ State(state.methodReturnType, state.expressionConverter, state.statementVisitorFactory, state.specialContext, importList, state.importsToAdd))
private fun withImportsToAdd(importsToAdd: MutableCollection): Converter
= Converter(project, settings, conversionScope, referenceSearcher, postProcessor,
- State(state.methodReturnType, state.expressionVisitorFactory, state.statementVisitorFactory, state.specialContext, state.importList, importsToAdd))
+ State(state.methodReturnType, state.expressionConverter, state.statementVisitorFactory, state.specialContext, state.importList, importsToAdd))
public fun elementToKotlin(element: PsiElement): String {
try {
@@ -141,7 +140,7 @@ public class Converter private(val project: Project,
is PsiJavaFile -> convertFile(element)
is PsiClass -> convertClass(element)
is PsiMethod -> convertMethod(element, null, null)
- is PsiField -> convertField(element)
+ is PsiField -> convertField(element, null)
is PsiStatement -> convertStatement(element)
is PsiExpression -> convertExpression(element)
is PsiImportList -> convertImportList(element)
@@ -185,18 +184,10 @@ public class Converter private(val project: Project,
}
fun convertAnonymousClassBody(anonymousClass: PsiAnonymousClass): AnonymousClassBody {
- return AnonymousClassBody(ClassBodyConverter(anonymousClass, this, null).convertBody(),
+ return AnonymousClassBody(ClassBodyConverter(anonymousClass, this).convertBody(),
anonymousClass.getBaseClassType().resolve()?.isInterface() ?: false).assignPrototype(anonymousClass)
}
- fun convertMember(member: PsiMember, membersToRemove: MutableSet, constructorConverter: ConstructorConverter?): Member? = when (member) {
- is PsiMethod -> convertMethod(member, membersToRemove, constructorConverter)
- is PsiField -> convertField(member)
- is PsiClass -> convertClass(member)
- is PsiClassInitializer -> convertInitializer(member)
- else -> throw IllegalArgumentException("Unknown member: $member")
- }
-
fun convertAnnotations(owner: PsiModifierListOwner): Annotations
= annotationConverter.convertAnnotations(owner)
@@ -212,9 +203,7 @@ public class Converter private(val project: Project,
val extendsTypes = convertToNotNullableTypes(psiClass.getExtendsListTypes())
val name = psiClass.declarationIdentifier()
- val constructorConverter = ConstructorConverter(psiClass, this)
- var classBody = ClassBodyConverter(psiClass, this, constructorConverter).convertBody()
- classBody = constructorConverter.postProcessConstructors(classBody)
+ var classBody = ClassBodyConverter(psiClass, this).convertBody()
return when {
psiClass.isInterface() -> Trait(name, annotations, modifiers, typeParameters, extendsTypes, listOf(), implementsTypes, classBody)
@@ -230,7 +219,7 @@ public class Converter private(val project: Project,
modifiers = modifiers.with(Modifier.INNER)
}
- Class(name, annotations, modifiers, typeParameters, extendsTypes, constructorConverter.baseClassParams, implementsTypes, classBody)
+ Class(name, annotations, modifiers, typeParameters, extendsTypes, classBody.baseClassParams, implementsTypes, classBody)
}
}.assignPrototype(psiClass)
}
@@ -259,8 +248,8 @@ public class Converter private(val project: Project,
val constructorSignature = PrimaryConstructorSignature(Annotations.Empty, Modifiers.Empty, parameterList).assignNoPrototype()
// to convert fields and nested types - they are not allowed in Kotlin but we convert them and let user refactor code
- var classBody = ClassBodyConverter(psiClass, this, null).convertBody()
- classBody = ClassBody(constructorSignature, classBody.members, classBody.classObjectMembers, listOf(), classBody.lBrace, classBody.rBrace)
+ var classBody = ClassBodyConverter(psiClass, this).convertBody()
+ classBody = ClassBody(constructorSignature, classBody.baseClassParams, classBody.members, classBody.classObjectMembers, listOf(), classBody.lBrace, classBody.rBrace)
val annotationAnnotation = Annotation(Identifier("annotation").assignNoPrototype(), listOf(), false, false).assignNoPrototype()
return Class(psiClass.declarationIdentifier(),
@@ -273,14 +262,19 @@ public class Converter private(val project: Project,
classBody).assignPrototype(psiClass)
}
- private fun convertInitializer(initializer: PsiClassInitializer): Initializer {
+ fun convertInitializer(initializer: PsiClassInitializer): Initializer {
return Initializer(convertBlock(initializer.getBody()), convertModifiers(initializer)).assignPrototype(initializer)
}
- private fun convertField(field: PsiField): Member {
+ fun convertField(field: PsiField, correction: FieldCorrectionInfo?): Member {
val annotations = annotationConverter.convertAnnotations(field)
- val modifiers = convertModifiers(field)
- val name = field.declarationIdentifier()
+
+ var modifiers = convertModifiers(field)
+ if (correction != null) {
+ modifiers = modifiers.without(modifiers.accessModifier()).with(correction.access)
+ }
+
+ val name = correction?.name ?: field.declarationIdentifier()
val converted = if (field is PsiEnumConstant) {
val argumentList = field.getArgumentList()
EnumConstant(name,
@@ -302,7 +296,8 @@ public class Converter private(val project: Project,
initializer,
isVal,
typeToDeclare != null,
- initializer.isEmpty && shouldGenerateDefaultInitializer(referenceSearcher, field))
+ initializer.isEmpty && shouldGenerateDefaultInitializer(referenceSearcher, field),
+ if (correction != null) correction.setterAccess else modifiers.accessModifier())
}
return converted.assignPrototype(field)
}
@@ -324,7 +319,7 @@ public class Converter private(val project: Project,
return if (convertedType == initializerType) null else convertedType
}
- private fun convertMethod(method: PsiMethod, membersToRemove: MutableSet?, constructorConverter: ConstructorConverter?): Member? {
+ fun convertMethod(method: PsiMethod, membersToRemove: MutableSet?, constructorConverter: ConstructorConverter?): Member? {
return withMethodReturnType(method.getReturnType()).doConvertMethod(method, membersToRemove, constructorConverter)?.assignPrototype(method)
}
@@ -438,9 +433,7 @@ public class Converter private(val project: Project,
fun convertExpression(expression: PsiExpression?): Expression {
if (expression == null) return Expression.Empty
- expressionVisitor.reset()
- expression.accept(expressionVisitor)
- return expressionVisitor.result.assignPrototype(expression)
+ return state.expressionConverter.convertExpression(expression, this).assignPrototype(expression)
}
fun convertLocalVariable(variable: PsiLocalVariable): LocalVariable {
diff --git a/j2k/src/org/jetbrains/jet/j2k/Utils.kt b/j2k/src/org/jetbrains/jet/j2k/Utils.kt
index a1c93facc19..9ccee917190 100644
--- a/j2k/src/org/jetbrains/jet/j2k/Utils.kt
+++ b/j2k/src/org/jetbrains/jet/j2k/Utils.kt
@@ -61,7 +61,7 @@ fun isVal(searcher: ReferenceSearcher, field: PsiField): Boolean {
val parent = write.getParent()
if (parent is PsiAssignmentExpression &&
parent.getOperationSign().getTokenType() == JavaTokenType.EQ &&
- isQualifierEmptyOrThis(write)) {
+ write.isQualifierEmptyOrThis()) {
val constructor = write.getContainingConstructor()
return constructor != null &&
constructor.getContainingClass() == containingClass &&
@@ -74,8 +74,8 @@ fun isVal(searcher: ReferenceSearcher, field: PsiField): Boolean {
fun shouldGenerateDefaultInitializer(searcher: ReferenceSearcher, field: PsiField)
= field.getInitializer() == null && !(isVal(searcher, field) && field.hasWriteAccesses(searcher, field.getContainingClass()))
-fun isQualifierEmptyOrThis(ref: PsiReferenceExpression): Boolean {
- val qualifier = ref.getQualifierExpression()
+fun PsiReferenceExpression.isQualifierEmptyOrThis(): Boolean {
+ val qualifier = getQualifierExpression()
return qualifier == null || (qualifier is PsiThisExpression && qualifier.getQualifier() == null)
}
@@ -93,6 +93,7 @@ fun PsiElement.isInSingleLine(): Boolean {
return true
}
+//TODO: check for variables that are definitely assigned in constructors
fun PsiElement.getContainingMethod(): PsiMethod? {
var context = getContext()
while (context != null) {
diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/ClassBody.kt b/j2k/src/org/jetbrains/jet/j2k/ast/ClassBody.kt
index d91763afbf5..d2ce78f18fa 100644
--- a/j2k/src/org/jetbrains/jet/j2k/ast/ClassBody.kt
+++ b/j2k/src/org/jetbrains/jet/j2k/ast/ClassBody.kt
@@ -20,9 +20,9 @@ import org.jetbrains.jet.j2k.*
abstract class Member(val annotations: Annotations, val modifiers: Modifiers) : Element()
-//TODO: should be Element?
class ClassBody (
val primaryConstructorSignature: PrimaryConstructorSignature?,
+ val baseClassParams: List,
val members: List,
val classObjectMembers: List,
val factoryFunctions: List,
diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt
index 901ae295fff..7ea324efc6e 100644
--- a/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt
+++ b/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt
@@ -26,7 +26,8 @@ class Field(
val initializer: Element,
val isVal: Boolean,
val explicitType: Boolean,
- private val defaultInitializer: Boolean
+ private val defaultInitializer: Boolean,
+ val setterAccess: Modifier?
) : Member(annotations, modifiers) {
override fun generateCode(builder: CodeBuilder) {
@@ -46,5 +47,13 @@ class Field(
if (!initializerToUse.isEmpty) {
builder append " = " append initializerToUse
}
+
+ if (!isVal && setterAccess != modifiers.accessModifier()) {
+ builder.append("\n")
+ if (setterAccess != null) {
+ builder.appendWithSpaceAfter(Modifiers(listOf(setterAccess)).assignNoPrototype())
+ }
+ builder.append("set")
+ }
}
}
diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt
index ff3244e7e39..27f6d277ddf 100644
--- a/j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt
+++ b/j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt
@@ -43,7 +43,8 @@ class Modifiers(val modifiers: Collection) : Element() {
fun with(modifier: Modifier?): Modifiers = if (modifier != null) Modifiers(modifiers + listOf(modifier)).assignPrototypesFrom(this) else this
- fun without(modifier: Modifier): Modifiers {
+ fun without(modifier: Modifier?): Modifiers {
+ if (modifier == null) return this
val set = HashSet(modifiers)
set.remove(modifier)
return Modifiers(set).assignPrototypesFrom(this)
diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt
index 2d45ab76de6..b8ef5e83522 100644
--- a/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt
+++ b/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt
@@ -38,14 +38,25 @@ import org.jetbrains.jet.lang.resolve.name.FqName
import org.jetbrains.jet.asJava.KotlinLightField
import org.jetbrains.jet.lang.psi.JetObjectDeclaration
-open class ExpressionVisitor(private val converter: Converter) : JavaElementVisitor() {
- private val typeConverter = converter.typeConverter
+trait ExpressionConverter {
+ fun convertExpression(expression: PsiExpression, converter: Converter): Expression
+}
- public var result: Expression = Expression.Empty
- protected set
+class ExpressionVisitor : JavaElementVisitor(), ExpressionConverter {
+ private var _converter: Converter? = null
+ private var result: Expression = Expression.Empty
- public fun reset() {
+ private val converter: Converter get() {
+ return _converter!!
+ }
+ private val typeConverter: TypeConverter get() = converter.typeConverter
+
+ override fun convertExpression(expression: PsiExpression, converter: Converter): Expression {
+ this._converter = converter
result = Expression.Empty
+
+ expression.accept(this)
+ return result
}
override fun visitArrayAccessExpression(expression: PsiArrayAccessExpression) {
diff --git a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java
index 03e0805b05d..f8ea3d63b20 100644
--- a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java
+++ b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java
@@ -17,10 +17,13 @@
package org.jetbrains.jet.j2k.test;
import com.intellij.testFramework.TestDataPath;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.junit.runner.RunWith;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.test.InnerTestClasses;
import org.jetbrains.jet.test.TestMetadata;
-import org.junit.runner.RunWith;
+import org.jetbrains.jet.JUnit3RunnerWithInners;
import java.io.File;
import java.util.regex.Pattern;
@@ -29,7 +32,7 @@ import java.util.regex.Pattern;
@SuppressWarnings("all")
@TestMetadata("j2k/tests/testData/ast")
@TestDataPath("$PROJECT_ROOT")
-@InnerTestClasses({JavaToKotlinConverterTestGenerated.Annotations.class, JavaToKotlinConverterTestGenerated.AnonymousBlock.class, JavaToKotlinConverterTestGenerated.ArrayAccessExpression.class, JavaToKotlinConverterTestGenerated.ArrayInitializerExpression.class, JavaToKotlinConverterTestGenerated.ArrayType.class, JavaToKotlinConverterTestGenerated.AssertStatement.class, JavaToKotlinConverterTestGenerated.AssignmentExpression.class, JavaToKotlinConverterTestGenerated.BinaryExpression.class, JavaToKotlinConverterTestGenerated.Blocks.class, JavaToKotlinConverterTestGenerated.BoxedType.class, JavaToKotlinConverterTestGenerated.BreakStatement.class, JavaToKotlinConverterTestGenerated.CallChainExpression.class, JavaToKotlinConverterTestGenerated.Class.class, JavaToKotlinConverterTestGenerated.ClassExpression.class, JavaToKotlinConverterTestGenerated.Comments.class, JavaToKotlinConverterTestGenerated.ConditionalExpression.class, JavaToKotlinConverterTestGenerated.Constructors.class, JavaToKotlinConverterTestGenerated.ContinueStatement.class, JavaToKotlinConverterTestGenerated.DeclarationStatement.class, JavaToKotlinConverterTestGenerated.DoWhileStatement.class, JavaToKotlinConverterTestGenerated.Enum.class, JavaToKotlinConverterTestGenerated.Equals.class, JavaToKotlinConverterTestGenerated.Field.class, JavaToKotlinConverterTestGenerated.For.class, JavaToKotlinConverterTestGenerated.ForeachStatement.class, JavaToKotlinConverterTestGenerated.Formatting.class, JavaToKotlinConverterTestGenerated.Function.class, JavaToKotlinConverterTestGenerated.Identifier.class, JavaToKotlinConverterTestGenerated.IfStatement.class, JavaToKotlinConverterTestGenerated.ImportStatement.class, JavaToKotlinConverterTestGenerated.InProjectionType.class, JavaToKotlinConverterTestGenerated.Inheritance.class, JavaToKotlinConverterTestGenerated.IsOperator.class, JavaToKotlinConverterTestGenerated.Issues.class, JavaToKotlinConverterTestGenerated.KotlinApiAccess.class, JavaToKotlinConverterTestGenerated.LabelStatement.class, JavaToKotlinConverterTestGenerated.List.class, JavaToKotlinConverterTestGenerated.LiteralExpression.class, JavaToKotlinConverterTestGenerated.LocalVariable.class, JavaToKotlinConverterTestGenerated.MethodCallExpression.class, JavaToKotlinConverterTestGenerated.Misc.class, JavaToKotlinConverterTestGenerated.NewClassExpression.class, JavaToKotlinConverterTestGenerated.Nullability.class, JavaToKotlinConverterTestGenerated.ObjectLiteral.class, JavaToKotlinConverterTestGenerated.OutProjectionType.class, JavaToKotlinConverterTestGenerated.PackageStatement.class, JavaToKotlinConverterTestGenerated.ParenthesizedExpression.class, JavaToKotlinConverterTestGenerated.PolyadicExpression.class, JavaToKotlinConverterTestGenerated.PostfixOperator.class, JavaToKotlinConverterTestGenerated.PrefixOperator.class, JavaToKotlinConverterTestGenerated.RawGenerics.class, JavaToKotlinConverterTestGenerated.ReturnStatement.class, JavaToKotlinConverterTestGenerated.Settings.class, JavaToKotlinConverterTestGenerated.StarProjectionType.class, JavaToKotlinConverterTestGenerated.StaticMembers.class, JavaToKotlinConverterTestGenerated.SuperExpression.class, JavaToKotlinConverterTestGenerated.Switch.class, JavaToKotlinConverterTestGenerated.SynchronizedStatement.class, JavaToKotlinConverterTestGenerated.ThisExpression.class, JavaToKotlinConverterTestGenerated.ThrowStatement.class, JavaToKotlinConverterTestGenerated.ToKotlinClasses.class, JavaToKotlinConverterTestGenerated.Trait.class, JavaToKotlinConverterTestGenerated.TryStatement.class, JavaToKotlinConverterTestGenerated.TryWithResource.class, JavaToKotlinConverterTestGenerated.TypeCastExpression.class, JavaToKotlinConverterTestGenerated.TypeParameters.class, JavaToKotlinConverterTestGenerated.VarArg.class, JavaToKotlinConverterTestGenerated.WhileStatement.class})
+@InnerTestClasses({JavaToKotlinConverterTestGenerated.Annotations.class, JavaToKotlinConverterTestGenerated.AnonymousBlock.class, JavaToKotlinConverterTestGenerated.ArrayAccessExpression.class, JavaToKotlinConverterTestGenerated.ArrayInitializerExpression.class, JavaToKotlinConverterTestGenerated.ArrayType.class, JavaToKotlinConverterTestGenerated.AssertStatement.class, JavaToKotlinConverterTestGenerated.AssignmentExpression.class, JavaToKotlinConverterTestGenerated.BinaryExpression.class, JavaToKotlinConverterTestGenerated.Blocks.class, JavaToKotlinConverterTestGenerated.BoxedType.class, JavaToKotlinConverterTestGenerated.BreakStatement.class, JavaToKotlinConverterTestGenerated.CallChainExpression.class, JavaToKotlinConverterTestGenerated.Class.class, JavaToKotlinConverterTestGenerated.ClassExpression.class, JavaToKotlinConverterTestGenerated.Comments.class, JavaToKotlinConverterTestGenerated.ConditionalExpression.class, JavaToKotlinConverterTestGenerated.Constructors.class, JavaToKotlinConverterTestGenerated.ContinueStatement.class, JavaToKotlinConverterTestGenerated.DeclarationStatement.class, JavaToKotlinConverterTestGenerated.DoWhileStatement.class, JavaToKotlinConverterTestGenerated.DropAccessors.class, JavaToKotlinConverterTestGenerated.Enum.class, JavaToKotlinConverterTestGenerated.Equals.class, JavaToKotlinConverterTestGenerated.Field.class, JavaToKotlinConverterTestGenerated.For.class, JavaToKotlinConverterTestGenerated.ForeachStatement.class, JavaToKotlinConverterTestGenerated.Formatting.class, JavaToKotlinConverterTestGenerated.Function.class, JavaToKotlinConverterTestGenerated.Identifier.class, JavaToKotlinConverterTestGenerated.IfStatement.class, JavaToKotlinConverterTestGenerated.ImportStatement.class, JavaToKotlinConverterTestGenerated.InProjectionType.class, JavaToKotlinConverterTestGenerated.Inheritance.class, JavaToKotlinConverterTestGenerated.IsOperator.class, JavaToKotlinConverterTestGenerated.Issues.class, JavaToKotlinConverterTestGenerated.KotlinApiAccess.class, JavaToKotlinConverterTestGenerated.LabelStatement.class, JavaToKotlinConverterTestGenerated.List.class, JavaToKotlinConverterTestGenerated.LiteralExpression.class, JavaToKotlinConverterTestGenerated.LocalVariable.class, JavaToKotlinConverterTestGenerated.MethodCallExpression.class, JavaToKotlinConverterTestGenerated.Misc.class, JavaToKotlinConverterTestGenerated.NewClassExpression.class, JavaToKotlinConverterTestGenerated.Nullability.class, JavaToKotlinConverterTestGenerated.ObjectLiteral.class, JavaToKotlinConverterTestGenerated.OutProjectionType.class, JavaToKotlinConverterTestGenerated.PackageStatement.class, JavaToKotlinConverterTestGenerated.ParenthesizedExpression.class, JavaToKotlinConverterTestGenerated.PolyadicExpression.class, JavaToKotlinConverterTestGenerated.PostfixOperator.class, JavaToKotlinConverterTestGenerated.PrefixOperator.class, JavaToKotlinConverterTestGenerated.RawGenerics.class, JavaToKotlinConverterTestGenerated.ReturnStatement.class, JavaToKotlinConverterTestGenerated.Settings.class, JavaToKotlinConverterTestGenerated.StarProjectionType.class, JavaToKotlinConverterTestGenerated.StaticMembers.class, JavaToKotlinConverterTestGenerated.SuperExpression.class, JavaToKotlinConverterTestGenerated.Switch.class, JavaToKotlinConverterTestGenerated.SynchronizedStatement.class, JavaToKotlinConverterTestGenerated.ThisExpression.class, JavaToKotlinConverterTestGenerated.ThrowStatement.class, JavaToKotlinConverterTestGenerated.ToKotlinClasses.class, JavaToKotlinConverterTestGenerated.Trait.class, JavaToKotlinConverterTestGenerated.TryStatement.class, JavaToKotlinConverterTestGenerated.TryWithResource.class, JavaToKotlinConverterTestGenerated.TypeCastExpression.class, JavaToKotlinConverterTestGenerated.TypeParameters.class, JavaToKotlinConverterTestGenerated.VarArg.class, JavaToKotlinConverterTestGenerated.WhileStatement.class})
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConverterTest {
public void testAllFilesPresentInAst() throws Exception {
@@ -1310,6 +1313,88 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
}
+ @TestMetadata("j2k/tests/testData/ast/dropAccessors")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
+ public static class DropAccessors extends AbstractJavaToKotlinConverterTest {
+ @TestMetadata("AccessInGetterWithThis.java")
+ public void testAccessInGetterWithThis() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/ast/dropAccessors/AccessInGetterWithThis.java");
+ doTest(fileName);
+ }
+
+ public void testAllFilesPresentInDropAccessors() throws Exception {
+ JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("j2k/tests/testData/ast/dropAccessors"), Pattern.compile("^(.+)\\.java$"), true);
+ }
+
+ @TestMetadata("CannotDropOnlySetter.java")
+ public void testCannotDropOnlySetter() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/ast/dropAccessors/CannotDropOnlySetter.java");
+ doTest(fileName);
+ }
+
+ @TestMetadata("DataClass.java")
+ public void testDataClass() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/ast/dropAccessors/DataClass.java");
+ doTest(fileName);
+ }
+
+ @TestMetadata("DataClassWithMutableField.java")
+ public void testDataClassWithMutableField() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/ast/dropAccessors/DataClassWithMutableField.java");
+ doTest(fileName);
+ }
+
+ @TestMetadata("DifferentFieldName.java")
+ public void testDifferentFieldName() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/ast/dropAccessors/DifferentFieldName.java");
+ doTest(fileName);
+ }
+
+ @TestMetadata("DropGetter.java")
+ public void testDropGetter() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/ast/dropAccessors/DropGetter.java");
+ doTest(fileName);
+ }
+
+ @TestMetadata("DropGetterAndSetter.java")
+ public void testDropGetterAndSetter() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/ast/dropAccessors/DropGetterAndSetter.java");
+ doTest(fileName);
+ }
+
+ @TestMetadata("DropGetterForMutable.java")
+ public void testDropGetterForMutable() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/ast/dropAccessors/DropGetterForMutable.java");
+ doTest(fileName);
+ }
+
+ @TestMetadata("FalseGetter.java")
+ public void testFalseGetter() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/ast/dropAccessors/FalseGetter.java");
+ doTest(fileName);
+ }
+
+ @TestMetadata("FalseSetter.java")
+ public void testFalseSetter() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/ast/dropAccessors/FalseSetter.java");
+ doTest(fileName);
+ }
+
+ @TestMetadata("FieldUsagesInFactoryMethods.java")
+ public void testFieldUsagesInFactoryMethods() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/ast/dropAccessors/FieldUsagesInFactoryMethods.java");
+ doTest(fileName);
+ }
+
+ @TestMetadata("GetterAndSetterNamesDifferent.java")
+ public void testGetterAndSetterNamesDifferent() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/ast/dropAccessors/GetterAndSetterNamesDifferent.java");
+ doTest(fileName);
+ }
+
+ }
+
@TestMetadata("j2k/tests/testData/ast/enum")
@TestDataPath("$PROJECT_ROOT")
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
diff --git a/j2k/tests/testData/ast/class/abstractClassShape.kt b/j2k/tests/testData/ast/class/abstractClassShape.kt
index 2b5e09efc31..d262fa91d72 100644
--- a/j2k/tests/testData/ast/class/abstractClassShape.kt
+++ b/j2k/tests/testData/ast/class/abstractClassShape.kt
@@ -1,12 +1,4 @@
abstract class Shape {
public var color: String
- public fun setColor(c: String) {
- color = c
- }
-
- public fun getColor(): String {
- return color
- }
-
public abstract fun area(): Double
}
\ No newline at end of file
diff --git a/j2k/tests/testData/ast/constructors/customerBuilder.kt b/j2k/tests/testData/ast/constructors/customerBuilder.kt
index df6785bdfbb..397a0871404 100644
--- a/j2k/tests/testData/ast/constructors/customerBuilder.kt
+++ b/j2k/tests/testData/ast/constructors/customerBuilder.kt
@@ -1,20 +1,12 @@
package org.test.customer
-class Customer(public val _firstName: String, public val _lastName: String) {
+class Customer(public val firstName: String, public val lastName: String) {
{
doSmthBefore()
doSmthAfter()
}
- public fun getFirstName(): String {
- return _firstName
- }
-
- public fun getLastName(): String {
- return _lastName
- }
-
private fun doSmthBefore() {
}
diff --git a/j2k/tests/testData/ast/constructors/genericIdentifier.kt b/j2k/tests/testData/ast/constructors/genericIdentifier.kt
index 6213f71e780..7b0132372d9 100644
--- a/j2k/tests/testData/ast/constructors/genericIdentifier.kt
+++ b/j2k/tests/testData/ast/constructors/genericIdentifier.kt
@@ -14,12 +14,8 @@ public fun Identifier(name: T, hasDollar: Boolean, isNullable: Boolean): Ide
return __
}
-public class Identifier(private val myName: T, private val myHasDollar: Boolean) {
+public class Identifier(public val name: T, private val myHasDollar: Boolean) {
private var myNullable = true
-
- public fun getName(): T {
- return myName
- }
}
public class User {
diff --git a/j2k/tests/testData/ast/constructors/identifier.kt b/j2k/tests/testData/ast/constructors/identifier.kt
index ec47a181791..7751d231896 100644
--- a/j2k/tests/testData/ast/constructors/identifier.kt
+++ b/j2k/tests/testData/ast/constructors/identifier.kt
@@ -14,12 +14,8 @@ public fun Identifier(name: String, hasDollar: Boolean, isNullable: Boolean): Id
return __
}
-public class Identifier(private val myName: String, private val myHasDollar: Boolean) {
+public class Identifier(public val name: String, private val myHasDollar: Boolean) {
private var myNullable = true
-
- public fun getName(): String {
- return myName
- }
}
public class User {
diff --git a/j2k/tests/testData/ast/dropAccessors/AccessInGetterWithThis.java b/j2k/tests/testData/ast/dropAccessors/AccessInGetterWithThis.java
new file mode 100644
index 00000000000..aab1d24e649
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/AccessInGetterWithThis.java
@@ -0,0 +1,7 @@
+public class AAA {
+ private final int x = 42;
+
+ public int getX() {
+ return this.x;
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/AccessInGetterWithThis.kt b/j2k/tests/testData/ast/dropAccessors/AccessInGetterWithThis.kt
new file mode 100644
index 00000000000..aa2614ee957
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/AccessInGetterWithThis.kt
@@ -0,0 +1,3 @@
+public class AAA {
+ public val x: Int = 42
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/CannotDropOnlySetter.java b/j2k/tests/testData/ast/dropAccessors/CannotDropOnlySetter.java
new file mode 100644
index 00000000000..4229549b735
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/CannotDropOnlySetter.java
@@ -0,0 +1,7 @@
+public class AAA {
+ private int x = 42;
+
+ public void setX(int x) {
+ this.x = x;
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/CannotDropOnlySetter.kt b/j2k/tests/testData/ast/dropAccessors/CannotDropOnlySetter.kt
new file mode 100644
index 00000000000..99073d68531
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/CannotDropOnlySetter.kt
@@ -0,0 +1,7 @@
+public class AAA {
+ private var x = 42
+
+ public fun setX(x: Int) {
+ this.x = x
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/DataClass.java b/j2k/tests/testData/ast/dropAccessors/DataClass.java
new file mode 100644
index 00000000000..fe49677a6cf
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/DataClass.java
@@ -0,0 +1,28 @@
+public class Test {
+ private String id;
+ private String name;
+ private int myAge;
+
+ public Test(String id, String name, int anAge) {
+ this.id = id;
+ this.name = name;
+ myAge = anAge;
+ System.out.println(anAge);
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getAge() {
+ return myAge;
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/DataClass.kt b/j2k/tests/testData/ast/dropAccessors/DataClass.kt
new file mode 100644
index 00000000000..e0065bd2328
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/DataClass.kt
@@ -0,0 +1,6 @@
+public class Test(public var id: String?, public val name: String, public val age: Int) {
+
+ {
+ System.out.println(age)
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/DataClassWithMutableField.java b/j2k/tests/testData/ast/dropAccessors/DataClassWithMutableField.java
new file mode 100644
index 00000000000..e215e8e735f
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/DataClassWithMutableField.java
@@ -0,0 +1,15 @@
+public class Test {
+ private int myCount;
+
+ public Test(int count) {
+ myCount = count;
+ }
+
+ public int getCount() {
+ return myCount;
+ }
+
+ public void inc() {
+ myCount++;
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/DataClassWithMutableField.kt b/j2k/tests/testData/ast/dropAccessors/DataClassWithMutableField.kt
new file mode 100644
index 00000000000..de84f032ed6
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/DataClassWithMutableField.kt
@@ -0,0 +1,12 @@
+public class Test(count: Int) {
+ public var count: Int = 0
+ private set
+
+ {
+ this.count = count
+ }
+
+ public fun inc() {
+ count++
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/DifferentFieldName.java b/j2k/tests/testData/ast/dropAccessors/DifferentFieldName.java
new file mode 100644
index 00000000000..f986c1f5e83
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/DifferentFieldName.java
@@ -0,0 +1,13 @@
+public class AAA {
+ private int myX = 42;
+
+ public int getX() {
+ return myX;
+ }
+
+ public void foo(AAA other) {
+ System.out.println(myX);
+ System.out.println(other.myX);
+ myX = 10;
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/DifferentFieldName.kt b/j2k/tests/testData/ast/dropAccessors/DifferentFieldName.kt
new file mode 100644
index 00000000000..1dd682bc711
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/DifferentFieldName.kt
@@ -0,0 +1,10 @@
+public class AAA {
+ public var x: Int = 42
+ private set
+
+ public fun foo(other: AAA) {
+ System.out.println(x)
+ System.out.println(other.x)
+ x = 10
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/DropGetter.java b/j2k/tests/testData/ast/dropAccessors/DropGetter.java
new file mode 100644
index 00000000000..a8d09e23780
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/DropGetter.java
@@ -0,0 +1,7 @@
+public class AAA {
+ private final int x = 42;
+
+ public int getX() {
+ return x;
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/DropGetter.kt b/j2k/tests/testData/ast/dropAccessors/DropGetter.kt
new file mode 100644
index 00000000000..aa2614ee957
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/DropGetter.kt
@@ -0,0 +1,3 @@
+public class AAA {
+ public val x: Int = 42
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/DropGetterAndSetter.java b/j2k/tests/testData/ast/dropAccessors/DropGetterAndSetter.java
new file mode 100644
index 00000000000..3b68f2b9d56
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/DropGetterAndSetter.java
@@ -0,0 +1,11 @@
+public class AAA {
+ private int x = 42;
+
+ public int getX() {
+ return x;
+ }
+
+ public void setX(int x) {
+ this.x = x;
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/DropGetterAndSetter.kt b/j2k/tests/testData/ast/dropAccessors/DropGetterAndSetter.kt
new file mode 100644
index 00000000000..0074fc2d309
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/DropGetterAndSetter.kt
@@ -0,0 +1,3 @@
+public class AAA {
+ public var x: Int = 42
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/DropGetterForMutable.java b/j2k/tests/testData/ast/dropAccessors/DropGetterForMutable.java
new file mode 100644
index 00000000000..6657f708da9
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/DropGetterForMutable.java
@@ -0,0 +1,11 @@
+public class AAA {
+ private int x = 42;
+
+ public int getX() {
+ return x;
+ }
+
+ public void foo() {
+ x = 10;
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/DropGetterForMutable.kt b/j2k/tests/testData/ast/dropAccessors/DropGetterForMutable.kt
new file mode 100644
index 00000000000..4c1a7d6a7eb
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/DropGetterForMutable.kt
@@ -0,0 +1,8 @@
+public class AAA {
+ public var x: Int = 42
+ private set
+
+ public fun foo() {
+ x = 10
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/FalseGetter.java b/j2k/tests/testData/ast/dropAccessors/FalseGetter.java
new file mode 100644
index 00000000000..5b6024908b9
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/FalseGetter.java
@@ -0,0 +1,8 @@
+public class AAA {
+ private int x = 42;
+ private AAA other = new AAA();
+
+ public int getX() {
+ return other.x;
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/FalseGetter.kt b/j2k/tests/testData/ast/dropAccessors/FalseGetter.kt
new file mode 100644
index 00000000000..ffab977787b
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/FalseGetter.kt
@@ -0,0 +1,8 @@
+public class AAA {
+ private val x = 42
+ private val other = AAA()
+
+ public fun getX(): Int {
+ return other.x
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/FalseSetter.java b/j2k/tests/testData/ast/dropAccessors/FalseSetter.java
new file mode 100644
index 00000000000..7c10fdb38f1
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/FalseSetter.java
@@ -0,0 +1,11 @@
+public class AAA {
+ private int x = 42;
+
+ public int getX() {
+ return x;
+ }
+
+ public void setX(int x) {
+ this.x += x;
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/FalseSetter.kt b/j2k/tests/testData/ast/dropAccessors/FalseSetter.kt
new file mode 100644
index 00000000000..55c8bd57c68
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/FalseSetter.kt
@@ -0,0 +1,8 @@
+public class AAA {
+ public var x: Int = 42
+ private set
+
+ public fun setX(x: Int) {
+ this.x += x
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/FieldUsagesInFactoryMethods.java b/j2k/tests/testData/ast/dropAccessors/FieldUsagesInFactoryMethods.java
new file mode 100644
index 00000000000..d06d660e129
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/FieldUsagesInFactoryMethods.java
@@ -0,0 +1,35 @@
+class C {
+ final int myArg1;
+ int myArg2;
+ int myArg3;
+
+ C(int arg1, int arg2, int arg3) {
+ this(arg1);
+ myArg2 = arg2;
+ myArg3 = arg3;
+ }
+
+ C(int arg1, int arg2) {
+ this(arg1);
+ myArg2 = arg2;
+ myArg3 = 0;
+ }
+
+ C(int arg1) {
+ myArg1 = arg1;
+ myArg2 = 0;
+ myArg3 = 0;
+ }
+
+ int getArg1() {
+ return myArg1;
+ }
+
+ int getArg2() {
+ return myArg2;
+ }
+
+ int getArg3() {
+ return myArg3;
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/FieldUsagesInFactoryMethods.kt b/j2k/tests/testData/ast/dropAccessors/FieldUsagesInFactoryMethods.kt
new file mode 100644
index 00000000000..01b45fb9412
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/FieldUsagesInFactoryMethods.kt
@@ -0,0 +1,23 @@
+fun C(arg1: Int, arg2: Int, arg3: Int): C {
+ val __ = C(arg1)
+ __.arg2 = arg2
+ __.arg3 = arg3
+ return __
+}
+
+fun C(arg1: Int, arg2: Int): C {
+ val __ = C(arg1)
+ __.arg2 = arg2
+ __.arg3 = 0
+ return __
+}
+
+class C(val arg1: Int) {
+ var arg2: Int = 0
+ var arg3: Int = 0
+
+ {
+ arg2 = 0
+ arg3 = 0
+ }
+}
\ No newline at end of file
diff --git a/j2k/tests/testData/ast/dropAccessors/GetterAndSetterNamesDifferent.java b/j2k/tests/testData/ast/dropAccessors/GetterAndSetterNamesDifferent.java
new file mode 100644
index 00000000000..e896854cbe6
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/GetterAndSetterNamesDifferent.java
@@ -0,0 +1,11 @@
+public class AAA {
+ private int x = 42;
+
+ public int getX() {
+ return x;
+ }
+
+ public void setY(int x) {
+ this.x = x;
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/GetterAndSetterNamesDifferent.kt b/j2k/tests/testData/ast/dropAccessors/GetterAndSetterNamesDifferent.kt
new file mode 100644
index 00000000000..27688bd3314
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/GetterAndSetterNamesDifferent.kt
@@ -0,0 +1,8 @@
+public class AAA {
+ public var x: Int = 42
+ private set
+
+ public fun setY(x: Int) {
+ this.x = x
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/GetterSetterUsages.java.todo b/j2k/tests/testData/ast/dropAccessors/GetterSetterUsages.java.todo
new file mode 100644
index 00000000000..d196f6614c5
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/GetterSetterUsages.java.todo
@@ -0,0 +1,19 @@
+public class AAA {
+ private int x = 42;
+
+ public int getX() {
+ return x;
+ }
+
+ public void setX(int x) {
+ this.x = x;
+ }
+
+ public void foo() {
+ setX(getX() + 1);
+ }
+
+ public void bar(AAA other) {
+ other.setX(other.getX() + 1);
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/GetterSetterUsages.kt b/j2k/tests/testData/ast/dropAccessors/GetterSetterUsages.kt
new file mode 100644
index 00000000000..87cd25fd2ca
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/GetterSetterUsages.kt
@@ -0,0 +1,11 @@
+public class AAA {
+ public var x: Int = 42
+
+ public fun foo() {
+ x = x + 1
+ }
+
+ public fun bar(other: AAA) {
+ other.x = other.x + 1
+ }
+}
diff --git a/j2k/tests/testData/ast/dropAccessors/QualifyFieldUsagesOnRename.java.todo b/j2k/tests/testData/ast/dropAccessors/QualifyFieldUsagesOnRename.java.todo
new file mode 100644
index 00000000000..7dd2f85fa3f
--- /dev/null
+++ b/j2k/tests/testData/ast/dropAccessors/QualifyFieldUsagesOnRename.java.todo
@@ -0,0 +1,32 @@
+public class AAA {
+ private int myX = 42;
+
+ public int getX() {
+ return myX;
+ }
+
+ public void foo(final int x) {
+ System.out.println(x);
+ System.out.println(getX());
+ System.out.println(myX);
+
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ System.out.println(x);
+ System.out.println(getX());
+ System.out.println(myX);
+ }
+ };
+ }
+
+ class Nested {
+ int x = myX;
+
+ void foo() {
+ System.out.println(x);
+ System.out.println(getX());
+ System.out.println(myX);
+ }
+ }
+}
diff --git a/j2k/tests/testData/ast/enum/colorEnum.kt b/j2k/tests/testData/ast/enum/colorEnum.kt
index a96ba5955a8..00dfc632fc1 100644
--- a/j2k/tests/testData/ast/enum/colorEnum.kt
+++ b/j2k/tests/testData/ast/enum/colorEnum.kt
@@ -1,10 +1,6 @@
package demo
-enum class MyEnum private(private val color: Int) {
+enum class MyEnum private(public val color: Int) {
RED : MyEnum(10)
BLUE : MyEnum(20)
-
- public fun getColor(): Int {
- return color
- }
}
\ No newline at end of file
diff --git a/j2k/tests/testData/ast/enum/fieldsWithPrimaryPrivateConstructor.kt b/j2k/tests/testData/ast/enum/fieldsWithPrimaryPrivateConstructor.kt
index 83a774702ba..d57aa80dad1 100644
--- a/j2k/tests/testData/ast/enum/fieldsWithPrimaryPrivateConstructor.kt
+++ b/j2k/tests/testData/ast/enum/fieldsWithPrimaryPrivateConstructor.kt
@@ -1,11 +1,7 @@
-enum class Color private(private val code: Int) {
+enum class Color private(public val code: Int) {
WHITE : Color(21)
BLACK : Color(22)
RED : Color(23)
YELLOW : Color(24)
BLUE : Color(25)
-
- public fun getCode(): Int {
- return code
- }
}
\ No newline at end of file
diff --git a/j2k/tests/testData/ast/enum/primaryPrivateConstructor.kt b/j2k/tests/testData/ast/enum/primaryPrivateConstructor.kt
index 838467a0bff..59d0da30bdb 100644
--- a/j2k/tests/testData/ast/enum/primaryPrivateConstructor.kt
+++ b/j2k/tests/testData/ast/enum/primaryPrivateConstructor.kt
@@ -1,8 +1,3 @@
package demo
-enum class Color private(private val code: Int) {
-
- public fun getCode(): Int {
- return code
- }
-}
\ No newline at end of file
+enum class Color private(public val code: Int)
\ No newline at end of file
diff --git a/j2k/tests/testData/ast/issues/kt-638.kt b/j2k/tests/testData/ast/issues/kt-638.kt
index 7d46a242a2f..611179a6135 100644
--- a/j2k/tests/testData/ast/issues/kt-638.kt
+++ b/j2k/tests/testData/ast/issues/kt-638.kt
@@ -14,12 +14,8 @@ public fun Identifier(name: T, hasDollar: Boolean, isNullable: Boolean): Ide
return __
}
-public class Identifier(private val myName: T, private val myHasDollar: Boolean) {
+public class Identifier(public val name: T, private val myHasDollar: Boolean) {
private var myNullable = true
-
- public fun getName(): T {
- return myName
- }
}
public class User {