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.codegen.context; 018 019 import kotlin.jvm.functions.Function0; 020 import org.jetbrains.annotations.NotNull; 021 import org.jetbrains.annotations.Nullable; 022 import org.jetbrains.annotations.ReadOnly; 023 import org.jetbrains.kotlin.codegen.*; 024 import org.jetbrains.kotlin.codegen.binding.MutableClosure; 025 import org.jetbrains.kotlin.codegen.state.GenerationState; 026 import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; 027 import org.jetbrains.kotlin.descriptors.*; 028 import org.jetbrains.kotlin.load.java.JavaVisibilities; 029 import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor; 030 import org.jetbrains.kotlin.psi.KtFile; 031 import org.jetbrains.kotlin.resolve.DescriptorUtils; 032 import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt; 033 import org.jetbrains.kotlin.storage.LockBasedStorageManager; 034 import org.jetbrains.kotlin.storage.NullableLazyValue; 035 import org.jetbrains.kotlin.types.KotlinType; 036 import org.jetbrains.org.objectweb.asm.Type; 037 038 import java.util.*; 039 040 import static org.jetbrains.kotlin.codegen.AsmUtil.getVisibilityAccessFlag; 041 import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface; 042 import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE; 043 import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PROTECTED; 044 045 public abstract class CodegenContext<T extends DeclarationDescriptor> { 046 private final T contextDescriptor; 047 private final OwnerKind contextKind; 048 private final CodegenContext parentContext; 049 private final ClassDescriptor thisDescriptor; 050 public final MutableClosure closure; 051 private final LocalLookup enclosingLocalLookup; 052 private final NullableLazyValue<StackValue.Field> outerExpression; 053 054 private Map<DeclarationDescriptor, CodegenContext> childContexts; 055 private Map<AccessorKey, AccessorForCallableDescriptor<?>> accessors; 056 private Map<AccessorKey, AccessorForPropertyDescriptorFactory> propertyAccessorFactories; 057 058 private static class AccessorKey { 059 public final DeclarationDescriptor descriptor; 060 public final ClassDescriptor superCallLabelTarget; 061 062 public AccessorKey( 063 @NotNull DeclarationDescriptor descriptor, 064 @Nullable ClassDescriptor superCallLabelTarget 065 ) { 066 this.descriptor = descriptor; 067 this.superCallLabelTarget = superCallLabelTarget; 068 } 069 070 @Override 071 public boolean equals(Object obj) { 072 if (!(obj instanceof AccessorKey)) return false; 073 AccessorKey other = (AccessorKey) obj; 074 return descriptor.equals(other.descriptor) && 075 (superCallLabelTarget == null ? other.superCallLabelTarget == null 076 : superCallLabelTarget.equals(other.superCallLabelTarget)); 077 } 078 079 @Override 080 public int hashCode() { 081 return 31 * descriptor.hashCode() + (superCallLabelTarget == null ? 0 : superCallLabelTarget.hashCode()); 082 } 083 084 @Override 085 public String toString() { 086 return descriptor.toString(); 087 } 088 } 089 090 private static class AccessorForPropertyDescriptorFactory { 091 private final @NotNull PropertyDescriptor property; 092 private final @NotNull DeclarationDescriptor containingDeclaration; 093 private final @Nullable ClassDescriptor superCallTarget; 094 private final @NotNull String nameSuffix; 095 096 private AccessorForPropertyDescriptor withSyntheticGetterAndSetter = null; 097 private AccessorForPropertyDescriptor withSyntheticGetter = null; 098 private AccessorForPropertyDescriptor withSyntheticSetter = null; 099 100 public AccessorForPropertyDescriptorFactory( 101 @NotNull PropertyDescriptor property, 102 @NotNull DeclarationDescriptor containingDeclaration, 103 @Nullable ClassDescriptor superCallTarget, 104 @NotNull String nameSuffix 105 ) { 106 this.property = property; 107 this.containingDeclaration = containingDeclaration; 108 this.superCallTarget = superCallTarget; 109 this.nameSuffix = nameSuffix; 110 } 111 112 @SuppressWarnings("ConstantConditions") 113 public PropertyDescriptor getOrCreateAccessorIfNeeded(boolean getterAccessorRequired, boolean setterAccessorRequired) { 114 if (getterAccessorRequired && setterAccessorRequired) { 115 return getOrCreateAccessorWithSyntheticGetterAndSetter(); 116 } 117 else if (getterAccessorRequired && !setterAccessorRequired) { 118 if (withSyntheticGetter == null) { 119 withSyntheticGetter = new AccessorForPropertyDescriptor( 120 property, containingDeclaration, superCallTarget, nameSuffix, 121 true, false); 122 } 123 return withSyntheticGetter; 124 } 125 else if (!getterAccessorRequired && setterAccessorRequired) { 126 if (withSyntheticSetter == null) { 127 withSyntheticSetter = new AccessorForPropertyDescriptor( 128 property, containingDeclaration, superCallTarget, nameSuffix, 129 false, true); 130 } 131 return withSyntheticSetter; 132 } 133 else { 134 return property; 135 } 136 } 137 138 @NotNull 139 public AccessorForPropertyDescriptor getOrCreateAccessorWithSyntheticGetterAndSetter() { 140 if (withSyntheticGetterAndSetter == null) { 141 withSyntheticGetterAndSetter = new AccessorForPropertyDescriptor( 142 property, containingDeclaration, superCallTarget, nameSuffix, 143 true, true); 144 } 145 return withSyntheticGetterAndSetter; 146 } 147 } 148 149 public CodegenContext( 150 @NotNull T contextDescriptor, 151 @NotNull OwnerKind contextKind, 152 @Nullable CodegenContext parentContext, 153 @Nullable MutableClosure closure, 154 @Nullable ClassDescriptor thisDescriptor, 155 @Nullable LocalLookup localLookup 156 ) { 157 this.contextDescriptor = contextDescriptor; 158 this.contextKind = contextKind; 159 this.parentContext = parentContext; 160 this.closure = closure; 161 this.thisDescriptor = thisDescriptor; 162 this.enclosingLocalLookup = localLookup; 163 this.outerExpression = LockBasedStorageManager.NO_LOCKS.createNullableLazyValue(new Function0<StackValue.Field>() { 164 @Override 165 public StackValue.Field invoke() { 166 return computeOuterExpression(); 167 } 168 }); 169 170 if (parentContext != null) { 171 parentContext.addChild(this); 172 } 173 } 174 175 @NotNull 176 public GenerationState getState() { 177 return parentContext.getState(); 178 } 179 180 @NotNull 181 public final ClassDescriptor getThisDescriptor() { 182 if (thisDescriptor == null) { 183 throw new UnsupportedOperationException("Context doesn't have a \"this\": " + this); 184 } 185 return thisDescriptor; 186 } 187 188 public final boolean hasThisDescriptor() { 189 return thisDescriptor != null; 190 } 191 192 @NotNull 193 @SuppressWarnings("unchecked") 194 public CodegenContext<? extends ClassOrPackageFragmentDescriptor> getClassOrPackageParentContext() { 195 CodegenContext<?> context = this; 196 while (true) { 197 if (context.getContextDescriptor() instanceof ClassOrPackageFragmentDescriptor) { 198 return (CodegenContext) context; 199 } 200 context = context.getParentContext(); 201 assert context != null : "Context which is not top-level has no parent: " + this; 202 } 203 } 204 205 /** 206 * This method returns not null only if context descriptor corresponds to method or function which has receiver 207 */ 208 @Nullable 209 public final CallableDescriptor getCallableDescriptorWithReceiver() { 210 if (contextDescriptor instanceof CallableDescriptor) { 211 CallableDescriptor callableDescriptor = (CallableDescriptor) getContextDescriptor(); 212 return callableDescriptor.getExtensionReceiverParameter() != null ? callableDescriptor : null; 213 } 214 return null; 215 } 216 217 public StackValue getOuterExpression(@Nullable StackValue prefix, boolean ignoreNoOuter) { 218 return getOuterExpression(prefix, ignoreNoOuter, true); 219 } 220 221 private StackValue getOuterExpression(@Nullable StackValue prefix, boolean ignoreNoOuter, boolean captureThis) { 222 if (outerExpression.invoke() == null) { 223 if (!ignoreNoOuter) { 224 throw new UnsupportedOperationException("Don't know how to generate outer expression for " + getContextDescriptor()); 225 } 226 return null; 227 } 228 if (captureThis) { 229 if (closure == null) { 230 throw new IllegalStateException("Can't capture this for context without closure: " + getContextDescriptor()); 231 } 232 closure.setCaptureThis(); 233 } 234 return StackValue.changeReceiverForFieldAndSharedVar(outerExpression.invoke(), prefix); 235 } 236 237 @NotNull 238 public T getContextDescriptor() { 239 return contextDescriptor; 240 } 241 242 @NotNull 243 public OwnerKind getContextKind() { 244 return contextKind; 245 } 246 247 @NotNull 248 public PackageContext intoPackagePart(@NotNull PackageFragmentDescriptor descriptor, Type packagePartType, @Nullable KtFile sourceFile) { 249 return new PackageContext(descriptor, this, packagePartType, sourceFile); 250 } 251 252 @NotNull 253 public MultifileClassPartContext intoMultifileClassPart( 254 @NotNull PackageFragmentDescriptor descriptor, 255 @NotNull Type multifileClassType, 256 @NotNull Type filePartType, 257 @NotNull Type filePartInitializerType, 258 @NotNull KtFile sourceFile 259 ) { 260 return new MultifileClassPartContext(descriptor, this, multifileClassType, filePartType, filePartInitializerType, sourceFile); 261 } 262 263 @NotNull 264 public FieldOwnerContext<PackageFragmentDescriptor> intoMultifileClass( 265 @NotNull PackageFragmentDescriptor descriptor, 266 @NotNull Type multifileClassType, 267 @NotNull Type filePartType 268 ) { 269 return new MultifileClassFacadeContext(descriptor, this, multifileClassType, filePartType); 270 } 271 272 public ClassContext intoDefaultImplsClass(ClassDescriptor descriptor, ClassContext interfaceContext, GenerationState state) { 273 return new DefaultImplsClassContext(state.getTypeMapper(), descriptor, OwnerKind.DEFAULT_IMPLS, this, null, interfaceContext); 274 } 275 276 @NotNull 277 public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind, GenerationState state) { 278 if (descriptor.isCompanionObject()) { 279 CodegenContext companionContext = this.findChildContext(descriptor); 280 if (companionContext != null) { 281 assert companionContext.getContextKind() == kind : "Kinds should be same, but: " + 282 companionContext.getContextKind() + "!= " + kind; 283 return (ClassContext) companionContext; 284 } 285 } 286 ClassContext classContext = new ClassContext(state.getTypeMapper(), descriptor, kind, this, null); 287 288 if (descriptor.getCompanionObjectDescriptor() != null) { 289 //We need to create companion object context ahead of time 290 // because otherwise we can't generate synthetic accessor for private members in companion object 291 classContext.intoClass(descriptor.getCompanionObjectDescriptor(), OwnerKind.IMPLEMENTATION, state); 292 } 293 return classContext; 294 } 295 296 @NotNull 297 public ClassContext intoAnonymousClass(@NotNull ClassDescriptor descriptor, @NotNull ExpressionCodegen codegen, @NotNull OwnerKind ownerKind) { 298 return new AnonymousClassContext(codegen.getState().getTypeMapper(), descriptor, ownerKind, this, codegen); 299 } 300 301 @NotNull 302 public MethodContext intoFunction(FunctionDescriptor descriptor) { 303 return new MethodContext(descriptor, getContextKind(), this, null); 304 } 305 306 @NotNull 307 public MethodContext intoInlinedLambda(FunctionDescriptor descriptor, boolean isCrossInline) { 308 return new InlineLambdaContext(descriptor, getContextKind(), this, null, isCrossInline); 309 } 310 311 @NotNull 312 public ConstructorContext intoConstructor(@NotNull ConstructorDescriptor descriptor) { 313 return new ConstructorContext(descriptor, getContextKind(), this, closure); 314 } 315 316 @NotNull 317 public ScriptContext intoScript( 318 @NotNull ScriptDescriptor script, 319 @NotNull List<ScriptDescriptor> earlierScripts, 320 @NotNull ClassDescriptor classDescriptor, 321 @NotNull KotlinTypeMapper typeMapper 322 ) { 323 return new ScriptContext(typeMapper, script, earlierScripts, classDescriptor, this); 324 } 325 326 @NotNull 327 public ClosureContext intoClosure( 328 @NotNull FunctionDescriptor funDescriptor, 329 @NotNull LocalLookup localLookup, 330 @NotNull KotlinTypeMapper typeMapper 331 ) { 332 return new ClosureContext(typeMapper, funDescriptor, this, localLookup); 333 } 334 335 @Nullable 336 public CodegenContext getParentContext() { 337 return parentContext; 338 } 339 340 public ClassDescriptor getEnclosingClass() { 341 CodegenContext cur = getParentContext(); 342 while (cur != null && !(cur.getContextDescriptor() instanceof ClassDescriptor)) { 343 cur = cur.getParentContext(); 344 } 345 346 return cur == null ? null : (ClassDescriptor) cur.getContextDescriptor(); 347 } 348 349 @Nullable 350 public CodegenContext findParentContextWithDescriptor(DeclarationDescriptor descriptor) { 351 CodegenContext c = this; 352 while (c != null) { 353 if (c.getContextDescriptor() == descriptor) break; 354 c = c.getParentContext(); 355 } 356 return c; 357 } 358 359 @NotNull 360 private PropertyDescriptor getPropertyAccessor( 361 @NotNull PropertyDescriptor propertyDescriptor, 362 @Nullable ClassDescriptor superCallTarget, 363 boolean getterAccessorRequired, 364 boolean setterAccessorRequired 365 ) { 366 return getAccessor(propertyDescriptor, FieldAccessorKind.NORMAL, null, superCallTarget, getterAccessorRequired, setterAccessorRequired); 367 } 368 369 @NotNull 370 private <D extends CallableMemberDescriptor> D getAccessor(@NotNull D descriptor, @Nullable ClassDescriptor superCallTarget) { 371 return getAccessor(descriptor, FieldAccessorKind.NORMAL, null, superCallTarget); 372 } 373 374 @SuppressWarnings("unchecked") 375 @NotNull 376 public <D extends CallableMemberDescriptor> D getAccessorForSuperCallIfNeeded(@NotNull D descriptor, @Nullable ClassDescriptor superCallTarget) { 377 if (superCallTarget != null && !isJvmInterface(descriptor.getContainingDeclaration())) { 378 CodegenContext afterInline = getFirstCrossInlineOrNonInlineContext(); 379 CodegenContext c = afterInline.findParentContextWithDescriptor(superCallTarget); 380 assert c != null : "Couldn't find a context for a super-call: " + descriptor; 381 if (c != afterInline.getParentContext()) { 382 return (D) c.getAccessor(descriptor, superCallTarget); 383 } 384 } 385 return descriptor; 386 } 387 388 @NotNull 389 public <D extends CallableMemberDescriptor> D getAccessor( 390 @NotNull D possiblySubstitutedDescriptor, 391 @NotNull FieldAccessorKind accessorKind, 392 @Nullable KotlinType delegateType, 393 @Nullable ClassDescriptor superCallTarget 394 ) { 395 // TODO this corresponds to default behavior for properties before fixing KT-9717. Is it Ok in general case? 396 // Does not matter for other descriptor kinds. 397 return getAccessor(possiblySubstitutedDescriptor, accessorKind, delegateType, superCallTarget, 398 /* getterAccessorRequired */ true, 399 /* setterAccessorRequired */ true); 400 } 401 402 @SuppressWarnings("unchecked") 403 @NotNull 404 private <D extends CallableMemberDescriptor> D getAccessor( 405 @NotNull D possiblySubstitutedDescriptor, 406 @NotNull FieldAccessorKind accessorKind, 407 @Nullable KotlinType delegateType, 408 @Nullable ClassDescriptor superCallTarget, 409 boolean getterAccessorRequired, 410 boolean setterAccessorRequired 411 ) { 412 if (accessors == null) { 413 accessors = new LinkedHashMap<AccessorKey, AccessorForCallableDescriptor<?>>(); 414 } 415 if (propertyAccessorFactories == null) { 416 propertyAccessorFactories = new LinkedHashMap<AccessorKey, AccessorForPropertyDescriptorFactory>(); 417 } 418 419 D descriptor = (D) possiblySubstitutedDescriptor.getOriginal(); 420 AccessorKey key = new AccessorKey(descriptor, superCallTarget); 421 422 // NB should check for property accessor factory first (or change property accessor tracking under propertyAccessorFactory creation) 423 AccessorForPropertyDescriptorFactory propertyAccessorFactory = propertyAccessorFactories.get(key); 424 if (propertyAccessorFactory != null) { 425 return (D) propertyAccessorFactory.getOrCreateAccessorIfNeeded(getterAccessorRequired, setterAccessorRequired); 426 } 427 AccessorForCallableDescriptor<?> accessor = accessors.get(key); 428 if (accessor != null) { 429 assert accessorKind == FieldAccessorKind.NORMAL || 430 accessor instanceof AccessorForPropertyBackingField : "There is already exists accessor with isForBackingField = false in this context"; 431 return (D) accessor; 432 } 433 String nameSuffix = SyntheticAccessorUtilKt.getAccessorNameSuffix(descriptor, key.superCallLabelTarget, accessorKind); 434 if (descriptor instanceof SimpleFunctionDescriptor) { 435 accessor = new AccessorForFunctionDescriptor( 436 (FunctionDescriptor) descriptor, contextDescriptor, superCallTarget, nameSuffix 437 ); 438 } 439 else if (descriptor instanceof ConstructorDescriptor) { 440 accessor = new AccessorForConstructorDescriptor((ConstructorDescriptor) descriptor, contextDescriptor, superCallTarget); 441 } 442 else if (descriptor instanceof PropertyDescriptor) { 443 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; 444 switch (accessorKind) { 445 case NORMAL: 446 propertyAccessorFactory = new AccessorForPropertyDescriptorFactory((PropertyDescriptor) descriptor, contextDescriptor, 447 superCallTarget, nameSuffix); 448 propertyAccessorFactories.put(key, propertyAccessorFactory); 449 450 // Record worst case accessor for accessor methods generation. 451 AccessorForPropertyDescriptor accessorWithGetterAndSetter = 452 propertyAccessorFactory.getOrCreateAccessorWithSyntheticGetterAndSetter(); 453 accessors.put(key, accessorWithGetterAndSetter); 454 455 PropertyDescriptor accessorDescriptor = 456 propertyAccessorFactory.getOrCreateAccessorIfNeeded(getterAccessorRequired, setterAccessorRequired); 457 return (D) accessorDescriptor; 458 case IN_CLASS_COMPANION: 459 accessor = new AccessorForPropertyBackingFieldInClassCompanion(propertyDescriptor, contextDescriptor, 460 delegateType, nameSuffix); 461 break; 462 case FIELD_FROM_LOCAL: 463 accessor = new AccessorForPropertyBackingFieldFromLocal(propertyDescriptor, contextDescriptor, nameSuffix); 464 break; 465 } 466 } 467 else { 468 throw new UnsupportedOperationException("Do not know how to create accessor for descriptor " + descriptor); 469 } 470 471 accessors.put(key, accessor); 472 473 return (D) accessor; 474 } 475 476 @Nullable 477 protected StackValue.Field computeOuterExpression() { 478 return null; 479 } 480 481 public StackValue lookupInContext(DeclarationDescriptor d, @Nullable StackValue result, GenerationState state, boolean ignoreNoOuter) { 482 StackValue myOuter = null; 483 if (closure != null) { 484 EnclosedValueDescriptor answer = closure.getCaptureVariables().get(d); 485 if (answer != null) { 486 return StackValue.changeReceiverForFieldAndSharedVar(answer.getInnerValue(), result); 487 } 488 489 for (LocalLookup.LocalLookupCase aCase : LocalLookup.LocalLookupCase.values()) { 490 if (aCase.isCase(d)) { 491 Type classType = state.getTypeMapper().mapType(getThisDescriptor()); 492 StackValue.StackValueWithSimpleReceiver innerValue = aCase.innerValue(d, enclosingLocalLookup, state, closure, classType); 493 if (innerValue == null) { 494 break; 495 } 496 else { 497 return StackValue.changeReceiverForFieldAndSharedVar(innerValue, result); 498 } 499 } 500 } 501 502 myOuter = getOuterExpression(result, ignoreNoOuter, false); 503 result = myOuter; 504 } 505 506 StackValue resultValue; 507 if (myOuter != null && getEnclosingClass() == d) { 508 resultValue = result; 509 } else { 510 resultValue = parentContext != null ? parentContext.lookupInContext(d, result, state, ignoreNoOuter) : null; 511 } 512 513 if (myOuter != null && resultValue != null && !isStaticField(resultValue)) { 514 closure.setCaptureThis(); 515 } 516 return resultValue; 517 } 518 519 @NotNull 520 @ReadOnly 521 public Collection<? extends AccessorForCallableDescriptor<?>> getAccessors() { 522 return accessors == null ? Collections.<AccessorForCallableDescriptor<CallableMemberDescriptor>>emptySet() : accessors.values(); 523 } 524 525 @SuppressWarnings("unchecked") 526 @NotNull 527 public <D extends CallableMemberDescriptor> D accessibleDescriptor( 528 @NotNull D descriptor, 529 @Nullable ClassDescriptor superCallTarget 530 ) { 531 CodegenContext properContext = getFirstCrossInlineOrNonInlineContext(); 532 DeclarationDescriptor enclosing = descriptor.getContainingDeclaration(); 533 boolean isInliningContext = properContext.isInlineMethodContext(); 534 if (!isInliningContext && ( 535 !properContext.hasThisDescriptor() || 536 enclosing == properContext.getThisDescriptor() || 537 enclosing == properContext.getClassOrPackageParentContext().getContextDescriptor())) { 538 return descriptor; 539 } 540 return (D) properContext.accessibleDescriptorIfNeeded(descriptor, superCallTarget, isInliningContext); 541 } 542 543 @SuppressWarnings("unchecked") 544 @NotNull 545 private <D extends CallableMemberDescriptor> D accessibleDescriptorIfNeeded( 546 @NotNull D descriptor, 547 @Nullable ClassDescriptor superCallTarget, 548 boolean withinInliningContext 549 ) { 550 CallableMemberDescriptor unwrappedDescriptor = DescriptorUtils.unwrapFakeOverride(descriptor); 551 552 DeclarationDescriptor enclosed = descriptor.getContainingDeclaration(); 553 CodegenContext descriptorContext = findParentContextWithDescriptor(enclosed); 554 if (descriptorContext == null && DescriptorUtils.isCompanionObject(enclosed)) { 555 CodegenContext classContext = findParentContextWithDescriptor(enclosed.getContainingDeclaration()); 556 if (classContext instanceof ClassContext) { 557 descriptorContext = ((ClassContext) classContext).getCompanionObjectContext(); 558 } 559 } 560 561 if (descriptorContext == null && 562 JavaVisibilities.PROTECTED_STATIC_VISIBILITY == descriptor.getVisibility() && 563 !(descriptor instanceof SamConstructorDescriptor)) { 564 //seems we need static receiver in resolved call 565 descriptorContext = ExpressionCodegen.getParentContextSubclassOf((ClassDescriptor) enclosed, this); 566 superCallTarget = (ClassDescriptor) enclosed; 567 } 568 569 if (descriptorContext == null && withinInliningContext && superCallTarget != null) { 570 //generate super calls within inline function through synthetic accessors 571 descriptorContext = ExpressionCodegen.getParentContextSubclassOf((ClassDescriptor) enclosed, this); 572 } 573 574 if (descriptorContext == null) { 575 return descriptor; 576 } 577 if (descriptor instanceof PropertyDescriptor) { 578 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; 579 int propertyAccessFlag = getVisibilityAccessFlag(descriptor); 580 581 PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); 582 int getterAccessFlag = getter == null ? propertyAccessFlag 583 : propertyAccessFlag | getVisibilityAccessFlag(getter); 584 boolean getterAccessorRequired = isAccessorRequired(getterAccessFlag, unwrappedDescriptor, descriptorContext, 585 withinInliningContext, superCallTarget != null); 586 587 PropertySetterDescriptor setter = propertyDescriptor.getSetter(); 588 int setterAccessFlag = setter == null ? propertyAccessFlag 589 : propertyAccessFlag | getVisibilityAccessFlag(setter); 590 boolean setterAccessorRequired = isAccessorRequired(setterAccessFlag, unwrappedDescriptor, descriptorContext, 591 withinInliningContext, superCallTarget != null); 592 593 if (!getterAccessorRequired && !setterAccessorRequired) { 594 return descriptor; 595 } 596 return (D) descriptorContext.getPropertyAccessor(propertyDescriptor, superCallTarget, getterAccessorRequired, setterAccessorRequired); 597 } 598 else { 599 int flag = getVisibilityAccessFlag(unwrappedDescriptor); 600 if (!isAccessorRequired(flag, unwrappedDescriptor, descriptorContext, withinInliningContext, superCallTarget != null)) { 601 return descriptor; 602 } 603 return (D) descriptorContext.getAccessor(descriptor, superCallTarget); 604 } 605 } 606 607 private static boolean isAccessorRequired( 608 int accessFlag, 609 @NotNull CallableMemberDescriptor unwrappedDescriptor, 610 @NotNull CodegenContext descriptorContext, 611 boolean withinInline, 612 boolean isSuperCall 613 ) { 614 if (AnnotationUtilKt.isInlineOnlyOrReified(unwrappedDescriptor)) return false; 615 616 return isSuperCall && withinInline || 617 (accessFlag & ACC_PRIVATE) != 0 || 618 ((accessFlag & ACC_PROTECTED) != 0 && 619 (withinInline || !isInSamePackage(unwrappedDescriptor, descriptorContext.getContextDescriptor()))); 620 } 621 622 private static boolean isInSamePackage(DeclarationDescriptor descriptor1, DeclarationDescriptor descriptor2) { 623 PackageFragmentDescriptor package1 = 624 DescriptorUtils.getParentOfType(descriptor1, PackageFragmentDescriptor.class, false); 625 PackageFragmentDescriptor package2 = 626 DescriptorUtils.getParentOfType(descriptor2, PackageFragmentDescriptor.class, false); 627 628 return package2 != null && package1 != null && 629 package1.getFqName().equals(package2.getFqName()); 630 } 631 632 private void addChild(@NotNull CodegenContext child) { 633 if (shouldAddChild(child)) { 634 if (childContexts == null) { 635 childContexts = new HashMap<DeclarationDescriptor, CodegenContext>(); 636 } 637 DeclarationDescriptor childContextDescriptor = child.getContextDescriptor(); 638 childContexts.put(childContextDescriptor, child); 639 } 640 } 641 642 protected boolean shouldAddChild(@NotNull CodegenContext child) { 643 return DescriptorUtils.isCompanionObject(child.contextDescriptor); 644 } 645 646 @Nullable 647 protected CodegenContext findChildContext(@NotNull DeclarationDescriptor child) { 648 return childContexts == null ? null : childContexts.get(child); 649 } 650 651 private static boolean isStaticField(@NotNull StackValue value) { 652 return value instanceof StackValue.Field && ((StackValue.Field) value).isStaticPut; 653 } 654 655 public boolean isInlineMethodContext() { 656 return false; 657 } 658 659 @NotNull 660 public CodegenContext getFirstCrossInlineOrNonInlineContext() { 661 return this; 662 } 663 }