001    /*
002     * Copyright 2010-2015 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.kotlin.resolve.calls.context;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.kotlin.resolve.BindingTrace;
022    import org.jetbrains.kotlin.resolve.StatementFilter;
023    import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker;
024    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
025    import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
026    import org.jetbrains.kotlin.types.KotlinType;
027    import org.jetbrains.kotlin.types.TypeUtils;
028    
029    /**
030     * This class together with its descendants is intended to transfer data flow analysis information
031     * in top-down direction, from AST parents to children.
032     *
033     * NB: all descendants must be immutable!
034     */
035    public abstract class ResolutionContext<Context extends ResolutionContext<Context>> {
036        @NotNull
037        public final BindingTrace trace;
038        @NotNull
039        public final LexicalScope scope;
040        @NotNull
041        public final KotlinType expectedType;
042        @NotNull
043        public final DataFlowInfo dataFlowInfo;
044        @NotNull
045        public final ContextDependency contextDependency;
046        @NotNull
047        public final ResolutionResultsCache resolutionResultsCache;
048        @NotNull
049        public final CallChecker callChecker;
050        @NotNull
051        public final StatementFilter statementFilter;
052    
053        public final boolean isAnnotationContext;
054    
055        public final boolean collectAllCandidates;
056    
057        protected ResolutionContext(
058                @NotNull BindingTrace trace,
059                @NotNull LexicalScope scope,
060                @NotNull KotlinType expectedType,
061                @NotNull DataFlowInfo dataFlowInfo,
062                @NotNull ContextDependency contextDependency,
063                @NotNull ResolutionResultsCache resolutionResultsCache,
064                @NotNull CallChecker callChecker,
065                @NotNull StatementFilter statementFilter,
066                boolean isAnnotationContext,
067                boolean collectAllCandidates
068        ) {
069            this.trace = trace;
070            this.scope = scope;
071            this.expectedType = expectedType;
072            this.dataFlowInfo = dataFlowInfo;
073            this.contextDependency = contextDependency;
074            this.resolutionResultsCache = resolutionResultsCache;
075            this.callChecker = callChecker;
076            this.statementFilter = statementFilter;
077            this.isAnnotationContext = isAnnotationContext;
078            this.collectAllCandidates = collectAllCandidates;
079        }
080    
081        protected abstract Context create(
082                @NotNull BindingTrace trace,
083                @NotNull LexicalScope scope,
084                @NotNull DataFlowInfo dataFlowInfo,
085                @NotNull KotlinType expectedType,
086                @NotNull ContextDependency contextDependency,
087                @NotNull ResolutionResultsCache resolutionResultsCache,
088                @NotNull StatementFilter statementFilter,
089                boolean collectAllCandidates
090        );
091    
092        @NotNull
093        private Context self() {
094            //noinspection unchecked
095            return (Context) this;
096        }
097    
098        @NotNull
099        public Context replaceBindingTrace(@NotNull BindingTrace trace) {
100            if (this.trace == trace) return self();
101            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
102                          collectAllCandidates);
103        }
104    
105        @NotNull
106        public Context replaceDataFlowInfo(@NotNull DataFlowInfo newDataFlowInfo) {
107            if (newDataFlowInfo == dataFlowInfo) return self();
108            return create(trace, scope, newDataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
109                          collectAllCandidates);
110        }
111    
112        @NotNull
113        public Context replaceExpectedType(@Nullable KotlinType newExpectedType) {
114            if (newExpectedType == null) return replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
115            if (expectedType == newExpectedType) return self();
116            return create(trace, scope, dataFlowInfo, newExpectedType, contextDependency, resolutionResultsCache, statementFilter,
117                          collectAllCandidates);
118        }
119    
120        @NotNull
121        public Context replaceScope(@NotNull LexicalScope newScope) {
122            if (newScope == scope) return self();
123            return create(trace, newScope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
124                          collectAllCandidates);
125        }
126    
127        @NotNull
128        public Context replaceContextDependency(@NotNull ContextDependency newContextDependency) {
129            if (newContextDependency == contextDependency) return self();
130            return create(trace, scope, dataFlowInfo, expectedType, newContextDependency, resolutionResultsCache, statementFilter,
131                          collectAllCandidates);
132        }
133    
134        @NotNull
135        public Context replaceResolutionResultsCache(@NotNull ResolutionResultsCache newResolutionResultsCache) {
136            if (newResolutionResultsCache == resolutionResultsCache) return self();
137            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, newResolutionResultsCache, statementFilter,
138                          collectAllCandidates);
139        }
140    
141        @NotNull
142        public Context replaceTraceAndCache(@NotNull TemporaryTraceAndCache traceAndCache) {
143            return replaceBindingTrace(traceAndCache.trace).replaceResolutionResultsCache(traceAndCache.cache);
144        }
145    
146        @NotNull
147        public Context replaceCollectAllCandidates(boolean newCollectAllCandidates) {
148            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
149                          newCollectAllCandidates);
150        }
151    
152        @NotNull
153        public Context replaceStatementFilter(@NotNull StatementFilter statementFilter) {
154            return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
155                          collectAllCandidates);
156        }
157    }