/* * Copyright 2010-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jetbrains.kotlin.codegen.context; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.AccessorForPropertyDescriptor; import org.jetbrains.kotlin.codegen.OwnerKind; import org.jetbrains.kotlin.codegen.binding.MutableClosure; import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.PropertyDescriptor; import org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt; import java.util.HashMap; import java.util.Map; public abstract class FieldOwnerContext<T extends DeclarationDescriptor> extends CodegenContext<T> { //default property name -> map<property descriptor -> bytecode name> private final Map<String, Map<PropertyDescriptor, String>> fieldNames = new HashMap<>(); public FieldOwnerContext( @NotNull T contextDescriptor, @NotNull OwnerKind contextKind, @Nullable CodegenContext parentContext, @Nullable MutableClosure closure, @Nullable ClassDescriptor thisDescriptor, @Nullable LocalLookup expressionCodegen ) { super(contextDescriptor, contextKind, parentContext, closure, thisDescriptor, expressionCodegen); } @NotNull public String getFieldName(@NotNull PropertyDescriptor possiblySubstitutedDescriptor, boolean isDelegated) { if (possiblySubstitutedDescriptor instanceof AccessorForPropertyDescriptor) { possiblySubstitutedDescriptor = ((AccessorForPropertyDescriptor) possiblySubstitutedDescriptor).getCalleeDescriptor(); } PropertyDescriptor descriptor = possiblySubstitutedDescriptor.getOriginal(); assert descriptor.getKind().isReal() : "Only declared properties can have backing fields: " + descriptor; String defaultPropertyName = KotlinTypeMapper.mapDefaultFieldName(descriptor, isDelegated); Map<PropertyDescriptor, String> descriptor2Name = fieldNames.computeIfAbsent(defaultPropertyName, unused -> new HashMap<>()); String actualName = descriptor2Name.get(descriptor); if (actualName != null) return actualName; String newName = descriptor2Name.isEmpty() || AnnotationUtilKt.hasJvmFieldAnnotation(descriptor) ? defaultPropertyName : defaultPropertyName + "$" + descriptor2Name.size(); descriptor2Name.put(descriptor, newName); return newName; } }