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