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