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.JetTypeMapper; 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 FieldOwnerContext<PackageFragmentDescriptor> intoMultifileClassPart( 254 @NotNull PackageFragmentDescriptor descriptor, 255 @NotNull Type multifileClassType, 256 @NotNull Type filePartType, 257 @NotNull KtFile sourceFile 258 ) { 259 return new MultifileClassPartContext(descriptor, this, multifileClassType, filePartType, sourceFile); 260 } 261 262 @NotNull 263 public FieldOwnerContext<PackageFragmentDescriptor> intoMultifileClass( 264 @NotNull PackageFragmentDescriptor descriptor, 265 @NotNull Type multifileClassType, 266 @NotNull Type filePartType 267 ) { 268 return new MultifileClassFacadeContext(descriptor, this, multifileClassType, filePartType); 269 } 270 271 public ClassContext intoDefaultImplsClass(ClassDescriptor descriptor, ClassContext interfaceContext, GenerationState state) { 272 return new DefaultImplsClassContext(state.getTypeMapper(), descriptor, OwnerKind.DEFAULT_IMPLS, this, null, interfaceContext); 273 } 274 275 @NotNull 276 public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind, GenerationState state) { 277 if (descriptor.isCompanionObject()) { 278 CodegenContext companionContext = this.findChildContext(descriptor); 279 if (companionContext != null) { 280 assert companionContext.getContextKind() == kind : "Kinds should be same, but: " + 281 companionContext.getContextKind() + "!= " + kind; 282 return (ClassContext) companionContext; 283 } 284 } 285 ClassContext classContext = new ClassContext(state.getTypeMapper(), descriptor, kind, this, null); 286 287 if (descriptor.getCompanionObjectDescriptor() != null) { 288 //We need to create companion object context ahead of time 289 // because otherwise we can't generate synthetic accessor for private members in companion object 290 classContext.intoClass(descriptor.getCompanionObjectDescriptor(), OwnerKind.IMPLEMENTATION, state); 291 } 292 return classContext; 293 } 294 295 @NotNull 296 public ClassContext intoAnonymousClass(@NotNull ClassDescriptor descriptor, @NotNull ExpressionCodegen codegen, @NotNull OwnerKind ownerKind) { 297 return new AnonymousClassContext(codegen.getState().getTypeMapper(), descriptor, ownerKind, this, codegen); 298 } 299 300 @NotNull 301 public MethodContext intoFunction(FunctionDescriptor descriptor) { 302 return new MethodContext(descriptor, getContextKind(), this, null); 303 } 304 305 @NotNull 306 public MethodContext intoInlinedLambda(FunctionDescriptor descriptor, boolean isCrossInline) { 307 return new InlineLambdaContext(descriptor, getContextKind(), this, null, isCrossInline); 308 } 309 310 @NotNull 311 public ConstructorContext intoConstructor(@NotNull ConstructorDescriptor descriptor) { 312 return new ConstructorContext(descriptor, getContextKind(), this, closure); 313 } 314 315 @NotNull 316 public ScriptContext intoScript( 317 @NotNull ScriptDescriptor script, 318 @NotNull List<ScriptDescriptor> earlierScripts, 319 @NotNull ClassDescriptor classDescriptor, 320 @NotNull JetTypeMapper typeMapper 321 ) { 322 return new ScriptContext(typeMapper, script, earlierScripts, classDescriptor, this); 323 } 324 325 @NotNull 326 public ClosureContext intoClosure( 327 @NotNull FunctionDescriptor funDescriptor, 328 @NotNull LocalLookup localLookup, 329 @NotNull JetTypeMapper typeMapper 330 ) { 331 return new ClosureContext(typeMapper, funDescriptor, this, localLookup); 332 } 333 334 @Nullable 335 public CodegenContext getParentContext() { 336 return parentContext; 337 } 338 339 public ClassDescriptor getEnclosingClass() { 340 CodegenContext cur = getParentContext(); 341 while (cur != null && !(cur.getContextDescriptor() instanceof ClassDescriptor)) { 342 cur = cur.getParentContext(); 343 } 344 345 return cur == null ? null : (ClassDescriptor) cur.getContextDescriptor(); 346 } 347 348 @Nullable 349 public CodegenContext findParentContextWithDescriptor(DeclarationDescriptor descriptor) { 350 CodegenContext c = this; 351 while (c != null) { 352 if (c.getContextDescriptor() == descriptor) break; 353 c = c.getParentContext(); 354 } 355 return c; 356 } 357 358 @NotNull 359 private PropertyDescriptor getPropertyAccessor( 360 @NotNull PropertyDescriptor propertyDescriptor, 361 @Nullable ClassDescriptor superCallTarget, 362 boolean getterAccessorRequired, 363 boolean setterAccessorRequired 364 ) { 365 return getAccessor(propertyDescriptor, FieldAccessorKind.NORMAL, null, superCallTarget, getterAccessorRequired, setterAccessorRequired); 366 } 367 368 @NotNull 369 private <D extends CallableMemberDescriptor> D getAccessor(@NotNull D descriptor, @Nullable ClassDescriptor superCallTarget) { 370 return getAccessor(descriptor, FieldAccessorKind.NORMAL, null, superCallTarget); 371 } 372 373 @SuppressWarnings("unchecked") 374 @NotNull 375 public <D extends CallableMemberDescriptor> D getAccessorForSuperCallIfNeeded(@NotNull D descriptor, @Nullable ClassDescriptor superCallTarget) { 376 if (superCallTarget != null && !isJvmInterface(descriptor.getContainingDeclaration())) { 377 CodegenContext afterInline = getFirstCrossInlineOrNonInlineContext(); 378 CodegenContext c = afterInline.findParentContextWithDescriptor(superCallTarget); 379 assert c != null : "Couldn't find a context for a super-call: " + descriptor; 380 if (c != afterInline.getParentContext()) { 381 return (D) c.getAccessor(descriptor, superCallTarget); 382 } 383 } 384 return descriptor; 385 } 386 387 @NotNull 388 public <D extends CallableMemberDescriptor> D getAccessor( 389 @NotNull D possiblySubstitutedDescriptor, 390 @NotNull FieldAccessorKind accessorKind, 391 @Nullable KotlinType delegateType, 392 @Nullable ClassDescriptor superCallTarget 393 ) { 394 // TODO this corresponds to default behavior for properties before fixing KT-9717. Is it Ok in general case? 395 // Does not matter for other descriptor kinds. 396 return getAccessor(possiblySubstitutedDescriptor, accessorKind, delegateType, superCallTarget, 397 /* getterAccessorRequired */ true, 398 /* setterAccessorRequired */ true); 399 } 400 401 @SuppressWarnings("unchecked") 402 @NotNull 403 private <D extends CallableMemberDescriptor> D getAccessor( 404 @NotNull D possiblySubstitutedDescriptor, 405 @NotNull FieldAccessorKind accessorKind, 406 @Nullable KotlinType delegateType, 407 @Nullable ClassDescriptor superCallTarget, 408 boolean getterAccessorRequired, 409 boolean setterAccessorRequired 410 ) { 411 if (accessors == null) { 412 accessors = new LinkedHashMap<AccessorKey, AccessorForCallableDescriptor<?>>(); 413 } 414 if (propertyAccessorFactories == null) { 415 propertyAccessorFactories = new LinkedHashMap<AccessorKey, AccessorForPropertyDescriptorFactory>(); 416 } 417 418 D descriptor = (D) possiblySubstitutedDescriptor.getOriginal(); 419 AccessorKey key = new AccessorKey(descriptor, superCallTarget); 420 421 // NB should check for property accessor factory first (or change property accessor tracking under propertyAccessorFactory creation) 422 AccessorForPropertyDescriptorFactory propertyAccessorFactory = propertyAccessorFactories.get(key); 423 if (propertyAccessorFactory != null) { 424 return (D) propertyAccessorFactory.getOrCreateAccessorIfNeeded(getterAccessorRequired, setterAccessorRequired); 425 } 426 AccessorForCallableDescriptor<?> accessor = accessors.get(key); 427 if (accessor != null) { 428 assert accessorKind == FieldAccessorKind.NORMAL || 429 accessor instanceof AccessorForPropertyBackingField : "There is already exists accessor with isForBackingField = false in this context"; 430 return (D) accessor; 431 } 432 String nameSuffix = SyntheticAccessorUtilKt.getAccessorNameSuffix(descriptor, key.superCallLabelTarget, accessorKind); 433 if (descriptor instanceof SimpleFunctionDescriptor) { 434 accessor = new AccessorForFunctionDescriptor( 435 (FunctionDescriptor) descriptor, contextDescriptor, superCallTarget, nameSuffix 436 ); 437 } 438 else if (descriptor instanceof ConstructorDescriptor) { 439 accessor = new AccessorForConstructorDescriptor((ConstructorDescriptor) descriptor, contextDescriptor, superCallTarget); 440 } 441 else if (descriptor instanceof PropertyDescriptor) { 442 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; 443 switch (accessorKind) { 444 case NORMAL: 445 propertyAccessorFactory = new AccessorForPropertyDescriptorFactory((PropertyDescriptor) descriptor, contextDescriptor, 446 superCallTarget, nameSuffix); 447 propertyAccessorFactories.put(key, propertyAccessorFactory); 448 449 // Record worst case accessor for accessor methods generation. 450 AccessorForPropertyDescriptor accessorWithGetterAndSetter = 451 propertyAccessorFactory.getOrCreateAccessorWithSyntheticGetterAndSetter(); 452 accessors.put(key, accessorWithGetterAndSetter); 453 454 PropertyDescriptor accessorDescriptor = 455 propertyAccessorFactory.getOrCreateAccessorIfNeeded(getterAccessorRequired, setterAccessorRequired); 456 return (D) accessorDescriptor; 457 case IN_CLASS_COMPANION: 458 accessor = new AccessorForPropertyBackingFieldInClassCompanion(propertyDescriptor, contextDescriptor, 459 delegateType, nameSuffix); 460 break; 461 case FIELD_FROM_LOCAL: 462 accessor = new AccessorForPropertyBackingFieldFromLocal(propertyDescriptor, contextDescriptor, nameSuffix); 463 break; 464 } 465 } 466 else { 467 throw new UnsupportedOperationException("Do not know how to create accessor for descriptor " + descriptor); 468 } 469 470 accessors.put(key, accessor); 471 472 return (D) accessor; 473 } 474 475 @Nullable 476 protected StackValue.Field computeOuterExpression() { 477 return null; 478 } 479 480 public StackValue lookupInContext(DeclarationDescriptor d, @Nullable StackValue result, GenerationState state, boolean ignoreNoOuter) { 481 StackValue myOuter = null; 482 if (closure != null) { 483 EnclosedValueDescriptor answer = closure.getCaptureVariables().get(d); 484 if (answer != null) { 485 return StackValue.changeReceiverForFieldAndSharedVar(answer.getInnerValue(), result); 486 } 487 488 for (LocalLookup.LocalLookupCase aCase : LocalLookup.LocalLookupCase.values()) { 489 if (aCase.isCase(d)) { 490 Type classType = state.getTypeMapper().mapType(getThisDescriptor()); 491 StackValue.StackValueWithSimpleReceiver innerValue = aCase.innerValue(d, enclosingLocalLookup, state, closure, classType); 492 if (innerValue == null) { 493 break; 494 } 495 else { 496 return StackValue.changeReceiverForFieldAndSharedVar(innerValue, result); 497 } 498 } 499 } 500 501 myOuter = getOuterExpression(result, ignoreNoOuter, false); 502 result = myOuter; 503 } 504 505 StackValue resultValue; 506 if (myOuter != null && getEnclosingClass() == d) { 507 resultValue = result; 508 } else { 509 resultValue = parentContext != null ? parentContext.lookupInContext(d, result, state, ignoreNoOuter) : null; 510 } 511 512 if (myOuter != null && resultValue != null && !isStaticField(resultValue)) { 513 closure.setCaptureThis(); 514 } 515 return resultValue; 516 } 517 518 @NotNull 519 @ReadOnly 520 public Collection<? extends AccessorForCallableDescriptor<?>> getAccessors() { 521 return accessors == null ? Collections.<AccessorForCallableDescriptor<CallableMemberDescriptor>>emptySet() : accessors.values(); 522 } 523 524 @SuppressWarnings("unchecked") 525 @NotNull 526 public <D extends CallableMemberDescriptor> D accessibleDescriptor( 527 @NotNull D descriptor, 528 @Nullable ClassDescriptor superCallTarget 529 ) { 530 CodegenContext properContext = getFirstCrossInlineOrNonInlineContext(); 531 DeclarationDescriptor enclosing = descriptor.getContainingDeclaration(); 532 boolean isInliningContext = properContext.isInlineMethodContext(); 533 if (!isInliningContext && ( 534 !properContext.hasThisDescriptor() || 535 enclosing == properContext.getThisDescriptor() || 536 enclosing == properContext.getClassOrPackageParentContext().getContextDescriptor())) { 537 return descriptor; 538 } 539 return (D) properContext.accessibleDescriptorIfNeeded(descriptor, superCallTarget, isInliningContext); 540 } 541 542 @SuppressWarnings("unchecked") 543 @NotNull 544 private <D extends CallableMemberDescriptor> D accessibleDescriptorIfNeeded( 545 @NotNull D descriptor, 546 @Nullable ClassDescriptor superCallTarget, 547 boolean withinInliningContext 548 ) { 549 CallableMemberDescriptor unwrappedDescriptor = DescriptorUtils.unwrapFakeOverride(descriptor); 550 551 DeclarationDescriptor enclosed = descriptor.getContainingDeclaration(); 552 CodegenContext descriptorContext = findParentContextWithDescriptor(enclosed); 553 if (descriptorContext == null && DescriptorUtils.isCompanionObject(enclosed)) { 554 CodegenContext classContext = findParentContextWithDescriptor(enclosed.getContainingDeclaration()); 555 if (classContext instanceof ClassContext) { 556 descriptorContext = ((ClassContext) classContext).getCompanionObjectContext(); 557 } 558 } 559 560 if (descriptorContext == null && 561 JavaVisibilities.PROTECTED_STATIC_VISIBILITY == descriptor.getVisibility() && 562 !(descriptor instanceof SamConstructorDescriptor)) { 563 //seems we need static receiver in resolved call 564 descriptorContext = ExpressionCodegen.getParentContextSubclassOf((ClassDescriptor) enclosed, this); 565 superCallTarget = (ClassDescriptor) enclosed; 566 } 567 568 if (descriptorContext == null && withinInliningContext && superCallTarget != null) { 569 //generate super calls within inline function through synthetic accessors 570 descriptorContext = ExpressionCodegen.getParentContextSubclassOf((ClassDescriptor) enclosed, this); 571 } 572 573 if (descriptorContext == null) { 574 return descriptor; 575 } 576 if (descriptor instanceof PropertyDescriptor) { 577 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; 578 int propertyAccessFlag = getVisibilityAccessFlag(descriptor); 579 580 PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); 581 int getterAccessFlag = getter == null ? propertyAccessFlag 582 : propertyAccessFlag | getVisibilityAccessFlag(getter); 583 boolean getterAccessorRequired = isAccessorRequired(getterAccessFlag, unwrappedDescriptor, descriptorContext, 584 withinInliningContext, superCallTarget != null); 585 586 PropertySetterDescriptor setter = propertyDescriptor.getSetter(); 587 int setterAccessFlag = setter == null ? propertyAccessFlag 588 : propertyAccessFlag | getVisibilityAccessFlag(setter); 589 boolean setterAccessorRequired = isAccessorRequired(setterAccessFlag, unwrappedDescriptor, descriptorContext, 590 withinInliningContext, superCallTarget != null); 591 592 if (!getterAccessorRequired && !setterAccessorRequired) { 593 return descriptor; 594 } 595 return (D) descriptorContext.getPropertyAccessor(propertyDescriptor, superCallTarget, getterAccessorRequired, setterAccessorRequired); 596 } 597 else { 598 int flag = getVisibilityAccessFlag(unwrappedDescriptor); 599 if (!isAccessorRequired(flag, unwrappedDescriptor, descriptorContext, withinInliningContext, superCallTarget != null)) { 600 return descriptor; 601 } 602 return (D) descriptorContext.getAccessor(descriptor, superCallTarget); 603 } 604 } 605 606 private static boolean isAccessorRequired( 607 int accessFlag, 608 @NotNull CallableMemberDescriptor unwrappedDescriptor, 609 @NotNull CodegenContext descriptorContext, 610 boolean withinInline, 611 boolean isSuperCall 612 ) { 613 if (AnnotationUtilKt.isInlineOnly(unwrappedDescriptor)) return false; 614 615 return isSuperCall && withinInline || 616 (accessFlag & ACC_PRIVATE) != 0 || 617 ((accessFlag & ACC_PROTECTED) != 0 && 618 (withinInline || !isInSamePackage(unwrappedDescriptor, descriptorContext.getContextDescriptor()))); 619 } 620 621 private static boolean isInSamePackage(DeclarationDescriptor descriptor1, DeclarationDescriptor descriptor2) { 622 PackageFragmentDescriptor package1 = 623 DescriptorUtils.getParentOfType(descriptor1, PackageFragmentDescriptor.class, false); 624 PackageFragmentDescriptor package2 = 625 DescriptorUtils.getParentOfType(descriptor2, PackageFragmentDescriptor.class, false); 626 627 return package2 != null && package1 != null && 628 package1.getFqName().equals(package2.getFqName()); 629 } 630 631 private void addChild(@NotNull CodegenContext child) { 632 if (shouldAddChild(child)) { 633 if (childContexts == null) { 634 childContexts = new HashMap<DeclarationDescriptor, CodegenContext>(); 635 } 636 DeclarationDescriptor childContextDescriptor = child.getContextDescriptor(); 637 childContexts.put(childContextDescriptor, child); 638 } 639 } 640 641 protected boolean shouldAddChild(@NotNull CodegenContext child) { 642 return DescriptorUtils.isCompanionObject(child.contextDescriptor); 643 } 644 645 @Nullable 646 protected CodegenContext findChildContext(@NotNull DeclarationDescriptor child) { 647 return childContexts == null ? null : childContexts.get(child); 648 } 649 650 private static boolean isStaticField(@NotNull StackValue value) { 651 return value instanceof StackValue.Field && ((StackValue.Field) value).isStaticPut; 652 } 653 654 public boolean isInlineMethodContext() { 655 return false; 656 } 657 658 @NotNull 659 public CodegenContext getFirstCrossInlineOrNonInlineContext() { 660 return this; 661 } 662 }