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