001    /*
002     * Copyright 2010-2013 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.jet.lang.resolve.calls.tasks;
018    
019    import com.google.common.collect.Lists;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
023    import org.jetbrains.jet.lang.psi.Call;
024    import org.jetbrains.jet.lang.psi.JetReferenceExpression;
025    import org.jetbrains.jet.lang.resolve.BindingTrace;
026    import org.jetbrains.jet.lang.resolve.calls.CallResolverExtension;
027    import org.jetbrains.jet.lang.resolve.calls.context.*;
028    import org.jetbrains.jet.lang.resolve.calls.model.MutableDataFlowInfoForArguments;
029    import org.jetbrains.jet.lang.resolve.calls.model.MutableResolvedCall;
030    import org.jetbrains.jet.lang.resolve.calls.smartcasts.DataFlowInfo;
031    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
032    import org.jetbrains.jet.lang.types.JetType;
033    
034    import java.util.Collection;
035    
036    /**
037     * Stores candidates for call resolution.
038     */
039    public class ResolutionTask<D extends CallableDescriptor, F extends D> extends CallResolutionContext<ResolutionTask<D, F>> {
040        private final Collection<ResolutionCandidate<D>> candidates;
041        private final Collection<MutableResolvedCall<F>> resolvedCalls;
042        private DescriptorCheckStrategy checkingStrategy;
043        public final TracingStrategy tracing;
044    
045        private ResolutionTask(
046                @NotNull Collection<ResolutionCandidate<D>> candidates,
047                @NotNull TracingStrategy tracing,
048                @NotNull BindingTrace trace,
049                @NotNull JetScope scope,
050                @NotNull Call call,
051                @NotNull JetType expectedType,
052                @NotNull DataFlowInfo dataFlowInfo,
053                @NotNull ContextDependency contextDependency,
054                @NotNull CheckValueArgumentsMode checkArguments,
055                @NotNull ResolutionResultsCache resolutionResultsCache,
056                @Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments,
057                @NotNull CallResolverExtension callResolverExtension,
058                @NotNull Collection<MutableResolvedCall<F>> resolvedCalls,
059                boolean isAnnotationContext,
060                boolean collectAllCandidates
061        ) {
062            super(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
063                  dataFlowInfoForArguments, callResolverExtension, isAnnotationContext, collectAllCandidates);
064            this.candidates = candidates;
065            this.resolvedCalls = resolvedCalls;
066            this.tracing = tracing;
067        }
068    
069        public ResolutionTask(
070                @NotNull Collection<ResolutionCandidate<D>> candidates,
071                @NotNull BasicCallResolutionContext context,
072                @NotNull TracingStrategy tracing
073        ) {
074            this(candidates, tracing,
075                 context.trace, context.scope, context.call,
076                 context.expectedType, context.dataFlowInfo, context.contextDependency, context.checkArguments,
077                 context.resolutionResultsCache, context.dataFlowInfoForArguments,
078                 context.callResolverExtension, Lists.<MutableResolvedCall<F>>newArrayList(), context.isAnnotationContext, context.collectAllCandidates);
079        }
080    
081        public ResolutionTask(
082                @NotNull Collection<ResolutionCandidate<D>> candidates,
083                @NotNull JetReferenceExpression reference,
084                @NotNull BasicCallResolutionContext context
085        ) {
086            this(candidates, context, TracingStrategyImpl.create(reference, context.call));
087        }
088    
089        @NotNull
090        public Collection<ResolutionCandidate<D>> getCandidates() {
091            return candidates;
092        }
093    
094        public void addResolvedCall(@NotNull MutableResolvedCall<F> resolvedCall) {
095            resolvedCalls.add(resolvedCall);
096        }
097    
098        @NotNull
099        public Collection<MutableResolvedCall<F>> getResolvedCalls() {
100            return resolvedCalls;
101        }
102    
103        public void setCheckingStrategy(DescriptorCheckStrategy strategy) {
104            checkingStrategy = strategy;
105        }
106    
107        public boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
108            if (checkingStrategy != null && !checkingStrategy.performAdvancedChecks(descriptor, trace, tracing)) {
109                return false;
110            }
111            return true;
112        }
113    
114        @Override
115        protected ResolutionTask<D, F> create(
116                @NotNull BindingTrace trace,
117                @NotNull JetScope scope,
118                @NotNull DataFlowInfo dataFlowInfo,
119                @NotNull JetType expectedType,
120                @NotNull ContextDependency contextDependency,
121                @NotNull ResolutionResultsCache resolutionResultsCache,
122                boolean collectAllCandidates
123        ) {
124            ResolutionTask<D, F> newTask = new ResolutionTask<D, F>(
125                    candidates, tracing, trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments,
126                    resolutionResultsCache, dataFlowInfoForArguments, callResolverExtension, resolvedCalls, isAnnotationContext,
127                    collectAllCandidates);
128            newTask.setCheckingStrategy(checkingStrategy);
129            return newTask;
130        }
131    
132        public ResolutionTask<D, F> replaceCall(@NotNull Call newCall) {
133            return new ResolutionTask<D, F>(
134                    candidates, tracing, trace, scope, newCall, expectedType, dataFlowInfo, contextDependency, checkArguments,
135                    resolutionResultsCache, dataFlowInfoForArguments, callResolverExtension, resolvedCalls,
136                    isAnnotationContext, collectAllCandidates);
137        }
138    
139        public interface DescriptorCheckStrategy {
140            <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing);
141        }
142    
143        @Override
144        public String toString() {
145            return candidates.toString();
146        }
147    }