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 NamespaceDescriptor), 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 // TODO these helper methods are added as a workaround to some compiler bugs in Kotlin...
105
106 // NOTE this is used by KDoc
107 @Nullable
108 public static NamespaceDescriptor namespaceDescriptor(@NotNull BindingContext context, @NotNull JetFile source) {
109 return context.get(BindingContext.FILE_TO_NAMESPACE, source);
110 }
111
112 @Nullable
113 private static PsiElement doGetDescriptorToDeclaration(@NotNull BindingContext context, @NotNull DeclarationDescriptor descriptor) {
114 return context.get(DESCRIPTOR_TO_DECLARATION, descriptor);
115 }
116
117 // NOTE this is also used by KDoc
118 @Nullable
119 public static PsiElement descriptorToDeclaration(@NotNull BindingContext context, @NotNull DeclarationDescriptor descriptor) {
120 if (descriptor instanceof CallableMemberDescriptor) {
121 return callableDescriptorToDeclaration(context, (CallableMemberDescriptor) descriptor);
122 }
123 else if (descriptor instanceof ClassDescriptor) {
124 return classDescriptorToDeclaration(context, (ClassDescriptor) descriptor);
125 }
126 else {
127 return doGetDescriptorToDeclaration(context, descriptor);
128 }
129 }
130
131 @NotNull
132 public static List<PsiElement> descriptorToDeclarations(@NotNull BindingContext context, @NotNull DeclarationDescriptor descriptor) {
133 if (descriptor instanceof CallableMemberDescriptor) {
134 return callableDescriptorToDeclarations(context, (CallableMemberDescriptor) descriptor);
135 }
136 else {
137 PsiElement psiElement = descriptorToDeclaration(context, descriptor);
138 if (psiElement != null) {
139 return Lists.newArrayList(psiElement);
140 } else {
141 return Lists.newArrayList();
142 }
143 }
144 }
145
146 @Nullable
147 public static PsiElement callableDescriptorToDeclaration(@NotNull BindingContext context, @NotNull CallableMemberDescriptor callable) {
148 if (callable.getKind() == SYNTHESIZED) {
149 CallableMemberDescriptor original = callable.getOriginal();
150 if (original instanceof SynthesizedCallableMemberDescriptor<?>) {
151 DeclarationDescriptor base = ((SynthesizedCallableMemberDescriptor<?>) original).getBaseForSynthesized();
152 return descriptorToDeclaration(context, base);
153 }
154 return null;
155 }
156
157 if (callable.getKind() == DECLARATION) {
158 return doGetDescriptorToDeclaration(context, callable.getOriginal());
159 }
160
161 Set<? extends CallableMemberDescriptor> overriddenDescriptors = callable.getOverriddenDescriptors();
162 if (overriddenDescriptors.size() != 1) {
163 throw new IllegalStateException(
164 "Cannot find declaration: fake descriptor " + callable + " has more than one overridden descriptor:\n" +
165 StringUtil.join(overriddenDescriptors, ",\n"));
166 }
167
168 return callableDescriptorToDeclaration(context, overriddenDescriptors.iterator().next());
169 }
170
171 @NotNull
172 public static List<PsiElement> callableDescriptorToDeclarations(
173 @NotNull BindingContext context,
174 @NotNull CallableMemberDescriptor callable
175 ) {
176 if (callable.getKind() == SYNTHESIZED) {
177 CallableMemberDescriptor original = callable.getOriginal();
178 if (original instanceof SynthesizedCallableMemberDescriptor<?>) {
179 DeclarationDescriptor base = ((SynthesizedCallableMemberDescriptor<?>) original).getBaseForSynthesized();
180 return descriptorToDeclarations(context, base);
181 }
182 return Collections.emptyList();
183 }
184
185 if (callable.getKind() == DECLARATION) {
186 PsiElement psiElement = doGetDescriptorToDeclaration(context, callable);
187 return psiElement != null ? Lists.newArrayList(psiElement) : Lists.<PsiElement>newArrayList();
188 }
189
190 List<PsiElement> r = new ArrayList<PsiElement>();
191 Set<? extends CallableMemberDescriptor> overriddenDescriptors = callable.getOverriddenDescriptors();
192 for (CallableMemberDescriptor overridden : overriddenDescriptors) {
193 r.addAll(callableDescriptorToDeclarations(context, overridden));
194 }
195 return r;
196 }
197
198 @Nullable
199 public static PsiElement classDescriptorToDeclaration(@NotNull BindingContext context, @NotNull ClassDescriptor clazz) {
200 return doGetDescriptorToDeclaration(context, clazz);
201 }
202
203 public static void recordFunctionDeclarationToDescriptor(@NotNull BindingTrace trace,
204 @NotNull PsiElement psiElement, @NotNull SimpleFunctionDescriptor function) {
205
206 if (function.getKind() != DECLARATION) {
207 throw new IllegalArgumentException("function of kind " + function.getKind() + " cannot have declaration");
208 }
209
210 trace.record(BindingContext.FUNCTION, psiElement, function);
211 }
212
213 @NotNull
214 public static <K, V> V getNotNull(
215 @NotNull BindingContext bindingContext,
216 @NotNull ReadOnlySlice<K, V> slice,
217 @NotNull K key
218 ) {
219 return getNotNull(bindingContext, slice, key, "Value at " + slice + " must not be null for " + key);
220 }
221
222 @NotNull
223 public static <K, V> V getNotNull(
224 @NotNull BindingContext bindingContext,
225 @NotNull ReadOnlySlice<K, V> slice,
226 @NotNull K key,
227 @NotNull String messageIfNull
228 ) {
229 V value = bindingContext.get(slice, key);
230 if (value == null) {
231 throw new IllegalStateException(messageIfNull);
232 }
233 return value;
234 }
235
236 @NotNull
237 public static DeclarationDescriptor getEnclosingDescriptor(@NotNull BindingContext context, @NotNull JetElement element) {
238 JetNamedDeclaration declaration = PsiTreeUtil.getParentOfType(element, JetNamedDeclaration.class);
239 if (declaration instanceof JetFunctionLiteral) {
240 return getEnclosingDescriptor(context, declaration);
241 }
242 DeclarationDescriptor descriptor = context.get(DECLARATION_TO_DESCRIPTOR, declaration);
243 assert descriptor != null : "No descriptor for named declaration: " + declaration.getText() + "\n(of type " + declaration.getClass() + ")";
244 return descriptor;
245 }
246
247 public static void reportAmbiguousLabel(
248 @NotNull BindingTrace trace,
249 @NotNull JetSimpleNameExpression targetLabel,
250 @NotNull Collection<DeclarationDescriptor> declarationsByLabel
251 ) {
252 Collection<PsiElement> targets = Lists.newArrayList();
253 for (DeclarationDescriptor descriptor : declarationsByLabel) {
254 PsiElement element = descriptorToDeclaration(trace.getBindingContext(), descriptor);
255 assert element != null : "Label can only point to something in the same lexical scope";
256 targets.add(element);
257 }
258 if (!targets.isEmpty()) {
259 trace.record(AMBIGUOUS_LABEL_TARGET, targetLabel, targets);
260 }
261 trace.report(AMBIGUOUS_LABEL.on(targetLabel));
262 }
263
264 @Nullable
265 public static JetType updateRecordedType(
266 @Nullable JetType type,
267 @NotNull JetExpression expression,
268 @NotNull BindingTrace trace,
269 boolean shouldBeMadeNullable
270 ) {
271 if (type == null) return null;
272 if (shouldBeMadeNullable) {
273 type = TypeUtils.makeNullable(type);
274 }
275 trace.record(BindingContext.EXPRESSION_TYPE, expression, type);
276 trace.record(BindingContext.PROCESSED, expression);
277 return type;
278 }
279
280 @Nullable
281 public static JetTypeInfo getRecordedTypeInfo(@NotNull JetExpression expression, @NotNull BindingContext context) {
282 if (!context.get(BindingContext.PROCESSED, expression)) return null;
283 DataFlowInfo dataFlowInfo = context.get(BindingContext.EXPRESSION_DATA_FLOW_INFO, expression);
284 if (dataFlowInfo == null) {
285 dataFlowInfo = DataFlowInfo.EMPTY;
286 }
287 JetType type = context.get(BindingContext.EXPRESSION_TYPE, expression);
288 return JetTypeInfo.create(type, dataFlowInfo);
289 }
290
291 public static boolean isExpressionWithValidReference(
292 @NotNull JetExpression expression,
293 @NotNull BindingContext context
294 ) {
295 if (expression instanceof JetCallExpression) {
296 return isCallExpressionWithValidReference(expression, context);
297 }
298
299 return expression instanceof JetReferenceExpression;
300 }
301
302 public static boolean isCallExpressionWithValidReference(
303 @NotNull JetExpression expression,
304 @NotNull BindingContext context
305 ) {
306 if (expression instanceof JetCallExpression) {
307 JetExpression calleeExpression = ((JetCallExpression) expression).getCalleeExpression();
308 ResolvedCall<? extends CallableDescriptor> resolvedCall = context.get(BindingContext.RESOLVED_CALL, calleeExpression);
309 if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
310 return true;
311 }
312 }
313 return false;
314 }
315
316 @NotNull
317 public static Set<CallableMemberDescriptor> getDirectlyOverriddenDeclarations(@NotNull CallableMemberDescriptor descriptor) {
318 Set<CallableMemberDescriptor> result = Sets.newHashSet();
319 Set<? extends CallableMemberDescriptor> overriddenDescriptors = descriptor.getOverriddenDescriptors();
320 for (CallableMemberDescriptor overriddenDescriptor : overriddenDescriptors) {
321 CallableMemberDescriptor.Kind kind = overriddenDescriptor.getKind();
322 if (kind == DECLARATION) {
323 result.add(overriddenDescriptor);
324 }
325 else if (kind == FAKE_OVERRIDE || kind == DELEGATION) {
326 result.addAll(getDirectlyOverriddenDeclarations(overriddenDescriptor));
327 }
328 else if (kind == SYNTHESIZED) {
329 //do nothing
330 }
331 else {
332 throw new AssertionError("Unexpected callable kind " + kind);
333 }
334 }
335 return OverridingUtil.filterOutOverridden(result);
336 }
337
338 @NotNull
339 public static Set<FunctionDescriptor> getDirectlyOverriddenDeclarations(@NotNull FunctionDescriptor descriptor) {
340 //noinspection unchecked
341 return (Set) getDirectlyOverriddenDeclarations((CallableMemberDescriptor) descriptor);
342 }
343
344 @NotNull
345 public static Set<PropertyDescriptor> getDirectlyOverriddenDeclarations(@NotNull PropertyDescriptor descriptor) {
346 //noinspection unchecked
347 return (Set) getDirectlyOverriddenDeclarations((CallableMemberDescriptor) descriptor);
348 }
349
350 @NotNull
351 public static Set<FunctionDescriptor> getAllOverriddenDeclarations(@NotNull FunctionDescriptor functionDescriptor) {
352 Set<FunctionDescriptor> result = Sets.newHashSet();
353 for (FunctionDescriptor overriddenDeclaration : functionDescriptor.getOverriddenDescriptors()) {
354 CallableMemberDescriptor.Kind kind = overriddenDeclaration.getKind();
355 if (kind == DECLARATION) {
356 result.add(overriddenDeclaration);
357 }
358 else if (kind == DELEGATION || kind == FAKE_OVERRIDE || kind == SYNTHESIZED) {
359 //do nothing
360 }
361 else {
362 throw new AssertionError("Unexpected callable kind " + kind);
363 }
364 result.addAll(getAllOverriddenDeclarations(overriddenDeclaration));
365 }
366 return result;
367 }
368 }