001 /*
002 * Copyright 2010-2013 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.jet.lang.resolve;
018
019 import com.google.common.collect.Lists;
020 import com.google.common.collect.Sets;
021 import com.intellij.openapi.util.text.StringUtil;
022 import com.intellij.psi.PsiElement;
023 import com.intellij.psi.PsiFile;
024 import com.intellij.psi.util.PsiTreeUtil;
025 import org.jetbrains.annotations.NotNull;
026 import org.jetbrains.annotations.Nullable;
027 import org.jetbrains.jet.lang.descriptors.*;
028 import org.jetbrains.jet.lang.psi.*;
029 import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
030 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
031 import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
032 import org.jetbrains.jet.lang.types.JetType;
033 import org.jetbrains.jet.lang.types.JetTypeInfo;
034 import org.jetbrains.jet.lang.types.TypeUtils;
035 import org.jetbrains.jet.util.slicedmap.ReadOnlySlice;
036 import org.jetbrains.jet.util.slicedmap.Slices;
037
038 import java.util.*;
039
040 import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.*;
041 import static org.jetbrains.jet.lang.diagnostics.Errors.AMBIGUOUS_LABEL;
042 import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_LABEL_TARGET;
043 import static org.jetbrains.jet.lang.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR;
044
045 public class BindingContextUtils {
046 private BindingContextUtils() {
047 }
048
049 private static final Slices.KeyNormalizer<DeclarationDescriptor> DECLARATION_DESCRIPTOR_NORMALIZER = new Slices.KeyNormalizer<DeclarationDescriptor>() {
050 @Override
051 public DeclarationDescriptor normalize(DeclarationDescriptor declarationDescriptor) {
052 if (declarationDescriptor instanceof CallableMemberDescriptor) {
053 CallableMemberDescriptor callable = (CallableMemberDescriptor) declarationDescriptor;
054 if (callable.getKind() != DECLARATION) {
055 throw new IllegalStateException("non-declaration descriptors should be filtered out earlier: " + callable);
056 }
057 }
058 //if (declarationDescriptor instanceof VariableAsFunctionDescriptor) {
059 // VariableAsFunctionDescriptor descriptor = (VariableAsFunctionDescriptor) declarationDescriptor;
060 // if (descriptor.getOriginal() != descriptor) {
061 // throw new IllegalStateException("original should be resolved earlier: " + descriptor);
062 // }
063 //}
064 return declarationDescriptor.getOriginal();
065 }
066 };
067
068 /*package*/ static final ReadOnlySlice<DeclarationDescriptor, PsiElement> DESCRIPTOR_TO_DECLARATION =
069 Slices.<DeclarationDescriptor, PsiElement>sliceBuilder().setKeyNormalizer(DECLARATION_DESCRIPTOR_NORMALIZER).setDebugName("DESCRIPTOR_TO_DECLARATION").build();
070
071 @Nullable
072 public static VariableDescriptor extractVariableDescriptorIfAny(@NotNull BindingContext bindingContext, @Nullable JetElement element, boolean onlyReference) {
073 DeclarationDescriptor descriptor = null;
074 if (!onlyReference && (element instanceof JetVariableDeclaration || element instanceof JetParameter)) {
075 descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
076 }
077 else if (element instanceof JetSimpleNameExpression) {
078 descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) element);
079 }
080 else if (element instanceof JetQualifiedExpression) {
081 descriptor = extractVariableDescriptorIfAny(bindingContext, ((JetQualifiedExpression) element).getSelectorExpression(), onlyReference);
082 }
083 if (descriptor instanceof VariableDescriptor) {
084 return (VariableDescriptor) descriptor;
085 }
086 return null;
087 }
088
089 @Nullable
090 public static JetFile getContainingFile(@NotNull BindingContext context, @NotNull DeclarationDescriptor declarationDescriptor) {
091 // declarationDescriptor may describe a synthesized element which doesn't have PSI
092 // To workaround that, we find a top-level parent (which is inside a PackageFragmentDescriptor), which is guaranteed to have PSI
093 DeclarationDescriptor descriptor = DescriptorUtils.findTopLevelParent(declarationDescriptor);
094 if (descriptor == null) return null;
095
096 PsiElement declaration = descriptorToDeclaration(context, descriptor);
097 if (declaration == null) return null;
098
099 PsiFile containingFile = declaration.getContainingFile();
100 if (!(containingFile instanceof JetFile)) return null;
101 return (JetFile) containingFile;
102 }
103
104 @Nullable
105 private static PsiElement doGetDescriptorToDeclaration(@NotNull BindingContext context, @NotNull DeclarationDescriptor descriptor) {
106 return context.get(DESCRIPTOR_TO_DECLARATION, descriptor);
107 }
108
109 // NOTE this is also used by KDoc
110 @Nullable
111 public static PsiElement descriptorToDeclaration(@NotNull BindingContext context, @NotNull DeclarationDescriptor descriptor) {
112 if (descriptor instanceof CallableMemberDescriptor) {
113 return callableDescriptorToDeclaration(context, (CallableMemberDescriptor) descriptor);
114 }
115 else if (descriptor instanceof ClassDescriptor) {
116 return classDescriptorToDeclaration(context, (ClassDescriptor) descriptor);
117 }
118 else {
119 return doGetDescriptorToDeclaration(context, descriptor);
120 }
121 }
122
123 @NotNull
124 public static List<PsiElement> descriptorToDeclarations(@NotNull BindingContext context, @NotNull DeclarationDescriptor descriptor) {
125 if (descriptor instanceof CallableMemberDescriptor) {
126 return callableDescriptorToDeclarations(context, (CallableMemberDescriptor) descriptor);
127 }
128 else {
129 PsiElement psiElement = descriptorToDeclaration(context, descriptor);
130 if (psiElement != null) {
131 return Lists.newArrayList(psiElement);
132 } else {
133 return Lists.newArrayList();
134 }
135 }
136 }
137
138 @Nullable
139 public static PsiElement callableDescriptorToDeclaration(@NotNull BindingContext context, @NotNull CallableMemberDescriptor callable) {
140 if (callable.getKind() == SYNTHESIZED) {
141 CallableMemberDescriptor original = callable.getOriginal();
142 if (original instanceof SynthesizedCallableMemberDescriptor<?>) {
143 DeclarationDescriptor base = ((SynthesizedCallableMemberDescriptor<?>) original).getBaseForSynthesized();
144 return descriptorToDeclaration(context, base);
145 }
146 return null;
147 }
148
149 if (callable.getKind() == DECLARATION) {
150 return doGetDescriptorToDeclaration(context, callable.getOriginal());
151 }
152
153 Set<? extends CallableMemberDescriptor> overriddenDescriptors = callable.getOverriddenDescriptors();
154 if (overriddenDescriptors.size() != 1) {
155 throw new IllegalStateException(
156 "Cannot find declaration: fake descriptor " + callable + " has more than one overridden descriptor:\n" +
157 StringUtil.join(overriddenDescriptors, ",\n"));
158 }
159
160 return callableDescriptorToDeclaration(context, overriddenDescriptors.iterator().next());
161 }
162
163 @NotNull
164 public static List<PsiElement> callableDescriptorToDeclarations(
165 @NotNull BindingContext context,
166 @NotNull CallableMemberDescriptor callable
167 ) {
168 if (callable.getKind() == SYNTHESIZED) {
169 CallableMemberDescriptor original = callable.getOriginal();
170 if (original instanceof SynthesizedCallableMemberDescriptor<?>) {
171 DeclarationDescriptor base = ((SynthesizedCallableMemberDescriptor<?>) original).getBaseForSynthesized();
172 return descriptorToDeclarations(context, base);
173 }
174 return Collections.emptyList();
175 }
176
177 if (callable.getKind() == DECLARATION) {
178 PsiElement psiElement = doGetDescriptorToDeclaration(context, callable);
179 return psiElement != null ? Lists.newArrayList(psiElement) : Lists.<PsiElement>newArrayList();
180 }
181
182 List<PsiElement> r = new ArrayList<PsiElement>();
183 Set<? extends CallableMemberDescriptor> overriddenDescriptors = callable.getOverriddenDescriptors();
184 for (CallableMemberDescriptor overridden : overriddenDescriptors) {
185 r.addAll(callableDescriptorToDeclarations(context, overridden));
186 }
187 return r;
188 }
189
190 @Nullable
191 public static PsiElement classDescriptorToDeclaration(@NotNull BindingContext context, @NotNull ClassDescriptor clazz) {
192 return doGetDescriptorToDeclaration(context, clazz);
193 }
194
195 public static void recordFunctionDeclarationToDescriptor(@NotNull BindingTrace trace,
196 @NotNull PsiElement psiElement, @NotNull SimpleFunctionDescriptor function) {
197
198 if (function.getKind() != DECLARATION) {
199 throw new IllegalArgumentException("function of kind " + function.getKind() + " cannot have declaration");
200 }
201
202 trace.record(BindingContext.FUNCTION, psiElement, function);
203 }
204
205 @NotNull
206 public static <K, V> V getNotNull(
207 @NotNull BindingContext bindingContext,
208 @NotNull ReadOnlySlice<K, V> slice,
209 @NotNull K key
210 ) {
211 return getNotNull(bindingContext, slice, key, "Value at " + slice + " must not be null for " + key);
212 }
213
214 @NotNull
215 public static <K, V> V getNotNull(
216 @NotNull BindingContext bindingContext,
217 @NotNull ReadOnlySlice<K, V> slice,
218 @NotNull K key,
219 @NotNull String messageIfNull
220 ) {
221 V value = bindingContext.get(slice, key);
222 if (value == null) {
223 throw new IllegalStateException(messageIfNull);
224 }
225 return value;
226 }
227
228 @NotNull
229 public static DeclarationDescriptor getEnclosingDescriptor(@NotNull BindingContext context, @NotNull JetElement element) {
230 JetNamedDeclaration declaration = PsiTreeUtil.getParentOfType(element, JetNamedDeclaration.class);
231 if (declaration instanceof JetFunctionLiteral) {
232 return getEnclosingDescriptor(context, declaration);
233 }
234 DeclarationDescriptor descriptor = context.get(DECLARATION_TO_DESCRIPTOR, declaration);
235 assert descriptor != null : "No descriptor for named declaration: " + declaration.getText() + "\n(of type " + declaration.getClass() + ")";
236 return descriptor;
237 }
238
239 public static FunctionDescriptor getEnclosingFunctionDescriptor(@NotNull BindingContext context, @NotNull JetElement element) {
240 JetFunction function = PsiTreeUtil.getParentOfType(element, JetFunction.class);
241 return (FunctionDescriptor)context.get(DECLARATION_TO_DESCRIPTOR, function);
242 }
243
244 public static void reportAmbiguousLabel(
245 @NotNull BindingTrace trace,
246 @NotNull JetSimpleNameExpression targetLabel,
247 @NotNull Collection<DeclarationDescriptor> declarationsByLabel
248 ) {
249 Collection<PsiElement> targets = Lists.newArrayList();
250 for (DeclarationDescriptor descriptor : declarationsByLabel) {
251 PsiElement element = descriptorToDeclaration(trace.getBindingContext(), descriptor);
252 assert element != null : "Label can only point to something in the same lexical scope";
253 targets.add(element);
254 }
255 if (!targets.isEmpty()) {
256 trace.record(AMBIGUOUS_LABEL_TARGET, targetLabel, targets);
257 }
258 trace.report(AMBIGUOUS_LABEL.on(targetLabel));
259 }
260
261 @Nullable
262 public static JetType updateRecordedType(
263 @Nullable JetType type,
264 @NotNull JetExpression expression,
265 @NotNull BindingTrace trace,
266 boolean shouldBeMadeNullable
267 ) {
268 if (type == null) return null;
269 if (shouldBeMadeNullable) {
270 type = TypeUtils.makeNullable(type);
271 }
272 trace.record(BindingContext.EXPRESSION_TYPE, expression, type);
273 return type;
274 }
275
276 @Nullable
277 public static JetTypeInfo getRecordedTypeInfo(@NotNull JetExpression expression, @NotNull BindingContext context) {
278 if (!context.get(BindingContext.PROCESSED, expression)) return null;
279 DataFlowInfo dataFlowInfo = context.get(BindingContext.EXPRESSION_DATA_FLOW_INFO, expression);
280 if (dataFlowInfo == null) {
281 dataFlowInfo = DataFlowInfo.EMPTY;
282 }
283 JetType type = context.get(BindingContext.EXPRESSION_TYPE, expression);
284 return JetTypeInfo.create(type, dataFlowInfo);
285 }
286
287 public static boolean isExpressionWithValidReference(
288 @NotNull JetExpression expression,
289 @NotNull BindingContext context
290 ) {
291 if (expression instanceof JetCallExpression) {
292 return isCallExpressionWithValidReference(expression, context);
293 }
294
295 return expression instanceof JetReferenceExpression;
296 }
297
298 public static boolean isCallExpressionWithValidReference(
299 @NotNull JetExpression expression,
300 @NotNull BindingContext context
301 ) {
302 if (expression instanceof JetCallExpression) {
303 JetExpression calleeExpression = ((JetCallExpression) expression).getCalleeExpression();
304 ResolvedCall<? extends CallableDescriptor> resolvedCall = context.get(BindingContext.RESOLVED_CALL, calleeExpression);
305 if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
306 return true;
307 }
308 }
309 return false;
310 }
311
312 @NotNull
313 public static Set<CallableMemberDescriptor> getDirectlyOverriddenDeclarations(@NotNull CallableMemberDescriptor descriptor) {
314 Set<CallableMemberDescriptor> result = Sets.newHashSet();
315 Set<? extends CallableMemberDescriptor> overriddenDescriptors = descriptor.getOverriddenDescriptors();
316 for (CallableMemberDescriptor overriddenDescriptor : overriddenDescriptors) {
317 CallableMemberDescriptor.Kind kind = overriddenDescriptor.getKind();
318 if (kind == DECLARATION) {
319 result.add(overriddenDescriptor);
320 }
321 else if (kind == FAKE_OVERRIDE || kind == DELEGATION) {
322 result.addAll(getDirectlyOverriddenDeclarations(overriddenDescriptor));
323 }
324 else if (kind == SYNTHESIZED) {
325 //do nothing
326 }
327 else {
328 throw new AssertionError("Unexpected callable kind " + kind);
329 }
330 }
331 return OverridingUtil.filterOutOverridden(result);
332 }
333
334 @NotNull
335 public static Set<FunctionDescriptor> getDirectlyOverriddenDeclarations(@NotNull FunctionDescriptor descriptor) {
336 //noinspection unchecked
337 return (Set) getDirectlyOverriddenDeclarations((CallableMemberDescriptor) descriptor);
338 }
339
340 @NotNull
341 public static Set<PropertyDescriptor> getDirectlyOverriddenDeclarations(@NotNull PropertyDescriptor descriptor) {
342 //noinspection unchecked
343 return (Set) getDirectlyOverriddenDeclarations((CallableMemberDescriptor) descriptor);
344 }
345
346 @NotNull
347 public static <T extends CallableMemberDescriptor> Set<T> getAllOverriddenDeclarations(@NotNull T memberDescriptor) {
348 Set<T> result = Sets.newHashSet();
349 for (CallableMemberDescriptor overriddenDeclaration : memberDescriptor.getOverriddenDescriptors()) {
350 CallableMemberDescriptor.Kind kind = overriddenDeclaration.getKind();
351 if (kind == DECLARATION) {
352 //noinspection unchecked
353 result.add((T) overriddenDeclaration);
354 }
355 else if (kind == DELEGATION || kind == FAKE_OVERRIDE || kind == SYNTHESIZED) {
356 //do nothing
357 }
358 else {
359 throw new AssertionError("Unexpected callable kind " + kind);
360 }
361 //noinspection unchecked
362 result.addAll(getAllOverriddenDeclarations((T) overriddenDeclaration));
363 }
364 return result;
365 }
366 }