Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[kotlin] K2 J2K: Avoid Using Any Type When Stricter Type is Known #2812

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6783,6 6783,11 @@ public void testNeedTypeArgs() throws Exception {
runTest("../../shared/tests/testData/newJ2k/typeParameters/needTypeArgs.java");
}

@TestMetadata("noUnnecessaryAny.java")
public void testNoUnnecessaryAny() throws Exception {
runTest("../../shared/tests/testData/newJ2k/typeParameters/noUnnecessaryAny.java");
}

@TestMetadata("rawTypeCast.java")
public void testRawTypeCast() throws Exception {
runTest("../../shared/tests/testData/newJ2k/typeParameters/rawTypeCast.java");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6783,6 6783,11 @@ public void testNeedTypeArgs() throws Exception {
runTest("../../shared/tests/testData/newJ2k/typeParameters/needTypeArgs.java");
}

@TestMetadata("noUnnecessaryAny.java")
public void testNoUnnecessaryAny() throws Exception {
runTest("../../shared/tests/testData/newJ2k/typeParameters/noUnnecessaryAny.java");
}

@TestMetadata("rawTypeCast.java")
public void testRawTypeCast() throws Exception {
runTest("../../shared/tests/testData/newJ2k/typeParameters/rawTypeCast.java");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 35,7 @@ class TypeMappingConversion(
JKNewExpression(
newClassSymbol,
element::arguments.detached(),
element::typeArgumentList.detached().fixTypeArguments(newClassSymbol),
element.fixTypeArguments(newClassSymbol),
element::classBody.detached(),
element.isAnonymousClass,
canMoveLambdaOutsideParentheses = element.canMoveLambdaOutsideParentheses
Expand All @@ -46,20 46,35 @@ class TypeMappingConversion(
return recurse(element)
}

private fun JKTypeArgumentList.fixTypeArguments(classSymbol: JKClassSymbol): JKTypeArgumentList {
if (typeArguments.isNotEmpty()) {
return JKTypeArgumentList(
typeArguments.map { typeArgument ->
JKTypeElement(typeArgument.type.mapType(null), typeArgument::annotationList.detached())
}
)
}
return when (val typeParametersCount = classSymbol.expectedTypeParametersCount()) {
0 -> this
else -> JKTypeArgumentList(List(typeParametersCount) {
private fun JKNewExpression.fixTypeArguments(classSymbol: JKClassSymbol): JKTypeArgumentList {
val typeArguments = this::typeArgumentList.detached()
val typeArgumentList = when {
typeArguments.typeArguments.isNotEmpty() -> typeArguments.typeArguments.map { typeArgument ->
JKTypeElement(typeArgument.type.mapType(null), typeArgument::annotationList.detached())
}

classSymbol.expectedTypeParametersCount() == 0 -> null
else -> List(classSymbol.expectedTypeParametersCount()) {
JKTypeElement(typeFactory.types.nullableAny)
})
}
} ?: return typeArguments

if (arguments.arguments.size != typeArgumentList.size) return JKTypeArgumentList(typeArgumentList)

val arrayTypes = listOf("java.util.ArrayList", "List", "HashMap", "demo.Collection")
val newTypeArgumentList = mutableListOf<JKTypeElement>()
typeArgumentList.forEachIndexed { index, jkTypeElement ->
val innerValueType = arguments.arguments[index].value.calculateType(typeFactory)
when {
jkTypeElement.type.fqName != "kotlin.Any" || innerValueType == null -> newTypeArgumentList.add(jkTypeElement)
innerValueType.fqName != "kotlin.Int" && !arrayTypes.contains(innerValueType.fqName) -> newTypeArgumentList.add(
innerValueType.asTypeElement()
)

typeArgumentList.size != 1 -> newTypeArgumentList.add(jkTypeElement)
}
}
return JKTypeArgumentList(newTypeArgumentList)
}

private fun JKType.fixRawType(typeElement: JKTypeElement?) =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 1,5 @@
// ERROR: The integer literal does not conform to the expected type CapturedType(*)
// ERROR: The integer literal does not conform to the expected type CapturedType(*)
// ERROR: Type argument is not within its bounds: should be subtype of 'String?'
internal class G<T : String?>(t: T)

class Java {
Expand All @@ -11,7 10,7 @@ class Java {

fun test2() {
val m: HashMap<*, *> = HashMap<Any?, Any?>()
val g: G<*> = G<Any?>("")
val g: G<*> = G("")
val g2 = G("")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 8,7 @@ internal class Collection<E>(e: E) {

internal class Test {
fun main() {
val raw1: Collection<*> = Collection<Any?>(1)
val raw1: Collection<*> = Collection(1)
val raw2: Collection<*> = Collection(1)
val raw3: Collection<*> = Collection("1")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 1,12 @@
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;

public class Test {
List<String> xs;
@Nullable List<String> strings;

public void typeParameterWeirdness() {
xs = strings != null ? new ArrayList<>(strings) : new ArrayList<String>();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 1,8 @@
class Test {
var xs: List<String?>? = null
var strings: List<String?>? = null

fun typeParameterWeirdness() {
xs = if (strings != null) ArrayList(strings) else ArrayList<String?>()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 1,8 @@
class Test {
var xs: List<String>? = null
var strings: List<String>? = null

fun typeParameterWeirdness() {
xs = if (strings != null) ArrayList(strings) else ArrayList()
}
}