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 }