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