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.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),
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 KotlinTypeInfo result;
181 try {
182 result = expression.accept(visitor, context);
183 // Some recursive definitions (object expressions) must put their types in the cache manually:
184 //noinspection ConstantConditions
185 if (context.trace.get(BindingContext.PROCESSED, expression)) {
186 KotlinType type = context.trace.getBindingContext().getType(expression);
187 return result.replaceType(type);
188 }
189
190 if (result.getType() instanceof DeferredType) {
191 result = result.replaceType(((DeferredType) result.getType()).getDelegate());
192 }
193 context.trace.record(BindingContext.EXPRESSION_TYPE_INFO, expression, result);
194 }
195 catch (ReenteringLazyValueComputationException e) {
196 context.trace.report(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.on(expression));
197 result = TypeInfoFactoryKt.noTypeInfo(context);
198 }
199
200 context.trace.record(BindingContext.PROCESSED, expression);
201
202 // todo save scope before analyze and fix debugger: see CodeFragmentAnalyzer.correctContextForExpression
203 BindingContextUtilsKt.recordScope(context.trace, context.scope, expression);
204 BindingContextUtilsKt.recordDataFlowInfo(context.replaceDataFlowInfo(result.getDataFlowInfo()), expression);
205 try {
206 // Here we have to resolve some types, so the following exception is possible
207 // Example: val a = ::a, fun foo() = ::foo
208 recordTypeInfo(expression, result);
209 }
210 catch (ReenteringLazyValueComputationException e) {
211 context.trace.report(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.on(expression));
212 return TypeInfoFactoryKt.noTypeInfo(context);
213 }
214 return result;
215 }
216 catch (ProcessCanceledException e) {
217 throw e;
218 }
219 catch (KotlinFrontEndException e) {
220 throw e;
221 }
222 catch (Throwable e) {
223 context.trace.report(Errors.EXCEPTION_FROM_ANALYZER.on(expression, e));
224 logOrThrowException(expression, e);
225 return TypeInfoFactoryKt.createTypeInfo(
226 ErrorUtils.createErrorType(e.getClass().getSimpleName() + " from analyzer"),
227 context
228 );
229 }
230 }
231 });
232 }
233
234 private void recordTypeInfo(@NotNull KtExpression expression, @NotNull KotlinTypeInfo typeInfo) {
235 LookupTracker lookupTracker = getComponents().lookupTracker;
236 KotlinType resultType = typeInfo.getType();
237
238 if (resultType != null) {
239 LookupTrackerUtilKt.record(lookupTracker, expression, resultType);
240 }
241 }
242
243 private static void logOrThrowException(@NotNull KtExpression expression, Throwable e) {
244 try {
245 // This trows AssertionError in CLI and reports the error in the IDE
246 LOG.error(
247 "Exception while analyzing expression at " + DiagnosticUtils.atLocation(expression) + ":\n" + expression.getText() + "\n",
248 e
249 );
250 }
251 catch (AssertionError errorFromLogger) {
252 // If we ended up here, we are in CLI, and the initial exception needs to be rethrown,
253 // simply throwing AssertionError causes its being wrapped over and over again
254 throw new KotlinFrontEndException(errorFromLogger.getMessage(), e);
255 }
256 }
257
258 //////////////////////////////////////////////////////////////////////////////////////////////
259
260 @Override
261 public KotlinTypeInfo visitLambdaExpression(@NotNull KtLambdaExpression expression, ExpressionTypingContext data) {
262 // Erasing call position to unknown is necessary to prevent wrong call positions when type checking lambda's body
263 return functions.visitLambdaExpression(expression, data.replaceCallPosition(CallPosition.Unknown.INSTANCE));
264 }
265
266 @Override
267 public KotlinTypeInfo visitNamedFunction(@NotNull KtNamedFunction function, ExpressionTypingContext data) {
268 return functions.visitNamedFunction(function, data);
269 }
270
271 //////////////////////////////////////////////////////////////////////////////////////////////
272
273 @Override
274 public KotlinTypeInfo visitThrowExpression(@NotNull KtThrowExpression expression, ExpressionTypingContext data) {
275 return controlStructures.visitThrowExpression(expression, data);
276 }
277
278 @Override
279 public KotlinTypeInfo visitReturnExpression(@NotNull KtReturnExpression expression, ExpressionTypingContext data) {
280 return controlStructures.visitReturnExpression(expression, data);
281 }
282
283 @Override
284 public KotlinTypeInfo visitContinueExpression(@NotNull KtContinueExpression expression, ExpressionTypingContext data) {
285 return controlStructures.visitContinueExpression(expression, data);
286 }
287
288 @Override
289 public KotlinTypeInfo visitIfExpression(@NotNull KtIfExpression expression, ExpressionTypingContext data) {
290 return controlStructures.visitIfExpression(expression, data);
291 }
292
293 @Override
294 public KotlinTypeInfo visitTryExpression(@NotNull KtTryExpression expression, ExpressionTypingContext data) {
295 return controlStructures.visitTryExpression(expression, data);
296 }
297
298 @Override
299 public KotlinTypeInfo visitForExpression(@NotNull KtForExpression expression, ExpressionTypingContext data) {
300 return controlStructures.visitForExpression(expression, data);
301 }
302
303 @Override
304 public KotlinTypeInfo visitWhileExpression(@NotNull KtWhileExpression expression, ExpressionTypingContext data) {
305 return controlStructures.visitWhileExpression(expression, data);
306 }
307
308 @Override
309 public KotlinTypeInfo visitDoWhileExpression(@NotNull KtDoWhileExpression expression, ExpressionTypingContext data) {
310 return controlStructures.visitDoWhileExpression(expression, data);
311 }
312
313 @Override
314 public KotlinTypeInfo visitBreakExpression(@NotNull KtBreakExpression expression, ExpressionTypingContext data) {
315 return controlStructures.visitBreakExpression(expression, data);
316 }
317
318 //////////////////////////////////////////////////////////////////////////////////////////////
319
320 @Override
321 public KotlinTypeInfo visitIsExpression(@NotNull KtIsExpression expression, ExpressionTypingContext data) {
322 return patterns.visitIsExpression(expression, data);
323 }
324
325 @Override
326 public KotlinTypeInfo visitWhenExpression(@NotNull KtWhenExpression expression, ExpressionTypingContext data) {
327 return patterns.visitWhenExpression(expression, data);
328 }
329
330 //////////////////////////////////////////////////////////////////////////////////////////////
331
332 @Override
333 public KotlinTypeInfo visitSimpleNameExpression(@NotNull KtSimpleNameExpression expression, ExpressionTypingContext data) {
334 return basic.visitSimpleNameExpression(expression, data);
335 }
336
337 @Override
338 public KotlinTypeInfo visitParenthesizedExpression(@NotNull KtParenthesizedExpression expression, ExpressionTypingContext data) {
339 return basic.visitParenthesizedExpression(expression, data);
340 }
341
342 @Override
343 public KotlinTypeInfo visitConstantExpression(@NotNull KtConstantExpression expression, ExpressionTypingContext data) {
344 return basic.visitConstantExpression(expression, data);
345 }
346
347 @Override
348 public KotlinTypeInfo visitBinaryWithTypeRHSExpression(@NotNull KtBinaryExpressionWithTypeRHS expression, ExpressionTypingContext data) {
349 return basic.visitBinaryWithTypeRHSExpression(expression, data);
350 }
351
352 @Override
353 public KotlinTypeInfo visitThisExpression(@NotNull KtThisExpression expression, ExpressionTypingContext data) {
354 return basic.visitThisExpression(expression, data);
355 }
356
357 @Override
358 public KotlinTypeInfo visitSuperExpression(@NotNull KtSuperExpression expression, ExpressionTypingContext data) {
359 return basic.visitSuperExpression(expression, data);
360 }
361
362 @Override
363 public KotlinTypeInfo visitBlockExpression(@NotNull KtBlockExpression expression, ExpressionTypingContext data) {
364 return basic.visitBlockExpression(expression, data);
365 }
366
367 @Override
368 public KotlinTypeInfo visitClassLiteralExpression(@NotNull KtClassLiteralExpression expression, ExpressionTypingContext data) {
369 return basic.visitClassLiteralExpression(expression, data);
370 }
371
372 @Override
373 public KotlinTypeInfo visitCallableReferenceExpression(@NotNull KtCallableReferenceExpression expression, ExpressionTypingContext data) {
374 return basic.visitCallableReferenceExpression(expression, data);
375 }
376
377 @Override
378 public KotlinTypeInfo visitObjectLiteralExpression(@NotNull KtObjectLiteralExpression expression, ExpressionTypingContext data) {
379 return basic.visitObjectLiteralExpression(expression, data);
380 }
381
382 @Override
383 public KotlinTypeInfo visitQualifiedExpression(@NotNull KtQualifiedExpression expression, ExpressionTypingContext data) {
384 return basic.visitQualifiedExpression(expression, data);
385 }
386
387 @Override
388 public KotlinTypeInfo visitCallExpression(@NotNull KtCallExpression expression, ExpressionTypingContext data) {
389 return basic.visitCallExpression(expression, data);
390 }
391
392 @Override
393 public KotlinTypeInfo visitUnaryExpression(@NotNull KtUnaryExpression expression, ExpressionTypingContext data) {
394 return basic.visitUnaryExpression(expression, data);
395 }
396
397 @Override
398 public KotlinTypeInfo visitLabeledExpression(@NotNull KtLabeledExpression expression, ExpressionTypingContext data) {
399 return basic.visitLabeledExpression(expression, data);
400 }
401
402 @Override
403 public KotlinTypeInfo visitBinaryExpression(@NotNull KtBinaryExpression expression, ExpressionTypingContext data) {
404 return basic.visitBinaryExpression(expression, data);
405 }
406
407 @Override
408 public KotlinTypeInfo visitArrayAccessExpression(@NotNull KtArrayAccessExpression expression, ExpressionTypingContext data) {
409 return basic.visitArrayAccessExpression(expression, data);
410 }
411
412 @Override
413 public KotlinTypeInfo visitDeclaration(@NotNull KtDeclaration dcl, ExpressionTypingContext data) {
414 return basic.visitDeclaration(dcl, data);
415 }
416
417 @Override
418 public KotlinTypeInfo visitClass(@NotNull KtClass klass, ExpressionTypingContext data) {
419 return basic.visitClass(klass, data);
420 }
421
422 @Override
423 public KotlinTypeInfo visitProperty(@NotNull KtProperty property, ExpressionTypingContext data) {
424 return basic.visitProperty(property, data);
425 }
426
427 @Override
428 public KotlinTypeInfo visitStringTemplateExpression(@NotNull KtStringTemplateExpression expression, ExpressionTypingContext data) {
429 return basic.visitStringTemplateExpression(expression, data);
430 }
431
432 @Override
433 public KotlinTypeInfo visitAnnotatedExpression(@NotNull KtAnnotatedExpression expression, ExpressionTypingContext data) {
434 return basic.visitAnnotatedExpression(expression, data);
435 }
436
437 @Override
438 public KotlinTypeInfo visitKtElement(@NotNull KtElement element, ExpressionTypingContext data) {
439 return element.accept(basic, data);
440 }
441 }