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.resolve;
018
019 import com.google.common.collect.Lists;
020 import com.intellij.openapi.util.Pair;
021 import com.intellij.psi.PsiElement;
022 import com.intellij.psi.util.PsiTreeUtil;
023 import kotlin.jvm.functions.Function3;
024 import org.jetbrains.annotations.NotNull;
025 import org.jetbrains.annotations.Nullable;
026 import org.jetbrains.kotlin.descriptors.*;
027 import org.jetbrains.kotlin.diagnostics.Diagnostic;
028 import org.jetbrains.kotlin.diagnostics.Severity;
029 import org.jetbrains.kotlin.psi.*;
030 import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
031 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
032 import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
033 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory;
034 import org.jetbrains.kotlin.resolve.diagnostics.MutableDiagnosticsWithSuppression;
035 import org.jetbrains.kotlin.types.KotlinType;
036 import org.jetbrains.kotlin.types.TypeUtils;
037 import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo;
038 import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
039 import org.jetbrains.kotlin.util.slicedMap.*;
040
041 import java.util.Collection;
042 import java.util.EnumMap;
043 import java.util.Map;
044
045 import static org.jetbrains.kotlin.diagnostics.Errors.AMBIGUOUS_LABEL;
046 import static org.jetbrains.kotlin.resolve.BindingContext.*;
047
048 public class BindingContextUtils {
049 private BindingContextUtils() {
050 }
051
052 @Nullable
053 public static VariableDescriptor extractVariableFromResolvedCall(
054 @NotNull BindingContext bindingContext,
055 @Nullable KtElement callElement
056 ) {
057 ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilKt.getResolvedCall(callElement, bindingContext);
058 if (resolvedCall == null || !(resolvedCall.getResultingDescriptor() instanceof VariableDescriptor)) return null;
059 return (VariableDescriptor) resolvedCall.getResultingDescriptor();
060 }
061
062 @Nullable
063 public static VariableDescriptor extractVariableDescriptorIfAny(@NotNull BindingContext bindingContext, @Nullable KtElement element, boolean onlyReference) {
064 DeclarationDescriptor descriptor = null;
065 if (!onlyReference && (element instanceof KtVariableDeclaration || element instanceof KtParameter)) {
066 descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
067 }
068 else if (element instanceof KtSimpleNameExpression) {
069 descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (KtSimpleNameExpression) element);
070 }
071 else if (element instanceof KtQualifiedExpression) {
072 descriptor = extractVariableDescriptorIfAny(bindingContext, ((KtQualifiedExpression) element).getSelectorExpression(), onlyReference);
073 }
074 if (descriptor instanceof VariableDescriptor) {
075 return (VariableDescriptor) descriptor;
076 }
077 return null;
078 }
079
080 public static void recordFunctionDeclarationToDescriptor(@NotNull BindingTrace trace,
081 @NotNull PsiElement psiElement, @NotNull SimpleFunctionDescriptor function) {
082 trace.record(BindingContext.FUNCTION, psiElement, function);
083 }
084
085 @NotNull
086 public static <K, V> V getNotNull(
087 @NotNull BindingContext bindingContext,
088 @NotNull ReadOnlySlice<K, V> slice,
089 @NotNull K key
090 ) {
091 return getNotNull(bindingContext, slice, key, "Value at " + slice + " must not be null for " + key);
092 }
093
094 @NotNull
095 public static KotlinType getTypeNotNull(
096 @NotNull BindingContext bindingContext,
097 @NotNull KtExpression expression
098 ) {
099 KotlinType result = bindingContext.getType(expression);
100 if (result == null) {
101 throw new IllegalStateException("Type must be not null for " + expression);
102 }
103 return result;
104 }
105
106 @NotNull
107 public static <K, V> V getNotNull(
108 @NotNull BindingContext bindingContext,
109 @NotNull ReadOnlySlice<K, V> slice,
110 @NotNull K key,
111 @NotNull String messageIfNull
112 ) {
113 V value = bindingContext.get(slice, key);
114 if (value == null) {
115 throw new IllegalStateException(messageIfNull);
116 }
117 return value;
118 }
119
120 @NotNull
121 public static DeclarationDescriptor getEnclosingDescriptor(@NotNull BindingContext context, @NotNull KtElement element) {
122 KtNamedDeclaration declaration = PsiTreeUtil.getParentOfType(element, KtNamedDeclaration.class);
123 if (declaration instanceof KtFunctionLiteral) {
124 return getEnclosingDescriptor(context, declaration);
125 }
126 DeclarationDescriptor descriptor = context.get(DECLARATION_TO_DESCRIPTOR, declaration);
127 assert descriptor != null : "No descriptor for named declaration: " + declaration.getText() + "\n(of type " + declaration.getClass() + ")";
128 return descriptor;
129 }
130
131 public static FunctionDescriptor getEnclosingFunctionDescriptor(@NotNull BindingContext context, @NotNull KtElement element) {
132 KtFunction function = PsiTreeUtil.getParentOfType(element, KtFunction.class);
133 return (FunctionDescriptor)context.get(DECLARATION_TO_DESCRIPTOR, function);
134 }
135
136 public static void reportAmbiguousLabel(
137 @NotNull BindingTrace trace,
138 @NotNull KtSimpleNameExpression targetLabel,
139 @NotNull Collection<DeclarationDescriptor> declarationsByLabel
140 ) {
141 Collection<PsiElement> targets = Lists.newArrayList();
142 for (DeclarationDescriptor descriptor : declarationsByLabel) {
143 PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
144 assert element != null : "Label can only point to something in the same lexical scope";
145 targets.add(element);
146 }
147 if (!targets.isEmpty()) {
148 trace.record(AMBIGUOUS_LABEL_TARGET, targetLabel, targets);
149 }
150 trace.report(AMBIGUOUS_LABEL.on(targetLabel));
151 }
152
153 @Nullable
154 public static KotlinType updateRecordedType(
155 @Nullable KotlinType type,
156 @NotNull KtExpression expression,
157 @NotNull BindingTrace trace,
158 boolean shouldBeMadeNullable
159 ) {
160 if (type == null) return null;
161 if (shouldBeMadeNullable) {
162 type = TypeUtils.makeNullable(type);
163 }
164 trace.recordType(expression, type);
165 return type;
166 }
167
168 @Nullable
169 public static KotlinTypeInfo getRecordedTypeInfo(@NotNull KtExpression expression, @NotNull BindingContext context) {
170 // noinspection ConstantConditions
171 if (!context.get(BindingContext.PROCESSED, expression)) return null;
172 // NB: should never return null if expression is already processed
173 KotlinTypeInfo result = context.get(BindingContext.EXPRESSION_TYPE_INFO, expression);
174 return result != null ? result : TypeInfoFactoryKt.noTypeInfo(DataFlowInfoFactory.EMPTY);
175 }
176
177 public static boolean isExpressionWithValidReference(
178 @NotNull KtExpression expression,
179 @NotNull BindingContext context
180 ) {
181 if (expression instanceof KtCallExpression) {
182 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expression, context);
183 return resolvedCall instanceof VariableAsFunctionResolvedCall;
184 }
185 return expression instanceof KtReferenceExpression;
186 }
187
188 public static boolean isVarCapturedInClosure(BindingContext bindingContext, DeclarationDescriptor descriptor) {
189 if (!(descriptor instanceof VariableDescriptor) || descriptor instanceof PropertyDescriptor) return false;
190 VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor;
191 return bindingContext.get(CAPTURED_IN_CLOSURE, variableDescriptor) != null && variableDescriptor.isVar();
192 }
193
194 @NotNull
195 public static Pair<FunctionDescriptor, PsiElement> getContainingFunctionSkipFunctionLiterals(
196 @Nullable DeclarationDescriptor startDescriptor,
197 boolean strict
198 ) {
199 FunctionDescriptor containingFunctionDescriptor = DescriptorUtils.getParentOfType(startDescriptor, FunctionDescriptor.class, strict);
200 PsiElement containingFunction =
201 containingFunctionDescriptor != null ? DescriptorToSourceUtils.getSourceFromDescriptor(containingFunctionDescriptor) : null;
202 while (containingFunction instanceof KtFunctionLiteral) {
203 containingFunctionDescriptor = DescriptorUtils.getParentOfType(containingFunctionDescriptor, FunctionDescriptor.class);
204 containingFunction = containingFunctionDescriptor != null ? DescriptorToSourceUtils
205 .getSourceFromDescriptor(containingFunctionDescriptor) : null;
206 }
207
208 return new Pair<FunctionDescriptor, PsiElement>(containingFunctionDescriptor, containingFunction);
209 }
210
211 @Nullable
212 public static ResolvedCall<ConstructorDescriptor> getDelegationConstructorCall(
213 @NotNull BindingContext bindingContext,
214 @NotNull ConstructorDescriptor constructorDescriptor
215 ) {
216 return bindingContext.get(CONSTRUCTOR_RESOLVED_DELEGATION_CALL, constructorDescriptor);
217 }
218
219 static void addOwnDataTo(
220 @NotNull final BindingTrace trace, @Nullable final TraceEntryFilter filter, boolean commitDiagnostics,
221 @NotNull MutableSlicedMap map, MutableDiagnosticsWithSuppression diagnostics
222 ) {
223 map.forEach(new Function3<WritableSlice, Object, Object, Void>() {
224 @Override
225 public Void invoke(WritableSlice slice, Object key, Object value) {
226 if (filter == null || filter.accept(slice, null, key)) {
227 trace.record(slice, key, value);
228 }
229
230 return null;
231 }
232 });
233
234 if (!commitDiagnostics) return;
235
236 for (Diagnostic diagnostic : diagnostics.getOwnDiagnostics()) {
237 if (filter == null || filter.accept(null, diagnostic, diagnostic.getPsiElement())) {
238 trace.report(diagnostic);
239 }
240 }
241
242 }
243 }