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    }