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.context;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.jet.lang.resolve.BindingTrace;
022    import org.jetbrains.jet.lang.resolve.calls.CallResolverExtension;
023    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
024    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
025    import org.jetbrains.jet.lang.types.JetType;
026    import org.jetbrains.jet.lang.types.TypeUtils;
027    import org.jetbrains.jet.lang.types.expressions.LabelResolver;
028    
029    public abstract class ResolutionContext<Context extends ResolutionContext<Context>> {
030        public final BindingTrace trace;
031        public final JetScope scope;
032        public final JetType expectedType;
033        public final DataFlowInfo dataFlowInfo;
034        public final ContextDependency contextDependency;
035        public final ResolutionResultsCache resolutionResultsCache;
036        public final LabelResolver labelResolver;
037        public final CallResolverExtension callResolverExtension;
038        public final boolean isAnnotationContext;
039        public final boolean collectAllCandidates;
040    
041        protected ResolutionContext(
042                @NotNull BindingTrace trace,
043                @NotNull JetScope scope,
044                @NotNull JetType expectedType,
045                @NotNull DataFlowInfo dataFlowInfo,
046                @NotNull ContextDependency contextDependency,
047                @NotNull ResolutionResultsCache resolutionResultsCache,
048                @NotNull LabelResolver labelResolver,
049                @NotNull CallResolverExtension callResolverExtension,
050                boolean isAnnotationContext,
051                boolean collectAllCandidates
052        ) {
053            this.trace = trace;
054            this.scope = scope;
055            this.expectedType = expectedType;
056            this.dataFlowInfo = dataFlowInfo;
057            this.contextDependency = contextDependency;
058            this.resolutionResultsCache = resolutionResultsCache;
059            this.labelResolver = labelResolver;
060            this.callResolverExtension = callResolverExtension;
061            this.isAnnotationContext = isAnnotationContext;
062            this.collectAllCandidates = collectAllCandidates;
063        }
064    
065        protected abstract Context create(
066                @NotNull BindingTrace trace,
067                @NotNull JetScope scope,
068                @NotNull DataFlowInfo dataFlowInfo,
069                @NotNull JetType expectedType,
070                @NotNull ContextDependency contextDependency,
071                @NotNull ResolutionResultsCache resolutionResultsCache,
072                @NotNull LabelResolver labelResolver,
073                boolean collectAllCandidates
074        );
075    
076        @NotNull
077        private Context self() {
078            //noinspection unchecked
079            return (Context) this;
080        }
081    
082        @NotNull
083        public Context replaceBindingTrace(@NotNull BindingTrace trace) {
084            if (this.trace == trace) return self();
085            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, labelResolver, collectAllCandidates);
086        }
087    
088        @NotNull
089        public Context replaceDataFlowInfo(@NotNull DataFlowInfo newDataFlowInfo) {
090            if (newDataFlowInfo == dataFlowInfo) return self();
091            return create(trace, scope, newDataFlowInfo, expectedType, contextDependency, resolutionResultsCache, labelResolver, collectAllCandidates);
092        }
093    
094        @NotNull
095        public Context replaceExpectedType(@Nullable JetType newExpectedType) {
096            if (newExpectedType == null) return replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
097            if (expectedType == newExpectedType) return self();
098            return create(trace, scope, dataFlowInfo, newExpectedType, contextDependency, resolutionResultsCache, labelResolver, collectAllCandidates);
099        }
100    
101        @NotNull
102        public Context replaceScope(@NotNull JetScope newScope) {
103            if (newScope == scope) return self();
104            return create(trace, newScope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, labelResolver, collectAllCandidates);
105        }
106    
107        @NotNull
108        public Context replaceContextDependency(@NotNull ContextDependency newContextDependency) {
109            if (newContextDependency == contextDependency) return self();
110            return create(trace, scope, dataFlowInfo, expectedType, newContextDependency, resolutionResultsCache, labelResolver, collectAllCandidates);
111        }
112    
113        @NotNull
114        public Context replaceResolutionResultsCache(@NotNull ResolutionResultsCache newResolutionResultsCache) {
115            if (newResolutionResultsCache == resolutionResultsCache) return self();
116            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, newResolutionResultsCache, labelResolver, collectAllCandidates);
117        }
118    
119        @NotNull
120        public Context replaceTraceAndCache(@NotNull TemporaryTraceAndCache traceAndCache) {
121            return replaceBindingTrace(traceAndCache.trace).replaceResolutionResultsCache(traceAndCache.cache);
122        }
123    
124        @NotNull
125        public Context replaceCollectAllCandidates(boolean newCollectAllCandidates) {
126            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, labelResolver, newCollectAllCandidates);
127        }
128    }