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