Fixed KT-5434 J2K: incorrect conversion of main method
#KT-5434 Fixed
This commit is contained in:
@@ -16,80 +16,52 @@
|
||||
|
||||
package org.jetbrains.jet.j2k
|
||||
|
||||
import java.text.MessageFormat
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiJavaFile
|
||||
import java.util.ArrayList
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiAnonymousClass
|
||||
import com.intellij.psi.PsiModifier
|
||||
import com.intellij.psi.PsiType
|
||||
import com.intellij.psi.PsiArrayType
|
||||
|
||||
fun createMainFunction(file: PsiFile): String {
|
||||
fun createMainFunction(file: PsiJavaFile): String {
|
||||
val classNamesWithMains = ArrayList<Pair<String, PsiMethod>>()
|
||||
for (c in (file as PsiJavaFile).getClasses()) {
|
||||
for (c in file.getClasses()) {
|
||||
val main = findMainMethod(c)
|
||||
val name = c.getName()
|
||||
if (name != null && main != null) {
|
||||
classNamesWithMains.add(Pair(name, main))
|
||||
classNamesWithMains.add(name to main)
|
||||
}
|
||||
}
|
||||
|
||||
if (classNamesWithMains.size() > 0) {
|
||||
var className = classNamesWithMains[0].first
|
||||
return MessageFormat.format("fun main(args : Array<String>) = {0}.main(args as Array<String?>?)", className)
|
||||
if (classNamesWithMains.isNotEmpty()) {
|
||||
var className = classNamesWithMains.first().first
|
||||
return "fun main(args : Array<String>) = $className.main(args)"
|
||||
}
|
||||
|
||||
return ""
|
||||
|
||||
}
|
||||
|
||||
private fun findMainMethod(aClass: PsiClass): PsiMethod? {
|
||||
if (isMainClass(aClass)) {
|
||||
return findMainMethod(aClass.findMethodsByName("main", false))
|
||||
}
|
||||
return null
|
||||
}
|
||||
private fun findMainMethod(aClass: PsiClass): PsiMethod?
|
||||
= if (isMainClass(aClass)) aClass.findMethodsByName("main", false).firstOrNull { it.isMainMethod() } else null
|
||||
|
||||
private fun isMainClass(psiClass: PsiClass): Boolean {
|
||||
if (psiClass is PsiAnonymousClass)
|
||||
return false
|
||||
private fun isMainClass(psiClass: PsiClass): Boolean
|
||||
= psiClass !is PsiAnonymousClass &&
|
||||
!psiClass.isInterface() &&
|
||||
(psiClass.getContainingClass() == null || psiClass.hasModifierProperty(PsiModifier.STATIC))
|
||||
|
||||
if (psiClass.isInterface())
|
||||
return false
|
||||
fun PsiMethod.isMainMethod(): Boolean {
|
||||
if (getReturnType() != PsiType.VOID) return false
|
||||
if (!hasModifierProperty(PsiModifier.STATIC)) return false
|
||||
if (!hasModifierProperty(PsiModifier.PUBLIC)) return false
|
||||
|
||||
return psiClass.getContainingClass() == null || psiClass.hasModifierProperty(PsiModifier.STATIC)
|
||||
val parameters = getParameterList().getParameters()
|
||||
if (parameters.size != 1) return false
|
||||
|
||||
}
|
||||
|
||||
private fun findMainMethod(mainMethods: Array<PsiMethod>): PsiMethod? {
|
||||
return mainMethods.find { isMainMethod(it) }
|
||||
}
|
||||
|
||||
fun isMainMethod(method: PsiMethod): Boolean {
|
||||
if (method.getContainingClass() == null)
|
||||
return false
|
||||
|
||||
if (PsiType.VOID != method.getReturnType())
|
||||
return false
|
||||
|
||||
if (!method.hasModifierProperty(PsiModifier.STATIC))
|
||||
return false
|
||||
|
||||
if (!method.hasModifierProperty(PsiModifier.PUBLIC))
|
||||
return false
|
||||
|
||||
val parameters = method.getParameterList().getParameters()
|
||||
if (parameters.size != 1)
|
||||
return false
|
||||
|
||||
val `type` = parameters[0].getType()
|
||||
if (`type` !is PsiArrayType)
|
||||
return false
|
||||
val `type` = parameters.single().getType()
|
||||
if (`type` !is PsiArrayType) return false
|
||||
|
||||
val componentType = `type`.getComponentType()
|
||||
return componentType.equalsToText("java.lang.String")
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@ import com.intellij.psi.CommonClassNames.JAVA_LANG_OBJECT
|
||||
import org.jetbrains.jet.j2k.ast.assignNoPrototype
|
||||
import org.jetbrains.jet.j2k.ast.ErrorType
|
||||
import com.intellij.codeInsight.NullableNotNullManager
|
||||
import org.jetbrains.jet.j2k.ast.ArrayType
|
||||
import org.jetbrains.jet.j2k.ast.ClassType
|
||||
import org.jetbrains.jet.j2k.ast.Identifier
|
||||
|
||||
class TypeConverter(val settings: ConverterSettings, val conversionScope: ConversionScope) {
|
||||
private val nullabilityCache = HashMap<PsiElement, Nullability>()
|
||||
@@ -59,8 +62,17 @@ class TypeConverter(val settings: ConverterSettings, val conversionScope: Conver
|
||||
public fun convertTypes(types: Array<PsiType>): List<Type>
|
||||
= types.map { convertType(it) }
|
||||
|
||||
public fun convertVariableType(variable: PsiVariable): Type
|
||||
= convertType(variable.getType(), variableNullability(variable)).assignPrototype(variable.getTypeElement())
|
||||
public fun convertVariableType(variable: PsiVariable): Type {
|
||||
val result = if (variable.isMainMethodParameter()) {
|
||||
ArrayType(ClassType(Identifier("String").assignNoPrototype(), listOf(), Nullability.NotNull, settings).assignNoPrototype(),
|
||||
Nullability.NotNull,
|
||||
settings)
|
||||
}
|
||||
else {
|
||||
convertType(variable.getType(), variableNullability(variable))
|
||||
}
|
||||
return result.assignPrototype(variable.getTypeElement())
|
||||
}
|
||||
|
||||
public fun variableNullability(variable: PsiVariable): Nullability {
|
||||
val cached = nullabilityCache[variable]
|
||||
@@ -108,6 +120,10 @@ class TypeConverter(val settings: ConverterSettings, val conversionScope: Conver
|
||||
return Nullability.Nullable
|
||||
}
|
||||
|
||||
if (nullability == Nullability.Default && variable.isMainMethodParameter() ) {
|
||||
return Nullability.NotNull
|
||||
}
|
||||
|
||||
if (!conversionScope.contains(variable)) { // do not analyze usages out of our conversion scope
|
||||
if (variable is PsiParameter) {
|
||||
// Object.equals corresponds to Any.equals which has nullable parameter:
|
||||
@@ -158,6 +174,8 @@ class TypeConverter(val settings: ConverterSettings, val conversionScope: Conver
|
||||
return nullability
|
||||
}
|
||||
|
||||
private fun PsiVariable.isMainMethodParameter() = this is PsiParameter && (getDeclarationScope() as? PsiMethod)?.isMainMethod() ?: false
|
||||
|
||||
public fun convertMethodReturnType(method: PsiMethod): Type
|
||||
= convertType(method.getReturnType(), methodNullability(method)).assignPrototype(method.getReturnTypeElement())
|
||||
|
||||
|
||||
@@ -1391,6 +1391,16 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
|
||||
doTest("j2k/tests/testData/ast/function/main.java");
|
||||
}
|
||||
|
||||
@TestMetadata("main2.java")
|
||||
public void testMain2() throws Exception {
|
||||
doTest("j2k/tests/testData/ast/function/main2.java");
|
||||
}
|
||||
|
||||
@TestMetadata("mainAndNullabilitySetting.java")
|
||||
public void testMainAndNullabilitySetting() throws Exception {
|
||||
doTest("j2k/tests/testData/ast/function/mainAndNullabilitySetting.java");
|
||||
}
|
||||
|
||||
@TestMetadata("methodClassType.java")
|
||||
public void testMethodClassType() throws Exception {
|
||||
doTest("j2k/tests/testData/ast/function/methodClassType.java");
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
//file
|
||||
public class A {
|
||||
public static void main(String[] args) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
public class A {
|
||||
class object {
|
||||
public fun main(args: Array<String>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
fun main(args: Array<String>) = A.main(args)
|
||||
@@ -0,0 +1,6 @@
|
||||
// !forceNotNullTypes: false
|
||||
//file
|
||||
public class A {
|
||||
public static void main(String[] args) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// !forceNotNullTypes: false
|
||||
public class A {
|
||||
class object {
|
||||
public fun main(args: Array<String>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
fun main(args: Array<String>) = A.main(args)
|
||||
@@ -31,4 +31,4 @@ public class User {
|
||||
}
|
||||
}
|
||||
}
|
||||
fun main(args: Array<String>) = User.main(args as Array<String?>?)
|
||||
fun main(args: Array<String>) = User.main(args)
|
||||
@@ -7,4 +7,4 @@ class Program {
|
||||
}
|
||||
}
|
||||
}
|
||||
fun main(args: Array<String>) = Program.main(args as Array<String?>?)
|
||||
fun main(args: Array<String>) = Program.main(args)
|
||||
@@ -83,4 +83,4 @@ public class SwitchDemo {
|
||||
}
|
||||
}
|
||||
}
|
||||
fun main(args: Array<String>) = SwitchDemo.main(args as Array<String?>?)
|
||||
fun main(args: Array<String>) = SwitchDemo.main(args)
|
||||
@@ -11,4 +11,4 @@ public class NonDefault {
|
||||
}
|
||||
}
|
||||
}
|
||||
fun main(args: Array<String>) = NonDefault.main(args as Array<String?>?)
|
||||
fun main(args: Array<String>) = NonDefault.main(args)
|
||||
@@ -13,4 +13,4 @@ public class SwitchDemo {
|
||||
}
|
||||
}
|
||||
}
|
||||
fun main(args: Array<String>) = SwitchDemo.main(args as Array<String?>?)
|
||||
fun main(args: Array<String>) = SwitchDemo.main(args)
|
||||
@@ -25,4 +25,4 @@ public class SwitchDemo {
|
||||
}
|
||||
}
|
||||
}
|
||||
fun main(args: Array<String>) = SwitchDemo.main(args as Array<String?>?)
|
||||
fun main(args: Array<String>) = SwitchDemo.main(args)
|
||||
@@ -13,4 +13,4 @@ public class NonDefault {
|
||||
}
|
||||
}
|
||||
}
|
||||
fun main(args: Array<String>) = NonDefault.main(args as Array<String?>?)
|
||||
fun main(args: Array<String>) = NonDefault.main(args)
|
||||
Reference in New Issue
Block a user