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 017package org.jetbrains.jet.lang.resolve; 018 019import com.google.common.base.Predicate; 020import com.google.common.collect.Lists; 021import com.google.common.collect.Sets; 022import org.jetbrains.annotations.NotNull; 023import org.jetbrains.annotations.Nullable; 024import org.jetbrains.jet.lang.descriptors.*; 025import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 026import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor; 027import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorParent; 028import org.jetbrains.jet.lang.psi.JetElement; 029import org.jetbrains.jet.lang.psi.JetFunction; 030import org.jetbrains.jet.lang.psi.JetParameter; 031import org.jetbrains.jet.lang.psi.JetProperty; 032import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; 033import org.jetbrains.jet.lang.resolve.name.FqName; 034import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; 035import org.jetbrains.jet.lang.resolve.name.Name; 036import org.jetbrains.jet.lang.resolve.scopes.FilteringScope; 037import org.jetbrains.jet.lang.resolve.scopes.JetScope; 038import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; 039import org.jetbrains.jet.lang.types.*; 040import org.jetbrains.jet.lang.types.checker.JetTypeChecker; 041import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 042import org.jetbrains.jet.renderer.DescriptorRenderer; 043 044import java.util.*; 045 046import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER; 047import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.DONT_CARE; 048 049public 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 isClass(@NotNull DeclarationDescriptor descriptor) { 293 return isKindOf(descriptor, ClassKind.CLASS); 294 } 295 296 public static boolean isKindOf(@NotNull JetType jetType, @NotNull ClassKind classKind) { 297 ClassifierDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); 298 return isKindOf(descriptor, classKind); 299 } 300 301 public static boolean isKindOf(@Nullable DeclarationDescriptor descriptor, @NotNull ClassKind classKind) { 302 if (descriptor instanceof ClassDescriptor) { 303 return ((ClassDescriptor) descriptor).getKind() == classKind; 304 } 305 return false; 306 } 307 308 @NotNull 309 public static List<ClassDescriptor> getSuperclassDescriptors(@NotNull ClassDescriptor classDescriptor) { 310 Collection<JetType> superclassTypes = classDescriptor.getTypeConstructor().getSupertypes(); 311 List<ClassDescriptor> superClassDescriptors = new ArrayList<ClassDescriptor>(); 312 for (JetType type : superclassTypes) { 313 ClassDescriptor result = getClassDescriptorForType(type); 314 if (isNotAny(result)) { 315 superClassDescriptors.add(result); 316 } 317 } 318 return superClassDescriptors; 319 } 320 321 @NotNull 322 public static ClassDescriptor getClassDescriptorForType(@NotNull JetType type) { 323 DeclarationDescriptor superClassDescriptor = 324 type.getConstructor().getDeclarationDescriptor(); 325 assert superClassDescriptor instanceof ClassDescriptor 326 : "Superclass descriptor of a type should be of type ClassDescriptor"; 327 return (ClassDescriptor)superClassDescriptor; 328 } 329 330 public static boolean isNotAny(@NotNull DeclarationDescriptor superClassDescriptor) { 331 return !superClassDescriptor.equals(KotlinBuiltIns.getInstance().getAny()); 332 } 333 334 public static boolean inStaticContext(@NotNull DeclarationDescriptor descriptor) { 335 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); 336 if (containingDeclaration instanceof NamespaceDescriptor) { 337 return true; 338 } 339 if (containingDeclaration instanceof ClassDescriptor) { 340 ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration; 341 342 if (classDescriptor.getKind().isObject()) { 343 return inStaticContext(classDescriptor.getContainingDeclaration()); 344 } 345 346 } 347 return false; 348 } 349 350 public static boolean isIteratorWithoutRemoveImpl(@NotNull ClassDescriptor classDescriptor) { 351 ClassDescriptor iteratorOfT = KotlinBuiltIns.getInstance().getIterator(); 352 JetType iteratorOfAny = TypeUtils.substituteParameters(iteratorOfT, Collections.singletonList(KotlinBuiltIns.getInstance().getAnyType())); 353 boolean isIterator = JetTypeChecker.INSTANCE.isSubtypeOf(classDescriptor.getDefaultType(), iteratorOfAny); 354 boolean hasRemove = hasMethod(classDescriptor, Name.identifier("remove")); 355 return isIterator && !hasRemove; 356 } 357 358 private static boolean hasMethod(ClassDescriptor classDescriptor, Name name) { 359 Collection<FunctionDescriptor> removeFunctions = classDescriptor.getDefaultType().getMemberScope().getFunctions(name); 360 for (FunctionDescriptor function : removeFunctions) { 361 if (function.getValueParameters().isEmpty() && function.getTypeParameters().isEmpty()) { 362 return true; 363 } 364 } 365 return false; 366 } 367 368 @NotNull 369 public static Name getClassObjectName(@NotNull Name className) { 370 return getClassObjectName(className.asString()); 371 } 372 373 @NotNull 374 public static Name getClassObjectName(@NotNull String className) { 375 return Name.special("<class-object-for-" + className + ">"); 376 } 377 378 public static boolean isEnumClassObject(@NotNull DeclarationDescriptor descriptor) { 379 if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() == ClassKind.CLASS_OBJECT) { 380 DeclarationDescriptor containing = descriptor.getContainingDeclaration(); 381 if ((containing instanceof ClassDescriptor) && ((ClassDescriptor) containing).getKind() == ClassKind.ENUM_CLASS) { 382 return true; 383 } 384 } 385 return false; 386 } 387 388 @NotNull 389 public static Visibility getDefaultConstructorVisibility(@NotNull ClassDescriptor classDescriptor) { 390 ClassKind classKind = classDescriptor.getKind(); 391 if (classKind == ClassKind.ENUM_CLASS) { 392 return Visibilities.PRIVATE; 393 } 394 if (classKind.isObject()) { 395 return Visibilities.PRIVATE; 396 } 397 assert classKind == ClassKind.CLASS || classKind == ClassKind.TRAIT || classKind == ClassKind.ANNOTATION_CLASS; 398 return Visibilities.PUBLIC; 399 } 400 401 @NotNull 402 public static List<String> getSortedValueArguments( 403 @NotNull AnnotationDescriptor descriptor, 404 @Nullable DescriptorRenderer rendererForTypesIfNecessary 405 ) { 406 List<String> resultList = Lists.newArrayList(); 407 for (Map.Entry<ValueParameterDescriptor, CompileTimeConstant<?>> entry : descriptor.getAllValueArguments().entrySet()) { 408 CompileTimeConstant<?> value = entry.getValue(); 409 String typeSuffix = rendererForTypesIfNecessary == null 410 ? "" 411 : ": " + rendererForTypesIfNecessary.renderType(value.getType(KotlinBuiltIns.getInstance())); 412 resultList.add(entry.getKey().getName().asString() + " = " + value.toString() + typeSuffix); 413 } 414 Collections.sort(resultList); 415 return resultList; 416 } 417 418 @Nullable 419 public static ClassDescriptor getInnerClassByName(@NotNull ClassDescriptor classDescriptor, @NotNull String innerClassName) { 420 ClassifierDescriptor classifier = classDescriptor.getDefaultType().getMemberScope().getClassifier(Name.identifier(innerClassName)); 421 assert classifier instanceof ClassDescriptor : 422 "Inner class " + innerClassName + " in " + classDescriptor + " should be instance of ClassDescriptor, but was: " 423 + (classifier == null ? "null" : classifier.getClass()); 424 return (ClassDescriptor) classifier; 425 } 426 427 @NotNull 428 public static ConstructorDescriptor getConstructorOfDataClass(ClassDescriptor classDescriptor) { 429 ConstructorDescriptor descriptor = getConstructorDescriptorIfOnlyOne(classDescriptor); 430 assert descriptor != null : "Data class must have only one constructor: " + classDescriptor.getConstructors(); 431 return descriptor; 432 } 433 434 @NotNull 435 public static ConstructorDescriptor getConstructorOfSingletonObject(ClassDescriptor classDescriptor) { 436 ConstructorDescriptor descriptor = getConstructorDescriptorIfOnlyOne(classDescriptor); 437 assert descriptor != null : "Class of singleton object must have only one constructor: " + classDescriptor.getConstructors(); 438 return descriptor; 439 } 440 441 @Nullable 442 private static ConstructorDescriptor getConstructorDescriptorIfOnlyOne(ClassDescriptor classDescriptor) { 443 Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors(); 444 return constructors.size() != 1 ? null : constructors.iterator().next(); 445 } 446 447 @Nullable 448 public static JetType getReceiverParameterType(@Nullable ReceiverParameterDescriptor receiverParameterDescriptor) { 449 if (receiverParameterDescriptor == null) { 450 return null; 451 } 452 return receiverParameterDescriptor.getType(); 453 } 454 455 @NotNull 456 public static ReceiverValue safeGetValue(@Nullable ReceiverParameterDescriptor receiverParameterDescriptor) { 457 if (receiverParameterDescriptor == null) { 458 return ReceiverValue.NO_RECEIVER; 459 } 460 return receiverParameterDescriptor.getValue(); 461 } 462 463 464 public static boolean isExternallyAccessible(PropertyDescriptor propertyDescriptor) { 465 return propertyDescriptor.getVisibility() != Visibilities.PRIVATE || isClassObject(propertyDescriptor.getContainingDeclaration()) 466 || isTopLevelDeclaration(propertyDescriptor); 467 } 468 469 @NotNull 470 public static JetType getVarargParameterType(@NotNull JetType elementType) { 471 return getVarargParameterType(elementType, Variance.INVARIANT); 472 } 473 474 @NotNull 475 public static JetType getVarargParameterType(@NotNull JetType elementType, @NotNull Variance projectionKind) { 476 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); 477 JetType primitiveArrayType = builtIns.getPrimitiveArrayJetTypeByPrimitiveJetType(elementType); 478 if (primitiveArrayType != null) { 479 return primitiveArrayType; 480 } 481 else { 482 return builtIns.getArrayType(projectionKind, elementType); 483 } 484 } 485 486 @NotNull 487 public static List<JetType> getValueParametersTypes(@NotNull List<ValueParameterDescriptor> valueParameters) { 488 List<JetType> parameterTypes = Lists.newArrayList(); 489 for (ValueParameterDescriptor parameter : valueParameters) { 490 parameterTypes.add(parameter.getType()); 491 } 492 return parameterTypes; 493 } 494 495 public static boolean isConstructorOfStaticNestedClass(@Nullable CallableDescriptor descriptor) { 496 return descriptor instanceof ConstructorDescriptor && isStaticNestedClass(descriptor.getContainingDeclaration()); 497 } 498 499 /** 500 * @return true if descriptor is a class inside another class and does not have access to the outer class 501 */ 502 public static boolean isStaticNestedClass(@NotNull DeclarationDescriptor descriptor) { 503 DeclarationDescriptor containing = descriptor.getContainingDeclaration(); 504 return descriptor instanceof ClassDescriptor && 505 containing instanceof ClassDescriptor && 506 !((ClassDescriptor) descriptor).isInner() && 507 !((ClassDescriptor) containing).getKind().isObject(); 508 } 509 510 @Nullable 511 public static ClassDescriptor getContainingClass(@NotNull JetScope scope) { 512 DeclarationDescriptor containingDeclaration = scope.getContainingDeclaration(); 513 return getParentOfType(containingDeclaration, ClassDescriptor.class, false); 514 } 515 516 @NotNull 517 public static JetScope getStaticNestedClassesScope(@NotNull ClassDescriptor descriptor) { 518 JetScope innerClassesScope = descriptor.getUnsubstitutedInnerClassesScope(); 519 return new FilteringScope(innerClassesScope, new Predicate<DeclarationDescriptor>() { 520 @Override 521 public boolean apply(@Nullable DeclarationDescriptor descriptor) { 522 return descriptor instanceof ClassDescriptor && !((ClassDescriptor) descriptor).isInner(); 523 } 524 }); 525 } 526 527 @Nullable 528 public static ClassDescriptor getClassForCorrespondingJavaNamespace(@NotNull NamespaceDescriptor correspondingNamespace) { 529 NamespaceDescriptorParent containingDeclaration = correspondingNamespace.getContainingDeclaration(); 530 if (!(containingDeclaration instanceof NamespaceDescriptor)) { 531 return null; 532 } 533 534 NamespaceDescriptor namespaceDescriptor = (NamespaceDescriptor) containingDeclaration; 535 536 ClassifierDescriptor classDescriptor = namespaceDescriptor.getMemberScope().getClassifier(correspondingNamespace.getName()); 537 if (classDescriptor != null && classDescriptor instanceof ClassDescriptor) { 538 return (ClassDescriptor) classDescriptor; 539 } 540 541 ClassDescriptor classDescriptorForOuterClass = getClassForCorrespondingJavaNamespace(namespaceDescriptor); 542 if (classDescriptorForOuterClass == null) { 543 return null; 544 } 545 546 ClassifierDescriptor innerClassDescriptor = 547 classDescriptorForOuterClass.getUnsubstitutedInnerClassesScope().getClassifier(correspondingNamespace.getName()); 548 if (innerClassDescriptor instanceof ClassDescriptor) { 549 return (ClassDescriptor) innerClassDescriptor; 550 } 551 return null; 552 } 553 554 public static boolean isEnumValueOfMethod(@NotNull FunctionDescriptor functionDescriptor) { 555 List<ValueParameterDescriptor> methodTypeParameters = functionDescriptor.getValueParameters(); 556 JetType nullableString = TypeUtils.makeNullable(KotlinBuiltIns.getInstance().getStringType()); 557 return "valueOf".equals(functionDescriptor.getName().asString()) 558 && methodTypeParameters.size() == 1 559 && JetTypeChecker.INSTANCE.isSubtypeOf(methodTypeParameters.get(0).getType(), nullableString); 560 } 561 562 public static boolean isEnumValuesMethod(@NotNull FunctionDescriptor functionDescriptor) { 563 List<ValueParameterDescriptor> methodTypeParameters = functionDescriptor.getValueParameters(); 564 return "values".equals(functionDescriptor.getName().asString()) 565 && methodTypeParameters.isEmpty(); 566 } 567 568 @NotNull 569 public static Set<ClassDescriptor> getAllSuperClasses(@NotNull ClassDescriptor klass) { 570 Set<JetType> allSupertypes = TypeUtils.getAllSupertypes(klass.getDefaultType()); 571 Set<ClassDescriptor> allSuperclasses = Sets.newHashSet(); 572 for (JetType supertype : allSupertypes) { 573 ClassDescriptor superclass = TypeUtils.getClassDescriptor(supertype); 574 assert superclass != null; 575 allSuperclasses.add(superclass); 576 } 577 return allSuperclasses; 578 } 579 580 @NotNull 581 public static PropertyDescriptor getPropertyDescriptor(@NotNull JetProperty property, @NotNull BindingContext bindingContext) { 582 VariableDescriptor descriptor = bindingContext.get(BindingContext.VARIABLE, property); 583 if (!(descriptor instanceof PropertyDescriptor)) { 584 throw new UnsupportedOperationException("expect a property to have a property descriptor"); 585 } 586 return (PropertyDescriptor) descriptor; 587 } 588 589 590 @NotNull 591 public static PropertyDescriptor getPropertyDescriptor(@NotNull JetParameter constructorParameter, @NotNull BindingContext bindingContext) { 592 assert constructorParameter.getValOrVarNode() != null; 593 PropertyDescriptor descriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, constructorParameter); 594 assert descriptor != null; 595 return descriptor; 596 } 597}