@NotNull private static FunctionDescriptor standardFunction( ClassDescriptor classDescriptor, String name, Project project, KotlinType... parameterTypes) { ModuleDescriptorImpl emptyModule = KotlinTestUtils.createEmptyModule(); ContainerForTests container = InjectionKt.createContainerForTests(project, emptyModule); emptyModule.setDependencies(emptyModule); emptyModule.initialize(PackageFragmentProvider.Empty.INSTANCE); LexicalScopeImpl lexicalScope = new LexicalScopeImpl( ImportingScope.Empty.INSTANCE, classDescriptor, false, classDescriptor.getThisAsReceiverParameter(), LexicalScopeKind.SYNTHETIC); ExpressionTypingContext context = ExpressionTypingContext.newContext( new BindingTraceContext(), lexicalScope, DataFlowInfoFactory.EMPTY, TypeUtils.NO_EXPECTED_TYPE); OverloadResolutionResults<FunctionDescriptor> functions = container .getFakeCallResolver() .resolveFakeCall( context, null, Name.identifier(name), null, null, FakeCallKind.OTHER, parameterTypes); 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(parameterTypes[i])) { return resolvedCall.getResultingDescriptor(); } } } throw new IllegalArgumentException( "Not found: kotlin::" + classDescriptor.getName() + "." + name + "(" + Arrays.toString(parameterTypes) + ")"); }
@Nullable private DataFlowInfo resolveSecondaryConstructorDelegationCall( @NotNull DataFlowInfo outerDataFlowInfo, @NotNull BindingTrace trace, @NotNull LexicalScope scope, @NotNull JetSecondaryConstructor constructor, @NotNull ConstructorDescriptor descriptor, @NotNull CallChecker callChecker) { OverloadResolutionResults<?> results = callResolver.resolveConstructorDelegationCall( trace, scope, outerDataFlowInfo, descriptor, constructor.getDelegationCall(), callChecker); if (results != null && results.isSingleResult()) { ResolvedCall<? extends CallableDescriptor> resolvedCall = results.getResultingCall(); recordConstructorDelegationCall(trace, descriptor, resolvedCall); return resolvedCall.getDataFlowInfoForArguments().getResultInfo(); } return null; }
@Nullable private KotlinType checkConventionForIterator( @NotNull ExpressionTypingContext context, @NotNull KtExpression loopRangeExpression, @NotNull KotlinType iteratorType, @NotNull String name, @NotNull DiagnosticFactory1<KtExpression, KotlinType> ambiguity, @NotNull DiagnosticFactory1<KtExpression, KotlinType> missing, @NotNull DiagnosticFactory1<KtExpression, KotlinType> noneApplicable, @NotNull WritableSlice<KtExpression, ResolvedCall<FunctionDescriptor>> resolvedCallKey) { OverloadResolutionResults<FunctionDescriptor> nextResolutionResults = fakeCallResolver.resolveFakeCall( context, new TransientReceiver(iteratorType), Name.identifier(name), loopRangeExpression); if (nextResolutionResults.isAmbiguity()) { context.trace.report(ambiguity.on(loopRangeExpression, iteratorType)); } else if (nextResolutionResults.isNothing()) { context.trace.report(missing.on(loopRangeExpression, iteratorType)); } else if (!nextResolutionResults.isSuccess()) { context.trace.report(noneApplicable.on(loopRangeExpression, iteratorType)); } else { assert nextResolutionResults.isSuccess(); ResolvedCall<FunctionDescriptor> resolvedCall = nextResolutionResults.getResultingCall(); context.trace.record(resolvedCallKey, loopRangeExpression, resolvedCall); FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor(); symbolUsageValidator.validateCall( resolvedCall, functionDescriptor, context.trace, loopRangeExpression); checkIfOperatorModifierPresent(loopRangeExpression, functionDescriptor, context.trace); return functionDescriptor.getReturnType(); } return null; }
@Nullable public KotlinType checkIterableConvention( @NotNull ExpressionReceiver loopRange, ExpressionTypingContext context) { KtExpression loopRangeExpression = loopRange.getExpression(); // Make a fake call loopRange.iterator(), and try to resolve it Name iterator = Name.identifier("iterator"); Pair<Call, OverloadResolutionResults<FunctionDescriptor>> calls = fakeCallResolver.makeAndResolveFakeCall( loopRange, context, Collections.<KtExpression>emptyList(), iterator, loopRangeExpression, FakeCallKind.ITERATOR, loopRangeExpression); OverloadResolutionResults<FunctionDescriptor> iteratorResolutionResults = calls.getSecond(); if (iteratorResolutionResults.isSuccess()) { ResolvedCall<FunctionDescriptor> iteratorResolvedCall = iteratorResolutionResults.getResultingCall(); context.trace.record( LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRangeExpression, iteratorResolvedCall); FunctionDescriptor iteratorFunction = iteratorResolvedCall.getResultingDescriptor(); checkIfOperatorModifierPresent(loopRangeExpression, iteratorFunction, context.trace); symbolUsageValidator.validateCall( iteratorResolvedCall, iteratorFunction, context.trace, loopRangeExpression); KotlinType iteratorType = iteratorFunction.getReturnType(); KotlinType hasNextType = checkConventionForIterator( context, loopRangeExpression, iteratorType, "hasNext", HAS_NEXT_FUNCTION_AMBIGUITY, HAS_NEXT_MISSING, HAS_NEXT_FUNCTION_NONE_APPLICABLE, LOOP_RANGE_HAS_NEXT_RESOLVED_CALL); if (hasNextType != null && !builtIns.isBooleanOrSubtype(hasNextType)) { context.trace.report(HAS_NEXT_FUNCTION_TYPE_MISMATCH.on(loopRangeExpression, hasNextType)); } return checkConventionForIterator( context, loopRangeExpression, iteratorType, "next", NEXT_AMBIGUITY, NEXT_MISSING, NEXT_NONE_APPLICABLE, LOOP_RANGE_NEXT_RESOLVED_CALL); } else { if (iteratorResolutionResults.isAmbiguity()) { context.trace.report( ITERATOR_AMBIGUITY.on( loopRangeExpression, iteratorResolutionResults.getResultingCalls())); } else { context.trace.report(ITERATOR_MISSING.on(loopRangeExpression)); } } return null; }