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.autocasts.DataFlowInfo;
023    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
024    import org.jetbrains.jet.lang.types.JetType;
025    import org.jetbrains.jet.lang.types.TypeUtils;
026    
027    public abstract class ResolutionContext<Context extends ResolutionContext> {
028        public final BindingTrace trace;
029        public final JetScope scope;
030        public final JetType expectedType;
031        public final DataFlowInfo dataFlowInfo;
032        public final ExpressionPosition expressionPosition;
033    
034        protected ResolutionContext(
035                @NotNull BindingTrace trace,
036                @NotNull JetScope scope,
037                @NotNull JetType expectedType,
038                @NotNull DataFlowInfo dataFlowInfo,
039                @NotNull ExpressionPosition expressionPosition
040        ) {
041            this.trace = trace;
042            this.scope = scope;
043            this.expectedType = expectedType;
044            this.dataFlowInfo = dataFlowInfo;
045            this.expressionPosition = expressionPosition;
046        }
047    
048        protected abstract Context create(
049                @NotNull BindingTrace trace,
050                @NotNull JetScope scope,
051                @NotNull DataFlowInfo dataFlowInfo,
052                @NotNull JetType expectedType,
053                @NotNull ExpressionPosition expressionPosition
054        );
055        
056        protected abstract Context self();
057        
058        public Context replaceBindingTrace(@NotNull BindingTrace trace) {
059            if (this.trace == trace) return self();
060            return create(trace, scope, dataFlowInfo, expectedType, expressionPosition);
061        }
062        
063        @NotNull
064        public Context replaceExpressionPosition(@NotNull ExpressionPosition expressionPosition) {
065            if (expressionPosition == this.expressionPosition) return self();
066            return create(trace, scope, dataFlowInfo, expectedType, expressionPosition);
067        }
068    
069        @NotNull
070        public Context replaceDataFlowInfo(@NotNull DataFlowInfo newDataFlowInfo) {
071            if (newDataFlowInfo == dataFlowInfo) return self();
072            return create(trace, scope, newDataFlowInfo, expectedType, expressionPosition);
073        }
074    
075        @NotNull
076        public Context replaceExpectedType(@Nullable JetType newExpectedType) {
077            if (newExpectedType == null) return replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
078            if (expectedType == newExpectedType) return self();
079            return create(trace, scope, dataFlowInfo, newExpectedType, expressionPosition);
080        }
081    
082        @NotNull
083        public Context replaceScope(@NotNull JetScope newScope) {
084            if (newScope == scope) return self();
085            return create(trace, newScope, dataFlowInfo, expectedType, expressionPosition);
086        }
087    }