Rendering flexible types with "!" and optional parts

This commit is contained in:
Andrey Breslav
2014-08-07 16:29:12 +04:00
parent c2a03d60f0
commit bdf7e924b5
4 changed files with 171 additions and 3 deletions
@@ -0,0 +1,51 @@
package test;
import java.lang.Integer;
import java.lang.String;
import java.util.*;
public class Rendering {
class A_Plain {}
class B_Super {}
class C_Sub extends B_Super {}
class D_SuperG<T> {}
class E_SubG extends D_SuperG<String> {}
interface F_Array {
void foo1(String[] strings);
void foo2(List<String>[] strings);
void foo3(Integer... args);
void foo4(String... args);
void foo5(List<String>... args);
}
interface G_Collections {
void foo1(Iterator<String> x);
void foo2(Iterable<String> x);
void foo3(Collection<String> x);
void foo4(List<String> x);
void foo5(Set<String> x);
void foo6(Map<String, String> x);
void foo7(Map.Entry<String, String> x);
}
interface H_Raw {
void foo1(List x);
void foo2(D_SuperG x);
}
interface I_Wildcard {
void foo1(List<? extends String> x);
void foo2(List<? super String> x);
void foo3(List<?> x);
void foo4(D_SuperG<? extends String> x);
void foo5(D_SuperG<? super String> x);
void foo6(D_SuperG<?> x);
}
}
@@ -0,0 +1,57 @@
package test
public open class Rendering {
public constructor Rendering()
public/*package*/ open inner class A_Plain {
public/*package*/ constructor A_Plain()
}
public/*package*/ open inner class B_Super {
public/*package*/ constructor B_Super()
}
public/*package*/ open inner class C_Sub : test.Rendering.B_Super {
public/*package*/ constructor C_Sub()
}
public/*package*/ open inner class D_SuperG</*0*/ T> {
public/*package*/ constructor D_SuperG</*0*/ T>()
}
public/*package*/ open inner class E_SubG : test.Rendering.D_SuperG<kotlin.String!> {
public/*package*/ constructor E_SubG()
}
public/*package*/ trait F_Array {
public abstract fun foo1(/*0*/ p0: kotlin.Array<(out) kotlin.String!>!): kotlin.Unit
public abstract fun foo2(/*0*/ p0: kotlin.Array<(out) kotlin.(Mutable)List<kotlin.String!>!>!): kotlin.Unit
public abstract fun foo3(/*0*/ vararg p0: kotlin.Int! /*kotlin.Array<(out) kotlin.Int!>!*/): kotlin.Unit
public abstract fun foo4(/*0*/ vararg p0: kotlin.String! /*kotlin.Array<(out) kotlin.String!>!*/): kotlin.Unit
public abstract fun foo5(/*0*/ vararg p0: kotlin.(Mutable)List<kotlin.String!>! /*kotlin.Array<(out) kotlin.(Mutable)List<kotlin.String!>!>!*/): kotlin.Unit
}
public/*package*/ trait G_Collections {
public abstract fun foo1(/*0*/ p0: kotlin.(Mutable)Iterator<kotlin.String!>!): kotlin.Unit
public abstract fun foo2(/*0*/ p0: kotlin.(Mutable)Iterable<kotlin.String!>!): kotlin.Unit
public abstract fun foo3(/*0*/ p0: kotlin.(Mutable)Collection<kotlin.String!>!): kotlin.Unit
public abstract fun foo4(/*0*/ p0: kotlin.(Mutable)List<kotlin.String!>!): kotlin.Unit
public abstract fun foo5(/*0*/ p0: kotlin.(Mutable)Set<kotlin.String!>!): kotlin.Unit
public abstract fun foo6(/*0*/ p0: kotlin.(Mutable)Map<kotlin.String!, kotlin.String!>!): kotlin.Unit
public abstract fun foo7(/*0*/ p0: (kotlin.MutableMap.MutableEntry<kotlin.String!, kotlin.String!>..kotlin.Map.Entry<kotlin.String!, kotlin.String!>?)): kotlin.Unit
}
public/*package*/ trait H_Raw {
public abstract fun foo1(/*0*/ p0: (kotlin.MutableList<out kotlin.Any?>..kotlin.List<kotlin.Any?>?)): kotlin.Unit
public abstract fun foo2(/*0*/ p0: test.Rendering.D_SuperG<out kotlin.Any?>!): kotlin.Unit
}
public/*package*/ trait I_Wildcard {
public abstract fun foo1(/*0*/ p0: (kotlin.MutableList<out kotlin.String!>..kotlin.List<kotlin.String!>?)): kotlin.Unit
public abstract fun foo2(/*0*/ p0: kotlin.(Mutable)List<in kotlin.String!>!): kotlin.Unit
public abstract fun foo3(/*0*/ p0: (kotlin.MutableList<out kotlin.Any?>..kotlin.List<kotlin.Any?>?)): kotlin.Unit
public abstract fun foo4(/*0*/ p0: test.Rendering.D_SuperG<out kotlin.String!>!): kotlin.Unit
public abstract fun foo5(/*0*/ p0: test.Rendering.D_SuperG<in kotlin.String!>!): kotlin.Unit
public abstract fun foo6(/*0*/ p0: test.Rendering.D_SuperG<out kotlin.Any?>!): kotlin.Unit
}
}
@@ -35,7 +35,7 @@ import java.util.regex.Pattern;
public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
@TestMetadata("compiler/testData/loadJava/compiledJava")
@TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({CompiledJava.Annotations.class, CompiledJava.Constructor.class, CompiledJava.JavaBean.class, CompiledJava.KotlinSignature.class, CompiledJava.Library.class, CompiledJava.Modality.class, CompiledJava.Mutability.class, CompiledJava.NotNull.class, CompiledJava.ProtectedPackage.class, CompiledJava.ProtectedStatic.class, CompiledJava.Sam.class, CompiledJava.SignaturePropagation.class, CompiledJava.Static.class, CompiledJava.Vararg.class})
@InnerTestClasses({CompiledJava.Annotations.class, CompiledJava.Constructor.class, CompiledJava.JavaBean.class, CompiledJava.KotlinSignature.class, CompiledJava.Library.class, CompiledJava.Modality.class, CompiledJava.Mutability.class, CompiledJava.NotNull.class, CompiledJava.ProtectedPackage.class, CompiledJava.ProtectedStatic.class, CompiledJava.Rendering.class, CompiledJava.Sam.class, CompiledJava.SignaturePropagation.class, CompiledJava.Static.class, CompiledJava.Vararg.class})
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
public static class CompiledJava extends AbstractLoadJavaTest {
public void testAllFilesPresentInCompiledJava() throws Exception {
@@ -1400,6 +1400,22 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
}
@TestMetadata("compiler/testData/loadJava/compiledJava/rendering")
@TestDataPath("$PROJECT_ROOT")
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
public static class Rendering extends AbstractLoadJavaTest {
public void testAllFilesPresentInRendering() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledJava/rendering"), Pattern.compile("^(.+)\\.java$"), true);
}
@TestMetadata("Rendering.java")
public void testRendering() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/rendering/Rendering.java");
doTestCompiledJava(fileName);
}
}
@TestMetadata("compiler/testData/loadJava/compiledJava/sam")
@TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({Sam.Adapters.class})
@@ -301,9 +301,14 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
}
return "???";
}
if (type instanceof FlexibleType && debugMode) {
if (type instanceof FlexibleType) {
FlexibleType flexibleType = (FlexibleType) type;
return "(" + renderType(flexibleType.getLowerBound()) + ".." + renderType(flexibleType.getUpperBound()) + ")";
if (!debugMode) {
return renderFlexibleType(flexibleType);
}
else {
return "(" + renderType(flexibleType.getLowerBound()) + ".." + renderType(flexibleType.getUpperBound()) + ")";
}
}
if (type instanceof LazyType && debugMode) {
return type.toString();
@@ -317,6 +322,45 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
return renderDefaultType(type);
}
@NotNull
private String renderFlexibleType(@NotNull FlexibleType type) {
JetType lower = type.getLowerBound();
JetType upper = type.getUpperBound();
String lowerRendered = renderDefaultType(lower);
String upperRendered = renderDefaultType(upper);
if (differsOnlyInNullability(lowerRendered, upperRendered)) {
return lowerRendered + "!";
}
String kotlinPrefix = "kotlin.";
String mutablePrefix = "Mutable";
// e.g. lower = kotlin.MutableList<Foo>, upper = kotlin.List<Foo?>?
if (lowerRendered.startsWith(kotlinPrefix + mutablePrefix)) {
// List<Foo>
String lowerWithoutPrefix = lowerRendered.substring(mutablePrefix.length() + kotlinPrefix.length());
if (differsOnlyInNullability(lowerWithoutPrefix, upperRendered.substring(kotlinPrefix.length()))) {
return kotlinPrefix + "(" + mutablePrefix + ")" + lowerWithoutPrefix + "!";
}
}
else {
String arrayPrefix = "kotlin.Array<";
String covariantArrayPrefix = "kotlin.Array<out ";
if (lowerRendered.startsWith(arrayPrefix) && upperRendered.startsWith(covariantArrayPrefix)) {
String lowerWithoutPrefix = lowerRendered.substring(arrayPrefix.length());
if (differsOnlyInNullability(lowerWithoutPrefix, upperRendered.substring(covariantArrayPrefix.length()))) {
return arrayPrefix + "(out) " + lowerWithoutPrefix + "!";
}
}
}
return "(" + renderType(lower) + ".." + renderType(upper) + ")";
}
private static boolean differsOnlyInNullability(String lower, String upper) {
return lower.equals(upper.replace("?", "")) || upper.endsWith("?") && (lower + "?").equals(upper);
}
@NotNull
@Override
public String renderTypeArguments(@NotNull List<TypeProjection> typeArguments) {