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