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 ExpressionPosition expressionPosition;
035        public final ContextDependency contextDependency;
036        public final ResolutionResultsCache resolutionResultsCache;
037        public final LabelResolver labelResolver;
038        public final CallResolverExtension callResolverExtension;
039    
040        protected ResolutionContext(
041                @NotNull BindingTrace trace,
042                @NotNull JetScope scope,
043                @NotNull JetType expectedType,
044                @NotNull DataFlowInfo dataFlowInfo,
045                @NotNull ExpressionPosition expressionPosition,
046                @NotNull ContextDependency contextDependency,
047                @NotNull ResolutionResultsCache resolutionResultsCache,
048                @NotNull LabelResolver labelResolver,
049                @NotNull CallResolverExtension callResolverExtension
050        ) {
051            this.trace = trace;
052            this.scope = scope;
053            this.expectedType = expectedType;
054            this.dataFlowInfo = dataFlowInfo;
055            this.expressionPosition = expressionPosition;
056            this.contextDependency = contextDependency;
057            this.resolutionResultsCache = resolutionResultsCache;
058            this.labelResolver = labelResolver;
059            this.callResolverExtension = callResolverExtension;
060        }
061    
062        protected abstract Context create(
063                @NotNull BindingTrace trace,
064                @NotNull JetScope scope,
065                @NotNull DataFlowInfo dataFlowInfo,
066                @NotNull JetType expectedType,
067                @NotNull ExpressionPosition expressionPosition,
068                @NotNull ContextDependency contextDependency,
069                @NotNull ResolutionResultsCache resolutionResultsCache,
070                @NotNull LabelResolver labelResolver
071        );
072        
073        protected abstract Context self();
074        
075        public Context replaceBindingTrace(@NotNull BindingTrace trace) {
076            if (this.trace == trace) return self();
077            return create(trace, scope, dataFlowInfo, expectedType, expressionPosition, contextDependency, resolutionResultsCache,
078                          labelResolver);
079        }
080    
081        @NotNull
082        public Context replaceExpressionPosition(@NotNull ExpressionPosition expressionPosition) {
083            if (expressionPosition == this.expressionPosition) return self();
084            return create(trace, scope, dataFlowInfo, expectedType, expressionPosition, contextDependency, resolutionResultsCache,
085                          labelResolver);
086        }
087    
088        @NotNull
089        public Context replaceDataFlowInfo(@NotNull DataFlowInfo newDataFlowInfo) {
090            if (newDataFlowInfo == dataFlowInfo) return self();
091            return create(trace, scope, newDataFlowInfo, expectedType, expressionPosition, contextDependency, resolutionResultsCache,
092                          labelResolver);
093        }
094    
095        @NotNull
096        public Context replaceExpectedType(@Nullable JetType newExpectedType) {
097            if (newExpectedType == null) return replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
098            if (expectedType == newExpectedType) return self();
099            return create(trace, scope, dataFlowInfo, newExpectedType, expressionPosition, contextDependency, resolutionResultsCache,
100                          labelResolver);
101        }
102    
103        @NotNull
104        public Context replaceScope(@NotNull JetScope newScope) {
105            if (newScope == scope) return self();
106            return create(trace, newScope, dataFlowInfo, expectedType, expressionPosition, contextDependency, resolutionResultsCache,
107                          labelResolver);
108        }
109    
110        @NotNull
111        public Context replaceContextDependency(@NotNull ContextDependency newContextDependency) {
112            if (newContextDependency == contextDependency) return self();
113            return create(trace, scope, dataFlowInfo, expectedType, expressionPosition, newContextDependency, resolutionResultsCache,
114                          labelResolver);
115        }
116    
117        @NotNull
118        public Context replaceResolutionResultsCache(@NotNull ResolutionResultsCache newResolutionResultsCache) {
119            if (newResolutionResultsCache == resolutionResultsCache) return self();
120            return create(trace, scope, dataFlowInfo, expectedType, expressionPosition, contextDependency, newResolutionResultsCache,
121                          labelResolver);
122        }
123    
124        public Context replaceTraceAndCache(@NotNull TemporaryTraceAndCache traceAndCache) {
125            return replaceBindingTrace(traceAndCache.trace).replaceResolutionResultsCache(traceAndCache.cache);
126        }
127    }