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 // True if we are inside call chain like x?.foo()!!.bar()?.gav() 058 public final boolean insideCallChain; 059 060 protected ResolutionContext( 061 @NotNull BindingTrace trace, 062 @NotNull LexicalScope scope, 063 @NotNull KotlinType expectedType, 064 @NotNull DataFlowInfo dataFlowInfo, 065 @NotNull ContextDependency contextDependency, 066 @NotNull ResolutionResultsCache resolutionResultsCache, 067 @NotNull CallChecker callChecker, 068 @NotNull StatementFilter statementFilter, 069 boolean isAnnotationContext, 070 boolean collectAllCandidates, 071 boolean insideCallChain 072 ) { 073 this.trace = trace; 074 this.scope = scope; 075 this.expectedType = expectedType; 076 this.dataFlowInfo = dataFlowInfo; 077 this.contextDependency = contextDependency; 078 this.resolutionResultsCache = resolutionResultsCache; 079 this.callChecker = callChecker; 080 this.statementFilter = statementFilter; 081 this.isAnnotationContext = isAnnotationContext; 082 this.collectAllCandidates = collectAllCandidates; 083 this.insideCallChain = insideCallChain; 084 } 085 086 protected abstract Context create( 087 @NotNull BindingTrace trace, 088 @NotNull LexicalScope scope, 089 @NotNull DataFlowInfo dataFlowInfo, 090 @NotNull KotlinType expectedType, 091 @NotNull ContextDependency contextDependency, 092 @NotNull ResolutionResultsCache resolutionResultsCache, 093 @NotNull StatementFilter statementFilter, 094 boolean collectAllCandidates, 095 boolean insideSafeCallChain 096 ); 097 098 @NotNull 099 private Context self() { 100 //noinspection unchecked 101 return (Context) this; 102 } 103 104 @NotNull 105 public Context replaceBindingTrace(@NotNull BindingTrace trace) { 106 if (this.trace == trace) return self(); 107 return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter, 108 collectAllCandidates, insideCallChain); 109 } 110 111 @NotNull 112 public Context replaceDataFlowInfo(@NotNull DataFlowInfo newDataFlowInfo) { 113 if (newDataFlowInfo == dataFlowInfo) return self(); 114 return create(trace, scope, newDataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter, 115 collectAllCandidates, insideCallChain); 116 } 117 118 @NotNull 119 public Context replaceExpectedType(@Nullable KotlinType newExpectedType) { 120 if (newExpectedType == null) return replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE); 121 if (expectedType == newExpectedType) return self(); 122 return create(trace, scope, dataFlowInfo, newExpectedType, contextDependency, resolutionResultsCache, statementFilter, 123 collectAllCandidates, insideCallChain); 124 } 125 126 @NotNull 127 public Context replaceScope(@NotNull LexicalScope newScope) { 128 if (newScope == scope) return self(); 129 return create(trace, newScope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter, 130 collectAllCandidates, insideCallChain); 131 } 132 133 @NotNull 134 public Context replaceContextDependency(@NotNull ContextDependency newContextDependency) { 135 if (newContextDependency == contextDependency) return self(); 136 return create(trace, scope, dataFlowInfo, expectedType, newContextDependency, resolutionResultsCache, statementFilter, 137 collectAllCandidates, insideCallChain); 138 } 139 140 @NotNull 141 public Context replaceResolutionResultsCache(@NotNull ResolutionResultsCache newResolutionResultsCache) { 142 if (newResolutionResultsCache == resolutionResultsCache) return self(); 143 return create(trace, scope, dataFlowInfo, expectedType, contextDependency, newResolutionResultsCache, statementFilter, 144 collectAllCandidates, insideCallChain); 145 } 146 147 @NotNull 148 public Context replaceTraceAndCache(@NotNull TemporaryTraceAndCache traceAndCache) { 149 return replaceBindingTrace(traceAndCache.trace).replaceResolutionResultsCache(traceAndCache.cache); 150 } 151 152 @NotNull 153 public Context replaceCollectAllCandidates(boolean newCollectAllCandidates) { 154 return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter, 155 newCollectAllCandidates, insideCallChain); 156 } 157 158 @NotNull 159 public Context replaceStatementFilter(@NotNull StatementFilter statementFilter) { 160 return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter, 161 collectAllCandidates, insideCallChain); 162 } 163 164 @NotNull 165 public Context replaceInsideCallChain(boolean insideSafeCallChain) { 166 return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter, 167 collectAllCandidates, insideSafeCallChain); 168 169 } 170 }