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