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.project.Project;
020    import com.intellij.psi.PsiElement;
021    import com.intellij.psi.tree.IElementType;
022    import com.intellij.psi.util.PsiTreeUtil;
023    import org.jetbrains.annotations.NotNull;
024    import org.jetbrains.annotations.Nullable;
025    import org.jetbrains.kotlin.descriptors.*;
026    import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
027    import org.jetbrains.kotlin.descriptors.impl.FunctionExpressionDescriptor;
028    import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
029    import org.jetbrains.kotlin.diagnostics.Diagnostic;
030    import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
031    import org.jetbrains.kotlin.diagnostics.Errors;
032    import org.jetbrains.kotlin.lexer.KtTokens;
033    import org.jetbrains.kotlin.psi.*;
034    import org.jetbrains.kotlin.resolve.*;
035    import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
036    import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
037    import org.jetbrains.kotlin.resolve.scopes.receivers.ClassReceiver;
038    import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
039    import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
040    import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt;
041    import org.jetbrains.kotlin.types.KotlinType;
042    import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
043    
044    import java.util.ArrayList;
045    import java.util.List;
046    
047    import static org.jetbrains.kotlin.diagnostics.Errors.*;
048    import static org.jetbrains.kotlin.resolve.BindingContext.PROCESSED;
049    
050    public class ExpressionTypingUtils {
051    
052        @NotNull
053        public static ReceiverValue normalizeReceiverValueForVisibility(@NotNull ReceiverValue receiverValue, @NotNull BindingContext trace) {
054            if (receiverValue instanceof ExpressionReceiver) {
055                KtExpression expression = ((ExpressionReceiver) receiverValue).getExpression();
056                KtReferenceExpression referenceExpression = null;
057                if (expression instanceof KtThisExpression) {
058                    referenceExpression = ((KtThisExpression) expression).getInstanceReference();
059                }
060                else if (expression instanceof KtConstructorDelegationReferenceExpression) {
061                    referenceExpression = (KtReferenceExpression) expression;
062                }
063    
064                if (referenceExpression != null) {
065                    DeclarationDescriptor descriptor = trace.get(BindingContext.REFERENCE_TARGET, referenceExpression);
066                    if (descriptor instanceof ClassDescriptor) {
067                        return new ClassReceiver((ClassDescriptor) descriptor.getOriginal());
068                    }
069                }
070            }
071            return receiverValue;
072        }
073    
074        @Nullable
075        public static ExpressionReceiver getExpressionReceiver(@NotNull KtExpression expression, @Nullable KotlinType type) {
076            if (type == null) return null;
077            return new ExpressionReceiver(expression, type);
078        }
079    
080        @Nullable
081        public static ExpressionReceiver getExpressionReceiver(
082                @NotNull ExpressionTypingFacade facade,
083                @NotNull KtExpression expression,
084                ExpressionTypingContext context
085        ) {
086            return getExpressionReceiver(expression, facade.getTypeInfo(expression, context).getType());
087        }
088    
089        @NotNull
090        public static ExpressionReceiver safeGetExpressionReceiver(
091                @NotNull ExpressionTypingFacade facade,
092                @NotNull KtExpression expression,
093                ExpressionTypingContext context
094        ) {
095            KotlinType type = safeGetType(facade.safeGetTypeInfo(expression, context));
096            return new ExpressionReceiver(expression, type);
097        }
098    
099        @NotNull
100        public static KotlinType safeGetType(@NotNull KotlinTypeInfo typeInfo) {
101            KotlinType type = typeInfo.getType();
102            assert type != null : "safeGetType should be invoked on safe KotlinTypeInfo; safeGetTypeInfo should return @NotNull type";
103            return type;
104        }
105    
106        @NotNull
107        public static LexicalWritableScope newWritableScopeImpl(ExpressionTypingContext context, @NotNull String scopeDebugName) {
108            LexicalWritableScope scope = new LexicalWritableScope(
109                    context.scope, context.scope.getOwnerDescriptor(), false, null, new TraceBasedRedeclarationHandler(context.trace), scopeDebugName);
110            scope.changeLockLevel(LexicalWritableScope.LockLevel.BOTH);
111            return scope;
112        }
113    
114        public static KtExpression createFakeExpressionOfType(
115                @NotNull Project project,
116                @NotNull BindingTrace trace,
117                @NotNull String argumentName,
118                @NotNull KotlinType argumentType
119        ) {
120            KtExpression fakeExpression = KtPsiFactoryKt.KtPsiFactory(project).createExpression(argumentName);
121            trace.recordType(fakeExpression, argumentType);
122            trace.record(PROCESSED, fakeExpression);
123            return fakeExpression;
124        }
125    
126        public static void checkVariableShadowing(
127                @NotNull LexicalScope scope,
128                @NotNull BindingTrace trace,
129                @NotNull VariableDescriptor variableDescriptor
130        ) {
131            VariableDescriptor oldDescriptor = ScopeUtilsKt.findLocalVariable(scope, variableDescriptor.getName());
132    
133            if (oldDescriptor != null && isLocal(variableDescriptor.getContainingDeclaration(), oldDescriptor)) {
134                PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(variableDescriptor);
135                if (declaration != null) {
136                    trace.report(Errors.NAME_SHADOWING.on(declaration, variableDescriptor.getName().asString()));
137                }
138            }
139        }
140    
141        public static ObservableBindingTrace makeTraceInterceptingTypeMismatch(
142                @NotNull BindingTrace trace,
143                @NotNull final KtElement expressionToWatch,
144                @NotNull final boolean[] mismatchFound
145        ) {
146            return new ObservableBindingTrace(trace) {
147    
148                @Override
149                public void report(@NotNull Diagnostic diagnostic) {
150                    DiagnosticFactory<?> factory = diagnostic.getFactory();
151                    if ((factory == TYPE_MISMATCH || factory == CONSTANT_EXPECTED_TYPE_MISMATCH || factory == NULL_FOR_NONNULL_TYPE)
152                        && diagnostic.getPsiElement() == expressionToWatch) {
153                        mismatchFound[0] = true;
154                    }
155                    if (TYPE_INFERENCE_ERRORS.contains(factory) &&
156                        PsiTreeUtil.isAncestor(expressionToWatch, diagnostic.getPsiElement(), false)) {
157                        mismatchFound[0] = true;
158                    }
159                    super.report(diagnostic);
160                }
161            };
162        }
163    
164        @NotNull
165        public static KotlinTypeInfo getTypeInfoOrNullType(
166                @Nullable KtExpression expression,
167                @NotNull ExpressionTypingContext context,
168                @NotNull ExpressionTypingInternals facade
169        ) {
170            return expression != null
171                   ? facade.getTypeInfo(expression, context)
172                   : TypeInfoFactoryKt.noTypeInfo(context);
173        }
174    
175        @SuppressWarnings("SuspiciousMethodCalls")
176        public static boolean isBinaryExpressionDependentOnExpectedType(@NotNull KtBinaryExpression expression) {
177            IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
178            return (operationType == KtTokens.IDENTIFIER || OperatorConventions.BINARY_OPERATION_NAMES.containsKey(operationType)
179                    || operationType == KtTokens.ELVIS);
180        }
181    
182        public static boolean isUnaryExpressionDependentOnExpectedType(@NotNull KtUnaryExpression expression) {
183            return expression.getOperationReference().getReferencedNameElementType() == KtTokens.EXCLEXCL;
184        }
185    
186        public static boolean isExclExclExpression(@Nullable KtExpression expression) {
187            return expression instanceof KtUnaryExpression
188                   && ((KtUnaryExpression) expression).getOperationReference().getReferencedNameElementType() == KtTokens.EXCLEXCL;
189        }
190    
191        @NotNull
192        public static List<KotlinType> getValueParametersTypes(@NotNull List<ValueParameterDescriptor> valueParameters) {
193            List<KotlinType> parameterTypes = new ArrayList<KotlinType>(valueParameters.size());
194            for (ValueParameterDescriptor parameter : valueParameters) {
195                parameterTypes.add(parameter.getType());
196            }
197            return parameterTypes;
198        }
199    
200        /**
201         * The primary case for local extensions is the following:
202         *
203         * I had a locally declared extension function or a local variable of function type called foo
204         * And I called it on my x
205         * Now, someone added function foo() to the class of x
206         * My code should not change
207         *
208         * thus
209         *
210         * local extension prevail over members (and members prevail over all non-local extensions)
211         */
212        public static boolean isLocal(DeclarationDescriptor containerOfTheCurrentLocality, DeclarationDescriptor candidate) {
213            if (candidate instanceof ValueParameterDescriptor) {
214                return true;
215            }
216            DeclarationDescriptor parent = candidate.getContainingDeclaration();
217            if (!(parent instanceof FunctionDescriptor)) {
218                return false;
219            }
220            FunctionDescriptor functionDescriptor = (FunctionDescriptor) parent;
221            DeclarationDescriptor current = containerOfTheCurrentLocality;
222            while (current != null) {
223                if (current == functionDescriptor) {
224                    return true;
225                }
226                current = current.getContainingDeclaration();
227            }
228            return false;
229        }
230    
231        public static boolean dependsOnExpectedType(@Nullable KtExpression expression) {
232            KtExpression expr = KtPsiUtil.deparenthesize(expression);
233            if (expr == null) return false;
234    
235            if (expr instanceof KtBinaryExpressionWithTypeRHS) {
236                return false;
237            }
238            if (expr instanceof KtBinaryExpression) {
239                return isBinaryExpressionDependentOnExpectedType((KtBinaryExpression) expr);
240            }
241            if (expr instanceof KtUnaryExpression) {
242                return isUnaryExpressionDependentOnExpectedType((KtUnaryExpression) expr);
243            }
244            return true;
245        }
246    
247        private ExpressionTypingUtils() {
248        }
249    
250        public static boolean isFunctionLiteral(@Nullable DeclarationDescriptor descriptor) {
251            return descriptor instanceof AnonymousFunctionDescriptor;
252        }
253    
254        public static boolean isLocalFunction(@Nullable DeclarationDescriptor descriptor) {
255            if (descriptor != null && descriptor.getClass() == SimpleFunctionDescriptorImpl.class) {
256                return ((SimpleFunctionDescriptorImpl) descriptor).getVisibility() == Visibilities.LOCAL;
257            }
258            return false;
259        }
260    
261        public static boolean isFunctionExpression(@Nullable DeclarationDescriptor descriptor) {
262            return descriptor instanceof FunctionExpressionDescriptor;
263        }
264    }