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