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 ) { 320 return new ScriptContext(script, earlierScripts, classDescriptor, OwnerKind.IMPLEMENTATION, this, closure); 321 } 322 323 @NotNull 324 public ClosureContext intoClosure( 325 @NotNull FunctionDescriptor funDescriptor, 326 @NotNull LocalLookup localLookup, 327 @NotNull JetTypeMapper typeMapper 328 ) { 329 return new ClosureContext(typeMapper, funDescriptor, this, localLookup); 330 } 331 332 @Nullable 333 public CodegenContext getParentContext() { 334 return parentContext; 335 } 336 337 public ClassDescriptor getEnclosingClass() { 338 CodegenContext cur = getParentContext(); 339 while (cur != null && !(cur.getContextDescriptor() instanceof ClassDescriptor)) { 340 cur = cur.getParentContext(); 341 } 342 343 return cur == null ? null : (ClassDescriptor) cur.getContextDescriptor(); 344 } 345 346 @Nullable 347 public CodegenContext findParentContextWithDescriptor(DeclarationDescriptor descriptor) { 348 CodegenContext c = this; 349 while (c != null) { 350 if (c.getContextDescriptor() == descriptor) break; 351 c = c.getParentContext(); 352 } 353 return c; 354 } 355 356 @NotNull 357 private PropertyDescriptor getPropertyAccessor( 358 @NotNull PropertyDescriptor propertyDescriptor, 359 @Nullable ClassDescriptor superCallTarget, 360 boolean getterAccessorRequired, 361 boolean setterAccessorRequired 362 ) { 363 return getAccessor(propertyDescriptor, FieldAccessorKind.NORMAL, null, superCallTarget, getterAccessorRequired, setterAccessorRequired); 364 } 365 366 @NotNull 367 public <D extends CallableMemberDescriptor> D getAccessor(@NotNull D descriptor, @Nullable ClassDescriptor superCallTarget) { 368 return getAccessor(descriptor, FieldAccessorKind.NORMAL, null, superCallTarget); 369 } 370 371 @SuppressWarnings("unchecked") 372 @NotNull 373 public <D extends CallableMemberDescriptor> D getAccessor( 374 @NotNull D possiblySubstitutedDescriptor, 375 @NotNull FieldAccessorKind accessorKind, 376 @Nullable KotlinType delegateType, 377 @Nullable ClassDescriptor superCallTarget 378 ) { 379 // TODO this corresponds to default behavior for properties before fixing KT-9717. Is it Ok in general case? 380 // Does not matter for other descriptor kinds. 381 return getAccessor(possiblySubstitutedDescriptor, accessorKind, delegateType, superCallTarget, 382 /* getterAccessorRequired */ true, 383 /* setterAccessorRequired */ true); 384 } 385 386 @SuppressWarnings("unchecked") 387 @NotNull 388 private <D extends CallableMemberDescriptor> D getAccessor( 389 @NotNull D possiblySubstitutedDescriptor, 390 @NotNull FieldAccessorKind accessorKind, 391 @Nullable KotlinType delegateType, 392 @Nullable ClassDescriptor superCallTarget, 393 boolean getterAccessorRequired, 394 boolean setterAccessorRequired 395 ) { 396 if (accessors == null) { 397 accessors = new LinkedHashMap<AccessorKey, AccessorForCallableDescriptor<?>>(); 398 } 399 if (propertyAccessorFactories == null) { 400 propertyAccessorFactories = new LinkedHashMap<AccessorKey, AccessorForPropertyDescriptorFactory>(); 401 } 402 403 D descriptor = (D) possiblySubstitutedDescriptor.getOriginal(); 404 AccessorKey key = new AccessorKey(descriptor, superCallTarget); 405 406 // NB should check for property accessor factory first (or change property accessor tracking under propertyAccessorFactory creation) 407 AccessorForPropertyDescriptorFactory propertyAccessorFactory = propertyAccessorFactories.get(key); 408 if (propertyAccessorFactory != null) { 409 return (D) propertyAccessorFactory.getOrCreateAccessorIfNeeded(getterAccessorRequired, setterAccessorRequired); 410 } 411 AccessorForCallableDescriptor<?> accessor = accessors.get(key); 412 if (accessor != null) { 413 assert accessorKind == FieldAccessorKind.NORMAL || 414 accessor instanceof AccessorForPropertyBackingField : "There is already exists accessor with isForBackingField = false in this context"; 415 return (D) accessor; 416 } 417 String nameSuffix = SyntheticAccessorUtilKt.getAccessorNameSuffix(descriptor, key.superCallLabelTarget, accessorKind); 418 if (descriptor instanceof SimpleFunctionDescriptor) { 419 accessor = new AccessorForFunctionDescriptor( 420 (FunctionDescriptor) descriptor, contextDescriptor, superCallTarget, nameSuffix 421 ); 422 } 423 else if (descriptor instanceof ConstructorDescriptor) { 424 accessor = new AccessorForConstructorDescriptor((ConstructorDescriptor) descriptor, contextDescriptor, superCallTarget); 425 } 426 else if (descriptor instanceof PropertyDescriptor) { 427 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; 428 switch (accessorKind) { 429 case NORMAL: 430 propertyAccessorFactory = new AccessorForPropertyDescriptorFactory((PropertyDescriptor) descriptor, contextDescriptor, 431 superCallTarget, nameSuffix); 432 propertyAccessorFactories.put(key, propertyAccessorFactory); 433 434 // Record worst case accessor for accessor methods generation. 435 AccessorForPropertyDescriptor accessorWithGetterAndSetter = 436 propertyAccessorFactory.getOrCreateAccessorWithSyntheticGetterAndSetter(); 437 accessors.put(key, accessorWithGetterAndSetter); 438 439 PropertyDescriptor accessorDescriptor = 440 propertyAccessorFactory.getOrCreateAccessorIfNeeded(getterAccessorRequired, setterAccessorRequired); 441 return (D) accessorDescriptor; 442 case IN_CLASS_COMPANION: 443 accessor = new AccessorForPropertyBackingFieldInClassCompanion(propertyDescriptor, contextDescriptor, 444 delegateType, nameSuffix); 445 break; 446 case FIELD_FROM_LOCAL: 447 accessor = new AccessorForPropertyBackingFieldFromLocal(propertyDescriptor, contextDescriptor, nameSuffix); 448 break; 449 } 450 } 451 else { 452 throw new UnsupportedOperationException("Do not know how to create accessor for descriptor " + descriptor); 453 } 454 455 accessors.put(key, accessor); 456 457 return (D) accessor; 458 } 459 460 @Nullable 461 protected StackValue.Field computeOuterExpression() { 462 return null; 463 } 464 465 public StackValue lookupInContext(DeclarationDescriptor d, @Nullable StackValue result, GenerationState state, boolean ignoreNoOuter) { 466 StackValue myOuter = null; 467 if (closure != null) { 468 EnclosedValueDescriptor answer = closure.getCaptureVariables().get(d); 469 if (answer != null) { 470 return StackValue.changeReceiverForFieldAndSharedVar(answer.getInnerValue(), result); 471 } 472 473 for (LocalLookup.LocalLookupCase aCase : LocalLookup.LocalLookupCase.values()) { 474 if (aCase.isCase(d)) { 475 Type classType = state.getTypeMapper().mapType(getThisDescriptor()); 476 StackValue.StackValueWithSimpleReceiver innerValue = aCase.innerValue(d, enclosingLocalLookup, state, closure, classType); 477 if (innerValue == null) { 478 break; 479 } 480 else { 481 return StackValue.changeReceiverForFieldAndSharedVar(innerValue, result); 482 } 483 } 484 } 485 486 myOuter = getOuterExpression(result, ignoreNoOuter, false); 487 result = myOuter; 488 } 489 490 StackValue resultValue; 491 if (myOuter != null && getEnclosingClass() == d) { 492 resultValue = result; 493 } else { 494 resultValue = parentContext != null ? parentContext.lookupInContext(d, result, state, ignoreNoOuter) : null; 495 } 496 497 if (myOuter != null && resultValue != null && !isStaticField(resultValue)) { 498 closure.setCaptureThis(); 499 } 500 return resultValue; 501 } 502 503 @NotNull 504 public Collection<? extends AccessorForCallableDescriptor<?>> getAccessors() { 505 return accessors == null ? Collections.<AccessorForCallableDescriptor<CallableMemberDescriptor>>emptySet() : accessors.values(); 506 } 507 508 @NotNull 509 public <D extends CallableMemberDescriptor> D accessibleDescriptor( 510 @NotNull D descriptor, 511 @Nullable ClassDescriptor superCallTarget 512 ) { 513 DeclarationDescriptor enclosing = descriptor.getContainingDeclaration(); 514 if (!isInlineMethodContext() && ( 515 !hasThisDescriptor() || 516 enclosing == getThisDescriptor() || 517 enclosing == getClassOrPackageParentContext().getContextDescriptor())) { 518 return descriptor; 519 } 520 521 return accessibleDescriptorIfNeeded(descriptor, superCallTarget); 522 } 523 524 public void recordSyntheticAccessorIfNeeded(@NotNull CallableMemberDescriptor descriptor, @NotNull BindingContext bindingContext) { 525 if (hasThisDescriptor() && Boolean.TRUE.equals(bindingContext.get(NEED_SYNTHETIC_ACCESSOR, descriptor))) { 526 // Not a super call because neither constructors nor private members can be targets of super calls 527 accessibleDescriptorIfNeeded(descriptor, /* superCallTarget = */ null); 528 } 529 } 530 531 @SuppressWarnings("unchecked") 532 @NotNull 533 private <D extends CallableMemberDescriptor> D accessibleDescriptorIfNeeded( 534 @NotNull D descriptor, 535 @Nullable ClassDescriptor superCallTarget 536 ) { 537 CallableMemberDescriptor unwrappedDescriptor = DescriptorUtils.unwrapFakeOverride(descriptor); 538 539 DeclarationDescriptor enclosed = descriptor.getContainingDeclaration(); 540 CodegenContext descriptorContext = findParentContextWithDescriptor(enclosed); 541 if (descriptorContext == null && DescriptorUtils.isCompanionObject(enclosed)) { 542 CodegenContext classContext = findParentContextWithDescriptor(enclosed.getContainingDeclaration()); 543 if (classContext instanceof ClassContext) { 544 descriptorContext = ((ClassContext) classContext).getCompanionObjectContext(); 545 } 546 } 547 548 if (descriptorContext == null && 549 JavaVisibilities.PROTECTED_STATIC_VISIBILITY == descriptor.getVisibility() && 550 !(descriptor instanceof SamConstructorDescriptor)) { 551 //seems we need static receiver in resolved call 552 descriptorContext = ExpressionCodegen.getParentContextSubclassOf((ClassDescriptor) enclosed, this); 553 superCallTarget = (ClassDescriptor) enclosed; 554 } 555 556 if (descriptorContext == null) { 557 return descriptor; 558 } 559 560 if (descriptor instanceof PropertyDescriptor) { 561 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; 562 int propertyAccessFlag = getVisibilityAccessFlag(descriptor); 563 564 PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); 565 int getterAccessFlag = getter == null ? propertyAccessFlag 566 : propertyAccessFlag | getVisibilityAccessFlag(getter); 567 boolean getterAccessorRequired = isAccessorRequired(getterAccessFlag, unwrappedDescriptor, descriptorContext); 568 569 PropertySetterDescriptor setter = propertyDescriptor.getSetter(); 570 int setterAccessFlag = setter == null ? propertyAccessFlag 571 : propertyAccessFlag | getVisibilityAccessFlag(setter); 572 boolean setterAccessorRequired = isAccessorRequired(setterAccessFlag, unwrappedDescriptor, descriptorContext); 573 574 if (!getterAccessorRequired && !setterAccessorRequired) { 575 return descriptor; 576 } 577 return (D) descriptorContext.getPropertyAccessor(propertyDescriptor, superCallTarget, getterAccessorRequired, setterAccessorRequired); 578 } 579 else { 580 int flag = getVisibilityAccessFlag(unwrappedDescriptor); 581 if (!isAccessorRequired(flag, unwrappedDescriptor, descriptorContext)) { 582 return descriptor; 583 } 584 return (D) descriptorContext.getAccessor(descriptor, superCallTarget); 585 } 586 } 587 588 private static boolean isAccessorRequired( 589 int accessFlag, 590 @NotNull CallableMemberDescriptor unwrappedDescriptor, 591 @NotNull CodegenContext descriptorContext 592 ) { 593 return (accessFlag & ACC_PRIVATE) != 0 || 594 ((accessFlag & ACC_PROTECTED) != 0 && !isInSamePackage(unwrappedDescriptor, descriptorContext.getContextDescriptor())); 595 } 596 597 private static boolean isInSamePackage(DeclarationDescriptor descriptor1, DeclarationDescriptor descriptor2) { 598 PackageFragmentDescriptor package1 = 599 DescriptorUtils.getParentOfType(descriptor1, PackageFragmentDescriptor.class, false); 600 PackageFragmentDescriptor package2 = 601 DescriptorUtils.getParentOfType(descriptor2, PackageFragmentDescriptor.class, false); 602 603 return package2 != null && package1 != null && 604 package1.getFqName().equals(package2.getFqName()); 605 } 606 607 private void addChild(@NotNull CodegenContext child) { 608 if (shouldAddChild(child)) { 609 if (childContexts == null) { 610 childContexts = new HashMap<DeclarationDescriptor, CodegenContext>(); 611 } 612 DeclarationDescriptor childContextDescriptor = child.getContextDescriptor(); 613 childContexts.put(childContextDescriptor, child); 614 } 615 } 616 617 protected boolean shouldAddChild(@NotNull CodegenContext child) { 618 return DescriptorUtils.isCompanionObject(child.contextDescriptor); 619 } 620 621 @Nullable 622 public CodegenContext findChildContext(@NotNull DeclarationDescriptor child) { 623 return childContexts == null ? null : childContexts.get(child); 624 } 625 626 private static boolean isStaticField(@NotNull StackValue value) { 627 return value instanceof StackValue.Field && ((StackValue.Field) value).isStaticPut; 628 } 629 630 private boolean isInsideInliningContext() { 631 CodegenContext current = this; 632 while (current != null) { 633 if (current instanceof MethodContext && ((MethodContext) current).isInlineFunction()) { 634 return true; 635 } 636 current = current.getParentContext(); 637 } 638 return false; 639 } 640 641 private boolean isInlineMethodContext() { 642 return this instanceof MethodContext && ((MethodContext) this).isInlineFunction(); 643 } 644 }