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