fun createIrProperty()

in compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt [218:366]


    fun createIrProperty(
        property: FirProperty,
        irParent: IrDeclarationParent?,
        symbols: PropertySymbols,
        predefinedOrigin: IrDeclarationOrigin? = null,
        fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null,
        allowLazyDeclarationsCreation: Boolean
    ): IrProperty = convertCatching(property) {
        val origin = when {
            !predefinedOrigin.isExternal &&
                    property.isStatic &&
                    property.name in Fir2IrDeclarationStorage.ENUM_SYNTHETIC_NAMES
            -> IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER

            else -> property.computeIrOrigin(
                predefinedOrigin,
                parentOrigin = (irParent as? IrDeclaration)?.origin,
                fakeOverrideOwnerLookupTag
            )
        }
        // See similar comments in createIrFunction above
        val parentIsExternal = irParent.isExternalParent()
        if (parentIsExternal) {
            if (!allowLazyDeclarationsCreation) {
                error("Lazy properties should be processed in Fir2IrDeclarationStorage: ${property.render()}")
            }
            @OptIn(UnsafeDuringIrConstructionAPI::class)
            if (symbols.propertySymbol.isBound) return symbols.propertySymbol.owner
            // For private functions signature is null, fallback to non-lazy property
            return lazyDeclarationsGenerator.createIrLazyProperty(property, irParent, symbols, origin)
        }
        return property.convertWithOffsets { startOffset, endOffset ->
            classifierStorage.preCacheTypeParameters(property)
            IrFactoryImpl.createProperty(
                startOffset = if (origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER) SYNTHETIC_OFFSET else startOffset,
                endOffset = if (origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER) SYNTHETIC_OFFSET else endOffset,
                origin = origin,
                name = property.name,
                visibility = c.visibilityConverter.convertToDescriptorVisibility(property.visibility),
                modality = property.modality!!,
                symbol = symbols.propertySymbol,
                isVar = property.isVar,
                isConst = property.isConst,
                isLateinit = property.isLateInit,
                isDelegated = property.delegate != null,
                isExternal = isEffectivelyExternal(property, irParent),
                containerSource = property.containerSource,
                isExpect = property.isExpect,
            ).apply {
                metadata = FirMetadataSource.Property(property)
                convertAnnotationsForNonDeclaredMembers(property, origin)
                declarationStorage.withScope(symbol) {
                    // IrProperty is never created for local variables
                    setParent(irParent)
                    addDeclarationToParent(this, irParent)
                    val type = property.returnTypeRef.toIrType()
                    val delegate = property.delegate
                    val getter = property.getter
                    val setter = property.setter
                    if (delegate != null || property.hasBackingField) {
                        val backingField = if (delegate != null) {
                            ((delegate as? FirQualifiedAccessExpression)?.calleeReference?.toResolvedBaseSymbol()?.fir as? FirTypeParameterRefsOwner)?.let {
                                classifierStorage.preCacheTypeParameters(it)
                            }
                            createBackingField(
                                irProperty = this,
                                firProperty = property,
                                origin = IrDeclarationOrigin.PROPERTY_DELEGATE,
                                symbol = symbols.backingFieldSymbol!!,
                                visibility = c.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility),
                                name = NameUtils.propertyDelegateName(property.name),
                                isFinal = true,
                                firInitializerExpression = delegate.takeIf { property.isReplSnippetDeclaration != true },
                                type = delegate.resolvedType.toIrType(),
                            )
                        } else {
                            // REPL snippet properties are initialized within the `$$eval` function.
                            // TODO(KT-82578): split declaration and initializer to hopefully simplify FIR2IR
                            val initializer = runIf(property.isReplSnippetDeclaration != true) {
                                getEffectivePropertyInitializer(property, resolveIfNeeded = true)
                            }

                            // There are cases when we get here for properties
                            // that have no backing field. For example, in the
                            // funExpression.kt test there's an attempt
                            // to access the `javaClass` property of the `foo0`'s
                            // `block` argument
                            val typeToUse = property.backingField?.returnTypeRef?.toIrType() ?: type
                            createBackingField(
                                this,
                                property,
                                IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
                                symbols.backingFieldSymbol!!,
                                c.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility),
                                property.name,
                                property.isVal,
                                initializer,
                                typeToUse,
                            ).also { field ->
                                if (initializer is FirLiteralExpression) {
                                    val constType = initializer.resolvedType.toIrType()
                                    field.initializer = factory.createExpressionBody(initializer.toIrConst(constType))
                                }
                            }
                        }
                        this.backingField = backingField
                    }
                    if (irParent != null) {
                        backingField?.parent = irParent
                    }
                    this.getter = symbols.getterSymbol?.let { getterSymbol ->
                        getter.convertWithOffsets(startOffset, endOffset) { startOffset, endOffset ->
                            createIrPropertyAccessor(
                                getter, property, this, getterSymbol, type, irParent, false,
                                when {
                                    origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin
                                    origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER -> origin
                                    delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
                                    origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin
                                    origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin
                                    getter == null || getter is FirDefaultPropertyGetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
                                    else -> origin
                                },
                                if (origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER) SYNTHETIC_OFFSET else startOffset,
                                if (origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER) SYNTHETIC_OFFSET else endOffset,
                                property.unwrapFakeOverrides().getter,
                            )
                        }
                    }
                    if (property.isVar && symbols.setterSymbol != null) {
                        this.setter = setter.convertWithOffsets(startOffset, endOffset) { startOffset, endOffset ->
                            createIrPropertyAccessor(
                                setter, property, this, symbols.setterSymbol, type, irParent, true,
                                when {
                                    delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
                                    origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin
                                    origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin
                                    setter is FirDefaultPropertySetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
                                    else -> origin
                                },
                                startOffset, endOffset,
                                property.unwrapFakeOverrides().setter,
                            )
                        }
                    }
                }
            }
        }
    }