private boolean canImportMembersFrom(
      @NotNull Collection<? extends DeclarationDescriptor> descriptors,
      @NotNull JetSimpleNameExpression reference,
      @NotNull BindingTrace trace,
      @NotNull LookupMode lookupMode) {

    if (lookupMode == LookupMode.ONLY_CLASSES) {
      return true;
    }

    if (descriptors.size() == 1) {
      return canImportMembersFrom(descriptors.iterator().next(), reference, trace, lookupMode);
    }
    TemporaryBindingTrace temporaryTrace =
        TemporaryBindingTrace.create(
            trace, "trace to find out if members can be imported from", reference);
    boolean canImport = false;
    for (DeclarationDescriptor descriptor : descriptors) {
      canImport |= canImportMembersFrom(descriptor, reference, temporaryTrace, lookupMode);
    }
    if (!canImport) {
      temporaryTrace.commit();
    }
    return canImport;
  }
  @Override
  public JetTypeInfo visitObjectLiteralExpression(
      @NotNull final JetObjectLiteralExpression expression, final ExpressionTypingContext context) {
    DelegatingBindingTrace delegatingBindingTrace =
        context.trace.get(TRACE_DELTAS_CACHE, expression.getObjectDeclaration());
    if (delegatingBindingTrace != null) {
      delegatingBindingTrace.addAllMyDataTo(context.trace);
      JetType type = context.trace.get(EXPRESSION_TYPE, expression);
      return DataFlowUtils.checkType(type, expression, context, context.dataFlowInfo);
    }
    final JetType[] result = new JetType[1];
    final TemporaryBindingTrace temporaryTrace =
        TemporaryBindingTrace.create(
            context.trace, "trace to resolve object literal expression", expression);
    ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor> handler =
        new ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor>() {

          @Override
          public void handleRecord(
              WritableSlice<PsiElement, ClassDescriptor> slice,
              PsiElement declaration,
              final ClassDescriptor descriptor) {
            if (slice == CLASS && declaration == expression.getObjectDeclaration()) {
              JetType defaultType =
                  DeferredType.create(
                      context.trace,
                      createRecursionIntolerantLazyValueWithDefault(
                          ErrorUtils.createErrorType("Recursive dependency"),
                          new Function0<JetType>() {
                            @Override
                            public JetType invoke() {
                              return descriptor.getDefaultType();
                            }
                          }));
              result[0] = defaultType;
              if (!context.trace.get(PROCESSED, expression)) {
                temporaryTrace.record(EXPRESSION_TYPE, expression, defaultType);
                temporaryTrace.record(PROCESSED, expression);
              }
            }
          }
        };
    ObservableBindingTrace traceAdapter = new ObservableBindingTrace(temporaryTrace);
    traceAdapter.addHandler(CLASS, handler);
    TopDownAnalyzer.processClassOrObject(
        context.replaceBindingTrace(traceAdapter).replaceContextDependency(INDEPENDENT),
        context.scope.getContainingDeclaration(),
        expression.getObjectDeclaration());

    DelegatingBindingTrace cloneDelta =
        new DelegatingBindingTrace(
            new BindingTraceContext().getBindingContext(),
            "cached delta trace for object literal expression resolve",
            expression);
    temporaryTrace.addAllMyDataTo(cloneDelta);
    context.trace.record(TRACE_DELTAS_CACHE, expression.getObjectDeclaration(), cloneDelta);
    temporaryTrace.commit();
    return DataFlowUtils.checkType(result[0], expression, context, context.dataFlowInfo);
  }
