@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);
  }
  public static @NotNull BindingContext resolveToExpression(
      @NotNull final ResolveSession resolveSession, @NotNull JetExpression expression) {
    final DelegatingBindingTrace trace =
        new DelegatingBindingTrace(
            resolveSession.getBindingContext(), "trace to resolve expression", expression);
    JetFile file = (JetFile) expression.getContainingFile();

    @SuppressWarnings("unchecked")
    PsiElement topmostCandidateForAdditionalResolve =
        JetPsiUtil.getTopmostParentOfTypes(
            expression,
            JetNamedFunction.class,
            JetClassInitializer.class,
            JetProperty.class,
            JetDelegationSpecifierList.class);

    if (topmostCandidateForAdditionalResolve != null) {
      if (topmostCandidateForAdditionalResolve instanceof JetNamedFunction) {
        functionAdditionalResolve(
            resolveSession, (JetNamedFunction) topmostCandidateForAdditionalResolve, trace, file);
      } else if (topmostCandidateForAdditionalResolve instanceof JetClassInitializer) {
        initializerAdditionalResolve(
            resolveSession,
            (JetClassInitializer) topmostCandidateForAdditionalResolve,
            trace,
            file);
      } else if (topmostCandidateForAdditionalResolve instanceof JetProperty) {
        propertyAdditionalResolve(
            resolveSession, (JetProperty) topmostCandidateForAdditionalResolve, trace, file);
      } else if (topmostCandidateForAdditionalResolve instanceof JetDelegationSpecifierList) {
        delegationSpecifierAdditionalResolve(
            resolveSession,
            (JetDelegationSpecifierList) topmostCandidateForAdditionalResolve,
            trace,
            file);
      } else {
        assert false : "Invalid type of the topmost parent";
      }

      return trace.getBindingContext();
    }

    // Setup resolution scope explicitly
    if (trace.getBindingContext().get(BindingContext.RESOLUTION_SCOPE, expression) == null) {
      JetScope scope = getExpressionMemberScope(resolveSession, expression);
      if (scope != null) {
        trace.record(BindingContext.RESOLUTION_SCOPE, expression, scope);
      }
    }

    return trace.getBindingContext();
  }
Exemple #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;
  }
Exemple #4
0
  private static <F extends CallableDescriptor> void cacheResults(
      @NotNull ResolutionResultsCache.MemberType<F> memberType,
      @NotNull BasicCallResolutionContext context,
      @NotNull OverloadResolutionResultsImpl<F> results,
      @NotNull DelegatingBindingTrace traceToResolveCall,
      @NotNull TracingStrategy tracing) {
    CallKey callKey = CallResolverUtil.createCallKey(context);
    if (callKey == null) return;

    DelegatingBindingTrace deltasTraceToCacheResolve =
        new DelegatingBindingTrace(
            new BindingTraceContext().getBindingContext(),
            "delta trace for caching resolve of",
            context.call);
    traceToResolveCall.addAllMyDataTo(deltasTraceToCacheResolve);

    context.resolutionResultsCache.recordResolutionResults(callKey, memberType, results);
    context.resolutionResultsCache.recordResolutionTrace(callKey, deltasTraceToCacheResolve);

    if (results.isSingleResult() && memberType == ResolutionResultsCache.FUNCTION_MEMBER_TYPE) {
      CallCandidateResolutionContext<F> callCandidateResolutionContext =
          CallCandidateResolutionContext.createForCallBeingAnalyzed(
              results.getResultingCall().getCallToCompleteTypeArgumentInference(),
              context,
              tracing);
      context.resolutionResultsCache.recordDeferredComputationForCall(
          callKey, callCandidateResolutionContext, memberType);
    }
  }