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.openapi.diagnostic.Logger;
020 import com.intellij.openapi.progress.ProcessCanceledException;
021 import kotlin.jvm.functions.Function0;
022 import org.jetbrains.annotations.NotNull;
023 import org.jetbrains.annotations.Nullable;
024 import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
025 import org.jetbrains.kotlin.diagnostics.Errors;
026 import org.jetbrains.kotlin.incremental.components.LookupTracker;
027 import org.jetbrains.kotlin.psi.*;
028 import org.jetbrains.kotlin.psi.codeFragmentUtil.CodeFragmentUtilKt;
029 import org.jetbrains.kotlin.resolve.AnnotationChecker;
030 import org.jetbrains.kotlin.resolve.BindingContext;
031 import org.jetbrains.kotlin.resolve.BindingContextUtils;
032 import org.jetbrains.kotlin.resolve.DeclarationsCheckerBuilder;
033 import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
034 import org.jetbrains.kotlin.resolve.calls.context.CallPosition;
035 import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind;
036 import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
037 import org.jetbrains.kotlin.types.DeferredType;
038 import org.jetbrains.kotlin.types.ErrorUtils;
039 import org.jetbrains.kotlin.types.KotlinType;
040 import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
041 import org.jetbrains.kotlin.util.KotlinFrontEndException;
042 import org.jetbrains.kotlin.util.LookupTrackerUtilKt;
043 import org.jetbrains.kotlin.util.PerformanceCounter;
044 import org.jetbrains.kotlin.util.ReenteringLazyValueComputationException;
045
046 import static org.jetbrains.kotlin.diagnostics.Errors.TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM;
047
048 public abstract class ExpressionTypingVisitorDispatcher extends KtVisitor<KotlinTypeInfo, ExpressionTypingContext>
049 implements ExpressionTypingInternals {
050
051 public static final PerformanceCounter typeInfoPerfCounter = PerformanceCounter.Companion.create("Type info", true);
052
053 private static final Logger LOG = Logger.getInstance(ExpressionTypingVisitor.class);
054
055 public static class ForDeclarations extends ExpressionTypingVisitorDispatcher {
056 public ForDeclarations(@NotNull ExpressionTypingComponents components, @NotNull AnnotationChecker annotationChecker) {
057 super(components, annotationChecker);
058 }
059
060 @Override
061 protected ExpressionTypingVisitorForStatements getStatementVisitor(@NotNull ExpressionTypingContext context) {
062 return createStatementVisitor(context);
063 }
064 }
065
066 protected abstract ExpressionTypingVisitorForStatements getStatementVisitor(@NotNull ExpressionTypingContext context);
067
068 public static class ForBlock extends ExpressionTypingVisitorDispatcher {
069
070 private final ExpressionTypingVisitorForStatements visitorForBlock;
071
072 public ForBlock(
073 @NotNull ExpressionTypingComponents components,
074 @NotNull AnnotationChecker annotationChecker,
075 @NotNull LexicalWritableScope writableScope
076 ) {
077 super(components, annotationChecker);
078 this.visitorForBlock = new ExpressionTypingVisitorForStatements(
079 this, writableScope, basic, controlStructures, patterns, functions
080 );
081 }
082
083 @Override
084 protected ExpressionTypingVisitorForStatements getStatementVisitor(@NotNull ExpressionTypingContext context) {
085 return visitorForBlock;
086 }
087 }
088
089 private final ExpressionTypingComponents components;
090 @NotNull private final AnnotationChecker annotationChecker;
091 protected final BasicExpressionTypingVisitor basic;
092 protected final FunctionsTypingVisitor functions;
093 protected final ControlStructureTypingVisitor controlStructures;
094 protected final PatternMatchingTypingVisitor patterns;
095 protected final DeclarationsCheckerBuilder declarationsCheckerBuilder;
096
097 private ExpressionTypingVisitorDispatcher(
098 @NotNull ExpressionTypingComponents components,
099 @NotNull AnnotationChecker annotationChecker
100 ) {
101 this.components = components;
102 this.annotationChecker = annotationChecker;
103 this.basic = new BasicExpressionTypingVisitor(this);
104 this.controlStructures = new ControlStructureTypingVisitor(this);
105 this.patterns = new PatternMatchingTypingVisitor(this);
106 this.functions = new FunctionsTypingVisitor(this);
107 this.declarationsCheckerBuilder = components.declarationsCheckerBuilder;
108 }
109
110 @Override
111 @NotNull
112 public ExpressionTypingComponents getComponents() {
113 return components;
114 }
115
116 @NotNull
117 @Override
118 public KotlinTypeInfo checkInExpression(
119 @NotNull KtElement callElement,
120 @NotNull KtSimpleNameExpression operationSign,
121 @NotNull ValueArgument leftArgument,
122 @Nullable KtExpression right,
123 @NotNull ExpressionTypingContext context
124 ) {
125 return basic.checkInExpression(callElement, operationSign, leftArgument, right, context);
126 }
127
128 @Override
129 @NotNull
130 public final KotlinTypeInfo safeGetTypeInfo(@NotNull KtExpression expression, ExpressionTypingContext context) {
131 KotlinTypeInfo typeInfo = getTypeInfo(expression, context);
132 if (typeInfo.getType() != null) {
133 return typeInfo;
134 }
135 return typeInfo
136 .replaceType(ErrorUtils.createErrorType("Type for " + expression.getText()))
137 .replaceDataFlowInfo(context.dataFlowInfo);
138 }
139
140 @Override
141 @NotNull
142 public final KotlinTypeInfo getTypeInfo(@NotNull KtExpression expression, ExpressionTypingContext context) {
143 KotlinTypeInfo result = getTypeInfo(expression, context, this);
144 annotationChecker.checkExpression(expression, context.trace);
145 return result;
146 }
147
148 @Override
149 @NotNull
150 public final KotlinTypeInfo getTypeInfo(@NotNull KtExpression expression, ExpressionTypingContext context, boolean isStatement) {
151 ExpressionTypingContext newContext = context;
152 if (CodeFragmentUtilKt.suppressDiagnosticsInDebugMode(expression)) {
153 newContext = ExpressionTypingContext.newContext(context, true);
154 }
155 if (!isStatement) return getTypeInfo(expression, newContext);
156 return getTypeInfo(expression, newContext, getStatementVisitor(newContext));
157 }
158
159 protected ExpressionTypingVisitorForStatements createStatementVisitor(ExpressionTypingContext context) {
160 return new ExpressionTypingVisitorForStatements(this,
161 ExpressionTypingUtils.newWritableScopeImpl(context, LexicalScopeKind.CODE_BLOCK, components.overloadChecker),
162 basic, controlStructures, patterns, functions);
163 }
164
165 @Override
166 public void checkStatementType(@NotNull KtExpression expression, ExpressionTypingContext context) {
167 expression.accept(createStatementVisitor(context), context);
168 }
169
170 @NotNull
171 private KotlinTypeInfo getTypeInfo(@NotNull final KtExpression expression, final ExpressionTypingContext context, final KtVisitor<KotlinTypeInfo, ExpressionTypingContext> visitor) {
172 return typeInfoPerfCounter.time(new Function0<KotlinTypeInfo>() {
173 @Override
174 public KotlinTypeInfo invoke() {
175 try {
176 KotlinTypeInfo recordedTypeInfo = BindingContextUtils.getRecordedTypeInfo(expression, context.trace.getBindingContext());
177 if (recordedTypeInfo != null) {
178 return recordedTypeInfo;
179 }
180
181 context.trace.record(BindingContext.DATA_FLOW_INFO_BEFORE, expression, context.dataFlowInfo);
182
183 KotlinTypeInfo result;
184 try {
185 result = expression.accept(visitor, context);
186 // Some recursive definitions (object expressions) must put their types in the cache manually:
187 //noinspection ConstantConditions
188 if (context.trace.get(BindingContext.PROCESSED, expression) == Boolean.TRUE) {
189 KotlinType type = context.trace.getBindingContext().getType(expression);
190 return result.replaceType(type);
191 }
192
193 if (result.getType() instanceof DeferredType) {
194 result = result.replaceType(((DeferredType) result.getType()).getDelegate());
195 }
196 context.trace.record(BindingContext.EXPRESSION_TYPE_INFO, expression, result);
197 }
198 catch (ReenteringLazyValueComputationException e) {
199 context.trace.report(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.on(expression));
200 result = TypeInfoFactoryKt.noTypeInfo(context);
201 }
202
203 context.trace.record(BindingContext.PROCESSED, expression);
204
205 // todo save scope before analyze and fix debugger: see CodeFragmentAnalyzer.correctContextForExpression
206 BindingContextUtilsKt.recordScope(context.trace, context.scope, expression);
207 BindingContextUtilsKt.recordDataFlowInfo(context.replaceDataFlowInfo(result.getDataFlowInfo()), expression);
208 try {
209 // Here we have to resolve some types, so the following exception is possible
210 // Example: val a = ::a, fun foo() = ::foo
211 recordTypeInfo(expression, result);
212 }
213 catch (ReenteringLazyValueComputationException e) {
214 context.trace.report(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.on(expression));
215 return TypeInfoFactoryKt.noTypeInfo(context);
216 }
217 return result;
218 }
219 catch (ProcessCanceledException e) {
220 throw e;
221 }
222 catch (KotlinFrontEndException e) {
223 throw e;
224 }
225 catch (Throwable e) {
226 context.trace.report(Errors.EXCEPTION_FROM_ANALYZER.on(expression, e));
227 logOrThrowException(expression, e);
228 return TypeInfoFactoryKt.createTypeInfo(
229 ErrorUtils.createErrorType(e.getClass().getSimpleName() + " from analyzer"),
230 context
231 );
232 }
233 }
234 });
235 }
236
237 private void recordTypeInfo(@NotNull KtExpression expression, @NotNull KotlinTypeInfo typeInfo) {
238 LookupTracker lookupTracker = getComponents().lookupTracker;
239 KotlinType resultType = typeInfo.getType();
240
241 if (resultType != null) {
242 LookupTrackerUtilKt.record(lookupTracker, expression, resultType);
243 }
244 }
245
246 private static void logOrThrowException(@NotNull KtExpression expression, Throwable e) {
247 try {
248 // This trows AssertionError in CLI and reports the error in the IDE
249 LOG.error(
250 "Exception while analyzing expression at " + DiagnosticUtils.atLocation(expression) + ":\n" + expression.getText() + "\n",
251 e
252 );
253 }
254 catch (AssertionError errorFromLogger) {
255 // If we ended up here, we are in CLI, and the initial exception needs to be rethrown,
256 // simply throwing AssertionError causes its being wrapped over and over again
257 throw new KotlinFrontEndException(errorFromLogger.getMessage(), e);
258 }
259 }
260
261 //////////////////////////////////////////////////////////////////////////////////////////////
262
263 @Override
264 public KotlinTypeInfo visitLambdaExpression(@NotNull KtLambdaExpression expression, ExpressionTypingContext data) {
265 // Erasing call position to unknown is necessary to prevent wrong call positions when type checking lambda's body
266 return functions.visitLambdaExpression(expression, data.replaceCallPosition(CallPosition.Unknown.INSTANCE));
267 }
268
269 @Override
270 public KotlinTypeInfo visitNamedFunction(@NotNull KtNamedFunction function, ExpressionTypingContext data) {
271 return functions.visitNamedFunction(function, data);
272 }
273
274 //////////////////////////////////////////////////////////////////////////////////////////////
275
276 @Override
277 public KotlinTypeInfo visitThrowExpression(@NotNull KtThrowExpression expression, ExpressionTypingContext data) {
278 return controlStructures.visitThrowExpression(expression, data);
279 }
280
281 @Override
282 public KotlinTypeInfo visitReturnExpression(@NotNull KtReturnExpression expression, ExpressionTypingContext data) {
283 return controlStructures.visitReturnExpression(expression, data);
284 }
285
286 @Override
287 public KotlinTypeInfo visitContinueExpression(@NotNull KtContinueExpression expression, ExpressionTypingContext data) {
288 return controlStructures.visitContinueExpression(expression, data);
289 }
290
291 @Override
292 public KotlinTypeInfo visitIfExpression(@NotNull KtIfExpression expression, ExpressionTypingContext data) {
293 return controlStructures.visitIfExpression(expression, data);
294 }
295
296 @Override
297 public KotlinTypeInfo visitTryExpression(@NotNull KtTryExpression expression, ExpressionTypingContext data) {
298 return controlStructures.visitTryExpression(expression, data);
299 }
300
301 @Override
302 public KotlinTypeInfo visitForExpression(@NotNull KtForExpression expression, ExpressionTypingContext data) {
303 return controlStructures.visitForExpression(expression, data);
304 }
305
306 @Override
307 public KotlinTypeInfo visitWhileExpression(@NotNull KtWhileExpression expression, ExpressionTypingContext data) {
308 return controlStructures.visitWhileExpression(expression, data);
309 }
310
311 @Override
312 public KotlinTypeInfo visitDoWhileExpression(@NotNull KtDoWhileExpression expression, ExpressionTypingContext data) {
313 return controlStructures.visitDoWhileExpression(expression, data);
314 }
315
316 @Override
317 public KotlinTypeInfo visitBreakExpression(@NotNull KtBreakExpression expression, ExpressionTypingContext data) {
318 return controlStructures.visitBreakExpression(expression, data);
319 }
320
321 //////////////////////////////////////////////////////////////////////////////////////////////
322
323 @Override
324 public KotlinTypeInfo visitIsExpression(@NotNull KtIsExpression expression, ExpressionTypingContext data) {
325 return patterns.visitIsExpression(expression, data);
326 }
327
328 @Override
329 public KotlinTypeInfo visitWhenExpression(@NotNull KtWhenExpression expression, ExpressionTypingContext data) {
330 return patterns.visitWhenExpression(expression, data);
331 }
332
333 //////////////////////////////////////////////////////////////////////////////////////////////
334
335 @Override
336 public KotlinTypeInfo visitSimpleNameExpression(@NotNull KtSimpleNameExpression expression, ExpressionTypingContext data) {
337 return basic.visitSimpleNameExpression(expression, data);
338 }
339
340 @Override
341 public KotlinTypeInfo visitParenthesizedExpression(@NotNull KtParenthesizedExpression expression, ExpressionTypingContext data) {
342 return basic.visitParenthesizedExpression(expression, data);
343 }
344
345 @Override
346 public KotlinTypeInfo visitConstantExpression(@NotNull KtConstantExpression expression, ExpressionTypingContext data) {
347 return basic.visitConstantExpression(expression, data);
348 }
349
350 @Override
351 public KotlinTypeInfo visitBinaryWithTypeRHSExpression(@NotNull KtBinaryExpressionWithTypeRHS expression, ExpressionTypingContext data) {
352 return basic.visitBinaryWithTypeRHSExpression(expression, data);
353 }
354
355 @Override
356 public KotlinTypeInfo visitThisExpression(@NotNull KtThisExpression expression, ExpressionTypingContext data) {
357 return basic.visitThisExpression(expression, data);
358 }
359
360 @Override
361 public KotlinTypeInfo visitSuperExpression(@NotNull KtSuperExpression expression, ExpressionTypingContext data) {
362 return basic.visitSuperExpression(expression, data);
363 }
364
365 @Override
366 public KotlinTypeInfo visitBlockExpression(@NotNull KtBlockExpression expression, ExpressionTypingContext data) {
367 return basic.visitBlockExpression(expression, data);
368 }
369
370 @Override
371 public KotlinTypeInfo visitClassLiteralExpression(@NotNull KtClassLiteralExpression expression, ExpressionTypingContext data) {
372 return basic.visitClassLiteralExpression(expression, data);
373 }
374
375 @Override
376 public KotlinTypeInfo visitCallableReferenceExpression(@NotNull KtCallableReferenceExpression expression, ExpressionTypingContext data) {
377 return basic.visitCallableReferenceExpression(expression, data);
378 }
379
380 @Override
381 public KotlinTypeInfo visitObjectLiteralExpression(@NotNull KtObjectLiteralExpression expression, ExpressionTypingContext data) {
382 return basic.visitObjectLiteralExpression(expression, data);
383 }
384
385 @Override
386 public KotlinTypeInfo visitQualifiedExpression(@NotNull KtQualifiedExpression expression, ExpressionTypingContext data) {
387 return basic.visitQualifiedExpression(expression, data);
388 }
389
390 @Override
391 public KotlinTypeInfo visitCallExpression(@NotNull KtCallExpression expression, ExpressionTypingContext data) {
392 return basic.visitCallExpression(expression, data);
393 }
394
395 @Override
396 public KotlinTypeInfo visitUnaryExpression(@NotNull KtUnaryExpression expression, ExpressionTypingContext data) {
397 return basic.visitUnaryExpression(expression, data);
398 }
399
400 @Override
401 public KotlinTypeInfo visitLabeledExpression(@NotNull KtLabeledExpression expression, ExpressionTypingContext data) {
402 return basic.visitLabeledExpression(expression, data);
403 }
404
405 @Override
406 public KotlinTypeInfo visitBinaryExpression(@NotNull KtBinaryExpression expression, ExpressionTypingContext data) {
407 return basic.visitBinaryExpression(expression, data);
408 }
409
410 @Override
411 public KotlinTypeInfo visitArrayAccessExpression(@NotNull KtArrayAccessExpression expression, ExpressionTypingContext data) {
412 return basic.visitArrayAccessExpression(expression, data);
413 }
414
415 @Override
416 public KotlinTypeInfo visitDeclaration(@NotNull KtDeclaration dcl, ExpressionTypingContext data) {
417 return basic.visitDeclaration(dcl, data);
418 }
419
420 @Override
421 public KotlinTypeInfo visitClass(@NotNull KtClass klass, ExpressionTypingContext data) {
422 return basic.visitClass(klass, data);
423 }
424
425 @Override
426 public KotlinTypeInfo visitProperty(@NotNull KtProperty property, ExpressionTypingContext data) {
427 return basic.visitProperty(property, data);
428 }
429
430 @Override
431 public KotlinTypeInfo visitStringTemplateExpression(@NotNull KtStringTemplateExpression expression, ExpressionTypingContext data) {
432 return basic.visitStringTemplateExpression(expression, data);
433 }
434
435 @Override
436 public KotlinTypeInfo visitAnnotatedExpression(@NotNull KtAnnotatedExpression expression, ExpressionTypingContext data) {
437 return basic.visitAnnotatedExpression(expression, data);
438 }
439
440 @Override
441 public KotlinTypeInfo visitKtElement(@NotNull KtElement element, ExpressionTypingContext data) {
442 return element.accept(basic, data);
443 }
444 }