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; 018 019 import com.intellij.openapi.util.Pair; 020 import com.intellij.psi.PsiElement; 021 import org.jetbrains.annotations.NotNull; 022 import org.jetbrains.annotations.Nullable; 023 import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithFakeAnnotations; 024 import org.jetbrains.kotlin.codegen.annotation.AnnotatedSimple; 025 import org.jetbrains.kotlin.codegen.context.*; 026 import org.jetbrains.kotlin.codegen.state.GenerationState; 027 import org.jetbrains.kotlin.codegen.state.JetTypeMapper; 028 import org.jetbrains.kotlin.descriptors.*; 029 import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget; 030 import org.jetbrains.kotlin.descriptors.annotations.Annotations; 031 import org.jetbrains.kotlin.descriptors.annotations.*; 032 import org.jetbrains.kotlin.load.java.JvmAbi; 033 import org.jetbrains.kotlin.psi.*; 034 import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage; 035 import org.jetbrains.kotlin.resolve.BindingContext; 036 import org.jetbrains.kotlin.resolve.DescriptorFactory; 037 import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; 038 import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage; 039 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; 040 import org.jetbrains.kotlin.resolve.constants.ConstantValue; 041 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature; 042 import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor; 043 import org.jetbrains.kotlin.storage.LockBasedStorageManager; 044 import org.jetbrains.kotlin.types.ErrorUtils; 045 import org.jetbrains.kotlin.types.JetType; 046 import org.jetbrains.kotlin.descriptors.annotations.AnnotationSplitter; 047 import org.jetbrains.org.objectweb.asm.FieldVisitor; 048 import org.jetbrains.org.objectweb.asm.MethodVisitor; 049 import org.jetbrains.org.objectweb.asm.Opcodes; 050 import org.jetbrains.org.objectweb.asm.Type; 051 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; 052 import org.jetbrains.org.objectweb.asm.commons.Method; 053 054 import java.util.List; 055 056 import static org.jetbrains.kotlin.codegen.AsmUtil.*; 057 import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isInterface; 058 import static org.jetbrains.kotlin.codegen.JvmSerializationBindings.*; 059 import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject; 060 import static org.jetbrains.kotlin.resolve.DescriptorUtils.isTrait; 061 import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.PROPERTY_METADATA_TYPE; 062 import static org.jetbrains.kotlin.resolve.jvm.diagnostics.DiagnosticsPackage.OtherOrigin; 063 import static org.jetbrains.org.objectweb.asm.Opcodes.*; 064 065 public class PropertyCodegen { 066 private final GenerationState state; 067 private final ClassBuilder v; 068 private final FunctionCodegen functionCodegen; 069 private final JetTypeMapper typeMapper; 070 private final BindingContext bindingContext; 071 private final FieldOwnerContext context; 072 private final MemberCodegen<?> memberCodegen; 073 private final OwnerKind kind; 074 075 public PropertyCodegen( 076 @NotNull FieldOwnerContext context, 077 @NotNull ClassBuilder v, 078 @NotNull FunctionCodegen functionCodegen, 079 @NotNull MemberCodegen<?> memberCodegen 080 ) { 081 this.state = functionCodegen.state; 082 this.v = v; 083 this.functionCodegen = functionCodegen; 084 this.typeMapper = state.getTypeMapper(); 085 this.bindingContext = state.getBindingContext(); 086 this.context = context; 087 this.memberCodegen = memberCodegen; 088 this.kind = context.getContextKind(); 089 } 090 091 public void gen(@NotNull JetProperty property) { 092 VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, property); 093 assert variableDescriptor instanceof PropertyDescriptor : "Property " + property.getText() + " should have a property descriptor: " + variableDescriptor; 094 095 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variableDescriptor; 096 gen(property, propertyDescriptor, property.getGetter(), property.getSetter()); 097 } 098 099 public void generateInPackageFacade(@NotNull DeserializedPropertyDescriptor deserializedProperty) { 100 assert context instanceof PackageFacadeContext : "should be called only for generating package facade: " + context; 101 gen(null, deserializedProperty, null, null); 102 } 103 104 private void gen( 105 @Nullable JetProperty declaration, 106 @NotNull PropertyDescriptor descriptor, 107 @Nullable JetPropertyAccessor getter, 108 @Nullable JetPropertyAccessor setter 109 ) { 110 assert kind == OwnerKind.PACKAGE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.TRAIT_IMPL 111 : "Generating property with a wrong kind (" + kind + "): " + descriptor; 112 113 String implClassName = CodegenContextUtil.getImplementationClassShortName(context); 114 if (implClassName != null) { 115 v.getSerializationBindings().put(IMPL_CLASS_NAME_FOR_CALLABLE, descriptor, implClassName); 116 } 117 118 if (CodegenContextUtil.isImplClassOwner(context)) { 119 assert declaration != null : "Declaration is null for different context: " + context; 120 121 boolean hasBackingField = hasBackingField(declaration, descriptor); 122 123 AnnotationSplitter annotationSplitter = AnnotationSplitter.create(LockBasedStorageManager.NO_LOCKS, 124 descriptor.getAnnotations(), AnnotationSplitter.getTargetSet(false, descriptor.isVar(), hasBackingField)); 125 126 Annotations fieldAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.FIELD); 127 Annotations propertyAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY); 128 129 generateBackingField(declaration, descriptor, fieldAnnotations); 130 generateSyntheticMethodIfNeeded(descriptor, propertyAnnotations); 131 } 132 133 if (isAccessorNeeded(declaration, descriptor, getter)) { 134 generateGetter(declaration, descriptor, getter); 135 } 136 if (isAccessorNeeded(declaration, descriptor, setter)) { 137 generateSetter(declaration, descriptor, setter); 138 } 139 140 context.recordSyntheticAccessorIfNeeded(descriptor, bindingContext); 141 } 142 143 /** 144 * Determines if it's necessary to generate an accessor to the property, i.e. if this property can be referenced via getter/setter 145 * for any reason 146 * 147 * @see JvmCodegenUtil#couldUseDirectAccessToProperty 148 */ 149 private boolean isAccessorNeeded( 150 @Nullable JetProperty declaration, 151 @NotNull PropertyDescriptor descriptor, 152 @Nullable JetPropertyAccessor accessor 153 ) { 154 boolean isDefaultAccessor = accessor == null || !accessor.hasBody(); 155 156 // Don't generate accessors for trait properties with default accessors in TRAIT_IMPL 157 if (kind == OwnerKind.TRAIT_IMPL && isDefaultAccessor) return false; 158 159 if (declaration == null) return true; 160 161 // Delegated or extension properties can only be referenced via accessors 162 if (declaration.hasDelegate() || declaration.getReceiverTypeReference() != null) return true; 163 164 // Companion object properties always should have accessors, because their backing fields are moved/copied to the outer class 165 if (isCompanionObject(descriptor.getContainingDeclaration())) return true; 166 167 // Private class properties have accessors only in cases when those accessors are non-trivial 168 if (kind == OwnerKind.IMPLEMENTATION && Visibilities.isPrivate(descriptor.getVisibility())) { 169 return !isDefaultAccessor; 170 } 171 172 return true; 173 } 174 175 public void generatePrimaryConstructorProperty(JetParameter p, PropertyDescriptor descriptor) { 176 AnnotationSplitter annotationSplitter = AnnotationSplitter.create(LockBasedStorageManager.NO_LOCKS, 177 descriptor.getAnnotations(), AnnotationSplitter.getTargetSet(true, descriptor.isVar(), hasBackingField(p, descriptor))); 178 179 Annotations fieldAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.FIELD); 180 Annotations propertyAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY); 181 182 generateBackingField(p, descriptor, fieldAnnotations); 183 generateSyntheticMethodIfNeeded(descriptor, propertyAnnotations); 184 185 if (!Visibilities.isPrivate(descriptor.getVisibility())) { 186 generateGetter(p, descriptor, null); 187 if (descriptor.isVar()) { 188 generateSetter(p, descriptor, null); 189 } 190 } 191 } 192 193 public void generateConstructorPropertyAsMethodForAnnotationClass(JetParameter p, PropertyDescriptor descriptor) { 194 JvmMethodSignature signature = typeMapper.mapAnnotationParameterSignature(descriptor); 195 String name = p.getName(); 196 if (name == null) return; 197 MethodVisitor mv = v.newMethod( 198 OtherOrigin(p, descriptor), ACC_PUBLIC | ACC_ABSTRACT, name, 199 signature.getAsmMethod().getDescriptor(), 200 signature.getGenericsSignature(), 201 null 202 ); 203 204 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { 205 JetExpression defaultValue = p.getDefaultValue(); 206 if (defaultValue != null) { 207 ConstantValue<?> constant = ExpressionCodegen.getCompileTimeConstant(defaultValue, bindingContext); 208 assert constant != null : "Default value for annotation parameter should be compile time value: " + defaultValue.getText(); 209 AnnotationCodegen annotationCodegen = AnnotationCodegen.forAnnotationDefaultValue(mv, typeMapper); 210 annotationCodegen.generateAnnotationDefaultValue(constant, descriptor.getType()); 211 } 212 } 213 214 mv.visitEnd(); 215 } 216 217 private boolean hasBackingField(@NotNull JetNamedDeclaration p, @NotNull PropertyDescriptor descriptor) { 218 return !isInterface(descriptor.getContainingDeclaration()) && 219 kind != OwnerKind.TRAIT_IMPL && 220 !Boolean.FALSE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor)); 221 } 222 223 private boolean generateBackingField( 224 @NotNull JetNamedDeclaration p, 225 @NotNull PropertyDescriptor descriptor, 226 @NotNull Annotations annotations 227 ) { 228 if (isInterface(descriptor.getContainingDeclaration()) || kind == OwnerKind.TRAIT_IMPL) { 229 return false; 230 } 231 232 if (p instanceof JetProperty && ((JetProperty) p).hasDelegate()) { 233 generatePropertyDelegateAccess((JetProperty) p, descriptor, annotations); 234 } 235 else if (Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) { 236 generateBackingFieldAccess(p, descriptor, annotations); 237 } 238 else { 239 return false; 240 } 241 return true; 242 } 243 244 // Annotations on properties are stored in bytecode on an empty synthetic method. This way they're still 245 // accessible via reflection, and 'deprecated' and 'private' flags prevent this method from being called accidentally 246 private void generateSyntheticMethodIfNeeded(@NotNull PropertyDescriptor descriptor, Annotations annotations) { 247 if (annotations.getAllAnnotations().isEmpty()) return; 248 249 ReceiverParameterDescriptor receiver = descriptor.getExtensionReceiverParameter(); 250 String name = JvmAbi.getSyntheticMethodNameForAnnotatedProperty(descriptor.getName()); 251 String desc = receiver == null ? "()V" : "(" + typeMapper.mapType(receiver.getType()) + ")V"; 252 253 if (!isTrait(context.getContextDescriptor()) || kind == OwnerKind.TRAIT_IMPL) { 254 int flags = ACC_DEPRECATED | ACC_FINAL | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC; 255 MethodVisitor mv = v.newMethod(OtherOrigin(descriptor), flags, name, desc, null, null); 256 AnnotationCodegen.forMethod(mv, typeMapper) 257 .genAnnotations(new AnnotatedSimple(annotations), Type.VOID_TYPE, AnnotationUseSiteTarget.PROPERTY); 258 mv.visitCode(); 259 mv.visitInsn(Opcodes.RETURN); 260 mv.visitEnd(); 261 } 262 else { 263 Type tImplType = typeMapper.mapTraitImpl((ClassDescriptor) context.getContextDescriptor()); 264 v.getSerializationBindings().put(IMPL_CLASS_NAME_FOR_CALLABLE, descriptor, shortNameByAsmType(tImplType)); 265 } 266 267 if (kind != OwnerKind.TRAIT_IMPL) { 268 v.getSerializationBindings().put(SYNTHETIC_METHOD_FOR_PROPERTY, descriptor, new Method(name, desc)); 269 } 270 } 271 272 private void generateBackingField( 273 JetNamedDeclaration element, 274 PropertyDescriptor propertyDescriptor, 275 boolean isDelegate, 276 JetType jetType, 277 Object defaultValue, 278 Annotations annotations 279 ) { 280 int modifiers = getDeprecatedAccessFlag(propertyDescriptor); 281 282 for (AnnotationCodegen.JvmFlagAnnotation flagAnnotation : AnnotationCodegen.FIELD_FLAGS) { 283 if (flagAnnotation.hasAnnotation(propertyDescriptor.getOriginal())) { 284 modifiers |= flagAnnotation.getJvmFlag(); 285 } 286 } 287 288 if (kind == OwnerKind.PACKAGE) { 289 modifiers |= ACC_STATIC; 290 } 291 292 if (!propertyDescriptor.isLateInit() && (!propertyDescriptor.isVar() || isDelegate)) { 293 modifiers |= ACC_FINAL; 294 } 295 296 Type type = typeMapper.mapType(jetType); 297 298 ClassBuilder builder = v; 299 300 boolean hasPublicFieldAnnotation = AnnotationsPackage.findPublicFieldAnnotation(propertyDescriptor) != null; 301 302 FieldOwnerContext backingFieldContext = context; 303 if (AsmUtil.isInstancePropertyWithStaticBackingField(propertyDescriptor) ) { 304 modifiers |= ACC_STATIC; 305 306 if (propertyDescriptor.isLateInit()) { 307 modifiers |= getVisibilityAccessFlag(propertyDescriptor); 308 } 309 else if (hasPublicFieldAnnotation && !isDelegate) { 310 modifiers |= ACC_PUBLIC; 311 } 312 else { 313 modifiers |= getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegate); 314 } 315 316 if (AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor)) { 317 ImplementationBodyCodegen codegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen(); 318 builder = codegen.v; 319 backingFieldContext = codegen.context; 320 v.getSerializationBindings().put(STATIC_FIELD_IN_OUTER_CLASS, propertyDescriptor); 321 } 322 } 323 else if (propertyDescriptor.isLateInit()) { 324 modifiers |= getVisibilityAccessFlag(propertyDescriptor); 325 } 326 else if (!isDelegate && hasPublicFieldAnnotation) { 327 modifiers |= ACC_PUBLIC; 328 } 329 else if (kind != OwnerKind.PACKAGE || isDelegate) { 330 modifiers |= ACC_PRIVATE; 331 } 332 333 if (AsmUtil.isPropertyWithBackingFieldCopyInOuterClass(propertyDescriptor)) { 334 ImplementationBodyCodegen parentBodyCodegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen(); 335 parentBodyCodegen.addCompanionObjectPropertyToCopy(propertyDescriptor, defaultValue); 336 } 337 338 String name = backingFieldContext.getFieldName(propertyDescriptor, isDelegate); 339 340 v.getSerializationBindings().put(FIELD_FOR_PROPERTY, propertyDescriptor, Pair.create(type, name)); 341 342 FieldVisitor fv = builder.newField(OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(), 343 typeMapper.mapFieldSignature(jetType), defaultValue); 344 345 Annotated fieldAnnotated = new AnnotatedWithFakeAnnotations(propertyDescriptor, annotations); 346 AnnotationCodegen.forField(fv, typeMapper).genAnnotations(fieldAnnotated, type, AnnotationUseSiteTarget.FIELD); 347 } 348 349 private void generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor, Annotations annotations) { 350 JetExpression delegateExpression = p.getDelegateExpression(); 351 JetType delegateType = delegateExpression != null ? bindingContext.getType(p.getDelegateExpression()) : null; 352 if (delegateType == null) { 353 // If delegate expression is unresolved reference 354 delegateType = ErrorUtils.createErrorType("Delegate type"); 355 } 356 357 generateBackingField(p, propertyDescriptor, true, delegateType, null, annotations); 358 } 359 360 private void generateBackingFieldAccess(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor, Annotations annotations) { 361 Object value = null; 362 363 if (shouldWriteFieldInitializer(propertyDescriptor)) { 364 ConstantValue<?> initializer = propertyDescriptor.getCompileTimeInitializer(); 365 if (initializer != null) { 366 value = initializer.getValue(); 367 } 368 } 369 370 generateBackingField(p, propertyDescriptor, false, propertyDescriptor.getType(), value, annotations); 371 } 372 373 private boolean shouldWriteFieldInitializer(@NotNull PropertyDescriptor descriptor) { 374 //final field of primitive or String type 375 if (!descriptor.isVar()) { 376 Type type = typeMapper.mapType(descriptor); 377 return AsmUtil.isPrimitive(type) || "java.lang.String".equals(type.getClassName()); 378 } 379 return false; 380 } 381 382 private void generateGetter(@Nullable JetNamedDeclaration p, @NotNull PropertyDescriptor descriptor, @Nullable JetPropertyAccessor getter) { 383 generateAccessor(p, getter, descriptor.getGetter() != null 384 ? descriptor.getGetter() 385 : DescriptorFactory.createDefaultGetter(descriptor, Annotations.EMPTY)); 386 } 387 388 private void generateSetter(@Nullable JetNamedDeclaration p, @NotNull PropertyDescriptor descriptor, @Nullable JetPropertyAccessor setter) { 389 if (!descriptor.isVar()) return; 390 391 generateAccessor(p, setter, descriptor.getSetter() != null 392 ? descriptor.getSetter() 393 : DescriptorFactory.createDefaultSetter(descriptor, Annotations.EMPTY)); 394 } 395 396 private void generateAccessor( 397 @Nullable JetNamedDeclaration p, 398 @Nullable JetPropertyAccessor accessor, 399 @NotNull PropertyAccessorDescriptor accessorDescriptor 400 ) { 401 FunctionGenerationStrategy strategy; 402 if (accessor == null || !accessor.hasBody()) { 403 if (p instanceof JetProperty && ((JetProperty) p).hasDelegate()) { 404 strategy = new DelegatedPropertyAccessorStrategy(state, accessorDescriptor, indexOfDelegatedProperty((JetProperty) p)); 405 } 406 else { 407 strategy = new DefaultPropertyAccessorStrategy(state, accessorDescriptor); 408 } 409 } 410 else { 411 strategy = new FunctionGenerationStrategy.FunctionDefault(state, accessorDescriptor, accessor); 412 } 413 414 functionCodegen.generateMethod(OtherOrigin(accessor != null ? accessor : p, accessorDescriptor), accessorDescriptor, strategy); 415 } 416 417 public static int indexOfDelegatedProperty(@NotNull JetProperty property) { 418 PsiElement parent = property.getParent(); 419 JetDeclarationContainer container; 420 if (parent instanceof JetClassBody) { 421 container = ((JetClassOrObject) parent.getParent()); 422 } 423 else if (parent instanceof JetFile) { 424 container = (JetFile) parent; 425 } 426 else { 427 throw new UnsupportedOperationException("Unknown delegated property container: " + parent); 428 } 429 430 int index = 0; 431 for (JetDeclaration declaration : container.getDeclarations()) { 432 if (declaration instanceof JetProperty && ((JetProperty) declaration).hasDelegate()) { 433 if (declaration == property) { 434 return index; 435 } 436 index++; 437 } 438 } 439 440 throw new IllegalStateException("Delegated property not found in its parent: " + PsiUtilPackage.getElementTextWithContext(property)); 441 } 442 443 444 private static class DefaultPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> { 445 public DefaultPropertyAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor) { 446 super(state, descriptor); 447 } 448 449 @Override 450 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 451 InstructionAdapter v = codegen.v; 452 PropertyDescriptor propertyDescriptor = callableDescriptor.getCorrespondingProperty(); 453 StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, true, null, StackValue.LOCAL_0); 454 455 PsiElement jetProperty = DescriptorToSourceUtils.descriptorToDeclaration(propertyDescriptor); 456 if (jetProperty instanceof JetProperty || jetProperty instanceof JetParameter) { 457 codegen.markLineNumber((JetElement) jetProperty, false); 458 } 459 460 if (callableDescriptor instanceof PropertyGetterDescriptor) { 461 Type type = signature.getReturnType(); 462 property.put(type, v); 463 v.areturn(type); 464 } 465 else if (callableDescriptor instanceof PropertySetterDescriptor) { 466 List<ValueParameterDescriptor> valueParameters = callableDescriptor.getValueParameters(); 467 assert valueParameters.size() == 1 : "Property setter should have only one value parameter but has " + callableDescriptor; 468 int parameterIndex = codegen.lookupLocalIndex(valueParameters.get(0)); 469 assert parameterIndex >= 0 : "Local index for setter parameter should be positive or zero: " + callableDescriptor; 470 Type type = codegen.typeMapper.mapType(propertyDescriptor); 471 property.store(StackValue.local(parameterIndex, type), codegen.v); 472 v.visitInsn(RETURN); 473 } 474 else { 475 throw new IllegalStateException("Unknown property accessor: " + callableDescriptor); 476 } 477 } 478 } 479 480 public static StackValue invokeDelegatedPropertyConventionMethod( 481 @NotNull PropertyDescriptor propertyDescriptor, 482 @NotNull ExpressionCodegen codegen, 483 @NotNull JetTypeMapper typeMapper, 484 @NotNull ResolvedCall<FunctionDescriptor> resolvedCall, 485 final int indexInPropertyMetadataArray, 486 int propertyMetadataArgumentIndex 487 ) { 488 CodegenContext<? extends ClassOrPackageFragmentDescriptor> ownerContext = codegen.getContext().getClassOrPackageParentContext(); 489 final Type owner; 490 if (ownerContext instanceof ClassContext) { 491 owner = typeMapper.mapClass(((ClassContext) ownerContext).getContextDescriptor()); 492 } 493 else if (ownerContext instanceof PackageContext) { 494 owner = ((PackageContext) ownerContext).getPackagePartType(); 495 } 496 else if (ownerContext instanceof MultifileClassContextBase) { 497 owner = ((MultifileClassContextBase) ownerContext).getFilePartType(); 498 } 499 else { 500 throw new UnsupportedOperationException("Unknown context: " + ownerContext); 501 } 502 503 codegen.tempVariables.put( 504 resolvedCall.getCall().getValueArguments().get(propertyMetadataArgumentIndex).asElement(), 505 new StackValue(PROPERTY_METADATA_TYPE) { 506 @Override 507 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 508 Field array = StackValue 509 .field(Type.getType("[" + PROPERTY_METADATA_TYPE), owner, JvmAbi.PROPERTY_METADATA_ARRAY_NAME, true, 510 StackValue.none()); 511 StackValue.arrayElement(PROPERTY_METADATA_TYPE, array, StackValue.constant(indexInPropertyMetadataArray, Type.INT_TYPE)).put(type, v); 512 } 513 } 514 ); 515 516 StackValue delegatedProperty = codegen.intermediateValueForProperty(propertyDescriptor, true, null, StackValue.LOCAL_0); 517 return codegen.invokeFunction(resolvedCall, delegatedProperty); 518 } 519 520 private static class DelegatedPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> { 521 private final int index; 522 523 public DelegatedPropertyAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor, int index) { 524 super(state, descriptor); 525 this.index = index; 526 } 527 528 @Override 529 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 530 InstructionAdapter v = codegen.v; 531 532 BindingContext bindingContext = state.getBindingContext(); 533 ResolvedCall<FunctionDescriptor> resolvedCall = 534 bindingContext.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, callableDescriptor); 535 assert resolvedCall != null : "Resolve call should be recorded for delegate call " + signature.toString(); 536 537 StackValue lastValue = invokeDelegatedPropertyConventionMethod(callableDescriptor.getCorrespondingProperty(), 538 codegen, state.getTypeMapper(), resolvedCall, index, 1); 539 Type asmType = signature.getReturnType(); 540 lastValue.put(asmType, v); 541 v.areturn(asmType); 542 } 543 } 544 545 public void genDelegate(@NotNull PropertyDescriptor delegate, @NotNull PropertyDescriptor delegateTo, @NotNull StackValue field) { 546 ClassDescriptor toClass = (ClassDescriptor) delegateTo.getContainingDeclaration(); 547 548 PropertyGetterDescriptor getter = delegate.getGetter(); 549 if (getter != null) { 550 //noinspection ConstantConditions 551 functionCodegen.genDelegate(getter, delegateTo.getGetter().getOriginal(), toClass, field); 552 } 553 554 PropertySetterDescriptor setter = delegate.getSetter(); 555 if (setter != null) { 556 //noinspection ConstantConditions 557 functionCodegen.genDelegate(setter, delegateTo.getSetter().getOriginal(), toClass, field); 558 } 559 } 560 }