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.base.Predicate;
020 import com.google.common.collect.Lists;
021 import com.google.common.collect.Sets;
022 import org.jetbrains.annotations.NotNull;
023 import org.jetbrains.annotations.Nullable;
024 import org.jetbrains.jet.lang.descriptors.*;
025 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
026 import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor;
027 import org.jetbrains.jet.lang.psi.JetElement;
028 import org.jetbrains.jet.lang.psi.JetFunction;
029 import org.jetbrains.jet.lang.psi.JetParameter;
030 import org.jetbrains.jet.lang.psi.JetProperty;
031 import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
032 import org.jetbrains.jet.lang.resolve.name.FqName;
033 import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
034 import org.jetbrains.jet.lang.resolve.name.Name;
035 import org.jetbrains.jet.lang.resolve.scopes.FilteringScope;
036 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
037 import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
038 import org.jetbrains.jet.lang.types.DescriptorSubstitutor;
039 import org.jetbrains.jet.lang.types.JetType;
040 import org.jetbrains.jet.lang.types.TypeUtils;
041 import org.jetbrains.jet.lang.types.Variance;
042 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
043 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
044 import org.jetbrains.jet.renderer.DescriptorRenderer;
045
046 import java.util.*;
047
048 import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
049
050 public class DescriptorUtils {
051
052 @NotNull
053 public static <D extends CallableDescriptor> D substituteBounds(@NotNull D functionDescriptor) {
054 List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
055 if (typeParameters.isEmpty()) return functionDescriptor;
056
057 // TODO: this does not handle any recursion in the bounds
058 @SuppressWarnings("unchecked")
059 D substitutedFunction = (D) functionDescriptor.substitute(DescriptorSubstitutor.createUpperBoundsSubstitutor(typeParameters));
060 assert substitutedFunction != null : "Substituting upper bounds should always be legal";
061
062 return substitutedFunction;
063 }
064
065 public static Modality convertModality(Modality modality, boolean makeNonAbstract) {
066 if (makeNonAbstract && modality == Modality.ABSTRACT) return Modality.OPEN;
067 return modality;
068 }
069
070 @Nullable
071 public static ReceiverParameterDescriptor getExpectedThisObjectIfNeeded(@NotNull DeclarationDescriptor containingDeclaration) {
072 if (containingDeclaration instanceof ClassDescriptor) {
073 ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
074 return classDescriptor.getThisAsReceiverParameter();
075 }
076 else if (containingDeclaration instanceof ScriptDescriptor) {
077 ScriptDescriptor scriptDescriptor = (ScriptDescriptor) containingDeclaration;
078 return scriptDescriptor.getThisAsReceiverParameter();
079 }
080 return NO_RECEIVER_PARAMETER;
081 }
082
083 /**
084 * The primary case for local extensions is the following:
085 *
086 * I had a locally declared extension function or a local variable of function type called foo
087 * And I called it on my x
088 * Now, someone added function foo() to the class of x
089 * My code should not change
090 *
091 * thus
092 *
093 * local extension prevail over members (and members prevail over all non-local extensions)
094 */
095 public static boolean isLocal(DeclarationDescriptor containerOfTheCurrentLocality, DeclarationDescriptor candidate) {
096 if (candidate instanceof ValueParameterDescriptor) {
097 return true;
098 }
099 DeclarationDescriptor parent = candidate.getContainingDeclaration();
100 if (!(parent instanceof FunctionDescriptor)) {
101 return false;
102 }
103 FunctionDescriptor functionDescriptor = (FunctionDescriptor) parent;
104 DeclarationDescriptor current = containerOfTheCurrentLocality;
105 while (current != null) {
106 if (current == functionDescriptor) {
107 return true;
108 }
109 current = current.getContainingDeclaration();
110 }
111 return false;
112 }
113
114 @NotNull
115 public static FqNameUnsafe getFQName(@NotNull DeclarationDescriptor descriptor) {
116 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
117
118 if (descriptor instanceof ModuleDescriptor || containingDeclaration instanceof ModuleDescriptor) {
119 return FqName.ROOT.toUnsafe();
120 }
121
122 if (containingDeclaration == null) {
123 if (descriptor instanceof NamespaceDescriptor) {
124 // TODO: namespace must always have parent
125 if (descriptor.getName().equals(Name.identifier("jet"))) {
126 return FqNameUnsafe.topLevel(Name.identifier("jet"));
127 }
128 if (descriptor.getName().equals(Name.special("<java_root>"))) {
129 return FqName.ROOT.toUnsafe();
130 }
131 }
132 throw new IllegalStateException("descriptor is not module descriptor and has null containingDeclaration: " + containingDeclaration);
133 }
134
135 if (containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.CLASS_OBJECT) {
136 DeclarationDescriptor classOfClassObject = containingDeclaration.getContainingDeclaration();
137 assert classOfClassObject != null;
138 return getFQName(classOfClassObject).child(descriptor.getName());
139 }
140
141 return getFQName(containingDeclaration).child(descriptor.getName());
142 }
143
144 public static boolean isTopLevelDeclaration(@NotNull DeclarationDescriptor descriptor) {
145 return descriptor.getContainingDeclaration() instanceof NamespaceDescriptor;
146 }
147
148 public static boolean isInSameModule(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second) {
149 ModuleDescriptor parentModule = DescriptorUtils.getParentOfType(first, ModuleDescriptorImpl.class, false);
150 ModuleDescriptor fromModule = DescriptorUtils.getParentOfType(second, ModuleDescriptorImpl.class, false);
151 assert parentModule != null && fromModule != null;
152 return parentModule.equals(fromModule);
153 }
154
155 @Nullable
156 public static DeclarationDescriptor findTopLevelParent(@NotNull DeclarationDescriptor declarationDescriptor) {
157 DeclarationDescriptor descriptor = declarationDescriptor;
158 if (declarationDescriptor instanceof PropertyAccessorDescriptor) {
159 descriptor = ((PropertyAccessorDescriptor)descriptor).getCorrespondingProperty();
160 }
161 while (!(descriptor == null || isTopLevelDeclaration(descriptor))) {
162 descriptor = descriptor.getContainingDeclaration();
163 }
164 return descriptor;
165 }
166
167 @Nullable
168 public static <D extends DeclarationDescriptor> D getParentOfType(@Nullable DeclarationDescriptor descriptor, @NotNull Class<D> aClass) {
169 return getParentOfType(descriptor, aClass, true);
170 }
171
172 @Nullable
173 public static <D extends DeclarationDescriptor> D getParentOfType(@Nullable DeclarationDescriptor descriptor, @NotNull Class<D> aClass, boolean strict) {
174 if (descriptor == null) return null;
175 if (strict) {
176 descriptor = descriptor.getContainingDeclaration();
177 }
178 while (descriptor != null) {
179 if (aClass.isInstance(descriptor)) {
180 //noinspection unchecked
181 return (D) descriptor;
182 }
183 descriptor = descriptor.getContainingDeclaration();
184 }
185 return null;
186 }
187
188 public static boolean isAncestor(@Nullable DeclarationDescriptor ancestor, @NotNull DeclarationDescriptor declarationDescriptor, boolean strict) {
189 if (ancestor == null) return false;
190 DeclarationDescriptor descriptor = strict ? declarationDescriptor.getContainingDeclaration() : declarationDescriptor;
191 while (descriptor != null) {
192 if (ancestor == descriptor) return true;
193 descriptor = descriptor.getContainingDeclaration();
194 }
195 return false;
196 }
197
198 @NotNull
199 public static JetType getFunctionExpectedReturnType(@NotNull FunctionDescriptor descriptor, @NotNull JetElement function) {
200 JetType expectedType;
201 if (function instanceof JetFunction) {
202 if (((JetFunction) function).getReturnTypeRef() != null || ((JetFunction) function).hasBlockBody()) {
203 expectedType = descriptor.getReturnType();
204 }
205 else {
206 expectedType = TypeUtils.NO_EXPECTED_TYPE;
207 }
208 }
209 else {
210 expectedType = descriptor.getReturnType();
211 }
212 return expectedType != null ? expectedType : TypeUtils.NO_EXPECTED_TYPE;
213 }
214
215 public static boolean isSubclass(@NotNull ClassDescriptor subClass, @NotNull ClassDescriptor superClass) {
216 return isSubtypeOfClass(subClass.getDefaultType(), superClass.getOriginal());
217 }
218
219 private static boolean isSubtypeOfClass(@NotNull JetType type, @NotNull DeclarationDescriptor superClass) {
220 DeclarationDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
221 if (descriptor != null && superClass == descriptor.getOriginal()) {
222 return true;
223 }
224 for (JetType superType : type.getConstructor().getSupertypes()) {
225 if (isSubtypeOfClass(superType, superClass)) {
226 return true;
227 }
228 }
229 return false;
230 }
231
232 public static void addSuperTypes(JetType type, Set<JetType> set) {
233 set.add(type);
234
235 for (JetType jetType : type.getConstructor().getSupertypes()) {
236 addSuperTypes(jetType, set);
237 }
238 }
239
240 public static boolean isRootNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
241 return namespaceDescriptor.getContainingDeclaration() instanceof ModuleDescriptor;
242 }
243
244 @NotNull
245 public static List<DeclarationDescriptor> getPathWithoutRootNsAndModule(@NotNull DeclarationDescriptor descriptor) {
246 List<DeclarationDescriptor> path = Lists.newArrayList();
247 DeclarationDescriptor current = descriptor;
248 while (true) {
249 if (current instanceof NamespaceDescriptor && isRootNamespace((NamespaceDescriptor) current)) {
250 return Lists.reverse(path);
251 }
252 path.add(current);
253 current = current.getContainingDeclaration();
254 }
255 }
256
257 public static boolean isFunctionLiteral(@NotNull FunctionDescriptor descriptor) {
258 return descriptor instanceof AnonymousFunctionDescriptor;
259 }
260
261 public static boolean isClassObject(@NotNull DeclarationDescriptor descriptor) {
262 return isKindOf(descriptor, ClassKind.CLASS_OBJECT);
263 }
264
265 public static boolean isAnonymous(@Nullable ClassifierDescriptor descriptor) {
266 return isKindOf(descriptor, ClassKind.OBJECT) && descriptor.getName().isSpecial();
267 }
268
269 public static boolean isEnumEntry(@NotNull DeclarationDescriptor descriptor) {
270 return isKindOf(descriptor, ClassKind.ENUM_ENTRY);
271 }
272
273 public static boolean isEnumClass(@NotNull DeclarationDescriptor descriptor) {
274 return isKindOf(descriptor, ClassKind.ENUM_CLASS);
275 }
276
277 public static boolean isAnnotationClass(@Nullable DeclarationDescriptor descriptor) {
278 return isKindOf(descriptor, ClassKind.ANNOTATION_CLASS);
279 }
280
281 public static boolean isClass(@NotNull DeclarationDescriptor descriptor) {
282 return isKindOf(descriptor, ClassKind.CLASS);
283 }
284
285 public static boolean isKindOf(@NotNull JetType jetType, @NotNull ClassKind classKind) {
286 ClassifierDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
287 return isKindOf(descriptor, classKind);
288 }
289
290 public static boolean isKindOf(@Nullable DeclarationDescriptor descriptor, @NotNull ClassKind classKind) {
291 if (descriptor instanceof ClassDescriptor) {
292 return ((ClassDescriptor) descriptor).getKind() == classKind;
293 }
294 return false;
295 }
296
297 @NotNull
298 public static List<ClassDescriptor> getSuperclassDescriptors(@NotNull ClassDescriptor classDescriptor) {
299 Collection<JetType> superclassTypes = classDescriptor.getTypeConstructor().getSupertypes();
300 List<ClassDescriptor> superClassDescriptors = new ArrayList<ClassDescriptor>();
301 for (JetType type : superclassTypes) {
302 ClassDescriptor result = getClassDescriptorForType(type);
303 if (isNotAny(result)) {
304 superClassDescriptors.add(result);
305 }
306 }
307 return superClassDescriptors;
308 }
309
310 @NotNull
311 public static ClassDescriptor getClassDescriptorForType(@NotNull JetType type) {
312 DeclarationDescriptor superClassDescriptor =
313 type.getConstructor().getDeclarationDescriptor();
314 assert superClassDescriptor instanceof ClassDescriptor
315 : "Superclass descriptor of a type should be of type ClassDescriptor";
316 return (ClassDescriptor)superClassDescriptor;
317 }
318
319 public static boolean isNotAny(@NotNull DeclarationDescriptor superClassDescriptor) {
320 return !superClassDescriptor.equals(KotlinBuiltIns.getInstance().getAny());
321 }
322
323 public static boolean inStaticContext(@NotNull DeclarationDescriptor descriptor) {
324 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
325 if (containingDeclaration instanceof NamespaceDescriptor) {
326 return true;
327 }
328 if (containingDeclaration instanceof ClassDescriptor) {
329 ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
330
331 if (classDescriptor.getKind().isObject()) {
332 return inStaticContext(classDescriptor.getContainingDeclaration());
333 }
334
335 }
336 return false;
337 }
338
339 public static boolean isIteratorWithoutRemoveImpl(@NotNull ClassDescriptor classDescriptor) {
340 ClassDescriptor iteratorOfT = KotlinBuiltIns.getInstance().getIterator();
341 JetType iteratorOfAny = TypeUtils.substituteParameters(iteratorOfT, Collections.singletonList(KotlinBuiltIns.getInstance().getAnyType()));
342 boolean isIterator = JetTypeChecker.INSTANCE.isSubtypeOf(classDescriptor.getDefaultType(), iteratorOfAny);
343 boolean hasRemove = hasMethod(classDescriptor, Name.identifier("remove"));
344 return isIterator && !hasRemove;
345 }
346
347 private static boolean hasMethod(ClassDescriptor classDescriptor, Name name) {
348 Collection<FunctionDescriptor> removeFunctions = classDescriptor.getDefaultType().getMemberScope().getFunctions(name);
349 for (FunctionDescriptor function : removeFunctions) {
350 if (function.getValueParameters().isEmpty() && function.getTypeParameters().isEmpty()) {
351 return true;
352 }
353 }
354 return false;
355 }
356
357 @NotNull
358 public static Name getClassObjectName(@NotNull Name className) {
359 return Name.special("<class-object-for-" + className.asString() + ">");
360 }
361
362 public static boolean isEnumClassObject(@NotNull DeclarationDescriptor descriptor) {
363 if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() == ClassKind.CLASS_OBJECT) {
364 DeclarationDescriptor containing = descriptor.getContainingDeclaration();
365 if ((containing instanceof ClassDescriptor) && ((ClassDescriptor) containing).getKind() == ClassKind.ENUM_CLASS) {
366 return true;
367 }
368 }
369 return false;
370 }
371
372 @NotNull
373 public static Visibility getDefaultConstructorVisibility(@NotNull ClassDescriptor classDescriptor) {
374 ClassKind classKind = classDescriptor.getKind();
375 if (classKind == ClassKind.ENUM_CLASS) {
376 return Visibilities.PRIVATE;
377 }
378 if (classKind.isObject()) {
379 return Visibilities.PRIVATE;
380 }
381 assert classKind == ClassKind.CLASS || classKind == ClassKind.TRAIT || classKind == ClassKind.ANNOTATION_CLASS;
382 return Visibilities.PUBLIC;
383 }
384
385 @NotNull
386 public static List<String> getSortedValueArguments(
387 @NotNull AnnotationDescriptor descriptor,
388 @Nullable DescriptorRenderer rendererForTypesIfNecessary
389 ) {
390 List<String> resultList = Lists.newArrayList();
391 for (Map.Entry<ValueParameterDescriptor, CompileTimeConstant<?>> entry : descriptor.getAllValueArguments().entrySet()) {
392 CompileTimeConstant<?> value = entry.getValue();
393 String typeSuffix = rendererForTypesIfNecessary == null
394 ? ""
395 : ": " + rendererForTypesIfNecessary.renderType(value.getType(KotlinBuiltIns.getInstance()));
396 resultList.add(entry.getKey().getName().asString() + " = " + value.toString() + typeSuffix);
397 }
398 Collections.sort(resultList);
399 return resultList;
400 }
401
402 @Nullable
403 public static ClassDescriptor getInnerClassByName(@NotNull ClassDescriptor classDescriptor, @NotNull String innerClassName) {
404 ClassifierDescriptor classifier = classDescriptor.getDefaultType().getMemberScope().getClassifier(Name.identifier(innerClassName));
405 assert classifier instanceof ClassDescriptor :
406 "Inner class " + innerClassName + " in " + classDescriptor + " should be instance of ClassDescriptor, but was: "
407 + (classifier == null ? "null" : classifier.getClass());
408 return (ClassDescriptor) classifier;
409 }
410
411 @NotNull
412 public static ConstructorDescriptor getConstructorOfDataClass(ClassDescriptor classDescriptor) {
413 ConstructorDescriptor descriptor = getConstructorDescriptorIfOnlyOne(classDescriptor);
414 assert descriptor != null : "Data class must have only one constructor: " + classDescriptor.getConstructors();
415 return descriptor;
416 }
417
418 @NotNull
419 public static ConstructorDescriptor getConstructorOfSingletonObject(ClassDescriptor classDescriptor) {
420 ConstructorDescriptor descriptor = getConstructorDescriptorIfOnlyOne(classDescriptor);
421 assert descriptor != null : "Class of singleton object must have only one constructor: " + classDescriptor.getConstructors();
422 return descriptor;
423 }
424
425 @Nullable
426 private static ConstructorDescriptor getConstructorDescriptorIfOnlyOne(ClassDescriptor classDescriptor) {
427 Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
428 return constructors.size() != 1 ? null : constructors.iterator().next();
429 }
430
431 @Nullable
432 public static JetType getReceiverParameterType(@Nullable ReceiverParameterDescriptor receiverParameterDescriptor) {
433 if (receiverParameterDescriptor == null) {
434 return null;
435 }
436 return receiverParameterDescriptor.getType();
437 }
438
439 @NotNull
440 public static ReceiverValue safeGetValue(@Nullable ReceiverParameterDescriptor receiverParameterDescriptor) {
441 if (receiverParameterDescriptor == null) {
442 return ReceiverValue.NO_RECEIVER;
443 }
444 return receiverParameterDescriptor.getValue();
445 }
446
447
448 public static boolean isExternallyAccessible(PropertyDescriptor propertyDescriptor) {
449 return propertyDescriptor.getVisibility() != Visibilities.PRIVATE || isClassObject(propertyDescriptor.getContainingDeclaration())
450 || isTopLevelDeclaration(propertyDescriptor);
451 }
452
453 @NotNull
454 public static JetType getVarargParameterType(@NotNull JetType elementType) {
455 return getVarargParameterType(elementType, Variance.INVARIANT);
456 }
457
458 @NotNull
459 public static JetType getVarargParameterType(@NotNull JetType elementType, @NotNull Variance projectionKind) {
460 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
461 JetType primitiveArrayType = builtIns.getPrimitiveArrayJetTypeByPrimitiveJetType(elementType);
462 if (primitiveArrayType != null) {
463 return primitiveArrayType;
464 }
465 else {
466 return builtIns.getArrayType(projectionKind, elementType);
467 }
468 }
469
470 @NotNull
471 public static List<JetType> getValueParametersTypes(@NotNull List<ValueParameterDescriptor> valueParameters) {
472 List<JetType> parameterTypes = Lists.newArrayList();
473 for (ValueParameterDescriptor parameter : valueParameters) {
474 parameterTypes.add(parameter.getType());
475 }
476 return parameterTypes;
477 }
478
479 public static boolean isConstructorOfStaticNestedClass(@Nullable CallableDescriptor descriptor) {
480 return descriptor instanceof ConstructorDescriptor && isStaticNestedClass(descriptor.getContainingDeclaration());
481 }
482
483 /**
484 * @return true if descriptor is a class inside another class and does not have access to the outer class
485 */
486 public static boolean isStaticNestedClass(@NotNull DeclarationDescriptor descriptor) {
487 DeclarationDescriptor containing = descriptor.getContainingDeclaration();
488 return descriptor instanceof ClassDescriptor &&
489 containing instanceof ClassDescriptor &&
490 !((ClassDescriptor) descriptor).isInner() &&
491 !((ClassDescriptor) containing).getKind().isObject();
492 }
493
494 @Nullable
495 public static ClassDescriptor getContainingClass(@NotNull JetScope scope) {
496 DeclarationDescriptor containingDeclaration = scope.getContainingDeclaration();
497 return getParentOfType(containingDeclaration, ClassDescriptor.class, false);
498 }
499
500 @NotNull
501 public static JetScope getStaticNestedClassesScope(@NotNull ClassDescriptor descriptor) {
502 JetScope innerClassesScope = descriptor.getUnsubstitutedInnerClassesScope();
503 return new FilteringScope(innerClassesScope, new Predicate<DeclarationDescriptor>() {
504 @Override
505 public boolean apply(@Nullable DeclarationDescriptor descriptor) {
506 return descriptor instanceof ClassDescriptor && !((ClassDescriptor) descriptor).isInner();
507 }
508 });
509 }
510
511 public static boolean isEnumValueOfMethod(@NotNull FunctionDescriptor functionDescriptor) {
512 List<ValueParameterDescriptor> methodTypeParameters = functionDescriptor.getValueParameters();
513 JetType nullableString = TypeUtils.makeNullable(KotlinBuiltIns.getInstance().getStringType());
514 return "valueOf".equals(functionDescriptor.getName().asString())
515 && methodTypeParameters.size() == 1
516 && JetTypeChecker.INSTANCE.isSubtypeOf(methodTypeParameters.get(0).getType(), nullableString);
517 }
518
519 public static boolean isEnumValuesMethod(@NotNull FunctionDescriptor functionDescriptor) {
520 List<ValueParameterDescriptor> methodTypeParameters = functionDescriptor.getValueParameters();
521 return "values".equals(functionDescriptor.getName().asString())
522 && methodTypeParameters.isEmpty();
523 }
524
525 @NotNull
526 public static Set<ClassDescriptor> getAllSuperClasses(@NotNull ClassDescriptor klass) {
527 Set<JetType> allSupertypes = TypeUtils.getAllSupertypes(klass.getDefaultType());
528 Set<ClassDescriptor> allSuperclasses = Sets.newHashSet();
529 for (JetType supertype : allSupertypes) {
530 ClassDescriptor superclass = TypeUtils.getClassDescriptor(supertype);
531 assert superclass != null;
532 allSuperclasses.add(superclass);
533 }
534 return allSuperclasses;
535 }
536
537 @NotNull
538 public static PropertyDescriptor getPropertyDescriptor(@NotNull JetProperty property, @NotNull BindingContext bindingContext) {
539 VariableDescriptor descriptor = bindingContext.get(BindingContext.VARIABLE, property);
540 if (!(descriptor instanceof PropertyDescriptor)) {
541 throw new UnsupportedOperationException("expect a property to have a property descriptor");
542 }
543 return (PropertyDescriptor) descriptor;
544 }
545
546
547 @NotNull
548 public static PropertyDescriptor getPropertyDescriptor(@NotNull JetParameter constructorParameter, @NotNull BindingContext bindingContext) {
549 assert constructorParameter.getValOrVarNode() != null;
550 PropertyDescriptor descriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, constructorParameter);
551 assert descriptor != null;
552 return descriptor;
553 }
554
555 /**
556 * @return true iff {@code descriptor}'s first non-class container is a namespace
557 */
558 public static boolean isTopLevelOrInnerClass(@NotNull ClassDescriptor descriptor) {
559 DeclarationDescriptor containing = descriptor.getContainingDeclaration();
560 return isTopLevelDeclaration(descriptor) ||
561 containing instanceof ClassDescriptor && isTopLevelOrInnerClass((ClassDescriptor) containing);
562 }
563
564 @NotNull
565 public static JetScope getEnumEntriesScope(@NotNull ClassDescriptor enumClass) {
566 assert enumClass.getKind() == ClassKind.ENUM_CLASS : "Only enum classes have enum entries: " + enumClass;
567 ClassDescriptor classObject = enumClass.getClassObjectDescriptor();
568 assert classObject != null : "Enum class should have a class object: " + enumClass;
569 return classObject.getDefaultType().getMemberScope();
570 }
571 }