@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)
            + ")");
  }
Exemple #2
0
  @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;
  }