diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt index be6147c605d..3c05ac4e327 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.types.FirTypeRef -import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef +import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImplWithoutSource import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* @@ -94,9 +94,7 @@ internal fun generateTemporaryVariable( this.source = source this.moduleData = moduleData origin = FirDeclarationOrigin.Source - returnTypeRef = typeRef ?: buildImplicitTypeRef { - this.source = source - } + returnTypeRef = typeRef ?: FirImplicitTypeRefImplWithoutSource this.name = name this.initializer = initializer symbol = FirPropertySymbol(name) diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 57531d6d733..d4660cf4c45 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -240,9 +240,7 @@ open class RawFirBuilder( valueParameter.toFirValueParameter(defaultTypeRef, functionSymbol, valueParameterDeclaration, additionalAnnotations) private fun KtTypeReference?.toFirOrImplicitType(): FirTypeRef = - convertSafe() ?: buildImplicitTypeRef { - source = this@toFirOrImplicitType?.toFirSourceElement(KtFakeSourceElementKind.ImplicitTypeRef) - } + this?.toFirOrErrorType() ?: FirImplicitTypeRefImplWithoutSource private fun KtTypeReference?.toFirOrUnitType(): FirTypeRef = convertSafe() ?: implicitUnitType diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/types/builder/FirImplicitTypeRefBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/types/builder/FirImplicitTypeRefBuilder.kt index 29c7eff3c78..ae57b681db6 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/types/builder/FirImplicitTypeRefBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/types/builder/FirImplicitTypeRefBuilder.kt @@ -23,7 +23,7 @@ import org.jetbrains.kotlin.fir.visitors.* @FirBuilderDsl class FirImplicitTypeRefBuilder { - var source: KtSourceElement? = null + lateinit var source: KtSourceElement fun build(): FirImplicitTypeRef { return FirImplicitTypeRefImpl( @@ -34,7 +34,7 @@ class FirImplicitTypeRefBuilder { } @OptIn(ExperimentalContracts::class) -inline fun buildImplicitTypeRef(init: FirImplicitTypeRefBuilder.() -> Unit = {}): FirImplicitTypeRef { +inline fun buildImplicitTypeRef(init: FirImplicitTypeRefBuilder.() -> Unit): FirImplicitTypeRef { contract { callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } @@ -42,11 +42,11 @@ inline fun buildImplicitTypeRef(init: FirImplicitTypeRefBuilder.() -> Unit = {}) } @OptIn(ExperimentalContracts::class) -inline fun buildImplicitTypeRefCopy(original: FirImplicitTypeRef, init: FirImplicitTypeRefBuilder.() -> Unit = {}): FirImplicitTypeRef { +inline fun buildImplicitTypeRefCopy(original: FirImplicitTypeRef, init: FirImplicitTypeRefBuilder.() -> Unit): FirImplicitTypeRef { contract { callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } val copyBuilder = FirImplicitTypeRefBuilder() - copyBuilder.source = original.source + original.source?.let { copyBuilder.source = it } return copyBuilder.apply(init).build() } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/types/impl/FirImplicitTypeRefImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/types/impl/FirImplicitTypeRefImpl.kt index 37d1354a25f..e268b8288f2 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/types/impl/FirImplicitTypeRefImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/types/impl/FirImplicitTypeRefImpl.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty */ internal class FirImplicitTypeRefImpl( - override val source: KtSourceElement?, + override val source: KtSourceElement, ) : FirImplicitTypeRef() { override val annotations: List get() = emptyList() diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirGeneration.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirGeneration.kt index ee1d6113d36..3e383973f01 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirGeneration.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirGeneration.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef +import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImplWithoutSource import org.jetbrains.kotlin.name.Name fun FirVariable.toQualifiedAccess( @@ -51,9 +52,7 @@ fun generateTemporaryVariable( this.source = source this.moduleData = moduleData origin = FirDeclarationOrigin.Source - returnTypeRef = typeRef ?: buildImplicitTypeRef { - this.source = source - } + returnTypeRef = typeRef ?: FirImplicitTypeRefImplWithoutSource this.name = name this.initializer = initializer symbol = FirPropertySymbol(name) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Utils.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Utils.kt index ee1f45e0191..9161aaf26fd 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Utils.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Utils.kt @@ -52,9 +52,9 @@ fun R.copyWithNewSource(newSource: KtSourceElement?): R { qualifier += typeRef.qualifier annotations += typeRef.annotations } - is FirImplicitTypeRef -> buildImplicitTypeRefCopy(typeRef) { - source = newSource - } + is FirImplicitTypeRef -> newSource?.let { + buildImplicitTypeRefCopy(typeRef) { source = it } + } ?: FirImplicitTypeRefImplWithoutSource is FirFunctionTypeRefImpl -> buildFunctionTypeRefCopy(typeRef) { source = newSource } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt index 31470cdade6..622fb7de9c1 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt @@ -482,6 +482,9 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator() impl(functionTypeRef) impl(implicitTypeRef) { defaultEmptyList("annotations") + default("source") { + notNull = true + } } impl(reference, "FirStubReference") { diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/context/AbstractBuilderConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/context/AbstractBuilderConfigurator.kt index b85ee602264..c32dd704c1e 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/context/AbstractBuilderConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/context/AbstractBuilderConfigurator.kt @@ -69,9 +69,11 @@ abstract class AbstractBuilderConfigurator(val firTr inner class DefaultValueContext(private val field: FieldWithDefault) { var value: String? = null + var notNull: Boolean? = null fun applyConfiguration() { if (value != null) field.defaultValueInBuilder = value + if (notNull != null) field.notNull = notNull!! } } } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/context/AbstractFirTreeImplementationConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/context/AbstractFirTreeImplementationConfigurator.kt index 169841f86e8..fad9ad1b869 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/context/AbstractFirTreeImplementationConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/context/AbstractFirTreeImplementationConfigurator.kt @@ -217,11 +217,17 @@ abstract class AbstractFirTreeImplementationConfigurator { var needAcceptAndTransform: Boolean = true + var notNull: Boolean = false + fun applyConfiguration() { field.withGetter = withGetter field.customSetter = customSetter isMutable?.let { field.isMutable = it } field.needAcceptAndTransform = needAcceptAndTransform + + if (notNull) { + field.notNull = true + } when { value != null -> field.defaultValueInImplementation = value delegate != null -> { diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/model/Field.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/model/Field.kt index 65e13576199..1c8dc61f1bf 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/model/Field.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/model/Field.kt @@ -30,6 +30,7 @@ sealed class Field : Importable { open val overridenTypes: MutableSet = mutableSetOf() open var useNullableForReplace: Boolean = false + open var notNull: Boolean = false var withBindThis = true diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/builder.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/builder.kt index 113696f2d89..86f33117c57 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/builder.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/builder.kt @@ -129,7 +129,7 @@ private fun SmartPrinter.printBuilder(builder: Builder) { private val String.nullable: String get() = if (endsWith("?")) this else "$this?" -private fun FieldWithDefault.needBackingField(fieldIsUseless: Boolean) = !nullable && origin !is FieldList && if (fieldIsUseless) { +private fun FieldWithDefault.needBackingField(fieldIsUseless: Boolean) = (!nullable || notNull) && origin !is FieldList && if (fieldIsUseless) { defaultValueInImplementation == null } else { defaultValueInBuilder == null @@ -145,7 +145,7 @@ private fun SmartPrinter.printFieldInBuilder(field: FieldWithDefault, builder: B return true to false } val name = field.name - val type = field.typeWithArguments + val type = field.getTypeWithArguments(field.notNull) val defaultValue = if (fieldIsUseless) field.defaultValueInImplementation.also { requireNotNull(it) } else @@ -305,6 +305,7 @@ private fun SmartPrinter.printDslBuildCopyFunction( when { field.origin is FieldList -> println("copyBuilder.${field.name}.addAll(original.${field.name})") field.type == declarationAttributesType.type -> println("copyBuilder.${field.name} = original.${field.name}.copy()") + field.notNull -> println("original.${field.name}?.let { copyBuilder.${field.name} = it }") else -> println("copyBuilder.${field.name} = original.${field.name}") } } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/field.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/field.kt index 13e5998f339..44eebbe9e32 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/field.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/field.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.fir.tree.generator.model.SimpleField import org.jetbrains.kotlin.util.SmartPrinter -fun SmartPrinter.printField(field: Field, isImplementation: Boolean, override: Boolean, end: String) { +fun SmartPrinter.printField(field: Field, isImplementation: Boolean, override: Boolean, end: String, notNull: Boolean = false) { if (isImplementation && !field.isVal && field.isVolatile) { println("@Volatile") } @@ -22,7 +22,7 @@ fun SmartPrinter.printField(field: Field, isImplementation: Boolean, override: B } else { print("var") } - val type = if (isImplementation) field.getMutableType() else field.typeWithArguments + val type = if (isImplementation) field.getMutableType(notNull = notNull) else field.getTypeWithArguments(notNull = notNull) println(" ${field.name}: $type$end") } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/implementation.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/implementation.kt index 314e64e3df7..90f968a81d6 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/implementation.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/implementation.kt @@ -77,7 +77,7 @@ fun SmartPrinter.printImplementation(implementation: Implementation) { withIndent { fieldsWithoutDefault.forEachIndexed { _, field -> - printField(field, isImplementation = true, override = true, end = ",") + printField(field, isImplementation = true, override = true, end = ",", notNull = field.notNull) } } print(")") @@ -94,7 +94,7 @@ fun SmartPrinter.printImplementation(implementation: Implementation) { allFields.forEach { abstract() - printField(it, isImplementation = true, override = true, end = "") + printField(it, isImplementation = true, override = true, end = "", notNull = it.notNull) } } else { fieldsWithDefault.forEach { diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/utils.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/utils.kt index 15e7f29a478..63b761f8f4e 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/utils.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/utils.kt @@ -122,14 +122,14 @@ fun Field.replaceFunctionDeclaration(overridenType: Importable? = null, forceNul return "fun replace$capName(new$capName: $typeWithNullable)" } -fun Field.getMutableType(forBuilder: Boolean = false): String = when (this) { +fun Field.getMutableType(forBuilder: Boolean = false, notNull: Boolean = false): String = when (this) { is FieldList -> when { isMutableOrEmpty && !forBuilder -> "MutableOrEmpty$typeWithArguments" isMutable -> "Mutable$typeWithArguments" else -> typeWithArguments } - is FieldWithDefault -> if (isMutable) origin.getMutableType() else typeWithArguments - else -> typeWithArguments + is FieldWithDefault -> if (isMutable) origin.getMutableType(notNull) else getTypeWithArguments(notNull) + else -> getTypeWithArguments(notNull) } fun Field.call(): String = if (nullable) "?." else "." @@ -151,18 +151,19 @@ fun Kind?.braces(): String = when (this) { val Element.safeDecapitalizedName: String get() = if (name == "Class") "klass" else name.replaceFirstChar(Char::lowercaseChar) -val Importable.typeWithArguments: String - get() = when (this) { - is AbstractElement -> type + generics - is Implementation -> type + element.generics - is FirField -> element.typeWithArguments + if (nullable) "?" else "" - is Field -> type + generics + if (nullable) "?" else "" - is Type -> type + generics - is ImplementationWithArg -> type + generics - is LeafBuilder -> type + implementation.element.generics - is IntermediateBuilder -> type - else -> throw IllegalArgumentException() - } +val Importable.typeWithArguments: String get() = getTypeWithArguments() + +fun Importable.getTypeWithArguments(notNull: Boolean = false): String = when (this) { + is AbstractElement -> type + generics + is Implementation -> type + element.generics + is FirField -> element.getTypeWithArguments(notNull) + if (nullable && !notNull) "?" else "" + is Field -> type + generics + if (nullable && !notNull) "?" else "" + is Type -> type + generics + is ImplementationWithArg -> type + generics + is LeafBuilder -> type + implementation.element.generics + is IntermediateBuilder -> type + else -> throw IllegalArgumentException() +} val ImplementationWithArg.generics: String get() = argument?.let { "<${it.type}>" } ?: ""