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 }