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 TracingStrategy tracing;
046    
047        public ResolutionTask(
048                @NotNull Collection<ResolutionCandidate<D>> candidates,
049                @NotNull TracingStrategy tracing, BindingTrace trace, JetScope scope, Call call, JetType expectedType,
050                DataFlowInfo dataFlowInfo, ContextDependency contextDependency, CheckValueArgumentsMode checkArguments,
051                ResolutionResultsCache resolutionResultsCache, @NotNull LabelResolver labelResolver,
052                @Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments, @NotNull CallResolverExtension callResolverExtension,
053                boolean isAnnotationContext
054        ) {
055            super(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
056                  labelResolver, dataFlowInfoForArguments, callResolverExtension, isAnnotationContext);
057            this.candidates = candidates;
058            this.tracing = tracing;
059        }
060    
061        public ResolutionTask(
062                @NotNull Collection<ResolutionCandidate<D>> candidates,
063                @NotNull BasicCallResolutionContext context,
064                @NotNull TracingStrategy tracing
065        ) {
066            this(candidates, tracing,
067                 context.trace, context.scope, context.call,
068                 context.expectedType, context.dataFlowInfo, context.contextDependency, context.checkArguments,
069                 context.resolutionResultsCache, context.labelResolver, context.dataFlowInfoForArguments,
070                 context.callResolverExtension, context.isAnnotationContext);
071        }
072    
073        public ResolutionTask(
074                @NotNull Collection<ResolutionCandidate<D>> candidates,
075                @NotNull JetReferenceExpression reference,
076                @NotNull BasicCallResolutionContext context
077        ) {
078            this(candidates, context, TracingStrategyImpl.create(reference, context.call));
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 ContextDependency contextDependency,
109                @NotNull ResolutionResultsCache resolutionResultsCache,
110                @NotNull LabelResolver labelResolver
111        ) {
112            ResolutionTask<D, F> newTask = new ResolutionTask<D, F>(
113                    candidates, tracing, trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments,
114                    resolutionResultsCache, labelResolver, dataFlowInfoForArguments, callResolverExtension, isAnnotationContext);
115            newTask.setCheckingStrategy(checkingStrategy);
116            return newTask;
117        }
118    
119        public ResolutionTask<D, F> replaceCall(@NotNull Call newCall) {
120            return new ResolutionTask<D, F>(
121                    candidates, tracing, trace, scope, newCall, expectedType, dataFlowInfo, contextDependency, checkArguments,
122                    resolutionResultsCache, labelResolver, dataFlowInfoForArguments, callResolverExtension, isAnnotationContext);
123        }
124    
125        public interface DescriptorCheckStrategy {
126            <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing);
127        }
128    
129        @Override
130        public String toString() {
131            return candidates.toString();
132        }
133    }