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