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.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),
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                        KotlinTypeInfo result;
181                        try {
182                            result = expression.accept(visitor, context);
183                            // Some recursive definitions (object expressions) must put their types in the cache manually:
184                            //noinspection ConstantConditions
185                            if (context.trace.get(BindingContext.PROCESSED, expression)) {
186                                KotlinType type = context.trace.getBindingContext().getType(expression);
187                                return result.replaceType(type);
188                            }
189    
190                            if (result.getType() instanceof DeferredType) {
191                                result = result.replaceType(((DeferredType) result.getType()).getDelegate());
192                            }
193                            context.trace.record(BindingContext.EXPRESSION_TYPE_INFO, expression, result);
194                        }
195                        catch (ReenteringLazyValueComputationException e) {
196                            context.trace.report(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.on(expression));
197                            result = TypeInfoFactoryKt.noTypeInfo(context);
198                        }
199    
200                        context.trace.record(BindingContext.PROCESSED, expression);
201    
202                        // todo save scope before analyze and fix debugger: see CodeFragmentAnalyzer.correctContextForExpression
203                        BindingContextUtilsKt.recordScope(context.trace, context.scope, expression);
204                        BindingContextUtilsKt.recordDataFlowInfo(context.replaceDataFlowInfo(result.getDataFlowInfo()), expression);
205                        try {
206                            // Here we have to resolve some types, so the following exception is possible
207                            // Example: val a = ::a, fun foo() = ::foo
208                            recordTypeInfo(expression, result);
209                        }
210                        catch (ReenteringLazyValueComputationException e) {
211                            context.trace.report(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.on(expression));
212                            return TypeInfoFactoryKt.noTypeInfo(context);
213                        }
214                        return result;
215                    }
216                    catch (ProcessCanceledException e) {
217                        throw e;
218                    }
219                    catch (KotlinFrontEndException e) {
220                        throw e;
221                    }
222                    catch (Throwable e) {
223                        context.trace.report(Errors.EXCEPTION_FROM_ANALYZER.on(expression, e));
224                        logOrThrowException(expression, e);
225                        return TypeInfoFactoryKt.createTypeInfo(
226                                ErrorUtils.createErrorType(e.getClass().getSimpleName() + " from analyzer"),
227                                context
228                        );
229                    }
230                }
231            });
232        }
233    
234        private void recordTypeInfo(@NotNull KtExpression expression, @NotNull KotlinTypeInfo typeInfo) {
235            LookupTracker lookupTracker = getComponents().lookupTracker;
236            KotlinType resultType = typeInfo.getType();
237    
238            if (resultType != null) {
239                LookupTrackerUtilKt.record(lookupTracker, expression, resultType);
240            }
241        }
242    
243        private static void logOrThrowException(@NotNull KtExpression expression, Throwable e) {
244            try {
245                // This trows AssertionError in CLI and reports the error in the IDE
246                LOG.error(
247                        "Exception while analyzing expression at " + DiagnosticUtils.atLocation(expression) + ":\n" + expression.getText() + "\n",
248                        e
249                );
250            }
251            catch (AssertionError errorFromLogger) {
252                // If we ended up here, we are in CLI, and the initial exception needs to be rethrown,
253                // simply throwing AssertionError causes its being wrapped over and over again
254                throw new KotlinFrontEndException(errorFromLogger.getMessage(), e);
255            }
256        }
257    
258        //////////////////////////////////////////////////////////////////////////////////////////////
259    
260        @Override
261        public KotlinTypeInfo visitLambdaExpression(@NotNull KtLambdaExpression expression, ExpressionTypingContext data) {
262            // Erasing call position to unknown is necessary to prevent wrong call positions when type checking lambda's body
263            return functions.visitLambdaExpression(expression, data.replaceCallPosition(CallPosition.Unknown.INSTANCE));
264        }
265    
266        @Override
267        public KotlinTypeInfo visitNamedFunction(@NotNull KtNamedFunction function, ExpressionTypingContext data) {
268            return functions.visitNamedFunction(function, data);
269        }
270    
271    //////////////////////////////////////////////////////////////////////////////////////////////
272    
273        @Override
274        public KotlinTypeInfo visitThrowExpression(@NotNull KtThrowExpression expression, ExpressionTypingContext data) {
275            return controlStructures.visitThrowExpression(expression, data);
276        }
277    
278        @Override
279        public KotlinTypeInfo visitReturnExpression(@NotNull KtReturnExpression expression, ExpressionTypingContext data) {
280            return controlStructures.visitReturnExpression(expression, data);
281        }
282    
283        @Override
284        public KotlinTypeInfo visitContinueExpression(@NotNull KtContinueExpression expression, ExpressionTypingContext data) {
285            return controlStructures.visitContinueExpression(expression, data);
286        }
287    
288        @Override
289        public KotlinTypeInfo visitIfExpression(@NotNull KtIfExpression expression, ExpressionTypingContext data) {
290            return controlStructures.visitIfExpression(expression, data);
291        }
292    
293        @Override
294        public KotlinTypeInfo visitTryExpression(@NotNull KtTryExpression expression, ExpressionTypingContext data) {
295            return controlStructures.visitTryExpression(expression, data);
296        }
297    
298        @Override
299        public KotlinTypeInfo visitForExpression(@NotNull KtForExpression expression, ExpressionTypingContext data) {
300            return controlStructures.visitForExpression(expression, data);
301        }
302    
303        @Override
304        public KotlinTypeInfo visitWhileExpression(@NotNull KtWhileExpression expression, ExpressionTypingContext data) {
305            return controlStructures.visitWhileExpression(expression, data);
306        }
307    
308        @Override
309        public KotlinTypeInfo visitDoWhileExpression(@NotNull KtDoWhileExpression expression, ExpressionTypingContext data) {
310            return controlStructures.visitDoWhileExpression(expression, data);
311        }
312    
313        @Override
314        public KotlinTypeInfo visitBreakExpression(@NotNull KtBreakExpression expression, ExpressionTypingContext data) {
315            return controlStructures.visitBreakExpression(expression, data);
316        }
317    
318    //////////////////////////////////////////////////////////////////////////////////////////////
319    
320        @Override
321        public KotlinTypeInfo visitIsExpression(@NotNull KtIsExpression expression, ExpressionTypingContext data) {
322            return patterns.visitIsExpression(expression, data);
323        }
324    
325        @Override
326        public KotlinTypeInfo visitWhenExpression(@NotNull KtWhenExpression expression, ExpressionTypingContext data) {
327            return patterns.visitWhenExpression(expression, data);
328        }
329    
330    //////////////////////////////////////////////////////////////////////////////////////////////
331    
332        @Override
333        public KotlinTypeInfo visitSimpleNameExpression(@NotNull KtSimpleNameExpression expression, ExpressionTypingContext data) {
334            return basic.visitSimpleNameExpression(expression, data);
335        }
336    
337        @Override
338        public KotlinTypeInfo visitParenthesizedExpression(@NotNull KtParenthesizedExpression expression, ExpressionTypingContext data) {
339            return basic.visitParenthesizedExpression(expression, data);
340        }
341    
342        @Override
343        public KotlinTypeInfo visitConstantExpression(@NotNull KtConstantExpression expression, ExpressionTypingContext data) {
344            return basic.visitConstantExpression(expression, data);
345        }
346    
347        @Override
348        public KotlinTypeInfo visitBinaryWithTypeRHSExpression(@NotNull KtBinaryExpressionWithTypeRHS expression, ExpressionTypingContext data) {
349            return basic.visitBinaryWithTypeRHSExpression(expression, data);
350        }
351    
352        @Override
353        public KotlinTypeInfo visitThisExpression(@NotNull KtThisExpression expression, ExpressionTypingContext data) {
354            return basic.visitThisExpression(expression, data);
355        }
356    
357        @Override
358        public KotlinTypeInfo visitSuperExpression(@NotNull KtSuperExpression expression, ExpressionTypingContext data) {
359            return basic.visitSuperExpression(expression, data);
360        }
361    
362        @Override
363        public KotlinTypeInfo visitBlockExpression(@NotNull KtBlockExpression expression, ExpressionTypingContext data) {
364            return basic.visitBlockExpression(expression, data);
365        }
366    
367        @Override
368        public KotlinTypeInfo visitClassLiteralExpression(@NotNull KtClassLiteralExpression expression, ExpressionTypingContext data) {
369            return basic.visitClassLiteralExpression(expression, data);
370        }
371    
372        @Override
373        public KotlinTypeInfo visitCallableReferenceExpression(@NotNull KtCallableReferenceExpression expression, ExpressionTypingContext data) {
374            return basic.visitCallableReferenceExpression(expression, data);
375        }
376    
377        @Override
378        public KotlinTypeInfo visitObjectLiteralExpression(@NotNull KtObjectLiteralExpression expression, ExpressionTypingContext data) {
379            return basic.visitObjectLiteralExpression(expression, data);
380        }
381    
382        @Override
383        public KotlinTypeInfo visitQualifiedExpression(@NotNull KtQualifiedExpression expression, ExpressionTypingContext data) {
384            return basic.visitQualifiedExpression(expression, data);
385        }
386    
387        @Override
388        public KotlinTypeInfo visitCallExpression(@NotNull KtCallExpression expression, ExpressionTypingContext data) {
389            return basic.visitCallExpression(expression, data);
390        }
391    
392        @Override
393        public KotlinTypeInfo visitUnaryExpression(@NotNull KtUnaryExpression expression, ExpressionTypingContext data) {
394            return basic.visitUnaryExpression(expression, data);
395        }
396    
397        @Override
398        public KotlinTypeInfo visitLabeledExpression(@NotNull KtLabeledExpression expression, ExpressionTypingContext data) {
399            return basic.visitLabeledExpression(expression, data);
400        }
401    
402        @Override
403        public KotlinTypeInfo visitBinaryExpression(@NotNull KtBinaryExpression expression, ExpressionTypingContext data) {
404            return basic.visitBinaryExpression(expression, data);
405        }
406    
407        @Override
408        public KotlinTypeInfo visitArrayAccessExpression(@NotNull KtArrayAccessExpression expression, ExpressionTypingContext data) {
409            return basic.visitArrayAccessExpression(expression, data);
410        }
411    
412        @Override
413        public KotlinTypeInfo visitDeclaration(@NotNull KtDeclaration dcl, ExpressionTypingContext data) {
414            return basic.visitDeclaration(dcl, data);
415        }
416    
417        @Override
418        public KotlinTypeInfo visitClass(@NotNull KtClass klass, ExpressionTypingContext data) {
419            return basic.visitClass(klass, data);
420        }
421    
422        @Override
423        public KotlinTypeInfo visitProperty(@NotNull KtProperty property, ExpressionTypingContext data) {
424            return basic.visitProperty(property, data);
425        }
426    
427        @Override
428        public KotlinTypeInfo visitStringTemplateExpression(@NotNull KtStringTemplateExpression expression, ExpressionTypingContext data) {
429            return basic.visitStringTemplateExpression(expression, data);
430        }
431    
432        @Override
433        public KotlinTypeInfo visitAnnotatedExpression(@NotNull KtAnnotatedExpression expression, ExpressionTypingContext data) {
434            return basic.visitAnnotatedExpression(expression, data);
435        }
436    
437        @Override
438        public KotlinTypeInfo visitKtElement(@NotNull KtElement element, ExpressionTypingContext data) {
439            return element.accept(basic, data);
440        }
441    }