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.Sets;
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.autocasts.DataFlowInfo;
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.ResolvedCallWithTrace;
030    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
031    import org.jetbrains.jet.lang.types.JetType;
032    import org.jetbrains.jet.lang.types.expressions.LabelResolver;
033    
034    import java.util.Collection;
035    import java.util.Set;
036    
037    /**
038     * Stores candidates for call resolution.
039     */
040    public class ResolutionTask<D extends CallableDescriptor, F extends D> extends CallResolutionContext<ResolutionTask<D, F>> {
041        private final Collection<ResolutionCandidate<D>> candidates;
042        private final Set<ResolvedCallWithTrace<F>> resolvedCalls = Sets.newLinkedHashSet();
043        private DescriptorCheckStrategy checkingStrategy;
044        public final JetReferenceExpression reference;
045        public final TracingStrategy tracing;
046    
047        public ResolutionTask(
048                @NotNull Collection<ResolutionCandidate<D>> candidates, @NotNull JetReferenceExpression reference,
049                @NotNull TracingStrategy tracing, BindingTrace trace, JetScope scope, Call call, JetType expectedType,
050                DataFlowInfo dataFlowInfo, ContextDependency contextDependency, CheckValueArgumentsMode checkArguments,
051                ExpressionPosition expressionPosition, ResolutionResultsCache resolutionResultsCache,
052                @NotNull LabelResolver labelResolver, @Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments
053        ) {
054            super(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, expressionPosition, resolutionResultsCache,
055                  labelResolver, dataFlowInfoForArguments);
056            this.candidates = candidates;
057            this.reference = reference;
058            this.tracing = tracing;
059        }
060    
061        public ResolutionTask(
062                @NotNull Collection<ResolutionCandidate<D>> candidates,
063                @NotNull JetReferenceExpression reference,
064                @NotNull BasicCallResolutionContext context,
065                @Nullable TracingStrategy tracing
066        ) {
067            this(candidates, reference, tracing != null ? tracing : TracingStrategyImpl.create(reference, context.call),
068                 context.trace, context.scope, context.call,
069                 context.expectedType, context.dataFlowInfo, context.contextDependency, context.checkArguments,
070                 context.expressionPosition, context.resolutionResultsCache, context.labelResolver, context.dataFlowInfoForArguments);
071        }
072    
073        public ResolutionTask(
074                @NotNull Collection<ResolutionCandidate<D>> candidates,
075                @NotNull JetReferenceExpression reference,
076                @NotNull BasicCallResolutionContext context
077        ) {
078            this(candidates, reference, context, null);
079        }
080    
081        @NotNull
082        public Collection<ResolutionCandidate<D>> getCandidates() {
083            return candidates;
084        }
085    
086        @NotNull
087        public Set<ResolvedCallWithTrace<F>> getResolvedCalls() {
088            return resolvedCalls;
089        }
090    
091        public void setCheckingStrategy(DescriptorCheckStrategy strategy) {
092            checkingStrategy = strategy;
093        }
094    
095        public boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
096            if (checkingStrategy != null && !checkingStrategy.performAdvancedChecks(descriptor, trace, tracing)) {
097                return false;
098            }
099            return true;
100        }
101    
102        @Override
103        protected ResolutionTask<D, F> create(
104                @NotNull BindingTrace trace,
105                @NotNull JetScope scope,
106                @NotNull DataFlowInfo dataFlowInfo,
107                @NotNull JetType expectedType,
108                @NotNull ExpressionPosition expressionPosition,
109                @NotNull ContextDependency contextDependency,
110                @NotNull ResolutionResultsCache resolutionResultsCache,
111                @NotNull LabelResolver labelResolver
112        ) {
113            ResolutionTask<D, F> newTask = new ResolutionTask<D, F>(
114                    candidates, reference, tracing, trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments,
115                    expressionPosition, resolutionResultsCache, labelResolver, dataFlowInfoForArguments);
116            newTask.setCheckingStrategy(checkingStrategy);
117            return newTask;
118        }
119    
120        @Override
121        protected ResolutionTask<D, F> self() {
122            return this;
123        }
124    
125        public ResolutionTask<D, F> replaceCall(@NotNull Call newCall) {
126            return new ResolutionTask<D, F>(
127                    candidates, reference, tracing, trace, scope, newCall, expectedType, dataFlowInfo, contextDependency, checkArguments,
128                    expressionPosition, resolutionResultsCache, labelResolver, dataFlowInfoForArguments);
129        }
130    
131        public interface DescriptorCheckStrategy {
132            <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing);
133        }
134    
135        @Override
136        public String toString() {
137            return candidates.toString();
138        }
139    }