KT-5492 J2K: convert field with getter/setter to property
#KT-5492 Fixed
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
<root>
|
||||
<item name='com.intellij.openapi.util.text.StringUtil java.lang.String decapitalize(java.lang.String)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
@@ -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<PsiMember>()
|
||||
private val fieldCorrections = HashMap<PsiField, FieldCorrectionInfo>()
|
||||
|
||||
public fun convertBody(): ClassBody {
|
||||
val membersToRemove = HashSet<PsiMember>()
|
||||
processAccessorsToDrop()
|
||||
|
||||
val correctedConverter = buildConverterWithCorrectedFieldNames()
|
||||
|
||||
val constructorConverter = if (psiClass.getName() != null)
|
||||
ConstructorConverter(psiClass, correctedConverter, fieldCorrections)
|
||||
else
|
||||
null
|
||||
|
||||
val convertedMembers = LinkedHashMap<PsiMember, Member>()
|
||||
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<PsiMember>,
|
||||
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<PsiField, AccessorInfo>()
|
||||
val fieldToSetterInfo = HashMap<PsiField, AccessorInfo>()
|
||||
val fieldsWithConflict = HashSet<PsiField>()
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<PsiField, FieldCorrectionInfo>) {
|
||||
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 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 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<FactoryFunction>): List<FactoryFunction> {
|
||||
@@ -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<String, String>, 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<String, String>,
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<String> = state.importList?.imports?.mapTo(HashSet<String>()) { it.name } ?: setOf()
|
||||
val importsToAdd: MutableCollection<String>? = 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<String>): 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<PsiMember>, 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<PsiMember>?, constructorConverter: ConstructorConverter?): Member? {
|
||||
fun convertMethod(method: PsiMethod, membersToRemove: MutableSet<PsiMember>?, 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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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<Expression>,
|
||||
val members: List<Member>,
|
||||
val classObjectMembers: List<Member>,
|
||||
val factoryFunctions: List<FactoryFunction>,
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,8 @@ class Modifiers(val modifiers: Collection<Modifier>) : 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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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() {
|
||||
}
|
||||
|
||||
|
||||
@@ -14,12 +14,8 @@ public fun <T> Identifier(name: T, hasDollar: Boolean, isNullable: Boolean): Ide
|
||||
return __
|
||||
}
|
||||
|
||||
public class Identifier<T>(private val myName: T, private val myHasDollar: Boolean) {
|
||||
public class Identifier<T>(public val name: T, private val myHasDollar: Boolean) {
|
||||
private var myNullable = true
|
||||
|
||||
public fun getName(): T {
|
||||
return myName
|
||||
}
|
||||
}
|
||||
|
||||
public class User {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
public class AAA {
|
||||
private final int x = 42;
|
||||
|
||||
public int getX() {
|
||||
return this.x;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
public class AAA {
|
||||
public val x: Int = 42
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
public class AAA {
|
||||
private int x = 42;
|
||||
|
||||
public void setX(int x) {
|
||||
this.x = x;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
public class AAA {
|
||||
private var x = 42
|
||||
|
||||
public fun setX(x: Int) {
|
||||
this.x = x
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
public class Test(public var id: String?, public val name: String, public val age: Int) {
|
||||
|
||||
{
|
||||
System.out.println(age)
|
||||
}
|
||||
}
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
public class Test(count: Int) {
|
||||
public var count: Int = 0
|
||||
private set
|
||||
|
||||
{
|
||||
this.count = count
|
||||
}
|
||||
|
||||
public fun inc() {
|
||||
count++
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
public class AAA {
|
||||
private final int x = 42;
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
public class AAA {
|
||||
public val x: Int = 42
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
public class AAA {
|
||||
private int x = 42;
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setX(int x) {
|
||||
this.x = x;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
public class AAA {
|
||||
public var x: Int = 42
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
public class AAA {
|
||||
private int x = 42;
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public void foo() {
|
||||
x = 10;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
public class AAA {
|
||||
public var x: Int = 42
|
||||
private set
|
||||
|
||||
public fun foo() {
|
||||
x = 10
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
public class AAA {
|
||||
private int x = 42;
|
||||
private AAA other = new AAA();
|
||||
|
||||
public int getX() {
|
||||
return other.x;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
public class AAA {
|
||||
private val x = 42
|
||||
private val other = AAA()
|
||||
|
||||
public fun getX(): Int {
|
||||
return other.x
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
public class AAA {
|
||||
private int x = 42;
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setX(int x) {
|
||||
this.x += x;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
public class AAA {
|
||||
public var x: Int = 42
|
||||
private set
|
||||
|
||||
public fun setX(x: Int) {
|
||||
this.x += x
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
public class AAA {
|
||||
private int x = 42;
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setY(int x) {
|
||||
this.x = x;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
public class AAA {
|
||||
public var x: Int = 42
|
||||
private set
|
||||
|
||||
public fun setY(x: Int) {
|
||||
this.x = x
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
package demo
|
||||
|
||||
enum class Color private(private val code: Int) {
|
||||
|
||||
public fun getCode(): Int {
|
||||
return code
|
||||
}
|
||||
}
|
||||
enum class Color private(public val code: Int)
|
||||
@@ -14,12 +14,8 @@ public fun <T> Identifier(name: T, hasDollar: Boolean, isNullable: Boolean): Ide
|
||||
return __
|
||||
}
|
||||
|
||||
public class Identifier<T>(private val myName: T, private val myHasDollar: Boolean) {
|
||||
public class Identifier<T>(public val name: T, private val myHasDollar: Boolean) {
|
||||
private var myNullable = true
|
||||
|
||||
public fun getName(): T {
|
||||
return myName
|
||||
}
|
||||
}
|
||||
|
||||
public class User {
|
||||
|
||||
Reference in New Issue
Block a user