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