private void checkParameterAndReturnTypesForOverridingMethods( @NotNull List<ValueParameterDescriptor> valueParameters, @NotNull List<TypeParameterDescriptor> methodTypeParameters, @Nullable JetType returnType) { TypeSubstitutor substitutor = DescriptorResolverUtils.createSubstitutorForTypeParameters(originalToAltTypeParameters); for (ValueParameterDescriptor parameter : valueParameters) { int index = parameter.getIndex(); ValueParameterDescriptor altParameter = altValueParameters.get(index); JetType substituted = substitutor.substitute(parameter.getType(), Variance.INVARIANT); assert substituted != null; if (!TypeUtils.equalTypes(substituted, altParameter.getType())) { throw new AlternativeSignatureMismatchException( "Parameter type changed for method which overrides another: " + altParameter.getType() + ", was: " + parameter.getType()); } } // don't check receiver for (TypeParameterDescriptor parameter : methodTypeParameters) { int index = parameter.getIndex(); JetType substituted = substitutor.substitute(parameter.getUpperBoundsAsType(), Variance.INVARIANT); assert substituted != null; if (!TypeUtils.equalTypes(substituted, altTypeParameters.get(index).getUpperBoundsAsType())) { throw new AlternativeSignatureMismatchException( "Type parameter's upper bound changed for method which overrides another: " + altTypeParameters.get(index).getUpperBoundsAsType() + ", was: " + parameter.getUpperBoundsAsType()); } } if (returnType != null) { JetType substitutedReturnType = substitutor.substitute(returnType, Variance.INVARIANT); assert substitutedReturnType != null; if (!JetTypeChecker.INSTANCE.isSubtypeOf(altReturnType, substitutedReturnType)) { throw new AlternativeSignatureMismatchException( "Return type is changed to not subtype for method which overrides another: " + altReturnType + ", was: " + returnType); } } }
@Nullable public static List<ValueParameterDescriptor> getSubstitutedValueParameters( FunctionDescriptor substitutedDescriptor, @NotNull FunctionDescriptor functionDescriptor, @NotNull TypeSubstitutor substitutor) { List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(); List<ValueParameterDescriptor> unsubstitutedValueParameters = functionDescriptor.getValueParameters(); for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) { ValueParameterDescriptor unsubstitutedValueParameter = unsubstitutedValueParameters.get(i); // TODO : Lazy? JetType substitutedType = substitutor.substitute(unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE); JetType varargElementType = unsubstitutedValueParameter.getVarargElementType(); JetType substituteVarargElementType = varargElementType == null ? null : substitutor.substitute(varargElementType, Variance.IN_VARIANCE); if (substitutedType == null) return null; result.add( new ValueParameterDescriptorImpl( substitutedDescriptor, unsubstitutedValueParameter, unsubstitutedValueParameter.getAnnotations(), unsubstitutedValueParameter.isVar(), substitutedType, substituteVarargElementType)); } return result; }
@NotNull public static SimpleFunctionDescriptor createSamAdapterFunction( @NotNull SimpleFunctionDescriptor original) { SimpleFunctionDescriptorImpl result = new SimpleFunctionDescriptorImpl( original.getContainingDeclaration(), original.getAnnotations(), original.getName(), CallableMemberDescriptor.Kind.SYNTHESIZED); TypeParameters typeParameters = recreateAndInitializeTypeParameters(original.getTypeParameters(), result); JetType returnTypeUnsubstituted = original.getReturnType(); assert returnTypeUnsubstituted != null : original; JetType returnType = typeParameters.substitutor.substitute(returnTypeUnsubstituted, Variance.OUT_VARIANCE); assert returnType != null : "couldn't substitute type: " + returnType + ", substitutor = " + typeParameters.substitutor; List<ValueParameterDescriptor> valueParameters = Lists.newArrayList(); for (ValueParameterDescriptor originalParam : original.getValueParameters()) { JetType originalType = originalParam.getType(); JetType newTypeUnsubstituted = isSamType(originalType) ? getFunctionTypeForSamType(originalType) : originalType; JetType newType = typeParameters.substitutor.substitute(newTypeUnsubstituted, Variance.IN_VARIANCE); assert newType != null : "couldn't substitute type: " + newTypeUnsubstituted + ", substitutor = " + typeParameters.substitutor; ValueParameterDescriptor newParam = new ValueParameterDescriptorImpl( result, originalParam.getIndex(), originalParam.getAnnotations(), originalParam.getName(), newType, false, null); valueParameters.add(newParam); } result.initialize( null, original.getExpectedThisObject(), typeParameters.descriptors, valueParameters, returnType, original.getModality(), original.getVisibility(), false); return result; }
public static boolean isSamAdapterNecessary(@NotNull SimpleFunctionDescriptor fun) { for (ValueParameterDescriptor param : fun.getValueParameters()) { if (isSamType(param.getType())) { return true; } } return false; }
@NotNull private VarargCheckResult checkVarargInSuperFunctions( @NotNull ValueParameterDescriptor originalParam) { boolean someSupersVararg = false; boolean someSupersNotVararg = false; for (FunctionDescriptor superFunction : superFunctions) { if (superFunction.getValueParameters().get(originalParam.getIndex()).getVarargElementType() != null) { someSupersVararg = true; } else { someSupersNotVararg = true; } } JetType originalVarargElementType = originalParam.getVarargElementType(); JetType originalType = originalParam.getType(); if (someSupersVararg && someSupersNotVararg) { reportError("Incompatible super methods: some have vararg parameter, some have not"); return new VarargCheckResult(originalType, originalVarargElementType != null); } KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); if (someSupersVararg && originalVarargElementType == null) { // convert to vararg assert isArrayType(originalType); if (builtIns.isPrimitiveArray(originalType)) { // replace IntArray? with IntArray return new VarargCheckResult(TypeUtils.makeNotNullable(originalType), true); } // replace Array<out Foo>? with Array<Foo> JetType varargElementType = builtIns.getArrayElementType(originalType); return new VarargCheckResult(builtIns.getArrayType(INVARIANT, varargElementType), true); } else if (someSupersNotVararg && originalVarargElementType != null) { // convert to non-vararg assert isArrayType(originalType); if (builtIns.isPrimitiveArray(originalType)) { // replace IntArray with IntArray? return new VarargCheckResult(TypeUtils.makeNullable(originalType), false); } // replace Array<Foo> with Array<out Foo>? return new VarargCheckResult( TypeUtils.makeNullable( builtIns.getArrayType(Variance.OUT_VARIANCE, originalVarargElementType)), false); } return new VarargCheckResult(originalType, originalVarargElementType != null); }
@NotNull private static List<ValueParameterDescriptor> createValueParameterDescriptors( @NotNull ExpressionTypingContext context, @NotNull JetFunctionLiteral functionLiteral, @NotNull FunctionDescriptorImpl functionDescriptor, boolean functionTypeExpected) { List<ValueParameterDescriptor> valueParameterDescriptors = Lists.newArrayList(); List<JetParameter> declaredValueParameters = functionLiteral.getValueParameters(); List<ValueParameterDescriptor> expectedValueParameters = (functionTypeExpected) ? KotlinBuiltIns.getInstance() .getValueParameters(functionDescriptor, context.expectedType) : null; JetParameterList valueParameterList = functionLiteral.getValueParameterList(); boolean hasDeclaredValueParameters = valueParameterList != null; if (functionTypeExpected && !hasDeclaredValueParameters && expectedValueParameters.size() == 1) { ValueParameterDescriptor valueParameterDescriptor = expectedValueParameters.get(0); ValueParameterDescriptor it = new ValueParameterDescriptorImpl( functionDescriptor, 0, Collections.<AnnotationDescriptor>emptyList(), Name.identifier("it"), valueParameterDescriptor.getType(), valueParameterDescriptor.hasDefaultValue(), valueParameterDescriptor.getVarargElementType()); valueParameterDescriptors.add(it); context.trace.record(AUTO_CREATED_IT, it); } else { if (expectedValueParameters != null && declaredValueParameters.size() != expectedValueParameters.size()) { List<JetType> expectedParameterTypes = DescriptorUtils.getValueParametersTypes(expectedValueParameters); context.trace.report( EXPECTED_PARAMETERS_NUMBER_MISMATCH.on( functionLiteral, expectedParameterTypes.size(), expectedParameterTypes)); } for (int i = 0; i < declaredValueParameters.size(); i++) { ValueParameterDescriptor valueParameterDescriptor = createValueParameterDescriptor( context, functionDescriptor, declaredValueParameters, expectedValueParameters, i); valueParameterDescriptors.add(valueParameterDescriptor); } } return valueParameterDescriptors; }
@NotNull private static JetType getFunctionTypeForSamType(@NotNull JetType samType) { FunctionDescriptor function = getAbstractMethodOfSamType(samType); JetType returnType = function.getReturnType(); assert returnType != null : "function is not initialized: " + function; List<JetType> parameterTypes = Lists.newArrayList(); for (ValueParameterDescriptor parameter : function.getValueParameters()) { parameterTypes.add(parameter.getType()); } JetType functionType = KotlinBuiltIns.getInstance() .getFunctionType( Collections.<AnnotationDescriptor>emptyList(), null, parameterTypes, returnType); return TypeUtils.makeNullableAsSpecified(functionType, samType.isNullable()); }
private void checkDefaultParameterValues( List<JetParameter> valueParameters, List<ValueParameterDescriptor> valueParameterDescriptors, JetScope declaringScope) { for (int i = 0; i < valueParameters.size(); i++) { ValueParameterDescriptor valueParameterDescriptor = valueParameterDescriptors.get(i); if (valueParameterDescriptor.hasDefaultValue()) { JetParameter jetParameter = valueParameters.get(i); JetExpression defaultValue = jetParameter.getDefaultValue(); if (defaultValue != null) { expressionTypingServices.getType( declaringScope, defaultValue, valueParameterDescriptor.getType(), trace); } } } }
public void serialize(ValueParameterDescriptor valueParameter) { sb.append("/*"); sb.append(valueParameter.getIndex()); sb.append("*/ "); if (valueParameter.getVarargElementType() != null) { sb.append("vararg "); } sb.append(valueParameter.getName()); sb.append(": "); if (valueParameter.getVarargElementType() != null) { new TypeSerializer(sb).serialize(valueParameter.getVarargElementType()); } else { new TypeSerializer(sb).serialize(valueParameter.getType()); } if (valueParameter.hasDefaultValue()) { sb.append(" = ?"); } }
private void createComponentFunctions( @NotNull MutableClassDescriptor classDescriptor, @NotNull ConstructorDescriptor constructorDescriptor) { int parameterIndex = 0; for (ValueParameterDescriptor parameter : constructorDescriptor.getValueParameters()) { if (!parameter.getType().isError()) { PropertyDescriptor property = trace.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameter); if (property != null) { ++parameterIndex; SimpleFunctionDescriptor functionDescriptor = DescriptorResolver.createComponentFunctionDescriptor( parameterIndex, property, parameter, classDescriptor, trace); classDescriptor.getBuilder().addFunctionDescriptor(functionDescriptor); } } } }
@NotNull private FunctionDescriptor standardFunction( ClassDescriptor classDescriptor, List<TypeProjection> typeArguments, String name, JetType... parameterType) { List<JetType> parameterTypeList = Arrays.asList(parameterType); // JetTypeInferrer.Services typeInferrerServices = // JetSemanticServices.createSemanticServices(getProject()).getTypeInferrerServices(new // BindingTraceContext()); CallResolver callResolver = new InjectorForTests(getProject()).getCallResolver(); OverloadResolutionResults<FunctionDescriptor> functions = callResolver.resolveExactSignature( classDescriptor.getMemberScope(typeArguments), ReceiverDescriptor.NO_RECEIVER, name, parameterTypeList); for (ResolvedCall<? extends FunctionDescriptor> resolvedCall : functions.getResultingCalls()) { List<ValueParameterDescriptor> unsubstitutedValueParameters = resolvedCall.getResultingDescriptor().getValueParameters(); for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) { ValueParameterDescriptor unsubstitutedValueParameter = unsubstitutedValueParameters.get(i); if (unsubstitutedValueParameter.getType().equals(parameterType[i])) { return resolvedCall.getResultingDescriptor(); } } } throw new IllegalArgumentException( "Not found: kotlin::" + classDescriptor.getName() + "." + name + "(" + parameterTypeList + ")"); }
public static boolean containsErrorType(@NotNull FunctionDescriptor function) { if (containsErrorType(function.getReturnType())) { return true; } ReceiverParameterDescriptor receiverParameter = function.getReceiverParameter(); if (receiverParameter != null && containsErrorType(receiverParameter.getType())) { return true; } for (ValueParameterDescriptor parameter : function.getValueParameters()) { if (containsErrorType(parameter.getType())) { return true; } } for (TypeParameterDescriptor parameter : function.getTypeParameters()) { for (JetType upperBound : parameter.getUpperBounds()) { if (containsErrorType(upperBound)) { return true; } } } return false; }
@Nullable private CompileTimeConstant<?> getCompileTimeConstFromArrayExpression( FqName annotationFqName, Name valueName, PsiArrayInitializerMemberValue value, PostponedTasks taskList) { PsiAnnotationMemberValue[] initializers = value.getInitializers(); List<CompileTimeConstant<?>> values = getCompileTimeConstantForArrayValues(annotationFqName, valueName, taskList, initializers); ClassDescriptor classDescriptor = classResolver.resolveClass(annotationFqName, DescriptorSearchRule.INCLUDE_KOTLIN, taskList); // TODO: nullability issues ValueParameterDescriptor valueParameterDescriptor = DescriptorResolverUtils.getValueParameterDescriptorForAnnotationParameter( valueName, classDescriptor); if (valueParameterDescriptor == null) { return null; } JetType expectedArrayType = valueParameterDescriptor.getType(); return new ArrayValue(values, expectedArrayType); }
private static JetType getActualParameterType(ValueParameterDescriptor descriptor) { JetType paramType = descriptor.getType(); if (descriptor.getVarargElementType() != null) paramType = descriptor.getVarargElementType(); return paramType; }
public static TabledDescriptorRenderer renderConflictingSubstitutionsInferenceError( ExtendedInferenceErrorData inferenceErrorData, TabledDescriptorRenderer result) { assert inferenceErrorData.constraintSystem.hasConflictingConstraints(); Collection<CallableDescriptor> substitutedDescriptors = Lists.newArrayList(); Collection<TypeSubstitutor> substitutors = ConstraintsUtil.getSubstitutorsForConflictingParameters( inferenceErrorData.constraintSystem); for (TypeSubstitutor substitutor : substitutors) { CallableDescriptor substitutedDescriptor = inferenceErrorData.descriptor.substitute(substitutor); substitutedDescriptors.add(substitutedDescriptor); } TypeParameterDescriptor firstConflictingParameter = ConstraintsUtil.getFirstConflictingParameter(inferenceErrorData.constraintSystem); assert firstConflictingParameter != null; result.text( newText() .normal("Cannot infer type parameter ") .strong(firstConflictingParameter.getName()) .normal(" in")); // String type = strong(firstConflictingParameter.getName()); TableRenderer table = newTable(); result.table(table); table.descriptor(inferenceErrorData.descriptor).text("None of the following substitutions"); for (CallableDescriptor substitutedDescriptor : substitutedDescriptors) { JetType receiverType = DescriptorUtils.getReceiverParameterType(substitutedDescriptor.getReceiverParameter()); final Collection<ConstraintPosition> errorPositions = Sets.newHashSet(); List<JetType> parameterTypes = Lists.newArrayList(); for (ValueParameterDescriptor valueParameterDescriptor : substitutedDescriptor.getValueParameters()) { parameterTypes.add(valueParameterDescriptor.getType()); if (valueParameterDescriptor.getIndex() >= inferenceErrorData.valueArgumentsTypes.size()) continue; JetType actualType = inferenceErrorData.valueArgumentsTypes.get(valueParameterDescriptor.getIndex()); if (!JetTypeChecker.INSTANCE.isSubtypeOf(actualType, valueParameterDescriptor.getType())) { errorPositions.add( ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex())); } } if (receiverType != null && inferenceErrorData.receiverArgumentType != null && !JetTypeChecker.INSTANCE.isSubtypeOf( inferenceErrorData.receiverArgumentType, receiverType)) { errorPositions.add(ConstraintPosition.RECEIVER_POSITION); } Predicate<ConstraintPosition> isErrorPosition = new Predicate<ConstraintPosition>() { @Override public boolean apply(@Nullable ConstraintPosition constraintPosition) { return errorPositions.contains(constraintPosition); } }; table.functionArgumentTypeList(receiverType, parameterTypes, isErrorPosition); } table .text("can be applied to") .functionArgumentTypeList( inferenceErrorData.receiverArgumentType, inferenceErrorData.valueArgumentsTypes); return result; }
private void computeValueParameters( @NotNull List<ValueParameterDescriptor> parameterDescriptors) { if (parameterDescriptors.size() != altFunDeclaration.getValueParameters().size()) { throw new AlternativeSignatureMismatchException( "Method signature has %d value parameters, but alternative signature has %d", parameterDescriptors.size(), altFunDeclaration.getValueParameters().size()); } List<ValueParameterDescriptor> altParamDescriptors = new ArrayList<ValueParameterDescriptor>(); for (int i = 0, size = parameterDescriptors.size(); i < size; i++) { ValueParameterDescriptor originalParameterDescriptor = parameterDescriptors.get(i); JetParameter annotationValueParameter = altFunDeclaration.getValueParameters().get(i); //noinspection ConstantConditions JetTypeElement alternativeTypeElement = annotationValueParameter.getTypeReference().getTypeElement(); assert alternativeTypeElement != null; JetType alternativeType; JetType alternativeVarargElementType; JetType originalParamVarargElementType = originalParameterDescriptor.getVarargElementType(); if (originalParamVarargElementType == null) { if (annotationValueParameter.isVarArg()) { throw new AlternativeSignatureMismatchException( "Parameter in method signature is not vararg, but in alternative signature it is vararg"); } alternativeType = TypeTransformingVisitor.computeType( alternativeTypeElement, originalParameterDescriptor.getType(), originalToAltTypeParameters, MEMBER_SIGNATURE_CONTRAVARIANT); alternativeVarargElementType = null; } else { if (!annotationValueParameter.isVarArg()) { throw new AlternativeSignatureMismatchException( "Parameter in method signature is vararg, but in alternative signature it is not"); } alternativeVarargElementType = TypeTransformingVisitor.computeType( alternativeTypeElement, originalParamVarargElementType, originalToAltTypeParameters, MEMBER_SIGNATURE_CONTRAVARIANT); alternativeType = KotlinBuiltIns.getInstance().getArrayType(alternativeVarargElementType); } Name altName = annotationValueParameter.getNameAsName(); altParamDescriptors.add( new ValueParameterDescriptorImpl( originalParameterDescriptor.getContainingDeclaration(), null, originalParameterDescriptor.getIndex(), originalParameterDescriptor.getAnnotations(), altName != null ? altName : originalParameterDescriptor.getName(), alternativeType, originalParameterDescriptor.declaresDefaultValue(), alternativeVarargElementType)); } altValueParameters = altParamDescriptors; }