Inline PLATFORM_TYPES = true, simplify signature propagation
This commit is contained in:
@@ -38,20 +38,17 @@ import org.jetbrains.kotlin.jvm.RuntimeAssertionInfo;
|
|||||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||||
import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
||||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
|
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
import org.jetbrains.kotlin.resolve.DeprecationUtilKt;
|
import org.jetbrains.kotlin.resolve.DeprecationUtilKt;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolverKt;
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
|
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
|
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
|
||||||
import org.jetbrains.kotlin.serialization.jvm.BitEncoding;
|
import org.jetbrains.kotlin.serialization.jvm.BitEncoding;
|
||||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
|
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
|
||||||
import org.jetbrains.kotlin.types.FlexibleTypesKt;
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.org.objectweb.asm.*;
|
import org.jetbrains.org.objectweb.asm.*;
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||||
@@ -643,43 +640,6 @@ public class AsmUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean genNotNullAssertionForField(
|
|
||||||
@NotNull InstructionAdapter v,
|
|
||||||
@NotNull GenerationState state,
|
|
||||||
@NotNull PropertyDescriptor descriptor
|
|
||||||
) {
|
|
||||||
return genNotNullAssertion(v, state, descriptor, "checkFieldIsNotNull");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean genNotNullAssertion(
|
|
||||||
@NotNull InstructionAdapter v,
|
|
||||||
@NotNull GenerationState state,
|
|
||||||
@NotNull CallableDescriptor descriptor,
|
|
||||||
@NotNull String assertMethodToCall
|
|
||||||
) {
|
|
||||||
// Assertions are generated elsewhere for platform types
|
|
||||||
if (JavaDescriptorResolverKt.getPLATFORM_TYPES()) return false;
|
|
||||||
|
|
||||||
if (!state.isCallAssertionsEnabled()) return false;
|
|
||||||
|
|
||||||
if (!isDeclaredInJava(descriptor)) return false;
|
|
||||||
|
|
||||||
KotlinType type = descriptor.getReturnType();
|
|
||||||
if (type == null || isNullableType(FlexibleTypesKt.lowerIfFlexible(type))) return false;
|
|
||||||
|
|
||||||
Type asmType = state.getTypeMapper().mapReturnType(descriptor);
|
|
||||||
if (asmType.getSort() == Type.OBJECT || asmType.getSort() == Type.ARRAY) {
|
|
||||||
v.dup();
|
|
||||||
v.visitLdcInsn(descriptor.getContainingDeclaration().getName().asString());
|
|
||||||
v.visitLdcInsn(descriptor.getName().asString());
|
|
||||||
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, assertMethodToCall,
|
|
||||||
"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V", false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static StackValue genNotNullAssertions(
|
public static StackValue genNotNullAssertions(
|
||||||
@NotNull GenerationState state,
|
@NotNull GenerationState state,
|
||||||
@@ -704,19 +664,6 @@ public class AsmUtil {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isDeclaredInJava(@NotNull CallableDescriptor callableDescriptor) {
|
|
||||||
CallableDescriptor descriptor = callableDescriptor;
|
|
||||||
while (true) {
|
|
||||||
if (descriptor instanceof JavaCallableMemberDescriptor) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
CallableDescriptor original = descriptor.getOriginal();
|
|
||||||
if (descriptor == original) break;
|
|
||||||
descriptor = original;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void pushDefaultValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) {
|
public static void pushDefaultValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) {
|
||||||
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
|
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
|
||||||
v.aconst(null);
|
v.aconst(null);
|
||||||
|
|||||||
@@ -1084,9 +1084,7 @@ public abstract class StackValue {
|
|||||||
|
|
||||||
v.visitFieldInsn(isStaticPut ? GETSTATIC : GETFIELD,
|
v.visitFieldInsn(isStaticPut ? GETSTATIC : GETFIELD,
|
||||||
backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor());
|
backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor());
|
||||||
if (!genNotNullAssertionForField(v, state, descriptor)) {
|
genNotNullAssertionForLateInitIfNeeded(v);
|
||||||
genNotNullAssertionForLateInitIfNeeded(v);
|
|
||||||
}
|
|
||||||
coerceTo(type, v);
|
coerceTo(type, v);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
+2
-2
@@ -50,8 +50,8 @@ public class TraceBasedExternalSignatureResolver implements ExternalSignatureRes
|
|||||||
SignaturesPropagationData data =
|
SignaturesPropagationData data =
|
||||||
new SignaturesPropagationData(owner, returnType, receiverType, valueParameters, typeParameters, method);
|
new SignaturesPropagationData(owner, returnType, receiverType, valueParameters, typeParameters, method);
|
||||||
return new AlternativeMethodSignature(
|
return new AlternativeMethodSignature(
|
||||||
data.getModifiedReturnType(), data.getModifiedReceiverType(), data.getModifiedValueParameters(),
|
returnType, data.getModifiedReceiverType(), data.getModifiedValueParameters(),
|
||||||
data.getModifiedTypeParameters(), data.getSignatureErrors(), data.getModifiedHasStableParameterNames()
|
typeParameters, data.getSignatureErrors(), data.getModifiedHasStableParameterNames()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.name.FqName;
|
|||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolverKt;
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JavaResolverUtils;
|
import org.jetbrains.kotlin.resolve.jvm.JavaResolverUtils;
|
||||||
import org.jetbrains.kotlin.types.*;
|
import org.jetbrains.kotlin.types.*;
|
||||||
|
|
||||||
@@ -104,7 +103,7 @@ public class SingleAbstractMethodUtils {
|
|||||||
KotlinType type = fixProjections(substitute);
|
KotlinType type = fixProjections(substitute);
|
||||||
if (type == null) return null;
|
if (type == null) return null;
|
||||||
|
|
||||||
if (JavaDescriptorResolverKt.getPLATFORM_TYPES() && FlexibleTypesKt.isNullabilityFlexible(samType)) {
|
if (FlexibleTypesKt.isNullabilityFlexible(samType)) {
|
||||||
return LazyJavaTypeResolver.FlexibleJavaClassifierTypeCapabilities.create(type, TypeUtils.makeNullable(type));
|
return LazyJavaTypeResolver.FlexibleJavaClassifierTypeCapabilities.create(type, TypeUtils.makeNullable(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-120
@@ -1,120 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.jvm.kotlinSignature;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.intellij.openapi.util.Condition;
|
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
|
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
|
||||||
import org.jetbrains.kotlin.types.KotlinTypeImpl;
|
|
||||||
import org.jetbrains.kotlin.types.TypeProjectionImpl;
|
|
||||||
import org.jetbrains.kotlin.types.Variance;
|
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isArray;
|
|
||||||
|
|
||||||
// This class contains heuristics for processing corner cases in propagation
|
|
||||||
class PropagationHeuristics {
|
|
||||||
// Checks for case when method returning Super[] is overridden with method returning Sub[]
|
|
||||||
static void checkArrayInReturnType(
|
|
||||||
@NotNull SignaturesPropagationData data,
|
|
||||||
@NotNull KotlinType type,
|
|
||||||
@NotNull List<SignaturesPropagationData.TypeAndVariance> typesFromSuper
|
|
||||||
) {
|
|
||||||
List<SignaturesPropagationData.TypeAndVariance> arrayTypesFromSuper = ContainerUtil
|
|
||||||
.filter(typesFromSuper, new Condition<SignaturesPropagationData.TypeAndVariance>() {
|
|
||||||
@Override
|
|
||||||
public boolean value(SignaturesPropagationData.TypeAndVariance typeAndVariance) {
|
|
||||||
return isArray(typeAndVariance.type);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (isArray(type) && !arrayTypesFromSuper.isEmpty()) {
|
|
||||||
assert type.getArguments().size() == 1;
|
|
||||||
if (type.getArguments().get(0).getProjectionKind() == Variance.INVARIANT) {
|
|
||||||
for (SignaturesPropagationData.TypeAndVariance typeAndVariance : arrayTypesFromSuper) {
|
|
||||||
KotlinType arrayTypeFromSuper = typeAndVariance.type;
|
|
||||||
assert arrayTypeFromSuper.getArguments().size() == 1;
|
|
||||||
KotlinType elementTypeInSuper = arrayTypeFromSuper.getArguments().get(0).getType();
|
|
||||||
KotlinType elementType = type.getArguments().get(0).getType();
|
|
||||||
|
|
||||||
if (KotlinTypeChecker.DEFAULT.isSubtypeOf(elementType, elementTypeInSuper)
|
|
||||||
&& !KotlinTypeChecker.DEFAULT.equalTypes(elementType, elementTypeInSuper)) {
|
|
||||||
KotlinTypeImpl betterTypeInSuper = KotlinTypeImpl.create(
|
|
||||||
arrayTypeFromSuper.getAnnotations(),
|
|
||||||
arrayTypeFromSuper.getConstructor(),
|
|
||||||
arrayTypeFromSuper.isMarkedNullable(),
|
|
||||||
Arrays.asList(new TypeProjectionImpl(Variance.OUT_VARIANCE, elementTypeInSuper)),
|
|
||||||
MemberScope.Empty.INSTANCE);
|
|
||||||
|
|
||||||
data.reportError("Return type is not a subtype of overridden method. " +
|
|
||||||
"To fix it, add annotation with Kotlin signature to super method with type "
|
|
||||||
+ DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(arrayTypeFromSuper) + " replaced with "
|
|
||||||
+ DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(betterTypeInSuper) + " in return type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Weird workaround for weird case. The sample code below is compiled by javac.
|
|
||||||
// In this case, we try to replace "Any" parameter type with "T" to fix substitution principle.
|
|
||||||
//
|
|
||||||
// public interface Super<T> {
|
|
||||||
// void foo(T t);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public interface Sub<T> extends Super<T> {
|
|
||||||
// void foo(Object o);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// This method is called from SignaturesPropagationData.
|
|
||||||
@Nullable
|
|
||||||
static ClassifierDescriptor tryToFixOverridingTWithRawType(
|
|
||||||
@NotNull SignaturesPropagationData data,
|
|
||||||
@NotNull List<SignaturesPropagationData.TypeAndVariance> typesFromSuper
|
|
||||||
) {
|
|
||||||
List<TypeParameterDescriptor> typeParameterClassifiersFromSuper = Lists.newArrayList();
|
|
||||||
for (SignaturesPropagationData.TypeAndVariance typeFromSuper : typesFromSuper) {
|
|
||||||
ClassifierDescriptor classifierFromSuper = typeFromSuper.type.getConstructor().getDeclarationDescriptor();
|
|
||||||
if (classifierFromSuper instanceof TypeParameterDescriptor) {
|
|
||||||
typeParameterClassifiersFromSuper.add((TypeParameterDescriptor) classifierFromSuper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!typeParameterClassifiersFromSuper.isEmpty() && typeParameterClassifiersFromSuper.size() == typesFromSuper.size()) {
|
|
||||||
for (TypeParameterDescriptor typeParameter : typeParameterClassifiersFromSuper) {
|
|
||||||
if (typeParameter.getContainingDeclaration() == data.containingClass) {
|
|
||||||
return typeParameter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private PropagationHeuristics() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+12
-424
@@ -17,8 +17,6 @@
|
|||||||
package org.jetbrains.kotlin.resolve.jvm.kotlinSignature;
|
package org.jetbrains.kotlin.resolve.jvm.kotlinSignature;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.intellij.util.Function;
|
import com.intellij.util.Function;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import kotlin.CollectionsKt;
|
import kotlin.CollectionsKt;
|
||||||
@@ -28,31 +26,23 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
|
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||||
import org.jetbrains.kotlin.load.java.components.TypeUsage;
|
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor;
|
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor;
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaMethod;
|
import org.jetbrains.kotlin.load.java.structure.JavaMethod;
|
||||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
|
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolverKt;
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JavaResolverUtils;
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.KotlinToJvmSignatureMapper;
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.KotlinToJvmSignatureMapper;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.KotlinToJvmSignatureMapperKt;
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.KotlinToJvmSignatureMapperKt;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.kotlin.types.*;
|
import org.jetbrains.kotlin.types.TypeUtils;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.load.java.components.TypeUsage.*;
|
|
||||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.getFqName;
|
import static org.jetbrains.kotlin.resolve.DescriptorUtils.getFqName;
|
||||||
import static org.jetbrains.kotlin.types.Variance.INVARIANT;
|
|
||||||
|
|
||||||
public class SignaturesPropagationData {
|
public class SignaturesPropagationData {
|
||||||
|
|
||||||
@@ -61,16 +51,9 @@ public class SignaturesPropagationData {
|
|||||||
KotlinToJvmSignatureMapper.class.getClassLoader()
|
KotlinToJvmSignatureMapper.class.getClassLoader()
|
||||||
).iterator().next();
|
).iterator().next();
|
||||||
|
|
||||||
private final JavaMethodDescriptor autoMethodDescriptor;
|
|
||||||
|
|
||||||
private final List<TypeParameterDescriptor> modifiedTypeParameters;
|
|
||||||
private final ValueParameters modifiedValueParameters;
|
private final ValueParameters modifiedValueParameters;
|
||||||
|
private final List<String> signatureErrors = new ArrayList<String>(0);
|
||||||
private final KotlinType modifiedReturnType;
|
|
||||||
private final List<String> signatureErrors = Lists.newArrayList();
|
|
||||||
private final List<FunctionDescriptor> superFunctions;
|
private final List<FunctionDescriptor> superFunctions;
|
||||||
private final Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> autoTypeParameterToModified;
|
|
||||||
final ClassDescriptor containingClass;
|
|
||||||
|
|
||||||
public SignaturesPropagationData(
|
public SignaturesPropagationData(
|
||||||
@NotNull ClassDescriptor containingClass,
|
@NotNull ClassDescriptor containingClass,
|
||||||
@@ -80,25 +63,21 @@ public class SignaturesPropagationData {
|
|||||||
@NotNull List<TypeParameterDescriptor> autoTypeParameters, // descriptors built by signature resolver
|
@NotNull List<TypeParameterDescriptor> autoTypeParameters, // descriptors built by signature resolver
|
||||||
@NotNull JavaMethod method
|
@NotNull JavaMethod method
|
||||||
) {
|
) {
|
||||||
this.containingClass = containingClass;
|
assert receiverType == null : "Parameters before propagation have receiver type," +
|
||||||
|
" but propagation should be disabled for functions compiled from Kotlin in class: " +
|
||||||
|
DescriptorUtils.getFqName(containingClass);
|
||||||
|
|
||||||
autoMethodDescriptor =
|
JavaMethodDescriptor autoMethodDescriptor =
|
||||||
createAutoMethodDescriptor(containingClass, method, autoReturnType, receiverType, autoValueParameters, autoTypeParameters);
|
createAutoMethodDescriptor(containingClass, method, autoReturnType, autoValueParameters, autoTypeParameters);
|
||||||
|
|
||||||
superFunctions = getSuperFunctionsForMethod(method, autoMethodDescriptor, containingClass);
|
superFunctions = getSuperFunctionsForMethod(method, autoMethodDescriptor, containingClass);
|
||||||
|
modifiedValueParameters = modifyValueParametersAccordingToSuperMethods(autoValueParameters);
|
||||||
autoTypeParameterToModified = JavaResolverUtils.recreateTypeParametersAndReturnMapping(autoTypeParameters, null);
|
|
||||||
|
|
||||||
modifiedTypeParameters = modifyTypeParametersAccordingToSuperMethods(autoTypeParameters);
|
|
||||||
modifiedReturnType = modifyReturnTypeAccordingToSuperMethods(autoReturnType);
|
|
||||||
modifiedValueParameters = modifyValueParametersAccordingToSuperMethods(receiverType, autoValueParameters);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static JavaMethodDescriptor createAutoMethodDescriptor(
|
private static JavaMethodDescriptor createAutoMethodDescriptor(
|
||||||
@NotNull ClassDescriptor containingClass,
|
@NotNull ClassDescriptor containingClass,
|
||||||
@NotNull JavaMethod method, KotlinType autoReturnType,
|
@NotNull JavaMethod method, KotlinType autoReturnType,
|
||||||
@Nullable KotlinType receiverType,
|
|
||||||
@NotNull List<ValueParameterDescriptor> autoValueParameters,
|
@NotNull List<ValueParameterDescriptor> autoValueParameters,
|
||||||
@NotNull List<TypeParameterDescriptor> autoTypeParameters
|
@NotNull List<TypeParameterDescriptor> autoTypeParameters
|
||||||
) {
|
) {
|
||||||
@@ -110,7 +89,7 @@ public class SignaturesPropagationData {
|
|||||||
SourceElement.NO_SOURCE
|
SourceElement.NO_SOURCE
|
||||||
);
|
);
|
||||||
autoMethodDescriptor.initialize(
|
autoMethodDescriptor.initialize(
|
||||||
receiverType,
|
/* receiverParameterType = */ null,
|
||||||
containingClass.getThisAsReceiverParameter(),
|
containingClass.getThisAsReceiverParameter(),
|
||||||
autoTypeParameters,
|
autoTypeParameters,
|
||||||
autoValueParameters,
|
autoValueParameters,
|
||||||
@@ -121,10 +100,6 @@ public class SignaturesPropagationData {
|
|||||||
return autoMethodDescriptor;
|
return autoMethodDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TypeParameterDescriptor> getModifiedTypeParameters() {
|
|
||||||
return modifiedTypeParameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
public KotlinType getModifiedReceiverType() {
|
public KotlinType getModifiedReceiverType() {
|
||||||
return modifiedValueParameters.receiverType;
|
return modifiedValueParameters.receiverType;
|
||||||
}
|
}
|
||||||
@@ -137,84 +112,15 @@ public class SignaturesPropagationData {
|
|||||||
return modifiedValueParameters.hasStableParameterNames;
|
return modifiedValueParameters.hasStableParameterNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KotlinType getModifiedReturnType() {
|
|
||||||
return modifiedReturnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getSignatureErrors() {
|
public List<String> getSignatureErrors() {
|
||||||
return signatureErrors;
|
return signatureErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FunctionDescriptor> getSuperFunctions() {
|
|
||||||
return superFunctions;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reportError(String error) {
|
void reportError(String error) {
|
||||||
signatureErrors.add(error);
|
signatureErrors.add(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
private KotlinType modifyReturnTypeAccordingToSuperMethods(
|
private ValueParameters modifyValueParametersAccordingToSuperMethods(@NotNull List<ValueParameterDescriptor> parameters) {
|
||||||
@NotNull KotlinType autoType // type built by JavaTypeTransformer
|
|
||||||
) {
|
|
||||||
if (JavaDescriptorResolverKt.getPLATFORM_TYPES()) return autoType;
|
|
||||||
|
|
||||||
List<TypeAndVariance> typesFromSuperMethods = ContainerUtil.map(superFunctions,
|
|
||||||
new Function<FunctionDescriptor, TypeAndVariance>() {
|
|
||||||
@Override
|
|
||||||
public TypeAndVariance fun(FunctionDescriptor superFunction) {
|
|
||||||
return new TypeAndVariance(superFunction.getReturnType(),
|
|
||||||
Variance.OUT_VARIANCE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return modifyTypeAccordingToSuperMethods(autoType, typesFromSuperMethods, MEMBER_SIGNATURE_COVARIANT);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<TypeParameterDescriptor> modifyTypeParametersAccordingToSuperMethods(List<TypeParameterDescriptor> autoTypeParameters) {
|
|
||||||
if (JavaDescriptorResolverKt.getPLATFORM_TYPES()) return autoTypeParameters;
|
|
||||||
|
|
||||||
List<TypeParameterDescriptor> result = Lists.newArrayList();
|
|
||||||
|
|
||||||
for (TypeParameterDescriptor autoParameter : autoTypeParameters) {
|
|
||||||
int index = autoParameter.getIndex();
|
|
||||||
TypeParameterDescriptorImpl modifiedTypeParameter = autoTypeParameterToModified.get(autoParameter);
|
|
||||||
|
|
||||||
List<Iterator<KotlinType>> upperBoundFromSuperFunctionsIterators = Lists.newArrayList();
|
|
||||||
for (FunctionDescriptor superFunction : superFunctions) {
|
|
||||||
upperBoundFromSuperFunctionsIterators.add(superFunction.getTypeParameters().get(index).getUpperBounds().iterator());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (KotlinType autoUpperBound : autoParameter.getUpperBounds()) {
|
|
||||||
List<TypeAndVariance> upperBoundsFromSuperFunctions = Lists.newArrayList();
|
|
||||||
|
|
||||||
for (Iterator<KotlinType> iterator : upperBoundFromSuperFunctionsIterators) {
|
|
||||||
assert iterator.hasNext();
|
|
||||||
upperBoundsFromSuperFunctions.add(new TypeAndVariance(iterator.next(), INVARIANT));
|
|
||||||
}
|
|
||||||
|
|
||||||
KotlinType modifiedUpperBound = modifyTypeAccordingToSuperMethods(autoUpperBound, upperBoundsFromSuperFunctions, UPPER_BOUND);
|
|
||||||
modifiedTypeParameter.addUpperBound(modifiedUpperBound);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Iterator<KotlinType> iterator : upperBoundFromSuperFunctionsIterators) {
|
|
||||||
assert !iterator.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
modifiedTypeParameter.setInitialized();
|
|
||||||
result.add(modifiedTypeParameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ValueParameters modifyValueParametersAccordingToSuperMethods(
|
|
||||||
@Nullable KotlinType receiverType,
|
|
||||||
@NotNull List<ValueParameterDescriptor> parameters // descriptors built by parameters resolver
|
|
||||||
) {
|
|
||||||
assert receiverType == null : "Parameters before propagation have receiver type," +
|
|
||||||
" but propagation should be disabled for functions compiled from Kotlin in class: " +
|
|
||||||
DescriptorUtils.getFqName(containingClass);
|
|
||||||
|
|
||||||
KotlinType resultReceiverType = null;
|
KotlinType resultReceiverType = null;
|
||||||
List<ValueParameterDescriptor> resultParameters = new ArrayList<ValueParameterDescriptor>(parameters.size());
|
List<ValueParameterDescriptor> resultParameters = new ArrayList<ValueParameterDescriptor>(parameters.size());
|
||||||
|
|
||||||
@@ -239,9 +145,7 @@ public class SignaturesPropagationData {
|
|||||||
|
|
||||||
VarargCheckResult varargCheckResult = checkVarargInSuperFunctions(originalParam);
|
VarargCheckResult varargCheckResult = checkVarargInSuperFunctions(originalParam);
|
||||||
|
|
||||||
KotlinType altType = modifyTypeAccordingToSuperMethods(varargCheckResult.parameterType,
|
KotlinType altType = varargCheckResult.parameterType;
|
||||||
convertToTypeVarianceList(typesFromSuperMethods),
|
|
||||||
MEMBER_SIGNATURE_CONTRAVARIANT);
|
|
||||||
|
|
||||||
if (shouldBeExtension && originalIndex == 0) {
|
if (shouldBeExtension && originalIndex == 0) {
|
||||||
resultReceiverType = altType;
|
resultReceiverType = altType;
|
||||||
@@ -284,16 +188,6 @@ public class SignaturesPropagationData {
|
|||||||
return new ValueParameters(resultReceiverType, resultParameters, hasStableParameterNames);
|
return new ValueParameters(resultReceiverType, resultParameters, hasStableParameterNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static List<TypeAndVariance> convertToTypeVarianceList(@NotNull List<TypeAndName> list) {
|
|
||||||
return CollectionsKt.map(list, new Function1<TypeAndName, TypeAndVariance>() {
|
|
||||||
@Override
|
|
||||||
public TypeAndVariance invoke(TypeAndName tvn) {
|
|
||||||
return new TypeAndVariance(tvn.type, INVARIANT);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<FunctionDescriptor> getSuperFunctionsForMethod(
|
private static List<FunctionDescriptor> getSuperFunctionsForMethod(
|
||||||
@NotNull JavaMethod method,
|
@NotNull JavaMethod method,
|
||||||
@NotNull JavaMethodDescriptor autoMethodDescriptor,
|
@NotNull JavaMethodDescriptor autoMethodDescriptor,
|
||||||
@@ -388,284 +282,6 @@ public class SignaturesPropagationData {
|
|||||||
return new VarargCheckResult(originalType, originalVarargElementType != null);
|
return new VarargCheckResult(originalType, originalVarargElementType != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private KotlinType modifyTypeAccordingToSuperMethods(
|
|
||||||
@NotNull KotlinType autoType,
|
|
||||||
@NotNull List<TypeAndVariance> typesFromSuper,
|
|
||||||
@NotNull TypeUsage howThisTypeIsUsed
|
|
||||||
) {
|
|
||||||
if (autoType.isError()) return autoType;
|
|
||||||
|
|
||||||
if (JavaDescriptorResolverKt.getPLATFORM_TYPES()) return autoType;
|
|
||||||
|
|
||||||
boolean resultNullable = typeMustBeNullable(autoType, typesFromSuper, howThisTypeIsUsed);
|
|
||||||
ClassifierDescriptor resultClassifier = modifyTypeClassifier(autoType, typesFromSuper);
|
|
||||||
List<TypeProjection> resultArguments = getTypeArgsOfType(autoType, resultClassifier, typesFromSuper);
|
|
||||||
MemberScope resultScope;
|
|
||||||
if (resultClassifier instanceof ClassDescriptor) {
|
|
||||||
resultScope = ((ClassDescriptor) resultClassifier).getMemberScope(resultArguments);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
resultScope = autoType.getMemberScope();
|
|
||||||
}
|
|
||||||
|
|
||||||
KotlinType type = KotlinTypeImpl.create(autoType.getAnnotations(),
|
|
||||||
resultClassifier.getTypeConstructor(),
|
|
||||||
resultNullable,
|
|
||||||
resultArguments,
|
|
||||||
resultScope);
|
|
||||||
|
|
||||||
PropagationHeuristics.checkArrayInReturnType(this, type, typesFromSuper);
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private List<TypeProjection> getTypeArgsOfType(
|
|
||||||
@NotNull KotlinType autoType,
|
|
||||||
@NotNull ClassifierDescriptor classifier,
|
|
||||||
@NotNull List<TypeAndVariance> typesFromSuper
|
|
||||||
) {
|
|
||||||
if (typesFromSuper.isEmpty()) return autoType.getArguments();
|
|
||||||
|
|
||||||
List<TypeProjection> autoArguments = autoType.getArguments();
|
|
||||||
|
|
||||||
if (!(classifier instanceof ClassDescriptor)) {
|
|
||||||
assert autoArguments.isEmpty() :
|
|
||||||
"Unexpected type arguments when type constructor is not ClassDescriptor, type = " + autoType +
|
|
||||||
", classifier = " + classifier + ", classifier class = " + classifier.getClass();
|
|
||||||
return autoArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<List<TypeProjectionAndVariance>> typeArgumentsFromSuper = calculateTypeArgumentsFromSuper((ClassDescriptor) classifier,
|
|
||||||
typesFromSuper);
|
|
||||||
|
|
||||||
// Modify type arguments using info from typesFromSuper
|
|
||||||
List<TypeProjection> resultArguments = Lists.newArrayList();
|
|
||||||
for (TypeParameterDescriptor parameter : classifier.getTypeConstructor().getParameters()) {
|
|
||||||
TypeProjection argument = autoArguments.get(parameter.getIndex());
|
|
||||||
|
|
||||||
KotlinType argumentType = argument.getType();
|
|
||||||
List<TypeProjectionAndVariance> projectionsFromSuper = typeArgumentsFromSuper.get(parameter.getIndex());
|
|
||||||
List<TypeAndVariance> argTypesFromSuper = getTypes(projectionsFromSuper);
|
|
||||||
|
|
||||||
KotlinType type = modifyTypeAccordingToSuperMethods(argumentType, argTypesFromSuper, TYPE_ARGUMENT);
|
|
||||||
Variance projectionKind = calculateArgumentProjectionKindFromSuper(argument, projectionsFromSuper);
|
|
||||||
|
|
||||||
resultArguments.add(new TypeProjectionImpl(projectionKind, type));
|
|
||||||
}
|
|
||||||
return resultArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Variance calculateArgumentProjectionKindFromSuper(
|
|
||||||
@NotNull TypeProjection argument,
|
|
||||||
@NotNull List<TypeProjectionAndVariance> projectionsFromSuper
|
|
||||||
) {
|
|
||||||
if (projectionsFromSuper.isEmpty()) return argument.getProjectionKind();
|
|
||||||
|
|
||||||
Set<Variance> projectionKindsInSuper = Sets.newLinkedHashSet();
|
|
||||||
for (TypeProjectionAndVariance projectionAndVariance : projectionsFromSuper) {
|
|
||||||
projectionKindsInSuper.add(projectionAndVariance.typeProjection.getProjectionKind());
|
|
||||||
}
|
|
||||||
|
|
||||||
Variance defaultProjectionKind = argument.getProjectionKind();
|
|
||||||
if (projectionKindsInSuper.size() == 0) {
|
|
||||||
return defaultProjectionKind;
|
|
||||||
}
|
|
||||||
else if (projectionKindsInSuper.size() == 1) {
|
|
||||||
Variance projectionKindInSuper = projectionKindsInSuper.iterator().next();
|
|
||||||
if (defaultProjectionKind == INVARIANT || defaultProjectionKind == projectionKindInSuper) {
|
|
||||||
return projectionKindInSuper;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
reportError("Incompatible projection kinds in type arguments of super methods' return types: "
|
|
||||||
+ projectionsFromSuper + ", defined in current: " + argument);
|
|
||||||
return defaultProjectionKind;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
reportError("Incompatible projection kinds in type arguments of super methods' return types: " + projectionsFromSuper);
|
|
||||||
return defaultProjectionKind;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static List<TypeAndVariance> getTypes(@NotNull List<TypeProjectionAndVariance> projections) {
|
|
||||||
List<TypeAndVariance> types = Lists.newArrayList();
|
|
||||||
for (TypeProjectionAndVariance projection : projections) {
|
|
||||||
types.add(new TypeAndVariance(projection.typeProjection.getType(),
|
|
||||||
merge(projection.varianceOfPosition, projection.typeProjection.getProjectionKind())));
|
|
||||||
}
|
|
||||||
return types;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Variance merge(Variance positionOfOuter, Variance projectionKind) {
|
|
||||||
// Inv<Inv<out X>>, X is in invariant position
|
|
||||||
if (positionOfOuter == INVARIANT) return INVARIANT;
|
|
||||||
// Out<X>, X is in out-position
|
|
||||||
if (projectionKind == INVARIANT) return positionOfOuter;
|
|
||||||
// Out<Out<X>>, X is in out-position
|
|
||||||
// In<In<X>>, X is in out-position
|
|
||||||
// Out<In<X>>, X is in in-position
|
|
||||||
// In<Out<X>>, X is in in-position
|
|
||||||
return positionOfOuter.superpose(projectionKind);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns list with type arguments info from supertypes
|
|
||||||
// Example:
|
|
||||||
// - Foo<A, B> is a subtype of Bar<A, List<B>>, Baz<Boolean, A>
|
|
||||||
// - input: klass = Foo, typesFromSuper = [Bar<String, List<Int>>, Baz<Boolean, CharSequence>]
|
|
||||||
// - output[0] = [String, CharSequence], output[1] = []
|
|
||||||
private static List<List<TypeProjectionAndVariance>> calculateTypeArgumentsFromSuper(
|
|
||||||
@NotNull ClassDescriptor klass,
|
|
||||||
@NotNull Collection<TypeAndVariance> typesFromSuper
|
|
||||||
) {
|
|
||||||
// For each superclass of klass and its parameters, hold their mapping to klass' parameters
|
|
||||||
// #0 of Bar -> A
|
|
||||||
// #1 of Bar -> List<B>
|
|
||||||
// #0 of Baz -> Boolean
|
|
||||||
// #1 of Baz -> A
|
|
||||||
// #0 of Foo -> A (mapped to itself)
|
|
||||||
// #1 of Foo -> B (mapped to itself)
|
|
||||||
Multimap<TypeParameterDescriptor, TypeProjection> substitution = SubstitutionUtils.buildDeepSubstitutionMultimap(
|
|
||||||
TypeUtils.makeUnsubstitutedType(klass, ErrorUtils.createErrorScope("Do not access this scope", true)));
|
|
||||||
|
|
||||||
// for each parameter of klass, hold arguments in corresponding supertypes
|
|
||||||
List<List<TypeProjectionAndVariance>> parameterToArgumentsFromSuper = Lists.newArrayList();
|
|
||||||
for (TypeParameterDescriptor ignored : klass.getTypeConstructor().getParameters()) {
|
|
||||||
parameterToArgumentsFromSuper.add(new ArrayList<TypeProjectionAndVariance>());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enumerate all types from super and all its parameters
|
|
||||||
for (TypeAndVariance typeFromSuper : typesFromSuper) {
|
|
||||||
for (TypeParameterDescriptor parameter : typeFromSuper.type.getConstructor().getParameters()) {
|
|
||||||
TypeProjection argument = typeFromSuper.type.getArguments().get(parameter.getIndex());
|
|
||||||
|
|
||||||
// for given example, this block is executed four times:
|
|
||||||
// 1. typeFromSuper = Bar<String, List<Int>>, parameter = "#0 of Bar", argument = String
|
|
||||||
// 2. typeFromSuper = Bar<String, List<Int>>, parameter = "#1 of Bar", argument = List<Int>
|
|
||||||
// 3. typeFromSuper = Baz<Boolean, CharSequence>, parameter = "#0 of Baz", argument = Boolean
|
|
||||||
// 4. typeFromSuper = Baz<Boolean, CharSequence>, parameter = "#1 of Baz", argument = CharSequence
|
|
||||||
|
|
||||||
// if it is mapped to klass' parameter, then store it into map
|
|
||||||
for (TypeProjection projection : substitution.get(parameter)) {
|
|
||||||
// 1. projection = A
|
|
||||||
// 2. projection = List<B>
|
|
||||||
// 3. projection = Boolean
|
|
||||||
// 4. projection = A
|
|
||||||
ClassifierDescriptor classifier = projection.getType().getConstructor().getDeclarationDescriptor();
|
|
||||||
|
|
||||||
// this condition is true for 1 and 4, false for 2 and 3
|
|
||||||
if (classifier instanceof TypeParameterDescriptor && classifier.getContainingDeclaration() == klass) {
|
|
||||||
int parameterIndex = ((TypeParameterDescriptor) classifier).getIndex();
|
|
||||||
Variance effectiveVariance = parameter.getVariance().superpose(typeFromSuper.varianceOfPosition);
|
|
||||||
parameterToArgumentsFromSuper.get(parameterIndex).add(new TypeProjectionAndVariance(argument, effectiveVariance));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return parameterToArgumentsFromSuper;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean typeMustBeNullable(
|
|
||||||
@NotNull KotlinType autoType,
|
|
||||||
@NotNull List<TypeAndVariance> typesFromSuper,
|
|
||||||
@NotNull TypeUsage howThisTypeIsUsed
|
|
||||||
) {
|
|
||||||
boolean someSupersNotCovariantNullable = false;
|
|
||||||
boolean someSupersCovariantNullable = false;
|
|
||||||
boolean someSupersNotNull = false;
|
|
||||||
for (TypeAndVariance typeFromSuper : typesFromSuper) {
|
|
||||||
if (!TypeUtils.isNullableType(typeFromSuper.type)) {
|
|
||||||
someSupersNotNull = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (typeFromSuper.varianceOfPosition == Variance.OUT_VARIANCE) {
|
|
||||||
someSupersCovariantNullable = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
someSupersNotCovariantNullable = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (someSupersNotNull && someSupersNotCovariantNullable) {
|
|
||||||
reportError("Incompatible types in superclasses: " + typesFromSuper);
|
|
||||||
return TypeUtils.isNullableType(autoType);
|
|
||||||
}
|
|
||||||
else if (someSupersNotNull) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (someSupersNotCovariantNullable || someSupersCovariantNullable) {
|
|
||||||
boolean annotatedAsNotNull = howThisTypeIsUsed != TYPE_ARGUMENT && !TypeUtils.isNullableType(autoType);
|
|
||||||
|
|
||||||
if (annotatedAsNotNull && someSupersNotCovariantNullable) {
|
|
||||||
DescriptorRenderer renderer = DescriptorRenderer.SHORT_NAMES_IN_TYPES;
|
|
||||||
reportError("In superclass type is nullable: " + typesFromSuper + ", in subclass it is not: " + renderer.renderType(autoType));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !annotatedAsNotNull;
|
|
||||||
}
|
|
||||||
return TypeUtils.isNullableType(autoType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private ClassifierDescriptor modifyTypeClassifier(
|
|
||||||
@NotNull KotlinType autoType,
|
|
||||||
@NotNull List<TypeAndVariance> typesFromSuper
|
|
||||||
) {
|
|
||||||
ClassifierDescriptor classifier = autoType.getConstructor().getDeclarationDescriptor();
|
|
||||||
if (!(classifier instanceof ClassDescriptor)) {
|
|
||||||
assert classifier != null : "no declaration descriptor for type " + autoType + ", auto method descriptor: " + autoMethodDescriptor;
|
|
||||||
|
|
||||||
if (classifier instanceof TypeParameterDescriptor && autoTypeParameterToModified.containsKey(classifier)) {
|
|
||||||
return autoTypeParameterToModified.get(classifier);
|
|
||||||
}
|
|
||||||
return classifier;
|
|
||||||
}
|
|
||||||
ClassDescriptor klass = (ClassDescriptor) classifier;
|
|
||||||
|
|
||||||
boolean someSupersMutable = false;
|
|
||||||
boolean someSupersCovariantReadOnly = false;
|
|
||||||
boolean someSupersNotCovariantReadOnly = false;
|
|
||||||
for (TypeAndVariance typeFromSuper : typesFromSuper) {
|
|
||||||
ClassifierDescriptor classifierFromSuper = typeFromSuper.type.getConstructor().getDeclarationDescriptor();
|
|
||||||
if (classifierFromSuper instanceof ClassDescriptor) {
|
|
||||||
ClassDescriptor classFromSuper = (ClassDescriptor) classifierFromSuper;
|
|
||||||
|
|
||||||
if (JavaToKotlinClassMap.INSTANCE.isMutable(classFromSuper)) {
|
|
||||||
someSupersMutable = true;
|
|
||||||
}
|
|
||||||
else if (JavaToKotlinClassMap.INSTANCE.isReadOnly(classFromSuper)) {
|
|
||||||
if (typeFromSuper.varianceOfPosition == Variance.OUT_VARIANCE) {
|
|
||||||
someSupersCovariantReadOnly = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
someSupersNotCovariantReadOnly = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (someSupersMutable && someSupersNotCovariantReadOnly) {
|
|
||||||
reportError("Incompatible types in superclasses: " + typesFromSuper);
|
|
||||||
return classifier;
|
|
||||||
}
|
|
||||||
else if (someSupersMutable) {
|
|
||||||
if (JavaToKotlinClassMap.INSTANCE.isReadOnly(klass)) {
|
|
||||||
return JavaToKotlinClassMap.INSTANCE.convertReadOnlyToMutable(klass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (someSupersNotCovariantReadOnly || someSupersCovariantReadOnly) {
|
|
||||||
if (JavaToKotlinClassMap.INSTANCE.isMutable(klass)) {
|
|
||||||
return JavaToKotlinClassMap.INSTANCE.convertMutableToReadOnly(klass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ClassifierDescriptor fixed = PropagationHeuristics.tryToFixOverridingTWithRawType(this, typesFromSuper);
|
|
||||||
return fixed != null ? fixed : classifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isArrayType(@NotNull KotlinType type) {
|
private static boolean isArrayType(@NotNull KotlinType type) {
|
||||||
return KotlinBuiltIns.isArray(type) || KotlinBuiltIns.isPrimitiveArray(type);
|
return KotlinBuiltIns.isArray(type) || KotlinBuiltIns.isPrimitiveArray(type);
|
||||||
}
|
}
|
||||||
@@ -680,34 +296,6 @@ public class SignaturesPropagationData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class TypeProjectionAndVariance {
|
|
||||||
public final TypeProjection typeProjection;
|
|
||||||
public final Variance varianceOfPosition;
|
|
||||||
|
|
||||||
public TypeProjectionAndVariance(TypeProjection typeProjection, Variance varianceOfPosition) {
|
|
||||||
this.typeProjection = typeProjection;
|
|
||||||
this.varianceOfPosition = varianceOfPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return typeProjection.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class TypeAndVariance {
|
|
||||||
public final KotlinType type;
|
|
||||||
public final Variance varianceOfPosition;
|
|
||||||
|
|
||||||
public TypeAndVariance(KotlinType type, Variance varianceOfPosition) {
|
|
||||||
this.type = type;
|
|
||||||
this.varianceOfPosition = varianceOfPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return type.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class TypeAndName {
|
private static class TypeAndName {
|
||||||
public final KotlinType type;
|
public final KotlinType type;
|
||||||
public final Name name;
|
public final Name name;
|
||||||
|
|||||||
+1
-2
@@ -34,14 +34,13 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
|||||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||||
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory
|
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
|
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
|
||||||
import org.jetbrains.kotlin.resolve.jvm.PLATFORM_TYPES
|
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.utils.keysToMapExceptNulls
|
import org.jetbrains.kotlin.utils.keysToMapExceptNulls
|
||||||
import org.jetbrains.kotlin.utils.valuesToMap
|
import org.jetbrains.kotlin.utils.valuesToMap
|
||||||
|
|
||||||
fun LazyJavaResolverContext.resolveAnnotation(annotation: JavaAnnotation): LazyJavaAnnotationDescriptor? {
|
fun LazyJavaResolverContext.resolveAnnotation(annotation: JavaAnnotation): LazyJavaAnnotationDescriptor? {
|
||||||
val classId = annotation.getClassId()
|
val classId = annotation.getClassId()
|
||||||
if (classId == null || isSpecialAnnotation(classId, !PLATFORM_TYPES)) return null
|
if (classId == null || isSpecialAnnotation(classId, false)) return null
|
||||||
return LazyJavaAnnotationDescriptor(this, annotation)
|
return LazyJavaAnnotationDescriptor(this, annotation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-7
@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
|
|||||||
import org.jetbrains.kotlin.load.java.typeEnhacement.enhanceSignatures
|
import org.jetbrains.kotlin.load.java.typeEnhacement.enhanceSignatures
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.jvm.PLATFORM_TYPES
|
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude.NonExtensions
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude.NonExtensions
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
@@ -278,15 +277,14 @@ public abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) :
|
|||||||
get() = isFinal && isStatic
|
get() = isFinal && isStatic
|
||||||
|
|
||||||
private fun getPropertyType(field: JavaField, annotations: Annotations): KotlinType {
|
private fun getPropertyType(field: JavaField, annotations: Annotations): KotlinType {
|
||||||
// Fields do not have their own generic parameters
|
// Fields do not have their own generic parameters.
|
||||||
val finalStatic = field.isFinalStatic
|
// Simple static constants should not have flexible types.
|
||||||
// simple static constants should not have flexible types:
|
val allowFlexible = !(field.isFinalStatic && c.components.javaPropertyInitializerEvaluator.isNotNullCompileTimeConstant(field))
|
||||||
val allowFlexible = PLATFORM_TYPES && !(finalStatic && c.components.javaPropertyInitializerEvaluator.isNotNullCompileTimeConstant(field))
|
|
||||||
val propertyType = c.typeResolver.transformJavaType(
|
val propertyType = c.typeResolver.transformJavaType(
|
||||||
field.getType(),
|
field.type,
|
||||||
LazyJavaTypeAttributes(TypeUsage.MEMBER_SIGNATURE_INVARIANT, annotations, allowFlexible)
|
LazyJavaTypeAttributes(TypeUsage.MEMBER_SIGNATURE_INVARIANT, annotations, allowFlexible)
|
||||||
)
|
)
|
||||||
if ((!allowFlexible || !PLATFORM_TYPES) && finalStatic) {
|
if (!allowFlexible) {
|
||||||
return TypeUtils.makeNotNullable(propertyType)
|
return TypeUtils.makeNotNullable(propertyType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-4
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeFlexibility.*
|
|||||||
import org.jetbrains.kotlin.load.java.structure.*
|
import org.jetbrains.kotlin.load.java.structure.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||||
import org.jetbrains.kotlin.resolve.jvm.PLATFORM_TYPES
|
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.Variance.*
|
import org.jetbrains.kotlin.types.Variance.*
|
||||||
import org.jetbrains.kotlin.types.typeUtil.createProjection
|
import org.jetbrains.kotlin.types.typeUtil.createProjection
|
||||||
@@ -54,7 +53,7 @@ class LazyJavaTypeResolver(
|
|||||||
else c.module.builtIns.getUnitType()
|
else c.module.builtIns.getUnitType()
|
||||||
}
|
}
|
||||||
is JavaClassifierType ->
|
is JavaClassifierType ->
|
||||||
if (PLATFORM_TYPES && attr.allowFlexible && attr.howThisTypeIsUsed != SUPERTYPE)
|
if (attr.allowFlexible && attr.howThisTypeIsUsed != SUPERTYPE)
|
||||||
FlexibleJavaClassifierTypeCapabilities.create(
|
FlexibleJavaClassifierTypeCapabilities.create(
|
||||||
LazyJavaClassifierType(javaType, attr.toFlexible(FLEXIBLE_LOWER_BOUND)),
|
LazyJavaClassifierType(javaType, attr.toFlexible(FLEXIBLE_LOWER_BOUND)),
|
||||||
LazyJavaClassifierType(javaType, attr.toFlexible(FLEXIBLE_UPPER_BOUND))
|
LazyJavaClassifierType(javaType, attr.toFlexible(FLEXIBLE_UPPER_BOUND))
|
||||||
@@ -71,7 +70,7 @@ class LazyJavaTypeResolver(
|
|||||||
val primitiveType = (javaComponentType as? JavaPrimitiveType)?.getType()
|
val primitiveType = (javaComponentType as? JavaPrimitiveType)?.getType()
|
||||||
if (primitiveType != null) {
|
if (primitiveType != null) {
|
||||||
val jetType = c.module.builtIns.getPrimitiveArrayKotlinType(primitiveType)
|
val jetType = c.module.builtIns.getPrimitiveArrayKotlinType(primitiveType)
|
||||||
return@run if (PLATFORM_TYPES && attr.allowFlexible)
|
return@run if (attr.allowFlexible)
|
||||||
FlexibleJavaClassifierTypeCapabilities.create(jetType, TypeUtils.makeNullable(jetType))
|
FlexibleJavaClassifierTypeCapabilities.create(jetType, TypeUtils.makeNullable(jetType))
|
||||||
else TypeUtils.makeNullableAsSpecified(jetType, !attr.isMarkedNotNull)
|
else TypeUtils.makeNullableAsSpecified(jetType, !attr.isMarkedNotNull)
|
||||||
}
|
}
|
||||||
@@ -79,7 +78,7 @@ class LazyJavaTypeResolver(
|
|||||||
val componentType = transformJavaType(javaComponentType,
|
val componentType = transformJavaType(javaComponentType,
|
||||||
TYPE_ARGUMENT.toAttributes(attr.allowFlexible, attr.isForAnnotationParameter))
|
TYPE_ARGUMENT.toAttributes(attr.allowFlexible, attr.isForAnnotationParameter))
|
||||||
|
|
||||||
if (PLATFORM_TYPES && attr.allowFlexible) {
|
if (attr.allowFlexible) {
|
||||||
return@run FlexibleJavaClassifierTypeCapabilities.create(
|
return@run FlexibleJavaClassifierTypeCapabilities.create(
|
||||||
c.module.builtIns.getArrayType(INVARIANT, componentType),
|
c.module.builtIns.getArrayType(INVARIANT, componentType),
|
||||||
TypeUtils.makeNullable(c.module.builtIns.getArrayType(OUT_VARIANCE, componentType)))
|
TypeUtils.makeNullable(c.module.builtIns.getArrayType(OUT_VARIANCE, componentType)))
|
||||||
|
|||||||
+4
-9
@@ -16,17 +16,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.jvm
|
package org.jetbrains.kotlin.resolve.jvm
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.load.java.structure.*
|
|
||||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaPackageFragmentProvider
|
import org.jetbrains.kotlin.load.java.lazy.LazyJavaPackageFragmentProvider
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||||
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
|
|
||||||
|
|
||||||
public var PLATFORM_TYPES: Boolean = true
|
class JavaDescriptorResolver(val packageFragmentProvider: LazyJavaPackageFragmentProvider) {
|
||||||
|
fun resolveClass(javaClass: JavaClass): ClassDescriptor? {
|
||||||
public class JavaDescriptorResolver(public val packageFragmentProvider: LazyJavaPackageFragmentProvider, private val module: ModuleDescriptor) {
|
|
||||||
|
|
||||||
public fun resolveClass(javaClass: JavaClass): ClassDescriptor? {
|
|
||||||
return packageFragmentProvider.getClass(javaClass)
|
return packageFragmentProvider.getClass(javaClass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -64,7 +64,7 @@ public class RuntimeModuleData private constructor(public val deserialization: D
|
|||||||
|
|
||||||
val lazyJavaPackageFragmentProvider =
|
val lazyJavaPackageFragmentProvider =
|
||||||
LazyJavaPackageFragmentProvider(globalJavaResolverContext, module, ReflectionTypes(module))
|
LazyJavaPackageFragmentProvider(globalJavaResolverContext, module, ReflectionTypes(module))
|
||||||
val javaDescriptorResolver = JavaDescriptorResolver(lazyJavaPackageFragmentProvider, module)
|
val javaDescriptorResolver = JavaDescriptorResolver(lazyJavaPackageFragmentProvider)
|
||||||
val javaClassDataFinder = JavaClassDataFinder(reflectKotlinClassFinder, deserializedDescriptorResolver)
|
val javaClassDataFinder = JavaClassDataFinder(reflectKotlinClassFinder, deserializedDescriptorResolver)
|
||||||
val binaryClassAnnotationAndConstantLoader = BinaryClassAnnotationAndConstantLoaderImpl(module, storageManager, reflectKotlinClassFinder, RuntimeErrorReporter)
|
val binaryClassAnnotationAndConstantLoader = BinaryClassAnnotationAndConstantLoaderImpl(module, storageManager, reflectKotlinClassFinder, RuntimeErrorReporter)
|
||||||
val deserializationComponentsForJava = DeserializationComponentsForJava(
|
val deserializationComponentsForJava = DeserializationComponentsForJava(
|
||||||
|
|||||||
Reference in New Issue
Block a user