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