@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); }
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; }
@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(); }