Preserve type annotations on type parameter when substituting
Subsitute(@A T, T:@B String) = @B @A String Nullability when loading Java: Subsitute(@NotNull T, T:String) = @NotNull String Subsitute(@NotNull T, T:String!) = @NotNull String Subsitute(@NotNull T, T:String?) = @NotNull String Subsitute(@Nullable T, T:String) = @Nullable String? Subsitute(@Nullable T, T:String!) = @Nullable String? Subsitute(@Nullable T, T:String?) = @Nullable String?
This commit is contained in:
Vendored
+1
-2
@@ -19,6 +19,5 @@ public class Y extends X<String> {
|
||||
|
||||
fun main() {
|
||||
checkSubtype<Any>(Y().fooN())
|
||||
Y().barN(null);
|
||||
Y().barN(<!NULL_FOR_NONNULL_TYPE!>null<!>);
|
||||
}
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -20,9 +20,9 @@ public open class X</*0*/ T> {
|
||||
|
||||
public open class Y : X<kotlin.String!> {
|
||||
public constructor Y()
|
||||
public/*package*/ open override /*1*/ /*fake_override*/ fun barN(/*0*/ org.jetbrains.annotations.NotNull() a: kotlin.String!): kotlin.Unit
|
||||
public/*package*/ open override /*1*/ /*fake_override*/ fun barN(/*0*/ org.jetbrains.annotations.NotNull() a: kotlin.String): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
org.jetbrains.annotations.NotNull() public/*package*/ open override /*1*/ /*fake_override*/ fun fooN(): kotlin.String!
|
||||
org.jetbrains.annotations.NotNull() public/*package*/ open override /*1*/ /*fake_override*/ fun fooN(): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
+1
-2
@@ -19,6 +19,5 @@ public class Y extends X<A> {
|
||||
|
||||
fun main() {
|
||||
checkSubtype<Any>(Y().fooN())
|
||||
Y().barN(null);
|
||||
Y().barN(<!NULL_FOR_NONNULL_TYPE!>null<!>);
|
||||
}
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -20,9 +20,9 @@ public open class X</*0*/ T> {
|
||||
|
||||
public open class Y : X<A!> {
|
||||
public constructor Y()
|
||||
public/*package*/ open override /*1*/ /*fake_override*/ fun barN(/*0*/ org.jetbrains.annotations.NotNull() a: A!): kotlin.Unit
|
||||
public/*package*/ open override /*1*/ /*fake_override*/ fun barN(/*0*/ org.jetbrains.annotations.NotNull() a: A): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
org.jetbrains.annotations.NotNull() public/*package*/ open override /*1*/ /*fake_override*/ fun fooN(): A!
|
||||
org.jetbrains.annotations.NotNull() public/*package*/ open override /*1*/ /*fake_override*/ fun fooN(): A
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/saveAnnotationAfterSubstitution.kt
Vendored
+47
@@ -0,0 +1,47 @@
|
||||
// FILE: A.java
|
||||
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
interface A<T> {
|
||||
void foo(@NotNull T x, @Nullable T y);
|
||||
}
|
||||
|
||||
// FILE: B1.java
|
||||
|
||||
// contains fake_override fun foo(/*0*/ org.jetbrains.annotations.NotNull() x: kotlin.String, /*1*/ org.jetbrains.annotations.Nullable() y: kotlin.String?)
|
||||
interface B1 extends A<String> {}
|
||||
|
||||
// FILE: B2.java
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
interface B2 extends A<String> {
|
||||
// Ok, consistent override
|
||||
// override fun foo(/*0*/ org.jetbrains.annotations.NotNull() x: kotlin.String, /*1*/ org.jetbrains.annotations.Nullable() y: kotlin.String?)
|
||||
void foo(@NotNull String x, @Nullable String y);
|
||||
}
|
||||
|
||||
// FILE: B3.java
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
interface B3 extends A<String> {
|
||||
// inconsistent override, second parameter type is platform
|
||||
// TODO: first one should be platform too, but it's not because when substituting T -> String!,
|
||||
// value parameter type becomes platform and it can be overridden with @NotNull String.
|
||||
// Conceptual problem: we can use type parameter as T?, but there is no way to specify same semantics as in Java `@NotNull T`.
|
||||
|
||||
// override /*1*/ fun foo(/*0*/ org.jetbrains.annotations.Nullable() x: kotlin.String?, /*1*/ org.jetbrains.annotations.NotNull() y: kotlin.String!): kotlin.Unit
|
||||
void foo(@Nullable String x, @NotNull String y);
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
// fake_override fun foo(/*0*/ org.jetbrains.annotations.NotNull() x: kotlin.String, /*1*/ org.jetbrains.annotations.Nullable() y: kotlin.String?): kotlin.Unit
|
||||
interface C1 : A<String>
|
||||
|
||||
// fake_override fun foo(/*0*/ org.jetbrains.annotations.NotNull() x: kotlin.String?, /*1*/ org.jetbrains.annotations.Nullable() y: kotlin.String?): kotlin.Unit
|
||||
interface C2 : A<String?>
|
||||
|
||||
interface C3 : B1 {
|
||||
// inconsistent override
|
||||
<!NOTHING_TO_OVERRIDE!>override<!> fun foo(x: String?, y: String?);
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package
|
||||
|
||||
public/*package*/ /*synthesized*/ fun </*0*/ T> A(/*0*/ function: (T!, T!) -> kotlin.Unit): A<T>
|
||||
public/*package*/ /*synthesized*/ fun B1(/*0*/ function: (kotlin.String!, kotlin.String?) -> kotlin.Unit): B1
|
||||
public/*package*/ /*synthesized*/ fun B2(/*0*/ function: (kotlin.String!, kotlin.String!) -> kotlin.Unit): B2
|
||||
public/*package*/ /*synthesized*/ fun B3(/*0*/ function: (kotlin.String!, kotlin.String!) -> kotlin.Unit): B3
|
||||
|
||||
public/*package*/ interface A</*0*/ T> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun foo(/*0*/ org.jetbrains.annotations.NotNull() x: T, /*1*/ org.jetbrains.annotations.Nullable() y: T?): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public/*package*/ interface B1 : A<kotlin.String!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ org.jetbrains.annotations.NotNull() x: kotlin.String, /*1*/ org.jetbrains.annotations.Nullable() y: kotlin.String?): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public/*package*/ interface B2 : A<kotlin.String!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract override /*1*/ fun foo(/*0*/ org.jetbrains.annotations.NotNull() x: kotlin.String, /*1*/ org.jetbrains.annotations.Nullable() y: kotlin.String?): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public/*package*/ interface B3 : A<kotlin.String!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract override /*1*/ fun foo(/*0*/ org.jetbrains.annotations.Nullable() x: kotlin.String?, /*1*/ org.jetbrains.annotations.NotNull() y: kotlin.String!): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
internal interface C1 : A<kotlin.String> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ org.jetbrains.annotations.NotNull() x: kotlin.String, /*1*/ org.jetbrains.annotations.Nullable() y: kotlin.String?): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
internal interface C2 : A<kotlin.String?> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ org.jetbrains.annotations.NotNull() x: kotlin.String?, /*1*/ org.jetbrains.annotations.Nullable() y: kotlin.String?): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
internal interface C3 : B1 {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ org.jetbrains.annotations.NotNull() x: kotlin.String, /*1*/ org.jetbrains.annotations.Nullable() y: kotlin.String?): kotlin.Unit
|
||||
internal abstract fun foo(/*0*/ x: kotlin.String?, /*1*/ y: kotlin.String?): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -10463,6 +10463,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("saveAnnotationAfterSubstitution.kt")
|
||||
public void testSaveAnnotationAfterSubstitution() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/saveAnnotationAfterSubstitution.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("supertypeDifferentParameterNullability.kt")
|
||||
public void testSupertypeDifferentParameterNullability() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/supertypeDifferentParameterNullability.kt");
|
||||
|
||||
@@ -69,6 +69,8 @@ class FilteredAnnotations(
|
||||
class CompositeAnnotations(
|
||||
private val delegates: List<Annotations>
|
||||
) : Annotations {
|
||||
constructor(vararg delegates: Annotations): this(delegates.toList())
|
||||
|
||||
override fun isEmpty() = delegates.all { it.isEmpty() }
|
||||
|
||||
override fun findAnnotation(fqName: FqName) = delegates.asSequence().map { it.findAnnotation(fqName) }.filterNotNull().firstOrNull()
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.CompositeAnnotations;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.InferencePackage;
|
||||
import org.jetbrains.kotlin.resolve.scopes.SubstitutingScope;
|
||||
import org.jetbrains.kotlin.types.typeUtil.TypeUtilPackage;
|
||||
@@ -221,6 +222,14 @@ public class TypeSubstitutor {
|
||||
substitutedType = TypeUtils.makeNullableIfNeeded(replacement.getType(), type.isMarkedNullable());
|
||||
}
|
||||
|
||||
// substitutionType.annotations = replacement.annotations ++ type.annotations
|
||||
if (!type.getAnnotations().isEmpty()) {
|
||||
substitutedType = TypeUtilPackage.replaceAnnotations(
|
||||
substitutedType,
|
||||
new CompositeAnnotations(substitutedType.getAnnotations(), type.getAnnotations())
|
||||
);
|
||||
}
|
||||
|
||||
Variance resultingProjectionKind = varianceConflict == VarianceConflictType.NO_CONFLICT
|
||||
? combine(originalProjectionKind, replacement.getProjectionKind())
|
||||
: originalProjectionKind;
|
||||
|
||||
@@ -95,7 +95,7 @@ public class UnusedReceiverParameterInspection : AbstractKotlinInspection() {
|
||||
return JetBundle.message("unused.receiver.parameter.remove")
|
||||
}
|
||||
|
||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor?) {
|
||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||
declaration.setReceiverTypeReference(null)
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
||||
|
||||
override fun getFamilyName() = "Safe delete"
|
||||
|
||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor?) {
|
||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||
if (!FileModificationService.getInstance().prepareFileForWrite(declaration.getContainingFile())) return
|
||||
SafeDeleteHandler.invoke(project, arrayOf(declaration), false)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user