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 }