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 ((factory == TYPE_MISMATCH || factory == CONSTANT_EXPECTED_TYPE_MISMATCH || factory == NULL_FOR_NONNULL_TYPE)
128 && diagnostic.getPsiElement() == expressionToWatch) {
129 mismatchFound[0] = true;
130 }
131 if (TYPE_INFERENCE_ERRORS.contains(factory) &&
132 PsiTreeUtil.isAncestor(expressionToWatch, diagnostic.getPsiElement(), false)) {
133 mismatchFound[0] = true;
134 }
135 super.report(diagnostic);
136 }
137 };
138 }
139
140 @NotNull
141 public static KotlinTypeInfo getTypeInfoOrNullType(
142 @Nullable KtExpression expression,
143 @NotNull ExpressionTypingContext context,
144 @NotNull ExpressionTypingInternals facade
145 ) {
146 return expression != null
147 ? facade.getTypeInfo(expression, context)
148 : TypeInfoFactoryKt.noTypeInfo(context);
149 }
150
151 @SuppressWarnings("SuspiciousMethodCalls")
152 public static boolean isBinaryExpressionDependentOnExpectedType(@NotNull KtBinaryExpression expression) {
153 IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
154 return (operationType == KtTokens.IDENTIFIER || OperatorConventions.BINARY_OPERATION_NAMES.containsKey(operationType)
155 || operationType == KtTokens.ELVIS);
156 }
157
158 public static boolean isUnaryExpressionDependentOnExpectedType(@NotNull KtUnaryExpression expression) {
159 return expression.getOperationReference().getReferencedNameElementType() == KtTokens.EXCLEXCL;
160 }
161
162 public static boolean isExclExclExpression(@Nullable KtExpression expression) {
163 return expression instanceof KtUnaryExpression
164 && ((KtUnaryExpression) expression).getOperationReference().getReferencedNameElementType() == KtTokens.EXCLEXCL;
165 }
166
167 @NotNull
168 public static List<KotlinType> getValueParametersTypes(@NotNull List<ValueParameterDescriptor> valueParameters) {
169 List<KotlinType> parameterTypes = new ArrayList<KotlinType>(valueParameters.size());
170 for (ValueParameterDescriptor parameter : valueParameters) {
171 parameterTypes.add(parameter.getType());
172 }
173 return parameterTypes;
174 }
175
176 /**
177 * The primary case for local extensions is the following:
178 *
179 * I had a locally declared extension function or a local variable of function type called foo
180 * And I called it on my x
181 * Now, someone added function foo() to the class of x
182 * My code should not change
183 *
184 * thus
185 *
186 * local extension prevail over members (and members prevail over all non-local extensions)
187 */
188 public static boolean isLocal(DeclarationDescriptor containerOfTheCurrentLocality, DeclarationDescriptor candidate) {
189 if (candidate instanceof ValueParameterDescriptor) {
190 return true;
191 }
192 DeclarationDescriptor parent = candidate.getContainingDeclaration();
193 if (!(parent instanceof FunctionDescriptor)) {
194 return false;
195 }
196 FunctionDescriptor functionDescriptor = (FunctionDescriptor) parent;
197 DeclarationDescriptor current = containerOfTheCurrentLocality;
198 while (current != null) {
199 if (current == functionDescriptor) {
200 return true;
201 }
202 current = current.getContainingDeclaration();
203 }
204 return false;
205 }
206
207 public static boolean dependsOnExpectedType(@Nullable KtExpression expression) {
208 KtExpression expr = KtPsiUtil.deparenthesize(expression);
209 if (expr == null) return false;
210
211 if (expr instanceof KtBinaryExpressionWithTypeRHS) {
212 return false;
213 }
214 if (expr instanceof KtBinaryExpression) {
215 return isBinaryExpressionDependentOnExpectedType((KtBinaryExpression) expr);
216 }
217 if (expr instanceof KtUnaryExpression) {
218 return isUnaryExpressionDependentOnExpectedType((KtUnaryExpression) expr);
219 }
220 return true;
221 }
222
223 private ExpressionTypingUtils() {
224 }
225
226 public static boolean isFunctionLiteral(@Nullable DeclarationDescriptor descriptor) {
227 return descriptor instanceof AnonymousFunctionDescriptor;
228 }
229
230 public static boolean isLocalFunction(@Nullable DeclarationDescriptor descriptor) {
231 if (descriptor != null && descriptor.getClass() == SimpleFunctionDescriptorImpl.class) {
232 return ((SimpleFunctionDescriptorImpl) descriptor).getVisibility() == Visibilities.LOCAL;
233 }
234 return false;
235 }
236
237 public static boolean isFunctionExpression(@Nullable DeclarationDescriptor descriptor) {
238 return descriptor instanceof FunctionExpressionDescriptor;
239 }
240 }