Beispiel #3
0
  private <D extends CallableDescriptor, F extends D>
      OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
          @NotNull ResolutionResultsCache.MemberType<F> memberType,
          @NotNull BasicCallResolutionContext context,
          @NotNull List<ResolutionTask<D, F>> prioritizedTasks,
          @NotNull CallTransformer<D, F> callTransformer,
          @NotNull JetReferenceExpression reference) {
    OverloadResolutionResultsImpl<F> results = null;
    TracingStrategy tracing =
        prioritizedTasks.isEmpty()
            ? TracingStrategy.EMPTY
            : prioritizedTasks.iterator().next().tracing;
    TemporaryBindingTrace traceToResolveCall =
        TemporaryBindingTrace.create(context.trace, "trace to resolve call", context.call);
    CallKey callKey = CallResolverUtil.createCallKey(context);
    if (callKey != null) {
      OverloadResolutionResultsImpl<F> cachedResults =
          context.resolutionResultsCache.getResolutionResults(callKey, memberType);
      if (cachedResults != null) {
        DelegatingBindingTrace deltasTraceForResolve =
            context.resolutionResultsCache.getResolutionTrace(callKey);
        assert deltasTraceForResolve != null;
        deltasTraceForResolve.addAllMyDataTo(traceToResolveCall);
        results = cachedResults;
      }
    }
    if (results == null) {
      BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
      results = doResolveCall(newContext, prioritizedTasks, callTransformer, reference);
      DelegatingBindingTrace deltasTraceForTypeInference =
          ((OverloadResolutionResultsImpl) results).getTrace();
      if (deltasTraceForTypeInference != null) {
        deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
      }
      completeTypeInferenceDependentOnFunctionLiterals(newContext, results, tracing);
      cacheResults(memberType, context, results, traceToResolveCall, tracing);
    }
    traceToResolveCall.commit();

    if (!prioritizedTasks.isEmpty() && context.contextDependency == ContextDependency.INDEPENDENT) {
      results = completeTypeInferenceDependentOnExpectedType(context, results, tracing);
    }

    if (extension != null) {
      extension.run(results, context);
    }

    return results;
  }
Beispiel #4
0
  @NotNull
  private <D extends CallableDescriptor, F extends D>
      OverloadResolutionResultsImpl<F> performResolutionGuardedForExtraFunctionLiteralArguments(
          @NotNull ResolutionTask<D, F> task, @NotNull CallTransformer<D, F> callTransformer) {
    OverloadResolutionResultsImpl<F> results = performResolution(task, callTransformer);

    // If resolution fails, we should check for some of the following situations:
    //   class A {
    //     val foo = Bar() // The following is intended to be an anonymous initializer,
    //                     // but is treated as a function literal argument
    //     {
    //       ...
    //     }
    //  }
    //
    //  fun foo() {
    //    bar {
    //      buzz()
    //      {...} // intended to be a returned from the outer literal
    //    }
    //  }
    ImmutableSet<OverloadResolutionResults.Code> someFailed =
        ImmutableSet.of(MANY_FAILED_CANDIDATES, SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
    if (someFailed.contains(results.getResultCode())
        && !task.call.getFunctionLiteralArguments().isEmpty()
        && task.contextDependency
            == ContextDependency.INDEPENDENT) { // For nested calls there are no such cases
      // We have some candidates that failed for some reason
      // And we have a suspect: the function literal argument
      // Now, we try to remove this argument and see if it helps
      DelegatingCall callWithoutFLArgs =
          new DelegatingCall(task.call) {
            @NotNull
            @Override
            public List<JetExpression> getFunctionLiteralArguments() {
              return Collections.emptyList();
            }
          };
      TemporaryBindingTrace temporaryTrace =
          TemporaryBindingTrace.create(
              task.trace, "trace for resolution guarded for extra function literal arguments");
      ResolutionTask<D, F> newTask =
          task.replaceBindingTrace(temporaryTrace).replaceCall(callWithoutFLArgs);

      OverloadResolutionResultsImpl<F> resultsWithFunctionLiteralsStripped =
          performResolution(newTask, callTransformer);
      if (resultsWithFunctionLiteralsStripped.isSuccess()
          || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
        task.tracing.danglingFunctionLiteralArgumentSuspected(
            task.trace, task.call.getFunctionLiteralArguments());
      }
    }

    return results;
  }
Beispiel #5
0
  @NotNull
  private <D extends CallableDescriptor, F extends D>
      OverloadResolutionResultsImpl<F> performResolution(
          @NotNull ResolutionTask<D, F> task, @NotNull CallTransformer<D, F> callTransformer) {

    for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
      TemporaryBindingTrace candidateTrace =
          TemporaryBindingTrace.create(task.trace, "trace to resolve candidate");
      Collection<CallCandidateResolutionContext<D>> contexts =
          callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace);
      for (CallCandidateResolutionContext<D> context : contexts) {

        candidateResolver.performResolutionForCandidateCall(context, task);

        /* important for 'variable as function case': temporary bind reference to descriptor (will be rewritten)
        to have a binding to variable while 'invoke' call resolve */
        task.tracing.bindReference(context.candidateCall.getTrace(), context.candidateCall);

        Collection<ResolvedCallWithTrace<F>> calls =
            callTransformer.transformCall(context, this, task);

        for (ResolvedCallWithTrace<F> call : calls) {
          task.tracing.bindReference(call.getTrace(), call);
          task.tracing.bindResolvedCall(call.getTrace(), call);
          task.getResolvedCalls().add(call);
        }
      }
    }

    OverloadResolutionResultsImpl<F> results =
        ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
            task.trace, task.tracing, task.getResolvedCalls());
    if (!results.isSingleResult() && !results.isIncomplete()) {
      argumentTypeResolver.checkTypesWithNoCallee(task.toBasic());
    }
    return results;
  }
