Java to Kotlin converter: code refactoring - extracted some code from Converter into TypeConverter
This commit is contained in:
@@ -27,9 +27,11 @@ import com.intellij.psi.util.PsiUtil
|
|||||||
|
|
||||||
public class Converter(val project: Project, val settings: ConverterSettings) {
|
public class Converter(val project: Project, val settings: ConverterSettings) {
|
||||||
|
|
||||||
|
private val typeConverter = TypeConverter(settings)
|
||||||
|
|
||||||
private var classIdentifiersSet: MutableSet<String> = HashSet()
|
private var classIdentifiersSet: MutableSet<String> = HashSet()
|
||||||
|
|
||||||
private val dispatcher: Dispatcher = Dispatcher(this)
|
private val dispatcher: Dispatcher = Dispatcher(this, typeConverter)
|
||||||
|
|
||||||
public var methodReturnType: PsiType? = null
|
public var methodReturnType: PsiType? = null
|
||||||
private set
|
private set
|
||||||
@@ -206,14 +208,14 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
return EnumConstant(Identifier(field.getName()!!),
|
return EnumConstant(Identifier(field.getName()!!),
|
||||||
getComments(field),
|
getComments(field),
|
||||||
modifiers,
|
modifiers,
|
||||||
convertType(field.getType(), Nullability.NotNull),
|
typeConverter.convertType(field.getType(), Nullability.NotNull),
|
||||||
convertElement(field.getArgumentList()))
|
convertElement(field.getArgumentList()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return Field(Identifier(field.getName()!!),
|
return Field(Identifier(field.getName()!!),
|
||||||
getComments(field),
|
getComments(field),
|
||||||
modifiers,
|
modifiers,
|
||||||
convertVariableType(field),
|
typeConverter.convertVariableType(field),
|
||||||
convertExpression(field.getInitializer(), field.getType()),
|
convertExpression(field.getInitializer(), field.getType()),
|
||||||
field.hasModifierProperty(PsiModifier.FINAL),
|
field.hasModifierProperty(PsiModifier.FINAL),
|
||||||
field.countWriteAccesses(field.getContainingClass()))
|
field.countWriteAccesses(field.getContainingClass()))
|
||||||
@@ -221,7 +223,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
|
|
||||||
private fun convertMethod(method: PsiMethod, membersToRemove: MutableSet<PsiMember>): Function {
|
private fun convertMethod(method: PsiMethod, membersToRemove: MutableSet<PsiMember>): Function {
|
||||||
methodReturnType = method.getReturnType()
|
methodReturnType = method.getReturnType()
|
||||||
val returnType = convertMethodReturnType(method)
|
val returnType = typeConverter.convertMethodReturnType(method)
|
||||||
|
|
||||||
val modifiers = convertModifiers(method)
|
val modifiers = convertModifiers(method)
|
||||||
|
|
||||||
@@ -262,7 +264,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
}
|
}
|
||||||
if (overridesMethodFromObject) {
|
if (overridesMethodFromObject) {
|
||||||
val correctedParameter = Parameter(Identifier("other"),
|
val correctedParameter = Parameter(Identifier("other"),
|
||||||
ClassType(Identifier("Any"), listOf(), Nullability.Nullable, this),
|
ClassType(Identifier("Any"), listOf(), Nullability.Nullable, settings),
|
||||||
Parameter.VarValModifier.None,
|
Parameter.VarValModifier.None,
|
||||||
listOf())
|
listOf())
|
||||||
params = ParameterList(listOf(correctedParameter))
|
params = ParameterList(listOf(correctedParameter))
|
||||||
@@ -275,38 +277,6 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun convertMethodReturnType(method: PsiMethod): Type {
|
|
||||||
var nullability = method.nullabilityFromAnnotations()
|
|
||||||
|
|
||||||
if (nullability == Nullability.Default) {
|
|
||||||
var isInAnonymousClass = false
|
|
||||||
method.getBody()?.accept(object: JavaRecursiveElementVisitor() {
|
|
||||||
override fun visitAnonymousClass(aClass: PsiAnonymousClass) {
|
|
||||||
isInAnonymousClass = true
|
|
||||||
super.visitAnonymousClass(aClass)
|
|
||||||
isInAnonymousClass = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitReturnStatement(statement: PsiReturnStatement) {
|
|
||||||
if (!isInAnonymousClass && statement.getReturnValue()?.nullability() == Nullability.Nullable) {
|
|
||||||
nullability = Nullability.Nullable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nullability == Nullability.Default) {
|
|
||||||
val scope = searchScope(method)
|
|
||||||
if (scope != null) {
|
|
||||||
if (findMethodCalls(method, scope).any { isNullableFromUsage(it) }) {
|
|
||||||
nullability = Nullability.Nullable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return convertType(method.getReturnType(), nullability)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides of methods from Object should not be marked as overrides in Kotlin unless the class itself has java ancestors
|
* Overrides of methods from Object should not be marked as overrides in Kotlin unless the class itself has java ancestors
|
||||||
*/
|
*/
|
||||||
@@ -355,8 +325,8 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
for (parameter in params) {
|
for (parameter in params) {
|
||||||
val (field, initializationStatement) = findBackingFieldForConstructorParameter(parameter, constructor) ?: continue
|
val (field, initializationStatement) = findBackingFieldForConstructorParameter(parameter, constructor) ?: continue
|
||||||
|
|
||||||
val fieldType = convertVariableType(field)
|
val fieldType = typeConverter.convertVariableType(field)
|
||||||
val parameterType = convertVariableType(parameter)
|
val parameterType = typeConverter.convertVariableType(parameter)
|
||||||
// types can be different only in nullability
|
// types can be different only in nullability
|
||||||
val `type` = if (fieldType == parameterType) {
|
val `type` = if (fieldType == parameterType) {
|
||||||
fieldType
|
fieldType
|
||||||
@@ -376,12 +346,12 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
usageReplacementMap.put(parameter, field.getName()!!)
|
usageReplacementMap.put(parameter, field.getName()!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dispatcher.expressionVisitor = ExpressionVisitor(this, usageReplacementMap)
|
dispatcher.expressionVisitor = ExpressionVisitor(this, typeConverter, usageReplacementMap)
|
||||||
try {
|
try {
|
||||||
Block(convertStatements(body.getStatements().filter{ !statementsToRemove.contains(it) }), false)
|
Block(convertStatements(body.getStatements().filter{ !statementsToRemove.contains(it) }), false)
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
dispatcher.expressionVisitor = ExpressionVisitor(this, mapOf())
|
dispatcher.expressionVisitor = ExpressionVisitor(this, typeConverter, mapOf())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -466,7 +436,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
public fun convertElement(element: PsiElement?): Element {
|
public fun convertElement(element: PsiElement?): Element {
|
||||||
if (element == null) return Element.Empty
|
if (element == null) return Element.Empty
|
||||||
|
|
||||||
val elementVisitor = ElementVisitor(this)
|
val elementVisitor = ElementVisitor(this, typeConverter)
|
||||||
element.accept(elementVisitor)
|
element.accept(elementVisitor)
|
||||||
return elementVisitor.result
|
return elementVisitor.result
|
||||||
}
|
}
|
||||||
@@ -483,122 +453,11 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
return TypeElement(if (element == null)
|
return TypeElement(if (element == null)
|
||||||
Type.Empty
|
Type.Empty
|
||||||
else
|
else
|
||||||
convertType(element.getType()))
|
typeConverter.convertType(element.getType()))
|
||||||
}
|
|
||||||
|
|
||||||
public fun convertType(`type`: PsiType?, nullability: Nullability = Nullability.Default): Type {
|
|
||||||
if (`type` == null) return Type.Empty
|
|
||||||
|
|
||||||
val result = `type`.accept<Type>(TypeVisitor(this))!!
|
|
||||||
return when (nullability) {
|
|
||||||
Nullability.NotNull -> result.toNotNullType()
|
|
||||||
Nullability.Nullable -> result.toNullableType()
|
|
||||||
Nullability.Default -> result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun convertTypes(types: Array<PsiType>): List<Type> {
|
|
||||||
return types.map { convertType(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun convertVariableType(variable: PsiVariable): Type {
|
|
||||||
var nullability = variable.nullabilityFromAnnotations()
|
|
||||||
|
|
||||||
if (nullability == Nullability.Default) {
|
|
||||||
val initializer = variable.getInitializer()
|
|
||||||
if (initializer != null) {
|
|
||||||
val initializerNullability = initializer.nullability()
|
|
||||||
if (variable.hasModifierProperty(PsiModifier.FINAL)) { //TODO: replace check for final modifier with effective final
|
|
||||||
nullability = initializerNullability
|
|
||||||
}
|
|
||||||
else if (initializerNullability == Nullability.Nullable) { // if variable is not final then non-nullability of initializer does not mean that variable is non-null
|
|
||||||
nullability = Nullability.Nullable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nullability == Nullability.Default) {
|
|
||||||
val scope = searchScope(variable)
|
|
||||||
if (scope != null) {
|
|
||||||
if (findVariableUsages(variable, scope).any { isNullableFromUsage(it) }) {
|
|
||||||
nullability = Nullability.Nullable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nullability == Nullability.Default && variable is PsiParameter) {
|
|
||||||
val method = variable.getDeclarationScope() as? PsiMethod
|
|
||||||
if (method != null) {
|
|
||||||
val scope = searchScope(method)
|
|
||||||
if (scope != null) {
|
|
||||||
val parameters = method.getParameterList().getParameters()
|
|
||||||
val parameterIndex = parameters.indexOf(variable)
|
|
||||||
for (call in findMethodCalls(method, scope)) {
|
|
||||||
val args = call.getArgumentList().getExpressions()
|
|
||||||
if (args.size == parameters.size) {
|
|
||||||
if (args[parameterIndex].nullability() == Nullability.Nullable) {
|
|
||||||
nullability = Nullability.Nullable
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return convertType(variable.getType(), nullability)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun searchScope(element: PsiElement): PsiElement? {
|
|
||||||
return when(element) {
|
|
||||||
is PsiParameter -> element.getDeclarationScope()
|
|
||||||
is PsiField -> if (element.hasModifierProperty(PsiModifier.PRIVATE)) element.getContainingClass() else element.getContainingFile()
|
|
||||||
is PsiMethod -> if (element.hasModifierProperty(PsiModifier.PRIVATE)) element.getContainingClass() else element.getContainingFile()
|
|
||||||
is PsiLocalVariable -> element.getContainingMethod()
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun PsiExpression.nullability(): Nullability {
|
|
||||||
return when (this) {
|
|
||||||
is PsiLiteralExpression -> if (getValue() != null) Nullability.NotNull else Nullability.Nullable
|
|
||||||
|
|
||||||
is PsiNewExpression -> Nullability.NotNull
|
|
||||||
|
|
||||||
is PsiConditionalExpression -> {
|
|
||||||
val nullability1 = getThenExpression()?.nullability()
|
|
||||||
if (nullability1 == Nullability.Nullable) return Nullability.Nullable
|
|
||||||
val nullability2 = getElseExpression()?.nullability()
|
|
||||||
if (nullability2 == Nullability.Nullable) return Nullability.Nullable
|
|
||||||
if (nullability1 == Nullability.NotNull && nullability2 == Nullability.NotNull) return Nullability.NotNull
|
|
||||||
Nullability.Default
|
|
||||||
}
|
|
||||||
|
|
||||||
is PsiParenthesizedExpression -> getExpression()?.nullability() ?: Nullability.Default
|
|
||||||
|
|
||||||
//TODO: some other cases
|
|
||||||
|
|
||||||
else -> Nullability.Default
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isNullableFromUsage(usage: PsiExpression): Boolean {
|
|
||||||
val parent = usage.getParent() ?: return false
|
|
||||||
if (parent is PsiAssignmentExpression && parent.getOperationTokenType() == JavaTokenType.EQ && usage == parent.getLExpression()) {
|
|
||||||
return parent.getRExpression()?.nullability() == Nullability.Nullable
|
|
||||||
}
|
|
||||||
else if (parent is PsiBinaryExpression) {
|
|
||||||
val operationType = parent.getOperationTokenType()
|
|
||||||
if (operationType == JavaTokenType.EQEQ || operationType == JavaTokenType.NE) {
|
|
||||||
val otherOperand = if (usage == parent.getLOperand()) parent.getROperand() else parent.getLOperand()
|
|
||||||
return otherOperand?.nullability() == Nullability.Nullable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun convertToNotNullableTypes(types: Array<out PsiType?>): List<Type>
|
private fun convertToNotNullableTypes(types: Array<out PsiType?>): List<Type>
|
||||||
= types.map { convertType(it, Nullability.NotNull) }
|
= types.map { typeConverter.convertType(it, Nullability.NotNull) }
|
||||||
|
|
||||||
public fun convertParameterList(parameterList: PsiParameterList): ParameterList
|
public fun convertParameterList(parameterList: PsiParameterList): ParameterList
|
||||||
= ParameterList(parameterList.getParameters().map { convertParameter(it) })
|
= ParameterList(parameterList.getParameters().map { convertParameter(it) })
|
||||||
@@ -607,7 +466,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
nullability: Nullability = Nullability.Default,
|
nullability: Nullability = Nullability.Default,
|
||||||
varValModifier: Parameter.VarValModifier = Parameter.VarValModifier.None,
|
varValModifier: Parameter.VarValModifier = Parameter.VarValModifier.None,
|
||||||
modifiers: Collection<Modifier> = listOf()): Parameter {
|
modifiers: Collection<Modifier> = listOf()): Parameter {
|
||||||
var `type` = convertVariableType(parameter)
|
var `type` = typeConverter.convertVariableType(parameter)
|
||||||
when (nullability) {
|
when (nullability) {
|
||||||
Nullability.NotNull -> `type` = `type`.toNotNullType()
|
Nullability.NotNull -> `type` = `type`.toNotNullType()
|
||||||
Nullability.Nullable -> `type` = `type`.toNullableType()
|
Nullability.Nullable -> `type` = `type`.toNullableType()
|
||||||
|
|||||||
@@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.j2k
|
||||||
|
|
||||||
|
import org.jetbrains.jet.j2k.ast.Type
|
||||||
|
import org.jetbrains.jet.j2k.ast.Nullability
|
||||||
|
import com.intellij.psi.*
|
||||||
|
import org.jetbrains.jet.j2k.visitors.TypeVisitor
|
||||||
|
|
||||||
|
class TypeConverter(val settings: ConverterSettings) {
|
||||||
|
public fun convertType(`type`: PsiType?, nullability: Nullability = Nullability.Default): Type {
|
||||||
|
if (`type` == null) return Type.Empty
|
||||||
|
|
||||||
|
val result = `type`.accept<Type>(TypeVisitor(this))!!
|
||||||
|
return when (nullability) {
|
||||||
|
Nullability.NotNull -> result.toNotNullType()
|
||||||
|
Nullability.Nullable -> result.toNullableType()
|
||||||
|
Nullability.Default -> result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun convertTypes(types: Array<PsiType>): List<Type> {
|
||||||
|
return types.map { convertType(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun convertVariableType(variable: PsiVariable): Type {
|
||||||
|
var nullability = variable.nullabilityFromAnnotations()
|
||||||
|
|
||||||
|
if (nullability == Nullability.Default) {
|
||||||
|
val initializer = variable.getInitializer()
|
||||||
|
if (initializer != null) {
|
||||||
|
val initializerNullability = initializer.nullability()
|
||||||
|
if (variable.hasModifierProperty(PsiModifier.FINAL)) { //TODO: replace check for final modifier with effective final
|
||||||
|
nullability = initializerNullability
|
||||||
|
}
|
||||||
|
else if (initializerNullability == Nullability.Nullable) { // if variable is not final then non-nullability of initializer does not mean that variable is non-null
|
||||||
|
nullability = Nullability.Nullable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullability == Nullability.Default) {
|
||||||
|
val scope = searchScope(variable)
|
||||||
|
if (scope != null) {
|
||||||
|
if (findVariableUsages(variable, scope).any { isNullableFromUsage(it) }) {
|
||||||
|
nullability = Nullability.Nullable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullability == Nullability.Default && variable is PsiParameter) {
|
||||||
|
val method = variable.getDeclarationScope() as? PsiMethod
|
||||||
|
if (method != null) {
|
||||||
|
val scope = searchScope(method)
|
||||||
|
if (scope != null) {
|
||||||
|
val parameters = method.getParameterList().getParameters()
|
||||||
|
val parameterIndex = parameters.indexOf(variable)
|
||||||
|
for (call in findMethodCalls(method, scope)) {
|
||||||
|
val args = call.getArgumentList().getExpressions()
|
||||||
|
if (args.size == parameters.size) {
|
||||||
|
if (args[parameterIndex].nullability() == Nullability.Nullable) {
|
||||||
|
nullability = Nullability.Nullable
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return convertType(variable.getType(), nullability)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun convertMethodReturnType(method: PsiMethod): Type {
|
||||||
|
var nullability = method.nullabilityFromAnnotations()
|
||||||
|
|
||||||
|
if (nullability == Nullability.Default) {
|
||||||
|
var isInAnonymousClass = false
|
||||||
|
method.getBody()?.accept(object: JavaRecursiveElementVisitor() {
|
||||||
|
override fun visitAnonymousClass(aClass: PsiAnonymousClass) {
|
||||||
|
isInAnonymousClass = true
|
||||||
|
super.visitAnonymousClass(aClass)
|
||||||
|
isInAnonymousClass = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitReturnStatement(statement: PsiReturnStatement) {
|
||||||
|
if (!isInAnonymousClass && statement.getReturnValue()?.nullability() == Nullability.Nullable) {
|
||||||
|
nullability = Nullability.Nullable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullability == Nullability.Default) {
|
||||||
|
val scope = searchScope(method)
|
||||||
|
if (scope != null) {
|
||||||
|
if (findMethodCalls(method, scope).any { isNullableFromUsage(it) }) {
|
||||||
|
nullability = Nullability.Nullable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return convertType(method.getReturnType(), nullability)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun searchScope(element: PsiElement): PsiElement? {
|
||||||
|
return when(element) {
|
||||||
|
is PsiParameter -> element.getDeclarationScope()
|
||||||
|
is PsiField -> if (element.hasModifierProperty(PsiModifier.PRIVATE)) element.getContainingClass() else element.getContainingFile()
|
||||||
|
is PsiMethod -> if (element.hasModifierProperty(PsiModifier.PRIVATE)) element.getContainingClass() else element.getContainingFile()
|
||||||
|
is PsiLocalVariable -> element.getContainingMethod()
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PsiExpression.nullability(): Nullability {
|
||||||
|
return when (this) {
|
||||||
|
is PsiLiteralExpression -> if (getValue() != null) Nullability.NotNull else Nullability.Nullable
|
||||||
|
|
||||||
|
is PsiNewExpression -> Nullability.NotNull
|
||||||
|
|
||||||
|
is PsiConditionalExpression -> {
|
||||||
|
val nullability1 = getThenExpression()?.nullability()
|
||||||
|
if (nullability1 == Nullability.Nullable) return Nullability.Nullable
|
||||||
|
val nullability2 = getElseExpression()?.nullability()
|
||||||
|
if (nullability2 == Nullability.Nullable) return Nullability.Nullable
|
||||||
|
if (nullability1 == Nullability.NotNull && nullability2 == Nullability.NotNull) return Nullability.NotNull
|
||||||
|
Nullability.Default
|
||||||
|
}
|
||||||
|
|
||||||
|
is PsiParenthesizedExpression -> getExpression()?.nullability() ?: Nullability.Default
|
||||||
|
|
||||||
|
//TODO: some other cases
|
||||||
|
|
||||||
|
else -> Nullability.Default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isNullableFromUsage(usage: PsiExpression): Boolean {
|
||||||
|
val parent = usage.getParent() ?: return false
|
||||||
|
if (parent is PsiAssignmentExpression && parent.getOperationTokenType() == JavaTokenType.EQ && usage == parent.getLExpression()) {
|
||||||
|
return parent.getRExpression()?.nullability() == Nullability.Nullable
|
||||||
|
}
|
||||||
|
else if (parent is PsiBinaryExpression) {
|
||||||
|
val operationType = parent.getOperationTokenType()
|
||||||
|
if (operationType == JavaTokenType.EQEQ || operationType == JavaTokenType.NE) {
|
||||||
|
val otherOperand = if (usage == parent.getLOperand()) parent.getROperand() else parent.getLOperand()
|
||||||
|
return otherOperand?.nullability() == Nullability.Nullable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -60,7 +60,7 @@ class SecondaryConstructor(converter: Converter,
|
|||||||
val typeParameters = ArrayList<TypeParameter>()
|
val typeParameters = ArrayList<TypeParameter>()
|
||||||
typeParameters.addAll(containingClass.typeParameterList.parameters)
|
typeParameters.addAll(containingClass.typeParameterList.parameters)
|
||||||
return Function(converter, Identifier("init"), MemberComments.Empty, modifiers,
|
return Function(converter, Identifier("init"), MemberComments.Empty, modifiers,
|
||||||
ClassType(containingClass.name, typeParameters, Nullability.NotNull, converter),
|
ClassType(containingClass.name, typeParameters, Nullability.NotNull, converter.settings),
|
||||||
TypeParameterList(typeParameters), parameterList, block, false)
|
TypeParameterList(typeParameters), parameterList, block, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.jetbrains.jet.j2k.ast
|
|||||||
|
|
||||||
import org.jetbrains.jet.j2k.Converter
|
import org.jetbrains.jet.j2k.Converter
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
import org.jetbrains.jet.j2k.ConverterSettings
|
||||||
|
|
||||||
fun Type.isPrimitive(): Boolean = this is PrimitiveType
|
fun Type.isPrimitive(): Boolean = this is PrimitiveType
|
||||||
fun Type.isUnit(): Boolean = this == Type.Unit
|
fun Type.isUnit(): Boolean = this == Type.Unit
|
||||||
@@ -28,11 +29,11 @@ enum class Nullability {
|
|||||||
Default
|
Default
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class MayBeNullableType(nullability: Nullability, val converter: Converter) : Type {
|
abstract class MayBeNullableType(nullability: Nullability, val settings: ConverterSettings) : Type {
|
||||||
override val isNullable: Boolean = when (nullability) {
|
override val isNullable: Boolean = when (nullability) {
|
||||||
Nullability.Nullable -> true
|
Nullability.Nullable -> true
|
||||||
Nullability.NotNull -> false
|
Nullability.NotNull -> false
|
||||||
Nullability.Default -> !converter.settings.forceNotNullTypes
|
Nullability.Default -> !settings.forceNotNullTypes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,8 +74,8 @@ trait Type : Element {
|
|||||||
override fun toString(): String = toKotlin()
|
override fun toString(): String = toKotlin()
|
||||||
}
|
}
|
||||||
|
|
||||||
open class ClassType(val `type`: Identifier, val parameters: List<Element>, nullability: Nullability, converter: Converter)
|
open class ClassType(val `type`: Identifier, val parameters: List<Element>, nullability: Nullability, settings: ConverterSettings)
|
||||||
: MayBeNullableType(nullability, converter) {
|
: MayBeNullableType(nullability, settings) {
|
||||||
|
|
||||||
override fun toKotlin(): String {
|
override fun toKotlin(): String {
|
||||||
// TODO change to map() when KT-2051 is fixed
|
// TODO change to map() when KT-2051 is fixed
|
||||||
@@ -90,12 +91,12 @@ open class ClassType(val `type`: Identifier, val parameters: List<Element>, null
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun toNotNullType(): Type = ClassType(`type`, parameters, Nullability.NotNull, converter)
|
override fun toNotNullType(): Type = ClassType(`type`, parameters, Nullability.NotNull, settings)
|
||||||
override fun toNullableType(): Type = ClassType(`type`, parameters, Nullability.Nullable, converter)
|
override fun toNullableType(): Type = ClassType(`type`, parameters, Nullability.Nullable, settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArrayType(val elementType: Type, nullability: Nullability, converter: Converter)
|
class ArrayType(val elementType: Type, nullability: Nullability, settings: ConverterSettings)
|
||||||
: MayBeNullableType(nullability, converter) {
|
: MayBeNullableType(nullability, settings) {
|
||||||
|
|
||||||
override fun toKotlin(): String {
|
override fun toKotlin(): String {
|
||||||
if (elementType is PrimitiveType) {
|
if (elementType is PrimitiveType) {
|
||||||
@@ -105,8 +106,8 @@ class ArrayType(val elementType: Type, nullability: Nullability, converter: Conv
|
|||||||
return "Array<" + elementType.toKotlin() + ">" + isNullableStr()
|
return "Array<" + elementType.toKotlin() + ">" + isNullableStr()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toNotNullType(): Type = ArrayType(elementType, Nullability.NotNull, converter)
|
override fun toNotNullType(): Type = ArrayType(elementType, Nullability.NotNull, settings)
|
||||||
override fun toNullableType(): Type = ArrayType(elementType, Nullability.Nullable, converter)
|
override fun toNullableType(): Type = ArrayType(elementType, Nullability.Nullable, settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
open class InProjectionType(val bound: Type) : NotNullType {
|
open class InProjectionType(val bound: Type) : NotNullType {
|
||||||
|
|||||||
@@ -17,7 +17,8 @@
|
|||||||
package org.jetbrains.jet.j2k.visitors
|
package org.jetbrains.jet.j2k.visitors
|
||||||
|
|
||||||
import org.jetbrains.jet.j2k.Converter
|
import org.jetbrains.jet.j2k.Converter
|
||||||
|
import org.jetbrains.jet.j2k.TypeConverter
|
||||||
|
|
||||||
open class Dispatcher(converter: Converter) {
|
open class Dispatcher(converter: Converter, typeConverter: TypeConverter) {
|
||||||
var expressionVisitor: ExpressionVisitor = ExpressionVisitor(converter)
|
var expressionVisitor: ExpressionVisitor = ExpressionVisitor(converter, typeConverter)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,14 +20,14 @@ import com.intellij.psi.*
|
|||||||
import org.jetbrains.jet.j2k.*
|
import org.jetbrains.jet.j2k.*
|
||||||
import org.jetbrains.jet.j2k.ast.*
|
import org.jetbrains.jet.j2k.ast.*
|
||||||
|
|
||||||
class ElementVisitor(public val converter: Converter) : JavaElementVisitor() {
|
class ElementVisitor(private val converter: Converter, private val typeConverter: TypeConverter) : JavaElementVisitor() {
|
||||||
public var result: Element = Element.Empty
|
public var result: Element = Element.Empty
|
||||||
protected set
|
protected set
|
||||||
|
|
||||||
override fun visitLocalVariable(variable: PsiLocalVariable) {
|
override fun visitLocalVariable(variable: PsiLocalVariable) {
|
||||||
result = LocalVariable(Identifier(variable.getName()!!),
|
result = LocalVariable(Identifier(variable.getName()!!),
|
||||||
converter.convertModifiers(variable),
|
converter.convertModifiers(variable),
|
||||||
{ converter.convertVariableType(variable) },
|
{ typeConverter.convertVariableType(variable) },
|
||||||
converter.convertExpression(variable.getInitializer(), variable.getType()),
|
converter.convertExpression(variable.getInitializer(), variable.getType()),
|
||||||
converter.settings.forceLocalVariableImmutability || variable.hasModifierProperty(PsiModifier.FINAL),
|
converter.settings.forceLocalVariableImmutability || variable.hasModifierProperty(PsiModifier.FINAL),
|
||||||
converter.settings)
|
converter.settings)
|
||||||
@@ -38,7 +38,7 @@ class ElementVisitor(public val converter: Converter) : JavaElementVisitor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitReferenceElement(reference: PsiJavaCodeReferenceElement) {
|
override fun visitReferenceElement(reference: PsiJavaCodeReferenceElement) {
|
||||||
val types = converter.convertTypes(reference.getTypeParameters())
|
val types = typeConverter.convertTypes(reference.getTypeParameters())
|
||||||
if (!reference.isQualified()) {
|
if (!reference.isQualified()) {
|
||||||
result = ReferenceElement(Identifier(reference.getReferenceName()!!), types)
|
result = ReferenceElement(Identifier(reference.getReferenceName()!!), types)
|
||||||
}
|
}
|
||||||
@@ -55,12 +55,12 @@ class ElementVisitor(public val converter: Converter) : JavaElementVisitor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitTypeElement(`type`: PsiTypeElement) {
|
override fun visitTypeElement(`type`: PsiTypeElement) {
|
||||||
result = TypeElement(converter.convertType(`type`.getType()))
|
result = TypeElement(typeConverter.convertType(`type`.getType()))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitTypeParameter(classParameter: PsiTypeParameter) {
|
override fun visitTypeParameter(classParameter: PsiTypeParameter) {
|
||||||
result = TypeParameter(Identifier(classParameter.getName()!!),
|
result = TypeParameter(Identifier(classParameter.getName()!!),
|
||||||
classParameter.getExtendsListTypes().map { converter.convertType(it) })
|
classParameter.getExtendsListTypes().map { typeConverter.convertType(it) })
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitParameterList(list: PsiParameterList) {
|
override fun visitParameterList(list: PsiParameterList) {
|
||||||
|
|||||||
@@ -34,8 +34,9 @@ import org.jetbrains.jet.lang.psi.psiUtil.isExtensionDeclaration
|
|||||||
import org.jetbrains.jet.lang.psi.JetPropertyAccessor
|
import org.jetbrains.jet.lang.psi.JetPropertyAccessor
|
||||||
import com.intellij.psi.impl.light.LightField
|
import com.intellij.psi.impl.light.LightField
|
||||||
|
|
||||||
open class ExpressionVisitor(protected val converter: Converter,
|
class ExpressionVisitor(private val converter: Converter,
|
||||||
private val usageReplacementMap: Map<PsiVariable, String> = mapOf()) : JavaElementVisitor() {
|
private val typeConverter: TypeConverter,
|
||||||
|
private val usageReplacementMap: Map<PsiVariable, String> = mapOf()) : JavaElementVisitor() {
|
||||||
public var result: Expression = Expression.Empty
|
public var result: Expression = Expression.Empty
|
||||||
protected set
|
protected set
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ open class ExpressionVisitor(protected val converter: Converter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitArrayInitializerExpression(expression: PsiArrayInitializerExpression) {
|
override fun visitArrayInitializerExpression(expression: PsiArrayInitializerExpression) {
|
||||||
val expressionType = converter.convertType(expression.getType())
|
val expressionType = typeConverter.convertType(expression.getType())
|
||||||
assert(expressionType is ArrayType, "Array initializer must have array type")
|
assert(expressionType is ArrayType, "Array initializer must have array type")
|
||||||
result = ArrayInitializerExpression(expressionType as ArrayType,
|
result = ArrayInitializerExpression(expressionType as ArrayType,
|
||||||
converter.convertExpressions(expression.getInitializers()))
|
converter.convertExpressions(expression.getInitializers()))
|
||||||
@@ -192,14 +193,14 @@ open class ExpressionVisitor(protected val converter: Converter,
|
|||||||
val qualifier = converter.convertExpression(arguments.firstOrNull())
|
val qualifier = converter.convertExpression(arguments.firstOrNull())
|
||||||
MethodCallExpression(QualifiedExpression(qualifier, Identifier(origin.getName()!!, false)),
|
MethodCallExpression(QualifiedExpression(qualifier, Identifier(origin.getName()!!, false)),
|
||||||
convertArguments(expression, isExtension = true),
|
convertArguments(expression, isExtension = true),
|
||||||
converter.convertTypes(expression.getTypeArguments()),
|
typeConverter.convertTypes(expression.getTypeArguments()),
|
||||||
converter.convertType(expression.getType()).isNullable)
|
typeConverter.convertType(expression.getType()).isNullable)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
MethodCallExpression(Identifier(origin.getName()!!, false),
|
MethodCallExpression(Identifier(origin.getName()!!, false),
|
||||||
convertArguments(expression),
|
convertArguments(expression),
|
||||||
converter.convertTypes(expression.getTypeArguments()),
|
typeConverter.convertTypes(expression.getTypeArguments()),
|
||||||
converter.convertType(expression.getType()).isNullable)
|
typeConverter.convertType(expression.getType()).isNullable)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -209,8 +210,8 @@ open class ExpressionVisitor(protected val converter: Converter,
|
|||||||
|
|
||||||
result = MethodCallExpression(converter.convertExpression(methodExpr),
|
result = MethodCallExpression(converter.convertExpression(methodExpr),
|
||||||
convertArguments(expression),
|
convertArguments(expression),
|
||||||
converter.convertTypes(expression.getTypeArguments()),
|
typeConverter.convertTypes(expression.getTypeArguments()),
|
||||||
converter.convertType(expression.getType()).isNullable)
|
typeConverter.convertType(expression.getType()).isNullable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitNewExpression(expression: PsiNewExpression) {
|
override fun visitNewExpression(expression: PsiNewExpression) {
|
||||||
@@ -240,14 +241,14 @@ open class ExpressionVisitor(protected val converter: Converter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
val reference = expression.getClassReference()
|
val reference = expression.getClassReference()
|
||||||
val typeParameters = if (reference != null) converter.convertTypes(reference.getTypeParameters()) else listOf()
|
val typeParameters = if (reference != null) typeConverter.convertTypes(reference.getTypeParameters()) else listOf()
|
||||||
return QualifiedExpression(Identifier(constructor.getName(), false),
|
return QualifiedExpression(Identifier(constructor.getName(), false),
|
||||||
MethodCallExpression(Identifier("init"), converter.convertExpressions(arguments), typeParameters, false))
|
MethodCallExpression(Identifier("init"), converter.convertExpressions(arguments), typeParameters, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createNewEmptyArrayWithoutInitialization(expression: PsiNewExpression): Expression {
|
private fun createNewEmptyArrayWithoutInitialization(expression: PsiNewExpression): Expression {
|
||||||
return ArrayWithoutInitializationExpression(
|
return ArrayWithoutInitializationExpression(
|
||||||
converter.convertType(expression.getType(), Nullability.NotNull),
|
typeConverter.convertType(expression.getType(), Nullability.NotNull),
|
||||||
converter.convertExpressions(expression.getArrayDimensions()))
|
converter.convertExpressions(expression.getArrayDimensions()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,7 +277,7 @@ open class ExpressionVisitor(protected val converter: Converter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitReferenceExpression(expression: PsiReferenceExpression) {
|
override fun visitReferenceExpression(expression: PsiReferenceExpression) {
|
||||||
val isNullable = converter.convertType(expression.getType(), expression.nullability()).isNullable
|
val isNullable = typeConverter.convertType(expression.getType(), expression.nullability()).isNullable
|
||||||
val referencedName = expression.getReferenceName()!!
|
val referencedName = expression.getReferenceName()!!
|
||||||
var identifier: Expression = Identifier(referencedName, isNullable)
|
var identifier: Expression = Identifier(referencedName, isNullable)
|
||||||
val qualifier = expression.getQualifierExpression()
|
val qualifier = expression.getQualifierExpression()
|
||||||
@@ -368,7 +369,7 @@ open class ExpressionVisitor(protected val converter: Converter,
|
|||||||
result = MethodCallExpression.build(converter.convertExpression(operand), typeConversion)
|
result = MethodCallExpression.build(converter.convertExpression(operand), typeConversion)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = TypeCastExpression(converter.convertType(castType.getType()),
|
result = TypeCastExpression(typeConverter.convertType(castType.getType()),
|
||||||
converter.convertExpression(operand))
|
converter.convertExpression(operand))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,16 +18,16 @@ package org.jetbrains.jet.j2k.visitors
|
|||||||
|
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.impl.source.PsiClassReferenceType
|
import com.intellij.psi.impl.source.PsiClassReferenceType
|
||||||
import org.jetbrains.jet.j2k.Converter
|
|
||||||
import org.jetbrains.jet.j2k.ast.*
|
import org.jetbrains.jet.j2k.ast.*
|
||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
import com.intellij.openapi.util.text.StringUtil
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType
|
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType
|
||||||
|
import org.jetbrains.jet.j2k.TypeConverter
|
||||||
|
|
||||||
private val PRIMITIVE_TYPES_NAMES = JvmPrimitiveType.values().map { it.getName() }
|
private val PRIMITIVE_TYPES_NAMES = JvmPrimitiveType.values().map { it.getName() }
|
||||||
|
|
||||||
open class TypeVisitor(private val converter: Converter) : PsiTypeVisitor<Type>() {
|
open class TypeVisitor(private val converter: TypeConverter) : PsiTypeVisitor<Type>() {
|
||||||
override fun visitPrimitiveType(primitiveType: PsiPrimitiveType): Type {
|
override fun visitPrimitiveType(primitiveType: PsiPrimitiveType): Type {
|
||||||
val name = primitiveType.getCanonicalText()
|
val name = primitiveType.getCanonicalText()
|
||||||
return if (name == "void") {
|
return if (name == "void") {
|
||||||
@@ -42,7 +42,7 @@ open class TypeVisitor(private val converter: Converter) : PsiTypeVisitor<Type>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitArrayType(arrayType: PsiArrayType): Type {
|
override fun visitArrayType(arrayType: PsiArrayType): Type {
|
||||||
return ArrayType(converter.convertType(arrayType.getComponentType()), Nullability.Default, converter)
|
return ArrayType(converter.convertType(arrayType.getComponentType()), Nullability.Default, converter.settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitClassType(classType: PsiClassType): Type {
|
override fun visitClassType(classType: PsiClassType): Type {
|
||||||
@@ -53,18 +53,18 @@ open class TypeVisitor(private val converter: Converter) : PsiTypeVisitor<Type>(
|
|||||||
if (resolvedClassTypeParams.size() == 1) {
|
if (resolvedClassTypeParams.size() == 1) {
|
||||||
if ((resolvedClassTypeParams.single() as ClassType).`type`.name == "Any") {
|
if ((resolvedClassTypeParams.single() as ClassType).`type`.name == "Any") {
|
||||||
starParamList.add(StarProjectionType())
|
starParamList.add(StarProjectionType())
|
||||||
return ClassType(identifier, starParamList, Nullability.Default, converter)
|
return ClassType(identifier, starParamList, Nullability.Default, converter.settings)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return ClassType(identifier, resolvedClassTypeParams, Nullability.Default, converter)
|
return ClassType(identifier, resolvedClassTypeParams, Nullability.Default, converter.settings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return ClassType(identifier, resolvedClassTypeParams, Nullability.Default, converter)
|
return ClassType(identifier, resolvedClassTypeParams, Nullability.Default, converter.settings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return ClassType(identifier, converter.convertTypes(classType.getParameters()), Nullability.Default, converter)
|
return ClassType(identifier, converter.convertTypes(classType.getParameters()), Nullability.Default, converter.settings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ open class TypeVisitor(private val converter: Converter) : PsiTypeVisitor<Type>(
|
|||||||
ClassType(Identifier(getClassTypeName(superTypes[0])),
|
ClassType(Identifier(getClassTypeName(superTypes[0])),
|
||||||
converter.convertTypes(superTypes[0].getParameters()),
|
converter.convertTypes(superTypes[0].getParameters()),
|
||||||
Nullability.Default,
|
Nullability.Default,
|
||||||
converter)
|
converter.settings)
|
||||||
else
|
else
|
||||||
StarProjectionType()
|
StarProjectionType()
|
||||||
typeParams.add(boundType)
|
typeParams.add(boundType)
|
||||||
|
|||||||
Reference in New Issue
Block a user