Java to Kotlin convertor: more code improvements
This commit is contained in:
@@ -21,8 +21,8 @@ import com.intellij.psi.PsiClass
|
|||||||
import com.intellij.psi.PsiReferenceExpression
|
import com.intellij.psi.PsiReferenceExpression
|
||||||
import com.intellij.psi.JavaRecursiveElementVisitor
|
import com.intellij.psi.JavaRecursiveElementVisitor
|
||||||
import java.util.LinkedHashSet
|
import java.util.LinkedHashSet
|
||||||
import com.intellij.psi.PsiReference
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiMethodCallExpression
|
||||||
|
|
||||||
fun PsiMethod.isPrimaryConstructor(): Boolean {
|
fun PsiMethod.isPrimaryConstructor(): Boolean {
|
||||||
if (!isConstructor()) return false
|
if (!isConstructor()) return false
|
||||||
@@ -64,12 +64,9 @@ fun PsiClass.getPrimaryConstructor(): PsiMethod? {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun isInsidePrimaryConstructor(element: PsiElement): Boolean
|
fun isInsidePrimaryConstructor(element: PsiElement): Boolean
|
||||||
= containingConstructor(element)?.isPrimaryConstructor() ?: false
|
= getContainingConstructor(element)?.isPrimaryConstructor() ?: false
|
||||||
|
|
||||||
fun isInsideSecondaryConstructor(element: PsiElement): Boolean
|
fun getContainingConstructor(element: PsiElement): PsiMethod? {
|
||||||
= !(containingConstructor(element)?.isPrimaryConstructor() ?: true)
|
|
||||||
|
|
||||||
fun containingConstructor(element: PsiElement): PsiMethod? {
|
|
||||||
var context = element.getContext()
|
var context = element.getContext()
|
||||||
while (context != null) {
|
while (context != null) {
|
||||||
val _context = context!!
|
val _context = context!!
|
||||||
@@ -82,10 +79,14 @@ fun containingConstructor(element: PsiElement): PsiMethod? {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isSuperConstructorRef(ref: PsiReference): Boolean {
|
fun PsiMethodCallExpression.isSuperConstructorCall(): Boolean {
|
||||||
|
val ref = getMethodExpression()
|
||||||
if (ref.getCanonicalText().equals("super")) {
|
if (ref.getCanonicalText().equals("super")) {
|
||||||
val target = ref.resolve()
|
val target = ref.resolve()
|
||||||
return target is PsiMethod && target.isConstructor()
|
return target is PsiMethod && target.isConstructor()
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun PsiReferenceExpression.isThisConstructorCall(): Boolean
|
||||||
|
= getReferences().filter { it.getCanonicalText() == "this" }.map { it.resolve() }.any { it is PsiMethod && it.isConstructor() }
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
is PsiJavaFile -> convertFile(element)
|
is PsiJavaFile -> convertFile(element)
|
||||||
is PsiClass -> convertClass(element)
|
is PsiClass -> convertClass(element)
|
||||||
is PsiMethod -> convertMethod(element)
|
is PsiMethod -> convertMethod(element)
|
||||||
is PsiField -> convertField(element, element.getContainingClass())
|
is PsiField -> convertField(element)
|
||||||
is PsiStatement -> convertStatement(element)
|
is PsiStatement -> convertStatement(element)
|
||||||
is PsiExpression -> convertExpression(element)
|
is PsiExpression -> convertExpression(element)
|
||||||
is PsiComment -> Comment(element.getText()!!)
|
is PsiComment -> Comment(element.getText()!!)
|
||||||
@@ -78,7 +78,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
private fun convertMembers(psiClass: PsiClass): List<Element> {
|
private fun convertMembers(psiClass: PsiClass): List<Element> {
|
||||||
val allChildren = psiClass.getChildren().toList()
|
val allChildren = psiClass.getChildren().toList()
|
||||||
val lBraceIndex = allChildren.indexOf(psiClass.getLBrace())
|
val lBraceIndex = allChildren.indexOf(psiClass.getLBrace())
|
||||||
return allChildren.subList(lBraceIndex, allChildren.size).map { convertMember(it, psiClass) }.filterNotNull()
|
return allChildren.subList(lBraceIndex, allChildren.size).map { convertMember(it) }.filterNotNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getComments(member: PsiMember): MemberComments {
|
private fun getComments(member: PsiMember): MemberComments {
|
||||||
@@ -93,9 +93,9 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
return MemberComments(whiteSpacesAndComments)
|
return MemberComments(whiteSpacesAndComments)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun convertMember(e: PsiElement?, containingClass: PsiClass): Element? = when(e) {
|
private fun convertMember(e: PsiElement?): Element? = when(e) {
|
||||||
is PsiMethod -> convertMethod(e, true)
|
is PsiMethod -> convertMethod(e, true)
|
||||||
is PsiField -> convertField(e, containingClass)
|
is PsiField -> convertField(e)
|
||||||
is PsiClass -> convertClass(e)
|
is PsiClass -> convertClass(e)
|
||||||
is PsiClassInitializer -> convertInitializer(e)
|
is PsiClassInitializer -> convertInitializer(e)
|
||||||
else -> convertElement(e)
|
else -> convertElement(e)
|
||||||
@@ -103,90 +103,86 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
|
|
||||||
private fun convertClass(psiClass: PsiClass): Class {
|
private fun convertClass(psiClass: PsiClass): Class {
|
||||||
val modifiers = convertModifierList(psiClass.getModifierList())
|
val modifiers = convertModifierList(psiClass.getModifierList())
|
||||||
val fields = convertFields(psiClass.getFields(), psiClass)
|
|
||||||
val typeParameters = convertTypeParameterList(psiClass.getTypeParameterList())
|
val typeParameters = convertTypeParameterList(psiClass.getTypeParameterList())
|
||||||
val implementsTypes = convertToNotNullableTypes(psiClass.getImplementsListTypes())
|
val implementsTypes = convertToNotNullableTypes(psiClass.getImplementsListTypes())
|
||||||
val extendsTypes = convertToNotNullableTypes(psiClass.getExtendsListTypes())
|
val extendsTypes = convertToNotNullableTypes(psiClass.getExtendsListTypes())
|
||||||
val name = Identifier(psiClass.getName()!!)
|
val name = Identifier(psiClass.getName()!!)
|
||||||
val members = ArrayList(convertMembers(psiClass))
|
val members = ArrayList(convertMembers(psiClass))
|
||||||
|
|
||||||
val baseClassParams: List<Expression> = run {
|
when {
|
||||||
val superVisitor = SuperVisitor()
|
psiClass.isInterface() -> return Trait(this, name, getComments(psiClass), modifiers, typeParameters, extendsTypes, listOf(), implementsTypes, members)
|
||||||
psiClass.accept(superVisitor)
|
|
||||||
val resolvedSuperCallParameters = superVisitor.resolvedSuperCallParameters
|
|
||||||
if (resolvedSuperCallParameters.size() == 1) {
|
|
||||||
convertExpressions(resolvedSuperCallParameters.single().getExpressions())
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
listOf()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!psiClass.isEnum() && !psiClass.isInterface() && psiClass.getConstructors().size > 1 && psiClass.getPrimaryConstructor() == null) {
|
psiClass.isEnum() -> return Enum(this, name, getComments(psiClass), modifiers, typeParameters, listOf(), listOf(), implementsTypes, members)
|
||||||
val finalOrWithEmptyInitializer = fields.filter { it.isVal() || it.initializer.toKotlin().isEmpty() }
|
|
||||||
val initializers = HashMap<String, String>()
|
|
||||||
for (member in members) {
|
|
||||||
if (member is Constructor && !member.isPrimary) {
|
|
||||||
for (field in finalOrWithEmptyInitializer) {
|
|
||||||
initializers.put(field.identifier.toKotlin(), getDefaultInitializer(field))
|
|
||||||
}
|
|
||||||
|
|
||||||
val newStatements = ArrayList<Statement>()
|
else -> {
|
||||||
for (statement in member.block!!.statements) {
|
if (psiClass.getConstructors().size > 1 && psiClass.getPrimaryConstructor() == null) {
|
||||||
var isRemoved = false
|
val finalOrWithEmptyInitializerFields = members.filterIsInstance(javaClass<Field>()).filter { it.isVal() || it.initializer.toKotlin().isEmpty() }
|
||||||
if (statement is AssignmentExpression) {
|
val initializers = HashMap<String, String>()
|
||||||
val assignee = statement.left
|
for (member in members) {
|
||||||
if (assignee is CallChainExpression) {
|
if (member is Constructor && !member.isPrimary) {
|
||||||
for (field in finalOrWithEmptyInitializer) {
|
for (field in finalOrWithEmptyInitializerFields) {
|
||||||
val id = field.identifier.toKotlin()
|
initializers.put(field.identifier.toKotlin(), getDefaultInitializer(field))
|
||||||
if (assignee.identifier.toKotlin().endsWith("." + id)) {
|
}
|
||||||
initializers.put(id, statement.right.toKotlin())
|
|
||||||
isRemoved = true
|
val newStatements = ArrayList<Statement>()
|
||||||
|
for (statement in member.block!!.statements) {
|
||||||
|
var keepStatement = true
|
||||||
|
if (statement is AssignmentExpression) {
|
||||||
|
val assignee = statement.left
|
||||||
|
if (assignee is CallChainExpression) {
|
||||||
|
for (field in finalOrWithEmptyInitializerFields) {
|
||||||
|
val id = field.identifier.toKotlin()
|
||||||
|
if (assignee.identifier.toKotlin().endsWith("." + id)) {
|
||||||
|
initializers.put(id, statement.right.toKotlin())
|
||||||
|
keepStatement = false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (keepStatement) {
|
||||||
|
newStatements.add(statement)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
newStatements.add(0, DummyStringExpression("val __ = " + createPrimaryConstructorInvocation(name.toKotlin(), finalOrWithEmptyInitializerFields, initializers)))
|
||||||
|
member.block = Block(newStatements)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isRemoved) {
|
|
||||||
newStatements.add(statement)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
newStatements.add(0, DummyStringExpression("val __ = " + createPrimaryConstructorInvocation(name.toKotlin(), finalOrWithEmptyInitializer, initializers)))
|
|
||||||
member.block = Block(newStatements)
|
//TODO: comments?
|
||||||
|
members.add(Constructor(this, Identifier.Empty, MemberComments.Empty, Collections.emptySet<Modifier>(),
|
||||||
|
ClassType(name, listOf(), false, this),
|
||||||
|
TypeParameterList.Empty,
|
||||||
|
ParameterList(createParametersFromFields(finalOrWithEmptyInitializerFields)),
|
||||||
|
Block(createInitStatementsFromFields(finalOrWithEmptyInitializerFields)),
|
||||||
|
true))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val baseClassParams: List<Expression> = run {
|
||||||
|
val superVisitor = SuperVisitor()
|
||||||
|
psiClass.accept(superVisitor)
|
||||||
|
val resolvedSuperCallParameters = superVisitor.resolvedSuperCallParameters
|
||||||
|
if (resolvedSuperCallParameters.size() == 1) {
|
||||||
|
convertExpressions(resolvedSuperCallParameters.single().getExpressions())
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
listOf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Class(this, name, getComments(psiClass), modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, members)
|
||||||
}
|
}
|
||||||
//TODO: comments?
|
|
||||||
members.add(Constructor(this, Identifier.Empty, MemberComments.Empty, Collections.emptySet<Modifier>(),
|
|
||||||
ClassType(name, listOf(), false, this),
|
|
||||||
TypeParameterList.Empty,
|
|
||||||
ParameterList(createParametersFromFields(finalOrWithEmptyInitializer)),
|
|
||||||
Block(createInitStatementsFromFields(finalOrWithEmptyInitializer)),
|
|
||||||
true))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (psiClass.isInterface()) {
|
|
||||||
return Trait(this, name, getComments(psiClass), modifiers, typeParameters, extendsTypes, listOf(), implementsTypes, members)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (psiClass.isEnum()) {
|
|
||||||
return Enum(this, name, getComments(psiClass), modifiers, typeParameters, listOf(), listOf(), implementsTypes, members)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Class(this, name, getComments(psiClass), modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, members)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun convertInitializer(initializer: PsiClassInitializer): Initializer {
|
private fun convertInitializer(initializer: PsiClassInitializer): Initializer {
|
||||||
return Initializer(convertBlock(initializer.getBody(), true), convertModifierList(initializer.getModifierList()))
|
return Initializer(convertBlock(initializer.getBody(), true), convertModifierList(initializer.getModifierList()))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun convertFields(fields: Array<PsiField>, psiClass: PsiClass): List<Field> {
|
private fun convertField(field: PsiField): Field {
|
||||||
return fields.map { convertField(it, psiClass) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun convertField(field: PsiField, psiClass: PsiClass?): Field {
|
|
||||||
val modifiers = convertModifierList(field.getModifierList())
|
val modifiers = convertModifierList(field.getModifierList())
|
||||||
if (field is PsiEnumConstant) {
|
if (field is PsiEnumConstant) {
|
||||||
return EnumConstant(Identifier(field.getName()!!),
|
return EnumConstant(Identifier(field.getName()!!),
|
||||||
@@ -196,8 +192,8 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
convertElement(field.getArgumentList()))
|
convertElement(field.getArgumentList()))
|
||||||
}
|
}
|
||||||
|
|
||||||
var kType = convertType(field.getType(), isAnnotatedAsNotNull(field.getModifierList()))
|
var kType = convertType(field.getType(), field.isAnnotatedAsNotNull())
|
||||||
if (field.hasModifierProperty(PsiModifier.FINAL) && isDefinitelyNotNull(field.getInitializer())) {
|
if (field.hasModifierProperty(PsiModifier.FINAL) && field.getInitializer().isDefinitelyNotNull()) {
|
||||||
kType = kType.convertedToNotNull();
|
kType = kType.convertedToNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +202,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
modifiers,
|
modifiers,
|
||||||
kType,
|
kType,
|
||||||
convertExpression(field.getInitializer(), field.getType()),
|
convertExpression(field.getInitializer(), field.getType()),
|
||||||
countWriteAccesses(field, psiClass))
|
field.countWriteAccesses(field.getContainingClass()))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun convertMethod(method: PsiMethod): Function {
|
private fun convertMethod(method: PsiMethod): Function {
|
||||||
@@ -222,7 +218,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
}
|
}
|
||||||
methodReturnType = method.getReturnType()
|
methodReturnType = method.getReturnType()
|
||||||
val identifier = Identifier(method.getName())
|
val identifier = Identifier(method.getName())
|
||||||
val returnType = convertType(method.getReturnType(), isAnnotatedAsNotNull(method.getModifierList()))
|
val returnType = convertType(method.getReturnType(), method.isAnnotatedAsNotNull())
|
||||||
val body = convertBlock(method.getBody(), notEmpty)
|
val body = convertBlock(method.getBody(), notEmpty)
|
||||||
|
|
||||||
val params = createFunctionParameters(method)
|
val params = createFunctionParameters(method)
|
||||||
@@ -253,8 +249,8 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
val result = ArrayList<Parameter>()
|
val result = ArrayList<Parameter>()
|
||||||
for (parameter in method.getParameterList().getParameters()) {
|
for (parameter in method.getParameterList().getParameters()) {
|
||||||
result.add(Parameter(Identifier(parameter.getName()!!),
|
result.add(Parameter(Identifier(parameter.getName()!!),
|
||||||
convertType(parameter.getType(), isAnnotatedAsNotNull(parameter.getModifierList())),
|
convertType(parameter.getType(), parameter.isAnnotatedAsNotNull()),
|
||||||
isReadOnly(parameter, method.getBody())))
|
parameter.countWriteAccesses(method.getBody()) == 0))
|
||||||
}
|
}
|
||||||
return ParameterList(result)
|
return ParameterList(result)
|
||||||
}
|
}
|
||||||
@@ -339,7 +335,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
|||||||
public fun convertParameter(parameter: PsiParameter, forceNotNull: Boolean = false): Parameter {
|
public fun convertParameter(parameter: PsiParameter, forceNotNull: Boolean = false): Parameter {
|
||||||
return Parameter(Identifier(parameter.getName()!!),
|
return Parameter(Identifier(parameter.getName()!!),
|
||||||
convertType(parameter.getType(),
|
convertType(parameter.getType(),
|
||||||
forceNotNull || isAnnotatedAsNotNull(parameter.getModifierList())), true)
|
forceNotNull || parameter.isAnnotatedAsNotNull()), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun convertArguments(expression: PsiCallExpression): List<Expression> {
|
public fun convertArguments(expression: PsiCallExpression): List<Expression> {
|
||||||
|
|||||||
@@ -19,53 +19,36 @@ package org.jetbrains.jet.j2k
|
|||||||
import org.jetbrains.jet.j2k.ast.Identifier
|
import org.jetbrains.jet.j2k.ast.Identifier
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.JavaRecursiveElementVisitor
|
import com.intellij.psi.JavaRecursiveElementVisitor
|
||||||
import java.util.ArrayList
|
|
||||||
import com.intellij.psi.PsiReferenceExpression
|
import com.intellij.psi.PsiReferenceExpression
|
||||||
import com.intellij.psi.util.PsiUtil
|
|
||||||
import com.intellij.psi.PsiModifierList
|
|
||||||
import com.intellij.psi.PsiAnnotation
|
|
||||||
import com.intellij.psi.PsiLiteralExpression
|
import com.intellij.psi.PsiLiteralExpression
|
||||||
import com.intellij.psi.PsiNewExpression
|
import com.intellij.psi.PsiNewExpression
|
||||||
import org.jetbrains.jet.j2k.ast.Field
|
import org.jetbrains.jet.j2k.ast.Field
|
||||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions
|
import org.jetbrains.jet.lang.types.expressions.OperatorConventions
|
||||||
|
import com.intellij.psi.util.PsiUtil
|
||||||
|
import com.intellij.psi.PsiModifierListOwner
|
||||||
|
|
||||||
fun quoteKeywords(packageName: String): String = packageName.split("\\.").map { Identifier(it).toKotlin() }.makeString(".")
|
fun quoteKeywords(packageName: String): String = packageName.split("\\.").map { Identifier(it).toKotlin() }.makeString(".")
|
||||||
|
|
||||||
fun countWriteAccesses(element: PsiElement?, container: PsiElement?): Int {
|
fun PsiElement.countWriteAccesses(scope: PsiElement?): Int {
|
||||||
if (container == null) return 0
|
if (scope == null) return 0
|
||||||
|
|
||||||
class ReferenceCollector() : JavaRecursiveElementVisitor() {
|
|
||||||
private val _collectedReferences = ArrayList<PsiReferenceExpression>()
|
|
||||||
|
|
||||||
public val collectedReferences: List<PsiReferenceExpression>
|
|
||||||
get() = _collectedReferences
|
|
||||||
|
|
||||||
|
var writes = 0
|
||||||
|
scope.accept(object: JavaRecursiveElementVisitor() {
|
||||||
override fun visitReferenceExpression(expression: PsiReferenceExpression) {
|
override fun visitReferenceExpression(expression: PsiReferenceExpression) {
|
||||||
super.visitReferenceExpression(expression)
|
super.visitReferenceExpression(expression)
|
||||||
_collectedReferences.add(expression)
|
if (PsiUtil.isAccessedForWriting(expression) && expression.isReferenceTo(this@countWriteAccesses)) {
|
||||||
|
writes++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
return writes
|
||||||
val collector = ReferenceCollector()
|
|
||||||
container.accept(collector)
|
|
||||||
return collector.collectedReferences.count { it.isReferenceTo(element) && PsiUtil.isAccessedForWriting(it) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isReadOnly(element: PsiElement?, container: PsiElement?): Boolean
|
fun PsiModifierListOwner.isAnnotatedAsNotNull(): Boolean
|
||||||
= countWriteAccesses(element, container) == 0
|
= getModifierList()?.getAnnotations()?.any { NOT_NULL_ANNOTATIONS.contains(it.getQualifiedName()) } ?: false
|
||||||
|
|
||||||
fun isAnnotatedAsNotNull(modifierList: PsiModifierList?): Boolean {
|
fun PsiElement?.isDefinitelyNotNull(): Boolean = when(this) {
|
||||||
if (modifierList != null) {
|
is PsiLiteralExpression -> getValue() != null
|
||||||
for (annotation in modifierList.getAnnotations()) {
|
|
||||||
val qualifiedName = annotation.getQualifiedName()
|
|
||||||
return qualifiedName != null && NOT_NULL_ANNOTATIONS.contains(qualifiedName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isDefinitelyNotNull(element: PsiElement?): Boolean = when(element) {
|
|
||||||
is PsiLiteralExpression -> element.getValue() != null
|
|
||||||
is PsiNewExpression -> true
|
is PsiNewExpression -> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ class ElementVisitor(public val converter: Converter) : JavaElementVisitor() {
|
|||||||
protected set
|
protected set
|
||||||
|
|
||||||
override fun visitLocalVariable(variable: PsiLocalVariable) {
|
override fun visitLocalVariable(variable: PsiLocalVariable) {
|
||||||
var kType = converter.convertType(variable.getType(), isAnnotatedAsNotNull(variable.getModifierList()))
|
var kType = converter.convertType(variable.getType(), variable.isAnnotatedAsNotNull())
|
||||||
if (variable.hasModifierProperty(PsiModifier.FINAL) && isDefinitelyNotNull(variable.getInitializer())) {
|
if (variable.hasModifierProperty(PsiModifier.FINAL) && variable.getInitializer().isDefinitelyNotNull()) {
|
||||||
kType = kType.convertedToNotNull();
|
kType = kType.convertedToNotNull()
|
||||||
}
|
}
|
||||||
result = LocalVariable(Identifier(variable.getName()!!),
|
result = LocalVariable(Identifier(variable.getName()!!),
|
||||||
converter.convertModifierList(variable.getModifierList()),
|
converter.convertModifierList(variable.getModifierList()),
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ open class ExpressionVisitor(public val converter: Converter) : JavaElementVisit
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected fun convertMethodCallExpression(expression: PsiMethodCallExpression) {
|
protected fun convertMethodCallExpression(expression: PsiMethodCallExpression) {
|
||||||
if (!isSuperConstructorRef(expression.getMethodExpression()) || !isInsidePrimaryConstructor(expression)) {
|
if (!expression.isSuperConstructorCall() || !isInsidePrimaryConstructor(expression)) {
|
||||||
result = MethodCallExpression(converter.convertExpression(expression.getMethodExpression()),
|
result = MethodCallExpression(converter.convertExpression(expression.getMethodExpression()),
|
||||||
converter.convertArguments(expression),
|
converter.convertArguments(expression),
|
||||||
converter.convertTypes(expression.getTypeArguments()),
|
converter.convertTypes(expression.getTypeArguments()),
|
||||||
@@ -212,21 +212,20 @@ open class ExpressionVisitor(public val converter: Converter) : JavaElementVisit
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitReferenceExpression(expression: PsiReferenceExpression) {
|
override fun visitReferenceExpression(expression: PsiReferenceExpression) {
|
||||||
val isFieldReference = isFieldReference(expression, getContainingClass(expression))
|
val containingConstructor = getContainingConstructor(expression)
|
||||||
val insideSecondaryConstructor = isInsideSecondaryConstructor(expression)
|
val insideSecondaryConstructor = containingConstructor != null && !containingConstructor.isPrimaryConstructor()
|
||||||
val hasReceiver = isFieldReference && insideSecondaryConstructor
|
val addReceiver = insideSecondaryConstructor && (expression.getReference()?.resolve() as? PsiField)?.getContainingClass() == containingConstructor!!.getContainingClass()
|
||||||
val isThis = isThisExpression(expression)
|
|
||||||
val notNull = isResolvedToNotNull(expression)
|
val isNullable = converter.convertType(expression.getType(), expression.isResolvedToNotNull()).isNullable
|
||||||
val isNullable = converter.convertType(expression.getType(), notNull).isNullable
|
|
||||||
val className = getClassNameWithConstructor(expression)
|
|
||||||
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()
|
||||||
if (hasReceiver) {
|
|
||||||
|
if (addReceiver) {
|
||||||
identifier = CallChainExpression(Identifier("__", false), Identifier(referencedName, isNullable))
|
identifier = CallChainExpression(Identifier("__", false), Identifier(referencedName, isNullable))
|
||||||
}
|
}
|
||||||
else if (insideSecondaryConstructor && isThis) {
|
else if (insideSecondaryConstructor && expression.isThisConstructorCall()) {
|
||||||
identifier = Identifier("val __ = " + className)
|
identifier = Identifier("val __ = " + (containingConstructor?.getContainingClass()?.getNameIdentifier()?.getText() ?: ""))
|
||||||
}
|
}
|
||||||
else if (qualifier != null && qualifier.getType() is PsiArrayType && referencedName == "length") {
|
else if (qualifier != null && qualifier.getType() is PsiArrayType && referencedName == "length") {
|
||||||
identifier = Identifier("size", isNullable)
|
identifier = Identifier("size", isNullable)
|
||||||
@@ -259,15 +258,13 @@ open class ExpressionVisitor(public val converter: Converter) : JavaElementVisit
|
|||||||
result = CallChainExpression(converter.convertExpression(qualifier), identifier)
|
result = CallChainExpression(converter.convertExpression(qualifier), identifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isResolvedToNotNull(expression: PsiReference): Boolean {
|
private fun PsiReference.isResolvedToNotNull(): Boolean {
|
||||||
val target = expression.resolve()
|
val target = resolve()
|
||||||
if (target is PsiEnumConstant) {
|
return when(target) {
|
||||||
return true;
|
is PsiEnumConstant -> true
|
||||||
|
is PsiModifierListOwner -> target.isAnnotatedAsNotNull()
|
||||||
|
else -> false
|
||||||
}
|
}
|
||||||
if (target is PsiModifierListOwner) {
|
|
||||||
return isAnnotatedAsNotNull(target.getModifierList());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitSuperExpression(expression: PsiSuperExpression) {
|
override fun visitSuperExpression(expression: PsiSuperExpression) {
|
||||||
@@ -287,19 +284,17 @@ open class ExpressionVisitor(public val converter: Converter) : JavaElementVisit
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitTypeCastExpression(expression: PsiTypeCastExpression) {
|
override fun visitTypeCastExpression(expression: PsiTypeCastExpression) {
|
||||||
val castType: PsiTypeElement? = expression.getCastType()
|
val castType = expression.getCastType() ?: return
|
||||||
if (castType != null) {
|
val operand = expression.getOperand()
|
||||||
val operand = expression.getOperand()
|
val operandType = operand?.getType()
|
||||||
val operandType = operand?.getType()
|
val typeText = castType.getType().getCanonicalText()
|
||||||
val typeText = castType.getType().getCanonicalText()
|
val typeConversion = PRIMITIVE_TYPE_CONVERSIONS[typeText]
|
||||||
val typeConversion = PRIMITIVE_TYPE_CONVERSIONS[typeText]
|
if (operandType is PsiPrimitiveType && typeConversion != null) {
|
||||||
if (operandType is PsiPrimitiveType && typeConversion != null) {
|
result = MethodCallExpression.build(converter.convertExpression(operand), typeConversion)
|
||||||
result = MethodCallExpression.build(converter.convertExpression(operand), typeConversion)
|
}
|
||||||
}
|
else {
|
||||||
else {
|
result = TypeCastExpression(converter.convertType(castType.getType()),
|
||||||
result = TypeCastExpression(converter.convertType(castType.getType()),
|
converter.convertExpression(operand))
|
||||||
converter.convertExpression(operand))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,26 +334,6 @@ open class ExpressionVisitor(public val converter: Converter) : JavaElementVisit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getClassNameWithConstructor(expression: PsiReferenceExpression): String {
|
|
||||||
var context = expression.getContext()
|
|
||||||
while (context != null) {
|
|
||||||
val _context = context!!
|
|
||||||
if (_context is PsiMethod && _context.isConstructor()) {
|
|
||||||
val containingClass = _context.getContainingClass()
|
|
||||||
if (containingClass != null) {
|
|
||||||
val identifier = containingClass.getNameIdentifier()
|
|
||||||
if (identifier != null) {
|
|
||||||
return identifier.getText()!!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
context = _context.getContext()
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun getClassName(expression: PsiExpression): String {
|
protected fun getClassName(expression: PsiExpression): String {
|
||||||
var context = expression.getContext()
|
var context = expression.getContext()
|
||||||
while (context != null) {
|
while (context != null) {
|
||||||
@@ -376,45 +351,6 @@ open class ExpressionVisitor(public val converter: Converter) : JavaElementVisit
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isFieldReference(expression: PsiReferenceExpression, currentClass: PsiClass?): Boolean {
|
|
||||||
val reference = expression.getReference()
|
|
||||||
if (reference != null) {
|
|
||||||
val target = reference.resolve()
|
|
||||||
if (target is PsiField) {
|
|
||||||
return target.getContainingClass() == currentClass
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getContainingClass(expression: PsiExpression): PsiClass? {
|
|
||||||
var context = expression.getContext()
|
|
||||||
while (context != null) {
|
|
||||||
val _context = context!!
|
|
||||||
if (_context is PsiMethod && _context.isConstructor()) {
|
|
||||||
return _context.getContainingClass()
|
|
||||||
}
|
|
||||||
|
|
||||||
context = _context.getContext()
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isThisExpression(expression: PsiReferenceExpression): Boolean {
|
|
||||||
for (ref in expression.getReferences()) {
|
|
||||||
if (ref.getCanonicalText() == "this") {
|
|
||||||
val target = ref.resolve()
|
|
||||||
if (target is PsiMethod && target.isConstructor()) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isStaticallyImported(member: PsiMember, context: PsiElement): Boolean {
|
private fun isStaticallyImported(member: PsiMember, context: PsiElement): Boolean {
|
||||||
val containingFile = context.getContainingFile()
|
val containingFile = context.getContainingFile()
|
||||||
val targetContainingClass = member.getContainingClass()
|
val targetContainingClass = member.getContainingClass()
|
||||||
|
|||||||
@@ -79,11 +79,13 @@ class StatementVisitor(public val converter: Converter) : JavaElementVisitor() {
|
|||||||
val update = statement.getUpdate()
|
val update = statement.getUpdate()
|
||||||
val condition = statement.getCondition()
|
val condition = statement.getCondition()
|
||||||
val body = statement.getBody()
|
val body = statement.getBody()
|
||||||
val firstChildLocalVar = initialization?.getFirstChild() as? PsiLocalVariable
|
|
||||||
var bodyWriteCount = countWriteAccesses(firstChildLocalVar, body)
|
val initializationVar = initialization?.getFirstChild() as? PsiLocalVariable
|
||||||
var conditionWriteCount = countWriteAccesses(firstChildLocalVar, condition)
|
val onceWritableIterator = initializationVar != null
|
||||||
var updateWriteCount = countWriteAccesses(firstChildLocalVar, update)
|
&& initializationVar.countWriteAccesses(body) == 0
|
||||||
val onceWritableIterator = updateWriteCount == 1 && bodyWriteCount + conditionWriteCount == 0
|
&& initializationVar.countWriteAccesses(condition) == 0
|
||||||
|
&& initializationVar.countWriteAccesses(update) == 1
|
||||||
|
|
||||||
val operationTokenType = (condition as? PsiBinaryExpression)?.getOperationTokenType()
|
val operationTokenType = (condition as? PsiBinaryExpression)?.getOperationTokenType()
|
||||||
if (initialization is PsiDeclarationStatement
|
if (initialization is PsiDeclarationStatement
|
||||||
&& initialization.getFirstChild() == initialization.getLastChild()
|
&& initialization.getFirstChild() == initialization.getLastChild()
|
||||||
@@ -92,16 +94,16 @@ class StatementVisitor(public val converter: Converter) : JavaElementVisitor() {
|
|||||||
&& update.getChildren().size == 1
|
&& update.getChildren().size == 1
|
||||||
&& isPlusPlusExpression(update.getChildren().single())
|
&& isPlusPlusExpression(update.getChildren().single())
|
||||||
&& (operationTokenType == JavaTokenType.LT || operationTokenType == JavaTokenType.LE)
|
&& (operationTokenType == JavaTokenType.LT || operationTokenType == JavaTokenType.LE)
|
||||||
&& firstChildLocalVar != null
|
&& initializationVar != null
|
||||||
&& firstChildLocalVar.getNameIdentifier() != null
|
&& initializationVar.getNameIdentifier() != null
|
||||||
&& onceWritableIterator) {
|
&& onceWritableIterator) {
|
||||||
val end = converter.convertExpression((condition as PsiBinaryExpression).getROperand())
|
val end = converter.convertExpression((condition as PsiBinaryExpression).getROperand())
|
||||||
val endExpression = if (operationTokenType == JavaTokenType.LT)
|
val endExpression = if (operationTokenType == JavaTokenType.LT)
|
||||||
BinaryExpression(end, Identifier("1"), "-")
|
BinaryExpression(end, Identifier("1"), "-")
|
||||||
else
|
else
|
||||||
end
|
end
|
||||||
result = ForeachWithRangeStatement(Identifier(firstChildLocalVar.getName()!!),
|
result = ForeachWithRangeStatement(Identifier(initializationVar.getName()!!),
|
||||||
converter.convertExpression(firstChildLocalVar.getInitializer()),
|
converter.convertExpression(initializationVar.getInitializer()),
|
||||||
endExpression,
|
endExpression,
|
||||||
converter.convertStatement(body))
|
converter.convertStatement(body))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ package org.jetbrains.jet.j2k.visitors
|
|||||||
|
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import java.util.HashSet
|
import java.util.HashSet
|
||||||
import org.jetbrains.jet.j2k.isSuperConstructorRef
|
import org.jetbrains.jet.j2k.isSuperConstructorCall
|
||||||
|
|
||||||
class SuperVisitor() : JavaRecursiveElementVisitor() {
|
class SuperVisitor() : JavaRecursiveElementVisitor() {
|
||||||
private val _resolvedSuperCallParameters = HashSet<PsiExpressionList>()
|
private val _resolvedSuperCallParameters = HashSet<PsiExpressionList>()
|
||||||
@@ -27,7 +27,7 @@ class SuperVisitor() : JavaRecursiveElementVisitor() {
|
|||||||
get() = _resolvedSuperCallParameters
|
get() = _resolvedSuperCallParameters
|
||||||
|
|
||||||
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
|
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
|
||||||
if (isSuperConstructorRef(expression.getMethodExpression())) {
|
if (expression.isSuperConstructorCall()) {
|
||||||
_resolvedSuperCallParameters.add(expression.getArgumentList())
|
_resolvedSuperCallParameters.add(expression.getArgumentList())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user