Beispiel #6
0
  @NotNull
  private <D extends CallableDescriptor, F extends D>
      OverloadResolutionResultsImpl<F> doResolveCall(
          @NotNull BasicCallResolutionContext context,
          @NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
          @NotNull CallTransformer<D, F> callTransformer,
          @NotNull JetReferenceExpression reference) {

    ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
    context.trace.record(
        ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement(), debugInfo);
    context.trace.record(RESOLUTION_SCOPE, context.call.getCalleeExpression(), context.scope);

    if (context.dataFlowInfo.hasTypeInfoConstraints()) {
      context.trace.record(
          NON_DEFAULT_EXPRESSION_DATA_FLOW,
          context.call.getCalleeExpression(),
          context.dataFlowInfo);
    }

    debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks);

    if (context.checkArguments == CheckValueArgumentsMode.ENABLED) {
      argumentTypeResolver.analyzeArgumentsAndRecordTypes(context);
    }

    TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
    OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null;
    for (ResolutionTask<D, F> task : prioritizedTasks) {
      TemporaryBindingTrace taskTrace =
          TemporaryBindingTrace.create(
              context.trace, "trace to resolve a task for", task.reference);
      OverloadResolutionResultsImpl<F> results =
          performResolutionGuardedForExtraFunctionLiteralArguments(
              task.replaceBindingTrace(taskTrace), callTransformer);
      if (results.isSuccess() || results.isAmbiguity()) {
        taskTrace.commit();

        if (results.isSuccess()) {
          debugInfo.set(ResolutionDebugInfo.RESULT, results.getResultingCall());
        }

        resolveFunctionArguments(context, results);
        return results;
      }
      if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
        results.setTrace(taskTrace);
        return results;
      }
      boolean updateResults =
          traceForFirstNonemptyCandidateSet == null
              || (resultsForFirstNonemptyCandidateSet.getResultCode()
                      == CANDIDATES_WITH_WRONG_RECEIVER
                  && results.getResultCode() != CANDIDATES_WITH_WRONG_RECEIVER);
      if (!task.getCandidates().isEmpty() && !results.isNothing() && updateResults) {
        traceForFirstNonemptyCandidateSet = taskTrace;
        resultsForFirstNonemptyCandidateSet = results;
      }
    }
    if (traceForFirstNonemptyCandidateSet != null) {
      traceForFirstNonemptyCandidateSet.commit();
      if (resultsForFirstNonemptyCandidateSet.isSingleResult()) {

        debugInfo.set(
            ResolutionDebugInfo.RESULT, resultsForFirstNonemptyCandidateSet.getResultingCall());
      }
      resolveFunctionArguments(context, resultsForFirstNonemptyCandidateSet);
    } else {
      context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
      argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
    }
    return resultsForFirstNonemptyCandidateSet != null
        ? resultsForFirstNonemptyCandidateSet
        : OverloadResolutionResultsImpl.<F>nameNotFound();
  }