001 /* 002 * Copyright 2010-2015 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.kotlin.resolve; 018 019 import kotlin.jvm.functions.Function1; 020 import org.jetbrains.annotations.NotNull; 021 import org.jetbrains.annotations.Nullable; 022 import org.jetbrains.kotlin.builtins.KotlinBuiltIns; 023 import org.jetbrains.kotlin.descriptors.*; 024 import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor; 025 import org.jetbrains.kotlin.descriptors.impl.FunctionExpressionDescriptor; 026 import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl; 027 import org.jetbrains.kotlin.name.FqName; 028 import org.jetbrains.kotlin.name.FqNameUnsafe; 029 import org.jetbrains.kotlin.name.Name; 030 import org.jetbrains.kotlin.name.SpecialNames; 031 import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter; 032 import org.jetbrains.kotlin.resolve.scopes.FilteringScope; 033 import org.jetbrains.kotlin.resolve.scopes.JetScope; 034 import org.jetbrains.kotlin.types.ErrorUtils; 035 import org.jetbrains.kotlin.types.JetType; 036 import org.jetbrains.kotlin.types.LazyType; 037 import org.jetbrains.kotlin.types.TypeConstructor; 038 import org.jetbrains.kotlin.types.checker.JetTypeChecker; 039 040 import java.util.*; 041 042 import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isAny; 043 import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.*; 044 import static org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER; 045 import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getBuiltIns; 046 047 public class DescriptorUtils { 048 public static final Name ENUM_VALUES = Name.identifier("values"); 049 public static final Name ENUM_VALUE_OF = Name.identifier("valueOf"); 050 051 private DescriptorUtils() { 052 } 053 054 @Nullable 055 public static ReceiverParameterDescriptor getDispatchReceiverParameterIfNeeded(@NotNull DeclarationDescriptor containingDeclaration) { 056 if (containingDeclaration instanceof ClassDescriptor) { 057 ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration; 058 return classDescriptor.getThisAsReceiverParameter(); 059 } 060 else if (containingDeclaration instanceof ScriptDescriptor) { 061 ScriptDescriptor scriptDescriptor = (ScriptDescriptor) containingDeclaration; 062 return scriptDescriptor.getThisAsReceiverParameter(); 063 } 064 return NO_RECEIVER_PARAMETER; 065 } 066 067 /** 068 * Descriptor may be local itself or have a local ancestor 069 */ 070 public static boolean isLocal(@NotNull DeclarationDescriptor descriptor) { 071 DeclarationDescriptor current = descriptor; 072 while (current != null) { 073 if (isAnonymousObject(current) || isDescriptorWithLocalVisibility(current)) { 074 return true; 075 } 076 current = current.getContainingDeclaration(); 077 } 078 return false; 079 } 080 081 private static boolean isDescriptorWithLocalVisibility(DeclarationDescriptor current) { 082 return current instanceof DeclarationDescriptorWithVisibility && 083 ((DeclarationDescriptorWithVisibility) current).getVisibility() == Visibilities.LOCAL; 084 } 085 086 @NotNull 087 public static FqNameUnsafe getFqName(@NotNull DeclarationDescriptor descriptor) { 088 FqName safe = getFqNameSafeIfPossible(descriptor); 089 return safe != null ? safe.toUnsafe() : getFqNameUnsafe(descriptor); 090 } 091 092 @NotNull 093 public static FqName getFqNameSafe(@NotNull DeclarationDescriptor descriptor) { 094 FqName safe = getFqNameSafeIfPossible(descriptor); 095 return safe != null ? safe : getFqNameUnsafe(descriptor).toSafe(); 096 } 097 098 099 @Nullable 100 private static FqName getFqNameSafeIfPossible(@NotNull DeclarationDescriptor descriptor) { 101 if (descriptor instanceof ModuleDescriptor || ErrorUtils.isError(descriptor)) { 102 return FqName.ROOT; 103 } 104 105 if (descriptor instanceof PackageViewDescriptor) { 106 return ((PackageViewDescriptor) descriptor).getFqName(); 107 } 108 else if (descriptor instanceof PackageFragmentDescriptor) { 109 return ((PackageFragmentDescriptor) descriptor).getFqName(); 110 } 111 112 return null; 113 } 114 115 @NotNull 116 private static FqNameUnsafe getFqNameUnsafe(@NotNull DeclarationDescriptor descriptor) { 117 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); 118 assert containingDeclaration != null : "Not package/module descriptor doesn't have containing declaration: " + descriptor; 119 return getFqName(containingDeclaration).child(descriptor.getName()); 120 } 121 122 @NotNull 123 public static FqName getFqNameFromTopLevelClass(@NotNull DeclarationDescriptor descriptor) { 124 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); 125 Name name = descriptor.getName(); 126 if (!(containingDeclaration instanceof ClassDescriptor)) { 127 return FqName.topLevel(name); 128 } 129 return getFqNameFromTopLevelClass(containingDeclaration).child(name); 130 } 131 132 public static boolean isTopLevelDeclaration(@NotNull DeclarationDescriptor descriptor) { 133 return descriptor.getContainingDeclaration() instanceof PackageFragmentDescriptor; 134 } 135 136 public static boolean isExtension(@NotNull CallableDescriptor descriptor) { 137 return (descriptor.getExtensionReceiverParameter() != null); 138 } 139 140 public static boolean isOverride(@NotNull CallableMemberDescriptor descriptor) { 141 return !descriptor.getOverriddenDescriptors().isEmpty(); 142 } 143 144 /** 145 * @return true iff this is a top-level declaration or a class member with no expected "this" object (e.g. static members in Java, 146 * values() and valueOf() methods of enum classes, etc.) 147 */ 148 public static boolean isStaticDeclaration(@NotNull CallableDescriptor descriptor) { 149 if (descriptor instanceof ConstructorDescriptor) return false; 150 151 DeclarationDescriptor container = descriptor.getContainingDeclaration(); 152 return container instanceof PackageFragmentDescriptor || 153 (container instanceof ClassDescriptor && descriptor.getDispatchReceiverParameter() == null); 154 } 155 156 // WARNING! Don't use this method in JVM backend, use JvmCodegenUtil.isCallInsideSameModuleAsDeclared() instead. 157 // The latter handles compilation against compiled part of our module correctly. 158 public static boolean areInSameModule(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second) { 159 return getContainingModule(first).equals(getContainingModule(second)); 160 } 161 162 @Nullable 163 public static <D extends DeclarationDescriptor> D getParentOfType( 164 @Nullable DeclarationDescriptor descriptor, 165 @NotNull Class<D> aClass 166 ) { 167 return getParentOfType(descriptor, aClass, true); 168 } 169 170 @Nullable 171 public static <D extends DeclarationDescriptor> D getParentOfType( 172 @Nullable DeclarationDescriptor descriptor, 173 @NotNull Class<D> aClass, 174 boolean strict 175 ) { 176 if (descriptor == null) return null; 177 if (strict) { 178 descriptor = descriptor.getContainingDeclaration(); 179 } 180 while (descriptor != null) { 181 if (aClass.isInstance(descriptor)) { 182 //noinspection unchecked 183 return (D) descriptor; 184 } 185 descriptor = descriptor.getContainingDeclaration(); 186 } 187 return null; 188 } 189 190 @NotNull 191 public static ModuleDescriptor getContainingModule(@NotNull DeclarationDescriptor descriptor) { 192 ModuleDescriptor module = getContainingModuleOrNull(descriptor); 193 assert module != null : "Descriptor without a containing module: " + descriptor; 194 return module; 195 } 196 197 @Nullable 198 public static ModuleDescriptor getContainingModuleOrNull(@NotNull DeclarationDescriptor descriptor) { 199 ModuleDescriptor moduleDescriptor = getParentOfType(descriptor, ModuleDescriptor.class, false); 200 if (moduleDescriptor != null) { 201 return moduleDescriptor; 202 } 203 PackageViewDescriptor packageViewDescriptor = getParentOfType(descriptor, PackageViewDescriptor.class, false); 204 if (packageViewDescriptor != null) { 205 return packageViewDescriptor.getModule(); 206 } 207 return null; 208 } 209 210 @Nullable 211 public static ClassDescriptor getContainingClass(@NotNull DeclarationDescriptor descriptor) { 212 DeclarationDescriptor containing = descriptor.getContainingDeclaration(); 213 while (containing != null) { 214 if (containing instanceof ClassDescriptor && !isCompanionObject(containing)) { 215 return (ClassDescriptor) containing; 216 } 217 containing = containing.getContainingDeclaration(); 218 } 219 return null; 220 } 221 222 public static boolean isAncestor( 223 @Nullable DeclarationDescriptor ancestor, 224 @NotNull DeclarationDescriptor declarationDescriptor, 225 boolean strict 226 ) { 227 if (ancestor == null) return false; 228 DeclarationDescriptor descriptor = strict ? declarationDescriptor.getContainingDeclaration() : declarationDescriptor; 229 while (descriptor != null) { 230 if (ancestor == descriptor) return true; 231 descriptor = descriptor.getContainingDeclaration(); 232 } 233 return false; 234 } 235 236 public static boolean isSubclass(@NotNull ClassDescriptor subClass, @NotNull ClassDescriptor superClass) { 237 return isSubtypeOfClass(subClass.getDefaultType(), superClass.getOriginal()); 238 } 239 240 private static boolean isSubtypeOfClass(@NotNull JetType type, @NotNull DeclarationDescriptor superClass) { 241 DeclarationDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); 242 if (descriptor != null) { 243 DeclarationDescriptor originalDescriptor = descriptor.getOriginal(); 244 if (originalDescriptor instanceof ClassifierDescriptor 245 && superClass instanceof ClassifierDescriptor 246 && ((ClassifierDescriptor) superClass).getTypeConstructor().equals(((ClassifierDescriptor) originalDescriptor).getTypeConstructor())) { 247 return true; 248 } 249 } 250 251 for (JetType superType : type.getConstructor().getSupertypes()) { 252 if (isSubtypeOfClass(superType, superClass)) { 253 return true; 254 } 255 } 256 return false; 257 } 258 259 public static boolean isFunctionLiteral(@Nullable DeclarationDescriptor descriptor) { 260 return descriptor instanceof AnonymousFunctionDescriptor; 261 } 262 263 public static boolean isLocalFunction(@Nullable DeclarationDescriptor descriptor) { 264 if (descriptor != null && descriptor.getClass() == SimpleFunctionDescriptorImpl.class) { 265 return ((SimpleFunctionDescriptorImpl) descriptor).getVisibility() == Visibilities.LOCAL; 266 } 267 return false; 268 } 269 270 public static boolean isFunctionExpression(@Nullable DeclarationDescriptor descriptor) { 271 return descriptor instanceof FunctionExpressionDescriptor; 272 } 273 274 public static boolean isCompanionObject(@Nullable DeclarationDescriptor descriptor) { 275 return isKindOf(descriptor, ClassKind.OBJECT) && ((ClassDescriptor) descriptor).isCompanionObject(); 276 } 277 278 public static boolean isAnonymousObject(@NotNull DeclarationDescriptor descriptor) { 279 return isClass(descriptor) && descriptor.getName().equals(SpecialNames.NO_NAME_PROVIDED); 280 } 281 282 public static boolean isNonCompanionObject(@NotNull DeclarationDescriptor descriptor) { 283 return isKindOf(descriptor, ClassKind.OBJECT) && !((ClassDescriptor) descriptor).isCompanionObject(); 284 } 285 286 public static boolean isObject(@NotNull DeclarationDescriptor descriptor) { 287 return isKindOf(descriptor, ClassKind.OBJECT); 288 } 289 290 public static boolean isEnumEntry(@NotNull DeclarationDescriptor descriptor) { 291 return isKindOf(descriptor, ClassKind.ENUM_ENTRY); 292 } 293 294 public static boolean isSingleton(@Nullable DeclarationDescriptor classifier) { 295 if (classifier instanceof ClassDescriptor) { 296 ClassDescriptor clazz = (ClassDescriptor) classifier; 297 return clazz.getKind().isSingleton(); 298 } 299 return false; 300 } 301 302 public static boolean isEnumClass(@Nullable DeclarationDescriptor descriptor) { 303 return isKindOf(descriptor, ClassKind.ENUM_CLASS); 304 } 305 306 public static boolean isAnnotationClass(@Nullable DeclarationDescriptor descriptor) { 307 return isKindOf(descriptor, ClassKind.ANNOTATION_CLASS); 308 } 309 310 public static boolean isTrait(@Nullable DeclarationDescriptor descriptor) { 311 return isKindOf(descriptor, ClassKind.INTERFACE); 312 } 313 314 public static boolean isClass(@Nullable DeclarationDescriptor descriptor) { 315 return isKindOf(descriptor, ClassKind.CLASS); 316 } 317 318 private static boolean isKindOf(@Nullable DeclarationDescriptor descriptor, @NotNull ClassKind classKind) { 319 return descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() == classKind; 320 } 321 322 @NotNull 323 public static List<ClassDescriptor> getSuperclassDescriptors(@NotNull ClassDescriptor classDescriptor) { 324 Collection<JetType> superclassTypes = classDescriptor.getTypeConstructor().getSupertypes(); 325 List<ClassDescriptor> superClassDescriptors = new ArrayList<ClassDescriptor>(); 326 for (JetType type : superclassTypes) { 327 ClassDescriptor result = getClassDescriptorForType(type); 328 if (!isAny(result)) { 329 superClassDescriptors.add(result); 330 } 331 } 332 return superClassDescriptors; 333 } 334 335 @NotNull 336 public static JetType getSuperClassType(@NotNull ClassDescriptor classDescriptor) { 337 Collection<JetType> superclassTypes = classDescriptor.getTypeConstructor().getSupertypes(); 338 for (JetType type : superclassTypes) { 339 ClassDescriptor superClassDescriptor = getClassDescriptorForType(type); 340 if (superClassDescriptor.getKind() != ClassKind.INTERFACE) { 341 return type; 342 } 343 } 344 return getBuiltIns(classDescriptor).getAnyType(); 345 } 346 347 @NotNull 348 public static ClassDescriptor getClassDescriptorForType(@NotNull JetType type) { 349 return getClassDescriptorForTypeConstructor(type.getConstructor()); 350 } 351 352 @NotNull 353 public static ClassDescriptor getClassDescriptorForTypeConstructor(@NotNull TypeConstructor typeConstructor) { 354 ClassifierDescriptor descriptor = typeConstructor.getDeclarationDescriptor(); 355 assert descriptor instanceof ClassDescriptor 356 : "Classifier descriptor of a type should be of type ClassDescriptor: " + typeConstructor; 357 return (ClassDescriptor) descriptor; 358 } 359 360 @NotNull 361 public static Visibility getDefaultConstructorVisibility(@NotNull ClassDescriptor classDescriptor) { 362 ClassKind classKind = classDescriptor.getKind(); 363 if (classKind == ClassKind.ENUM_CLASS || classKind.isSingleton()) { 364 return Visibilities.PRIVATE; 365 } 366 if (isAnonymousObject(classDescriptor)) { 367 return Visibilities.INTERNAL; 368 } 369 assert classKind == ClassKind.CLASS || classKind == ClassKind.INTERFACE || classKind == ClassKind.ANNOTATION_CLASS; 370 return Visibilities.PUBLIC; 371 } 372 373 @Nullable 374 public static ClassDescriptor getInnerClassByName(@NotNull ClassDescriptor classDescriptor, @NotNull String innerClassName) { 375 ClassifierDescriptor classifier = classDescriptor.getDefaultType().getMemberScope().getClassifier(Name.identifier(innerClassName)); 376 assert classifier instanceof ClassDescriptor : 377 "Inner class " + innerClassName + " in " + classDescriptor + " should be instance of ClassDescriptor, but was: " 378 + (classifier == null ? "null" : classifier.getClass()); 379 return (ClassDescriptor) classifier; 380 } 381 382 @Nullable 383 public static JetType getReceiverParameterType(@Nullable ReceiverParameterDescriptor receiverParameterDescriptor) { 384 return receiverParameterDescriptor == null ? null : receiverParameterDescriptor.getType(); 385 } 386 387 /** 388 * @return true if descriptor is a class inside another class and does not have access to the outer class 389 */ 390 public static boolean isStaticNestedClass(@NotNull DeclarationDescriptor descriptor) { 391 DeclarationDescriptor containing = descriptor.getContainingDeclaration(); 392 return descriptor instanceof ClassDescriptor && 393 containing instanceof ClassDescriptor && 394 !((ClassDescriptor) descriptor).isInner(); 395 } 396 397 @NotNull 398 public static JetScope getStaticNestedClassesScope(@NotNull ClassDescriptor descriptor) { 399 JetScope innerClassesScope = descriptor.getUnsubstitutedInnerClassesScope(); 400 return new FilteringScope(innerClassesScope, new Function1<DeclarationDescriptor, Boolean>() { 401 @Override 402 public Boolean invoke(DeclarationDescriptor descriptor) { 403 return descriptor instanceof ClassDescriptor && !((ClassDescriptor) descriptor).isInner(); 404 } 405 }); 406 } 407 408 /** 409 * @return true iff {@code descriptor}'s first non-class container is a package 410 */ 411 public static boolean isTopLevelOrInnerClass(@NotNull ClassDescriptor descriptor) { 412 DeclarationDescriptor containing = descriptor.getContainingDeclaration(); 413 return isTopLevelDeclaration(descriptor) || 414 containing instanceof ClassDescriptor && isTopLevelOrInnerClass((ClassDescriptor) containing); 415 } 416 417 /** 418 * Given a fake override, finds any declaration of it in the overridden descriptors. Keep in mind that there may be many declarations 419 * of the fake override in the supertypes, this method finds just the only one. 420 * TODO: probably all call-sites of this method are wrong, they should handle all super-declarations 421 */ 422 @NotNull 423 public static <D extends CallableMemberDescriptor> D unwrapFakeOverride(@NotNull D descriptor) { 424 while (descriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { 425 Set<? extends CallableMemberDescriptor> overridden = descriptor.getOverriddenDescriptors(); 426 if (overridden.isEmpty()) { 427 throw new IllegalStateException("Fake override should have at least one overridden descriptor: " + descriptor); 428 } 429 //noinspection unchecked 430 descriptor = (D) overridden.iterator().next(); 431 } 432 return descriptor; 433 } 434 435 public static boolean shouldRecordInitializerForProperty(@NotNull VariableDescriptor variable, @NotNull JetType type) { 436 if (variable.isVar() || type.isError()) return false; 437 438 if (type instanceof LazyType || type.isMarkedNullable()) return true; 439 440 KotlinBuiltIns builtIns = getBuiltIns(variable); 441 return KotlinBuiltIns.isPrimitiveType(type) || 442 JetTypeChecker.DEFAULT.equalTypes(builtIns.getStringType(), type) || 443 JetTypeChecker.DEFAULT.equalTypes(builtIns.getNumber().getDefaultType(), type) || 444 JetTypeChecker.DEFAULT.equalTypes(builtIns.getAnyType(), type); 445 } 446 447 public static boolean classCanHaveAbstractMembers(@NotNull ClassDescriptor classDescriptor) { 448 return classDescriptor.getModality() == Modality.ABSTRACT || classDescriptor.getKind() == ClassKind.ENUM_CLASS; 449 } 450 451 public static boolean classCanHaveOpenMembers(@NotNull ClassDescriptor classDescriptor) { 452 return classDescriptor.getModality() != Modality.FINAL || classDescriptor.getKind() == ClassKind.ENUM_CLASS; 453 } 454 455 @NotNull 456 @SuppressWarnings("unchecked") 457 public static <D extends CallableDescriptor> Set<D> getAllOverriddenDescriptors(@NotNull D f) { 458 Set<D> result = new LinkedHashSet<D>(); 459 collectAllOverriddenDescriptors((D) f.getOriginal(), result); 460 return result; 461 } 462 463 private static <D extends CallableDescriptor> void collectAllOverriddenDescriptors(@NotNull D current, @NotNull Set<D> result) { 464 if (result.contains(current)) return; 465 for (CallableDescriptor callableDescriptor : current.getOriginal().getOverriddenDescriptors()) { 466 @SuppressWarnings("unchecked") 467 D descriptor = (D) callableDescriptor; 468 collectAllOverriddenDescriptors(descriptor, result); 469 result.add(descriptor); 470 } 471 } 472 473 @NotNull 474 public static <D extends CallableMemberDescriptor> Set<D> getAllOverriddenDeclarations(@NotNull D memberDescriptor) { 475 Set<D> result = new HashSet<D>(); 476 for (CallableMemberDescriptor overriddenDeclaration : memberDescriptor.getOverriddenDescriptors()) { 477 CallableMemberDescriptor.Kind kind = overriddenDeclaration.getKind(); 478 if (kind == DECLARATION) { 479 //noinspection unchecked 480 result.add((D) overriddenDeclaration); 481 } 482 else if (kind == DELEGATION || kind == FAKE_OVERRIDE || kind == SYNTHESIZED) { 483 //do nothing 484 } 485 else { 486 throw new AssertionError("Unexpected callable kind " + kind); 487 } 488 //noinspection unchecked 489 result.addAll(getAllOverriddenDeclarations((D) overriddenDeclaration)); 490 } 491 return result; 492 } 493 494 public static boolean containsReifiedTypeParameterWithName(@NotNull CallableDescriptor descriptor, @NotNull String name) { 495 for (TypeParameterDescriptor typeParameterDescriptor : descriptor.getTypeParameters()) { 496 if (typeParameterDescriptor.isReified() && typeParameterDescriptor.getName().asString().equals(name)) return true; 497 } 498 499 return false; 500 } 501 502 public static boolean containsReifiedTypeParameters(@NotNull CallableDescriptor descriptor) { 503 for (TypeParameterDescriptor typeParameterDescriptor : descriptor.getTypeParameters()) { 504 if (typeParameterDescriptor.isReified()) return true; 505 } 506 507 return false; 508 } 509 510 public static boolean isSingletonOrAnonymousObject(@NotNull ClassDescriptor classDescriptor) { 511 return classDescriptor.getKind().isSingleton() || isAnonymousObject(classDescriptor); 512 } 513 514 public static boolean canHaveDeclaredConstructors(@NotNull ClassDescriptor classDescriptor) { 515 return !isSingletonOrAnonymousObject(classDescriptor) && !isTrait(classDescriptor); 516 } 517 518 public static Set<FqName> getPackagesFqNames(ModuleDescriptor module) { 519 Set<FqName> result = getSubPackagesFqNames(module.getPackage(FqName.ROOT)); 520 result.add(FqName.ROOT); 521 return result; 522 } 523 524 public static Set<FqName> getSubPackagesFqNames(PackageViewDescriptor packageView) { 525 Set<FqName> result = new HashSet<FqName>(); 526 getSubPackagesFqNames(packageView, result); 527 528 return result; 529 } 530 531 private static void getSubPackagesFqNames(PackageViewDescriptor packageView, Set<FqName> result) { 532 FqName fqName = packageView.getFqName(); 533 if (!fqName.isRoot()) { 534 result.add(fqName); 535 } 536 537 for (DeclarationDescriptor descriptor : packageView.getMemberScope().getDescriptors(DescriptorKindFilter.PACKAGES, JetScope.ALL_NAME_FILTER)) { 538 if (descriptor instanceof PackageViewDescriptor) { 539 getSubPackagesFqNames((PackageViewDescriptor) descriptor, result); 540 } 541 } 542 } 543 544 public static boolean isJavaLangClass(ClassDescriptor descriptor) { 545 return "java.lang.Class".equals(getFqName(descriptor).asString()); 546 } 547 }