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.psi.tree.IElementType;
020    import kotlin.jvm.functions.Function1;
021    import org.jetbrains.annotations.NotNull;
022    import org.jetbrains.annotations.Nullable;
023    import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
024    import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
025    import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
026    import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
027    import org.jetbrains.kotlin.lexer.KtTokens;
028    import org.jetbrains.kotlin.psi.*;
029    import org.jetbrains.kotlin.resolve.*;
030    import org.jetbrains.kotlin.resolve.calls.context.ContextDependency;
031    import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
032    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
033    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
034    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
035    import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
036    import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind;
037    import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
038    import org.jetbrains.kotlin.resolve.scopes.TraceBasedLocalRedeclarationChecker;
039    import org.jetbrains.kotlin.types.ErrorUtils;
040    import org.jetbrains.kotlin.types.KotlinType;
041    import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
042    
043    import java.util.Iterator;
044    import java.util.List;
045    
046    import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
047    import static org.jetbrains.kotlin.types.TypeUtils.UNIT_EXPECTED_TYPE;
048    import static org.jetbrains.kotlin.types.expressions.CoercionStrategy.COERCION_TO_UNIT;
049    
050    public class ExpressionTypingServices {
051    
052        private final ExpressionTypingFacade expressionTypingFacade;
053        private final ExpressionTypingComponents expressionTypingComponents;
054    
055        @NotNull private final AnnotationChecker annotationChecker;
056        @NotNull private final StatementFilter statementFilter;
057    
058        public ExpressionTypingServices(
059                @NotNull ExpressionTypingComponents components,
060                @NotNull AnnotationChecker annotationChecker,
061                @NotNull StatementFilter statementFilter,
062                @NotNull ExpressionTypingVisitorDispatcher.ForDeclarations facade
063        ) {
064            this.expressionTypingComponents = components;
065            this.annotationChecker = annotationChecker;
066            this.statementFilter = statementFilter;
067            this.expressionTypingFacade = facade;
068        }
069    
070        @NotNull public StatementFilter getStatementFilter() {
071            return statementFilter;
072        }
073    
074        @NotNull
075        public KotlinType safeGetType(
076                @NotNull LexicalScope scope,
077                @NotNull KtExpression expression,
078                @NotNull KotlinType expectedType,
079                @NotNull DataFlowInfo dataFlowInfo,
080                @NotNull BindingTrace trace
081        ) {
082            KotlinType type = getType(scope, expression, expectedType, dataFlowInfo, trace);
083    
084            return type != null ? type : ErrorUtils.createErrorType("Type for " + expression.getText());
085        }
086    
087        @NotNull
088        public KotlinTypeInfo getTypeInfo(
089                @NotNull LexicalScope scope,
090                @NotNull KtExpression expression,
091                @NotNull KotlinType expectedType,
092                @NotNull DataFlowInfo dataFlowInfo,
093                @NotNull BindingTrace trace,
094                boolean isStatement
095        ) {
096            return getTypeInfo(scope, expression, expectedType, dataFlowInfo, trace, isStatement, expression, ContextDependency.INDEPENDENT);
097        }
098    
099        @NotNull
100        public KotlinTypeInfo getTypeInfo(
101                @NotNull LexicalScope scope,
102                @NotNull final KtExpression expression,
103                @NotNull KotlinType expectedType,
104                @NotNull DataFlowInfo dataFlowInfo,
105                @NotNull BindingTrace trace,
106                boolean isStatement,
107                @NotNull final KtExpression contextExpression,
108                @NotNull ContextDependency contextDependency
109        ) {
110            ExpressionTypingContext context = ExpressionTypingContext.newContext(
111                    trace, scope, dataFlowInfo, expectedType, contextDependency
112            );
113            if (contextExpression != expression) {
114                context = context.replaceExpressionContextProvider(new Function1<KtExpression, KtExpression>() {
115                    @Override
116                    public KtExpression invoke(KtExpression arg) {
117                        return arg == expression ? contextExpression : null;
118                    }
119                });
120            }
121            return expressionTypingFacade.getTypeInfo(expression, context, isStatement);
122        }
123    
124        @NotNull
125        public KotlinTypeInfo getTypeInfo(@NotNull KtExpression expression, @NotNull ResolutionContext resolutionContext) {
126            return expressionTypingFacade.getTypeInfo(expression, ExpressionTypingContext.newContext(resolutionContext));
127        }
128    
129        @Nullable
130        public KotlinType getType(
131                @NotNull LexicalScope scope,
132                @NotNull KtExpression expression,
133                @NotNull KotlinType expectedType,
134                @NotNull DataFlowInfo dataFlowInfo,
135                @NotNull BindingTrace trace
136        ) {
137            return getTypeInfo(scope, expression, expectedType, dataFlowInfo, trace, false).getType();
138        }
139    
140        /////////////////////////////////////////////////////////
141    
142        public void checkFunctionReturnType(
143                @NotNull LexicalScope functionInnerScope,
144                @NotNull KtDeclarationWithBody function,
145                @NotNull FunctionDescriptor functionDescriptor,
146                @NotNull DataFlowInfo dataFlowInfo,
147                @Nullable KotlinType expectedReturnType,
148                BindingTrace trace
149        ) {
150            if (expectedReturnType == null) {
151                expectedReturnType = functionDescriptor.getReturnType();
152                if (!function.hasBlockBody() && !function.hasDeclaredReturnType()) {
153                    expectedReturnType = NO_EXPECTED_TYPE;
154                }
155            }
156            checkFunctionReturnType(function, ExpressionTypingContext.newContext(
157                    trace,
158                    functionInnerScope, dataFlowInfo, expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE
159            ));
160        }
161    
162        /*package*/ void checkFunctionReturnType(KtDeclarationWithBody function, ExpressionTypingContext context) {
163            KtExpression bodyExpression = function.getBodyExpression();
164            if (bodyExpression == null) return;
165    
166            boolean blockBody = function.hasBlockBody();
167            ExpressionTypingContext newContext =
168                    blockBody
169                    ? context.replaceExpectedType(NO_EXPECTED_TYPE)
170                    : context;
171    
172            expressionTypingFacade.getTypeInfo(bodyExpression, newContext, blockBody);
173        }
174    
175        @NotNull
176        public KotlinTypeInfo getBlockReturnedType(KtBlockExpression expression, ExpressionTypingContext context, boolean isStatement) {
177            return getBlockReturnedType(expression, isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION, context);
178        }
179    
180        @NotNull
181        public KotlinTypeInfo getBlockReturnedType(
182                @NotNull KtBlockExpression expression,
183                @NotNull CoercionStrategy coercionStrategyForLastExpression,
184                @NotNull ExpressionTypingContext context
185        ) {
186            List<KtExpression> block = StatementFilterKt.filterStatements(statementFilter, expression);
187    
188            DeclarationDescriptor containingDescriptor = context.scope.getOwnerDescriptor();
189            LexicalWritableScope scope = new LexicalWritableScope(context.scope, containingDescriptor, false, null,
190                                                                  new TraceBasedLocalRedeclarationChecker(context.trace), LexicalScopeKind.CODE_BLOCK);
191    
192            KotlinTypeInfo r;
193            if (block.isEmpty()) {
194                r = expressionTypingComponents.dataFlowAnalyzer
195                        .createCheckedTypeInfo(expressionTypingComponents.builtIns.getUnitType(), context, expression);
196            }
197            else {
198                r = getBlockReturnedTypeWithWritableScope(scope, block, coercionStrategyForLastExpression,
199                                                          context.replaceStatementFilter(statementFilter));
200            }
201            scope.freeze();
202    
203            if (containingDescriptor instanceof ScriptDescriptor) {
204                context.trace.record(BindingContext.SCRIPT_SCOPE, (ScriptDescriptor) containingDescriptor, scope);
205            }
206    
207            return r;
208        }
209    
210        @NotNull
211        public KotlinType getBodyExpressionType(
212                @NotNull BindingTrace trace,
213                @NotNull LexicalScope outerScope,
214                @NotNull DataFlowInfo dataFlowInfo,
215                @NotNull KtDeclarationWithBody function,
216                @NotNull FunctionDescriptor functionDescriptor
217        ) {
218            KtExpression bodyExpression = function.getBodyExpression();
219            assert bodyExpression != null;
220            LexicalScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
221    
222            ExpressionTypingContext context = ExpressionTypingContext.newContext(
223                    trace, functionInnerScope, dataFlowInfo, NO_EXPECTED_TYPE
224            );
225            KotlinTypeInfo typeInfo = expressionTypingFacade.getTypeInfo(bodyExpression, context, function.hasBlockBody());
226    
227            KotlinType type = typeInfo.getType();
228            if (type != null) {
229                return type;
230            }
231            else {
232                return ErrorUtils.createErrorType("Error function type");
233            }
234        }
235    
236        /**
237         * Visits block statements propagating data flow information from the first to the last.
238         * Determines block returned type and data flow information at the end of the block AND
239         * at the nearest jump point from the block beginning.
240         */
241        /*package*/ KotlinTypeInfo getBlockReturnedTypeWithWritableScope(
242                @NotNull LexicalWritableScope scope,
243                @NotNull List<? extends KtElement> block,
244                @NotNull CoercionStrategy coercionStrategyForLastExpression,
245                @NotNull ExpressionTypingContext context
246        ) {
247            if (block.isEmpty()) {
248                return TypeInfoFactoryKt.createTypeInfo(expressionTypingComponents.builtIns.getUnitType(), context);
249            }
250    
251            ExpressionTypingInternals blockLevelVisitor = new ExpressionTypingVisitorDispatcher.ForBlock(
252                    expressionTypingComponents, annotationChecker, scope);
253            ExpressionTypingContext newContext = context.replaceScope(scope).replaceExpectedType(NO_EXPECTED_TYPE);
254    
255            KotlinTypeInfo result = TypeInfoFactoryKt.noTypeInfo(context);
256            // Jump point data flow info
257            DataFlowInfo beforeJumpInfo = newContext.dataFlowInfo;
258            boolean jumpOutPossible = false;
259            for (Iterator<? extends KtElement> iterator = block.iterator(); iterator.hasNext(); ) {
260                KtElement statement = iterator.next();
261                if (!(statement instanceof KtExpression)) {
262                    continue;
263                }
264                KtExpression statementExpression = (KtExpression) statement;
265                if (!iterator.hasNext()) {
266                    result = getTypeOfLastExpressionInBlock(
267                            statementExpression, newContext.replaceExpectedType(context.expectedType), coercionStrategyForLastExpression,
268                            blockLevelVisitor);
269                    if (result.getType() != null && statementExpression.getParent() instanceof KtBlockExpression) {
270                        DataFlowValue lastExpressionValue = DataFlowValueFactory.createDataFlowValue(
271                                statementExpression, result.getType(), context);
272                        DataFlowValue blockExpressionValue = DataFlowValueFactory.createDataFlowValue(
273                                (KtBlockExpression) statementExpression.getParent(), result.getType(), context);
274                        result = result.replaceDataFlowInfo(result.getDataFlowInfo().assign(blockExpressionValue, lastExpressionValue));
275                    }
276                }
277                else {
278                    result = blockLevelVisitor
279                            .getTypeInfo(statementExpression, newContext.replaceContextDependency(ContextDependency.INDEPENDENT), true);
280                }
281    
282                DataFlowInfo newDataFlowInfo = result.getDataFlowInfo();
283                // If jump is not possible, we take new data flow info before jump
284                if (!jumpOutPossible) {
285                    beforeJumpInfo = result.getJumpFlowInfo();
286                    jumpOutPossible = result.getJumpOutPossible();
287                }
288                if (newDataFlowInfo != context.dataFlowInfo) {
289                    newContext = newContext.replaceDataFlowInfo(newDataFlowInfo);
290                    // We take current data flow info if jump there is not possible
291                }
292                blockLevelVisitor = new ExpressionTypingVisitorDispatcher.ForBlock(expressionTypingComponents, annotationChecker, scope);
293            }
294            return result.replaceJumpOutPossible(jumpOutPossible).replaceJumpFlowInfo(beforeJumpInfo);
295        }
296    
297        private KotlinTypeInfo getTypeOfLastExpressionInBlock(
298                @NotNull KtExpression statementExpression,
299                @NotNull ExpressionTypingContext context,
300                @NotNull CoercionStrategy coercionStrategyForLastExpression,
301                @NotNull ExpressionTypingInternals blockLevelVisitor
302        ) {
303            if (context.expectedType != NO_EXPECTED_TYPE) {
304                KotlinType expectedType;
305                if (context.expectedType == UNIT_EXPECTED_TYPE ||//the first check is necessary to avoid invocation 'isUnit(UNIT_EXPECTED_TYPE)'
306                    (coercionStrategyForLastExpression == COERCION_TO_UNIT && KotlinBuiltIns.isUnit(context.expectedType))) {
307                    expectedType = UNIT_EXPECTED_TYPE;
308                }
309                else {
310                    expectedType = context.expectedType;
311                }
312    
313                return blockLevelVisitor.getTypeInfo(statementExpression, context.replaceExpectedType(expectedType), true);
314            }
315            KotlinTypeInfo result = blockLevelVisitor.getTypeInfo(statementExpression, context, true);
316            if (coercionStrategyForLastExpression == COERCION_TO_UNIT) {
317                boolean mightBeUnit = false;
318                if (statementExpression instanceof KtDeclaration) {
319                    if (!(statementExpression instanceof KtNamedFunction) || statementExpression.getName() != null) {
320                        mightBeUnit = true;
321                    }
322                }
323                if (statementExpression instanceof KtBinaryExpression) {
324                    KtBinaryExpression binaryExpression = (KtBinaryExpression) statementExpression;
325                    IElementType operationType = binaryExpression.getOperationToken();
326                    //noinspection SuspiciousMethodCalls
327                    if (operationType == KtTokens.EQ || OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
328                        mightBeUnit = true;
329                    }
330                }
331                if (mightBeUnit) {
332                    // ExpressionTypingVisitorForStatements should return only null or Unit for declarations and assignments,
333                    // but (for correct assignment / initialization analysis) data flow info must be preserved
334                    assert result.getType() == null || KotlinBuiltIns.isUnit(result.getType());
335                    result = result.replaceType(expressionTypingComponents.builtIns.getUnitType());
336                }
337            }
338            return result;
339        }
340    
341    }