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