refactoring
extracted methods
This commit is contained in:
+82
-74
@@ -57,85 +57,13 @@ public class ResolutionResultsHandler {
|
|||||||
failedCandidates.add(candidateCall);
|
failedCandidates.add(candidateCall);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return computeResultAndReportErrors(trace, tracing, successfulCandidates, failedCandidates, incompleteCandidates);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> computeResultAndReportErrors(
|
|
||||||
@NotNull BindingTrace trace,
|
|
||||||
@NotNull TracingStrategy tracing,
|
|
||||||
@NotNull Set<ResolvedCallWithTrace<D>> successfulCandidates,
|
|
||||||
@NotNull Set<ResolvedCallWithTrace<D>> failedCandidates,
|
|
||||||
@NotNull Set<ResolvedCallWithTrace<D>> incompleteCandidates
|
|
||||||
) {
|
|
||||||
// TODO : maybe it's better to filter overrides out first, and only then look for the maximally specific
|
// TODO : maybe it's better to filter overrides out first, and only then look for the maximally specific
|
||||||
|
|
||||||
if (!successfulCandidates.isEmpty() || !incompleteCandidates.isEmpty()) {
|
if (!successfulCandidates.isEmpty() || !incompleteCandidates.isEmpty()) {
|
||||||
Set<ResolvedCallWithTrace<D>> successfulAndIncomplete = Sets.newLinkedHashSet();
|
return computeSuccessfulResult(trace, tracing, successfulCandidates, incompleteCandidates);
|
||||||
successfulAndIncomplete.addAll(successfulCandidates);
|
|
||||||
successfulAndIncomplete.addAll(incompleteCandidates);
|
|
||||||
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(successfulAndIncomplete, true);
|
|
||||||
if (results.isSingleResult()) {
|
|
||||||
ResolvedCallWithTrace<D> resultingCall = results.getResultingCall();
|
|
||||||
resultingCall.getTrace().moveAllMyDataTo(trace);
|
|
||||||
if (resultingCall.getStatus() == INCOMPLETE_TYPE_INFERENCE) {
|
|
||||||
return OverloadResolutionResultsImpl.incompleteTypeInference(resultingCall);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (results.isAmbiguity()) {
|
|
||||||
tracing.recordAmbiguity(trace, results.getResultingCalls());
|
|
||||||
if (allIncomplete(results.getResultingCalls())) {
|
|
||||||
tracing.cannotCompleteResolve(trace, results.getResultingCalls());
|
|
||||||
return OverloadResolutionResultsImpl.incompleteTypeInference(results.getResultingCalls());
|
|
||||||
}
|
|
||||||
// This check is needed for the following case:
|
|
||||||
// x.foo(unresolved) -- if there are multiple foo's, we'd report an ambiguity, and it does not make sense here
|
|
||||||
if (allClean(results.getResultingCalls())) {
|
|
||||||
tracing.ambiguity(trace, results.getResultingCalls());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
else if (!failedCandidates.isEmpty()) {
|
else if (!failedCandidates.isEmpty()) {
|
||||||
if (failedCandidates.size() != 1) {
|
return computeFailedResult(trace, tracing, failedCandidates);
|
||||||
// This is needed when there are several overloads some of which are OK but for nullability of the receiver,
|
|
||||||
// and some are not OK at all. In this case we'd like to say "unsafe call" rather than "none applicable"
|
|
||||||
// Used to be: weak errors. Generalized for future extensions
|
|
||||||
for (EnumSet<ResolutionStatus> severityLevel : SEVERITY_LEVELS) {
|
|
||||||
Set<ResolvedCallWithTrace<D>> thisLevel = Sets.newLinkedHashSet();
|
|
||||||
for (ResolvedCallWithTrace<D> candidate : failedCandidates) {
|
|
||||||
if (severityLevel.contains(candidate.getStatus())) {
|
|
||||||
thisLevel.add(candidate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!thisLevel.isEmpty()) {
|
|
||||||
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(thisLevel, false);
|
|
||||||
if (results.isSingleResult()) {
|
|
||||||
results.getResultingCall().getTrace().moveAllMyDataTo(trace);
|
|
||||||
return OverloadResolutionResultsImpl.singleFailedCandidate(results.getResultingCall());
|
|
||||||
}
|
|
||||||
|
|
||||||
tracing.noneApplicable(trace, results.getResultingCalls());
|
|
||||||
tracing.recordAmbiguity(trace, results.getResultingCalls());
|
|
||||||
return OverloadResolutionResultsImpl.manyFailedCandidates(results.getResultingCalls());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert false : "Should not be reachable, cause every status must belong to some level";
|
|
||||||
|
|
||||||
Set<ResolvedCallWithTrace<D>> noOverrides = OverridingUtil.filterOverrides(failedCandidates, MAP_TO_CANDIDATE);
|
|
||||||
if (noOverrides.size() != 1) {
|
|
||||||
tracing.noneApplicable(trace, noOverrides);
|
|
||||||
tracing.recordAmbiguity(trace, noOverrides);
|
|
||||||
return OverloadResolutionResultsImpl.manyFailedCandidates(noOverrides);
|
|
||||||
}
|
|
||||||
|
|
||||||
failedCandidates = noOverrides;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResolvedCallWithTrace<D> failed = failedCandidates.iterator().next();
|
|
||||||
failed.getTrace().moveAllMyDataTo(trace);
|
|
||||||
return OverloadResolutionResultsImpl.singleFailedCandidate(failed);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tracing.unresolvedReference(trace);
|
tracing.unresolvedReference(trace);
|
||||||
@@ -143,6 +71,86 @@ public class ResolutionResultsHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> computeSuccessfulResult(
|
||||||
|
BindingTrace trace,
|
||||||
|
TracingStrategy tracing,
|
||||||
|
Set<ResolvedCallWithTrace<D>> successfulCandidates,
|
||||||
|
Set<ResolvedCallWithTrace<D>> incompleteCandidates
|
||||||
|
) {
|
||||||
|
Set<ResolvedCallWithTrace<D>> successfulAndIncomplete = Sets.newLinkedHashSet();
|
||||||
|
successfulAndIncomplete.addAll(successfulCandidates);
|
||||||
|
successfulAndIncomplete.addAll(incompleteCandidates);
|
||||||
|
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(successfulAndIncomplete, true);
|
||||||
|
if (results.isSingleResult()) {
|
||||||
|
ResolvedCallWithTrace<D> resultingCall = results.getResultingCall();
|
||||||
|
resultingCall.getTrace().moveAllMyDataTo(trace);
|
||||||
|
if (resultingCall.getStatus() == INCOMPLETE_TYPE_INFERENCE) {
|
||||||
|
return OverloadResolutionResultsImpl.incompleteTypeInference(resultingCall);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (results.isAmbiguity()) {
|
||||||
|
tracing.recordAmbiguity(trace, results.getResultingCalls());
|
||||||
|
if (allIncomplete(results.getResultingCalls())) {
|
||||||
|
tracing.cannotCompleteResolve(trace, results.getResultingCalls());
|
||||||
|
return OverloadResolutionResultsImpl.incompleteTypeInference(results.getResultingCalls());
|
||||||
|
}
|
||||||
|
// This check is needed for the following case:
|
||||||
|
// x.foo(unresolved) -- if there are multiple foo's, we'd report an ambiguity, and it does not make sense here
|
||||||
|
if (allClean(results.getResultingCalls())) {
|
||||||
|
tracing.ambiguity(trace, results.getResultingCalls());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> computeFailedResult(
|
||||||
|
BindingTrace trace,
|
||||||
|
TracingStrategy tracing,
|
||||||
|
Set<ResolvedCallWithTrace<D>> failedCandidates
|
||||||
|
) {
|
||||||
|
if (failedCandidates.size() != 1) {
|
||||||
|
// This is needed when there are several overloads some of which are OK but for nullability of the receiver,
|
||||||
|
// and some are not OK at all. In this case we'd like to say "unsafe call" rather than "none applicable"
|
||||||
|
// Used to be: weak errors. Generalized for future extensions
|
||||||
|
for (EnumSet<ResolutionStatus> severityLevel : SEVERITY_LEVELS) {
|
||||||
|
Set<ResolvedCallWithTrace<D>> thisLevel = Sets.newLinkedHashSet();
|
||||||
|
for (ResolvedCallWithTrace<D> candidate : failedCandidates) {
|
||||||
|
if (severityLevel.contains(candidate.getStatus())) {
|
||||||
|
thisLevel.add(candidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!thisLevel.isEmpty()) {
|
||||||
|
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(thisLevel, false);
|
||||||
|
if (results.isSingleResult()) {
|
||||||
|
results.getResultingCall().getTrace().moveAllMyDataTo(trace);
|
||||||
|
return OverloadResolutionResultsImpl.singleFailedCandidate(results.getResultingCall());
|
||||||
|
}
|
||||||
|
|
||||||
|
tracing.noneApplicable(trace, results.getResultingCalls());
|
||||||
|
tracing.recordAmbiguity(trace, results.getResultingCalls());
|
||||||
|
return OverloadResolutionResultsImpl.manyFailedCandidates(results.getResultingCalls());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert false : "Should not be reachable, cause every status must belong to some level";
|
||||||
|
|
||||||
|
Set<ResolvedCallWithTrace<D>> noOverrides = OverridingUtil.filterOverrides(failedCandidates, MAP_TO_CANDIDATE);
|
||||||
|
if (noOverrides.size() != 1) {
|
||||||
|
tracing.noneApplicable(trace, noOverrides);
|
||||||
|
tracing.recordAmbiguity(trace, noOverrides);
|
||||||
|
return OverloadResolutionResultsImpl.manyFailedCandidates(noOverrides);
|
||||||
|
}
|
||||||
|
|
||||||
|
failedCandidates = noOverrides;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResolvedCallWithTrace<D> failed = failedCandidates.iterator().next();
|
||||||
|
failed.getTrace().moveAllMyDataTo(trace);
|
||||||
|
return OverloadResolutionResultsImpl.singleFailedCandidate(failed);
|
||||||
|
}
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> boolean allClean(@NotNull Collection<ResolvedCallWithTrace<D>> results) {
|
private static <D extends CallableDescriptor> boolean allClean(@NotNull Collection<ResolvedCallWithTrace<D>> results) {
|
||||||
for (ResolvedCallWithTrace<D> result : results) {
|
for (ResolvedCallWithTrace<D> result : results) {
|
||||||
if (result.isDirty()) return false;
|
if (result.isDirty()) return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user