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