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