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