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.types.expressions;
018
019 import com.intellij.psi.tree.IElementType;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
023 import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
024 import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
025 import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
026 import org.jetbrains.kotlin.lexer.KtTokens;
027 import org.jetbrains.kotlin.psi.*;
028 import org.jetbrains.kotlin.resolve.*;
029 import org.jetbrains.kotlin.resolve.calls.context.ContextDependency;
030 import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
031 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
032 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
033 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
034 import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
035 import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind;
036 import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
037 import org.jetbrains.kotlin.types.ErrorUtils;
038 import org.jetbrains.kotlin.types.KotlinType;
039 import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
040
041 import java.util.Iterator;
042 import java.util.List;
043
044 import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
045 import static org.jetbrains.kotlin.types.TypeUtils.UNIT_EXPECTED_TYPE;
046 import static org.jetbrains.kotlin.types.expressions.CoercionStrategy.COERCION_TO_UNIT;
047
048 public class ExpressionTypingServices {
049
050 private final ExpressionTypingFacade expressionTypingFacade;
051 private final ExpressionTypingComponents expressionTypingComponents;
052
053 @NotNull private final AnnotationChecker annotationChecker;
054 @NotNull private final StatementFilter statementFilter;
055
056 public ExpressionTypingServices(
057 @NotNull ExpressionTypingComponents components,
058 @NotNull AnnotationChecker annotationChecker,
059 @NotNull StatementFilter statementFilter,
060 @NotNull ExpressionTypingVisitorDispatcher.ForDeclarations facade
061 ) {
062 this.expressionTypingComponents = components;
063 this.annotationChecker = annotationChecker;
064 this.statementFilter = statementFilter;
065 this.expressionTypingFacade = facade;
066 }
067
068 @NotNull public StatementFilter getStatementFilter() {
069 return statementFilter;
070 }
071
072 @NotNull
073 public KotlinType safeGetType(
074 @NotNull LexicalScope scope,
075 @NotNull KtExpression expression,
076 @NotNull KotlinType expectedType,
077 @NotNull DataFlowInfo dataFlowInfo,
078 @NotNull BindingTrace trace
079 ) {
080 KotlinType type = getType(scope, expression, expectedType, dataFlowInfo, trace);
081
082 return type != null ? type : ErrorUtils.createErrorType("Type for " + expression.getText());
083 }
084
085 @NotNull
086 public KotlinTypeInfo getTypeInfo(
087 @NotNull LexicalScope scope,
088 @NotNull KtExpression expression,
089 @NotNull KotlinType expectedType,
090 @NotNull DataFlowInfo dataFlowInfo,
091 @NotNull BindingTrace trace,
092 boolean isStatement
093 ) {
094 ExpressionTypingContext context = ExpressionTypingContext.newContext(
095 trace, scope, dataFlowInfo, expectedType
096 );
097 return expressionTypingFacade.getTypeInfo(expression, context, isStatement);
098 }
099
100 @NotNull
101 public KotlinTypeInfo getTypeInfo(@NotNull KtExpression expression, @NotNull ResolutionContext resolutionContext) {
102 return expressionTypingFacade.getTypeInfo(expression, ExpressionTypingContext.newContext(resolutionContext));
103 }
104
105 @Nullable
106 public KotlinType getType(
107 @NotNull LexicalScope scope,
108 @NotNull KtExpression expression,
109 @NotNull KotlinType expectedType,
110 @NotNull DataFlowInfo dataFlowInfo,
111 @NotNull BindingTrace trace
112 ) {
113 return getTypeInfo(scope, expression, expectedType, dataFlowInfo, trace, false).getType();
114 }
115
116 /////////////////////////////////////////////////////////
117
118 public void checkFunctionReturnType(
119 @NotNull LexicalScope functionInnerScope,
120 @NotNull KtDeclarationWithBody function,
121 @NotNull FunctionDescriptor functionDescriptor,
122 @NotNull DataFlowInfo dataFlowInfo,
123 @Nullable KotlinType expectedReturnType,
124 BindingTrace trace
125 ) {
126 if (expectedReturnType == null) {
127 expectedReturnType = functionDescriptor.getReturnType();
128 if (!function.hasBlockBody() && !function.hasDeclaredReturnType()) {
129 expectedReturnType = NO_EXPECTED_TYPE;
130 }
131 }
132 checkFunctionReturnType(function, ExpressionTypingContext.newContext(
133 trace,
134 functionInnerScope, dataFlowInfo, expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE
135 ));
136 }
137
138 /*package*/ void checkFunctionReturnType(KtDeclarationWithBody function, ExpressionTypingContext context) {
139 KtExpression bodyExpression = function.getBodyExpression();
140 if (bodyExpression == null) return;
141
142 boolean blockBody = function.hasBlockBody();
143 ExpressionTypingContext newContext =
144 blockBody
145 ? context.replaceExpectedType(NO_EXPECTED_TYPE)
146 : context;
147
148 expressionTypingFacade.getTypeInfo(bodyExpression, newContext, blockBody);
149 }
150
151 @NotNull
152 public KotlinTypeInfo getBlockReturnedType(KtBlockExpression expression, ExpressionTypingContext context, boolean isStatement) {
153 return getBlockReturnedType(expression, isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION, context);
154 }
155
156 @NotNull
157 public KotlinTypeInfo getBlockReturnedType(
158 @NotNull KtBlockExpression expression,
159 @NotNull CoercionStrategy coercionStrategyForLastExpression,
160 @NotNull ExpressionTypingContext context
161 ) {
162 List<KtExpression> block = StatementFilterKt.filterStatements(statementFilter, expression);
163
164 DeclarationDescriptor containingDescriptor = context.scope.getOwnerDescriptor();
165 LexicalWritableScope scope = new LexicalWritableScope(context.scope, containingDescriptor, false, null,
166 new TraceBasedRedeclarationHandler(context.trace), LexicalScopeKind.CODE_BLOCK);
167 scope.changeLockLevel(LexicalWritableScope.LockLevel.BOTH);
168
169 KotlinTypeInfo r;
170 if (block.isEmpty()) {
171 r = expressionTypingComponents.dataFlowAnalyzer
172 .createCheckedTypeInfo(expressionTypingComponents.builtIns.getUnitType(), context, expression);
173 }
174 else {
175 r = getBlockReturnedTypeWithWritableScope(scope, block, coercionStrategyForLastExpression,
176 context.replaceStatementFilter(statementFilter));
177 }
178 scope.changeLockLevel(LexicalWritableScope.LockLevel.READING);
179
180 if (containingDescriptor instanceof ScriptDescriptor) {
181 context.trace.record(BindingContext.SCRIPT_SCOPE, (ScriptDescriptor) containingDescriptor, scope);
182 }
183
184 return r;
185 }
186
187 @NotNull
188 public KotlinType getBodyExpressionType(
189 @NotNull BindingTrace trace,
190 @NotNull LexicalScope outerScope,
191 @NotNull DataFlowInfo dataFlowInfo,
192 @NotNull KtDeclarationWithBody function,
193 @NotNull FunctionDescriptor functionDescriptor
194 ) {
195 KtExpression bodyExpression = function.getBodyExpression();
196 assert bodyExpression != null;
197 LexicalScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
198
199 ExpressionTypingContext context = ExpressionTypingContext.newContext(
200 trace, functionInnerScope, dataFlowInfo, NO_EXPECTED_TYPE
201 );
202 KotlinTypeInfo typeInfo = expressionTypingFacade.getTypeInfo(bodyExpression, context, function.hasBlockBody());
203
204 KotlinType type = typeInfo.getType();
205 if (type != null) {
206 return type;
207 }
208 else {
209 return ErrorUtils.createErrorType("Error function type");
210 }
211 }
212
213 /**
214 * Visits block statements propagating data flow information from the first to the last.
215 * Determines block returned type and data flow information at the end of the block AND
216 * at the nearest jump point from the block beginning.
217 */
218 /*package*/ KotlinTypeInfo getBlockReturnedTypeWithWritableScope(
219 @NotNull LexicalWritableScope scope,
220 @NotNull List<? extends KtElement> block,
221 @NotNull CoercionStrategy coercionStrategyForLastExpression,
222 @NotNull ExpressionTypingContext context
223 ) {
224 if (block.isEmpty()) {
225 return TypeInfoFactoryKt.createTypeInfo(expressionTypingComponents.builtIns.getUnitType(), context);
226 }
227
228 ExpressionTypingInternals blockLevelVisitor = new ExpressionTypingVisitorDispatcher.ForBlock(
229 expressionTypingComponents, annotationChecker, scope);
230 ExpressionTypingContext newContext = context.replaceScope(scope).replaceExpectedType(NO_EXPECTED_TYPE);
231
232 KotlinTypeInfo result = TypeInfoFactoryKt.noTypeInfo(context);
233 // Jump point data flow info
234 DataFlowInfo beforeJumpInfo = newContext.dataFlowInfo;
235 boolean jumpOutPossible = false;
236 for (Iterator<? extends KtElement> iterator = block.iterator(); iterator.hasNext(); ) {
237 KtElement statement = iterator.next();
238 if (!(statement instanceof KtExpression)) {
239 continue;
240 }
241 KtExpression statementExpression = (KtExpression) statement;
242 if (!iterator.hasNext()) {
243 result = getTypeOfLastExpressionInBlock(
244 statementExpression, newContext.replaceExpectedType(context.expectedType), coercionStrategyForLastExpression,
245 blockLevelVisitor);
246 if (result.getType() != null && statementExpression.getParent() instanceof KtBlockExpression) {
247 DataFlowValue lastExpressionValue = DataFlowValueFactory.createDataFlowValue(
248 statementExpression, result.getType(), context);
249 DataFlowValue blockExpressionValue = DataFlowValueFactory.createDataFlowValue(
250 (KtBlockExpression) statementExpression.getParent(), result.getType(), context);
251 result = result.replaceDataFlowInfo(result.getDataFlowInfo().assign(blockExpressionValue, lastExpressionValue));
252 }
253 }
254 else {
255 result = blockLevelVisitor
256 .getTypeInfo(statementExpression, newContext.replaceContextDependency(ContextDependency.INDEPENDENT), true);
257 }
258
259 DataFlowInfo newDataFlowInfo = result.getDataFlowInfo();
260 // If jump is not possible, we take new data flow info before jump
261 if (!jumpOutPossible) {
262 beforeJumpInfo = result.getJumpFlowInfo();
263 jumpOutPossible = result.getJumpOutPossible();
264 }
265 if (newDataFlowInfo != context.dataFlowInfo) {
266 newContext = newContext.replaceDataFlowInfo(newDataFlowInfo);
267 // We take current data flow info if jump there is not possible
268 }
269 blockLevelVisitor = new ExpressionTypingVisitorDispatcher.ForBlock(expressionTypingComponents, annotationChecker, scope);
270 }
271 return result.replaceJumpOutPossible(jumpOutPossible).replaceJumpFlowInfo(beforeJumpInfo);
272 }
273
274 private KotlinTypeInfo getTypeOfLastExpressionInBlock(
275 @NotNull KtExpression statementExpression,
276 @NotNull ExpressionTypingContext context,
277 @NotNull CoercionStrategy coercionStrategyForLastExpression,
278 @NotNull ExpressionTypingInternals blockLevelVisitor
279 ) {
280 if (context.expectedType != NO_EXPECTED_TYPE) {
281 KotlinType expectedType;
282 if (context.expectedType == UNIT_EXPECTED_TYPE ||//the first check is necessary to avoid invocation 'isUnit(UNIT_EXPECTED_TYPE)'
283 (coercionStrategyForLastExpression == COERCION_TO_UNIT && KotlinBuiltIns.isUnit(context.expectedType))) {
284 expectedType = UNIT_EXPECTED_TYPE;
285 }
286 else {
287 expectedType = context.expectedType;
288 }
289
290 return blockLevelVisitor.getTypeInfo(statementExpression, context.replaceExpectedType(expectedType), true);
291 }
292 KotlinTypeInfo result = blockLevelVisitor.getTypeInfo(statementExpression, context, true);
293 if (coercionStrategyForLastExpression == COERCION_TO_UNIT) {
294 boolean mightBeUnit = false;
295 if (statementExpression instanceof KtDeclaration) {
296 mightBeUnit = true;
297 }
298 if (statementExpression instanceof KtBinaryExpression) {
299 KtBinaryExpression binaryExpression = (KtBinaryExpression) statementExpression;
300 IElementType operationType = binaryExpression.getOperationToken();
301 //noinspection SuspiciousMethodCalls
302 if (operationType == KtTokens.EQ || OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
303 mightBeUnit = true;
304 }
305 }
306 if (mightBeUnit) {
307 // ExpressionTypingVisitorForStatements should return only null or Unit for declarations and assignments,
308 // but (for correct assignment / initialization analysis) data flow info must be preserved
309 assert result.getType() == null || KotlinBuiltIns.isUnit(result.getType());
310 result = result.replaceType(expressionTypingComponents.builtIns.getUnitType());
311 }
312 }
313 return result;
314 }
315
316 }