FIR checker: report uninitialized member/extension properties
This commit is contained in:
committed by
Dmitriy Novozhilov
parent
e8028e7825
commit
e009b71f88
@@ -8,8 +8,8 @@ class KotlinType
|
|||||||
class KClassValue(value: Value) : ConstantValue<KClassValue.Value>(value) {
|
class KClassValue(value: Value) : ConstantValue<KClassValue.Value>(value) {
|
||||||
sealed class Value {
|
sealed class Value {
|
||||||
data class NormalClass(val value: ClassLiteralValue) : Value() {
|
data class NormalClass(val value: ClassLiteralValue) : Value() {
|
||||||
val classId: ClassId
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val classId: ClassId<!>
|
||||||
val arrayDimensions: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val arrayDimensions: Int<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
data class LocalClass(val type: KotlinType) : Value()
|
data class LocalClass(val type: KotlinType) : Value()
|
||||||
|
|||||||
+1
-1
@@ -2,6 +2,6 @@ annotation class A() {
|
|||||||
<!ANNOTATION_CLASS_MEMBER!><!PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor(s: Nothing?)<!> {}<!>
|
<!ANNOTATION_CLASS_MEMBER!><!PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor(s: Nothing?)<!> {}<!>
|
||||||
<!ANNOTATION_CLASS_MEMBER!>init {}<!>
|
<!ANNOTATION_CLASS_MEMBER!>init {}<!>
|
||||||
<!ANNOTATION_CLASS_MEMBER!>fun foo() {}<!>
|
<!ANNOTATION_CLASS_MEMBER!>fun foo() {}<!>
|
||||||
<!ANNOTATION_CLASS_MEMBER!>val bar: Nothing?<!>
|
<!ANNOTATION_CLASS_MEMBER, MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val bar: Nothing?<!>
|
||||||
<!ANNOTATION_CLASS_MEMBER!>val baz get() = Unit<!>
|
<!ANNOTATION_CLASS_MEMBER!>val baz get() = Unit<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -10,6 +10,6 @@ class A {
|
|||||||
class B {
|
class B {
|
||||||
val field: String = ""
|
val field: String = ""
|
||||||
|
|
||||||
val x: Int
|
<!MUST_BE_INITIALIZED!>val x: Int<!>
|
||||||
get() = field.<!UNRESOLVED_REFERENCE!>length<!> // should be an error
|
get() = field.<!UNRESOLVED_REFERENCE!>length<!> // should be an error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,5 +15,5 @@ class SomeClass : SomeInterface {
|
|||||||
get() = true
|
get() = true
|
||||||
set(value) {}
|
set(value) {}
|
||||||
|
|
||||||
var fau: Double
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var fau: Double<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -14,10 +14,10 @@ class A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Property {
|
class Property {
|
||||||
var var1: String
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var var1: String<!>
|
||||||
var var2: String
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var var2: String<!>
|
||||||
var var3: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var var3: Int<!>
|
||||||
<!EXPOSED_PROPERTY_TYPE{LT}!>var <!EXPOSED_PROPERTY_TYPE{PSI}!>var4<!>: A.AInnerPrivate<!>
|
<!EXPOSED_PROPERTY_TYPE{LT}, MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var <!EXPOSED_PROPERTY_TYPE{PSI}!>var4<!>: A.AInnerPrivate<!>
|
||||||
var var5: A.AInnerPublic
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var var5: A.AInnerPublic<!>
|
||||||
<!EXPOSED_PROPERTY_TYPE{LT}!>var <!EXPOSED_PROPERTY_TYPE{PSI}!>var6<!>: A.AInnerProtectedEnum<!>
|
<!EXPOSED_PROPERTY_TYPE{LT}, MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var <!EXPOSED_PROPERTY_TYPE{PSI}!>var6<!>: A.AInnerProtectedEnum<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
private var Int.readOnlyWrapper: CharSequence? get() = null
|
<!MUST_BE_INITIALIZED!>private var Int.readOnlyWrapper: CharSequence?<!> get() = null
|
||||||
private var Int.mutableWrapper: CharSequence? get() = null
|
<!MUST_BE_INITIALIZED!>private var Int.mutableWrapper: CharSequence?<!> get() = null
|
||||||
|
|
||||||
fun main(x: Int) {
|
fun main(x: Int) {
|
||||||
val x = if (x > 1) x::readOnlyWrapper else x::mutableWrapper
|
val x = if (x > 1) x::readOnlyWrapper else x::mutableWrapper
|
||||||
|
|||||||
+4
@@ -319,6 +319,10 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
|||||||
val PROPERTY_INITIALIZER_IN_INTERFACE by error<FirSourceElement, KtExpression>()
|
val PROPERTY_INITIALIZER_IN_INTERFACE by error<FirSourceElement, KtExpression>()
|
||||||
val PROPERTY_WITH_NO_TYPE_NO_INITIALIZER by error<FirSourceElement, KtProperty>(PositioningStrategy.DECLARATION_SIGNATURE)
|
val PROPERTY_WITH_NO_TYPE_NO_INITIALIZER by error<FirSourceElement, KtProperty>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||||
|
|
||||||
|
val MUST_BE_INITIALIZED by error<FirSourceElement, KtProperty>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||||
|
val MUST_BE_INITIALIZED_OR_BE_ABSTRACT by error<FirSourceElement, KtProperty>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||||
|
val EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT by error<FirSourceElement, KtProperty>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||||
|
|
||||||
val BACKING_FIELD_IN_INTERFACE by error<FirSourceElement, KtProperty>(PositioningStrategy.DECLARATION_SIGNATURE)
|
val BACKING_FIELD_IN_INTERFACE by error<FirSourceElement, KtProperty>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||||
val EXTENSION_PROPERTY_WITH_BACKING_FIELD by error<FirSourceElement, KtExpression>()
|
val EXTENSION_PROPERTY_WITH_BACKING_FIELD by error<FirSourceElement, KtExpression>()
|
||||||
val PROPERTY_INITIALIZER_NO_BACKING_FIELD by error<FirSourceElement, KtExpression>()
|
val PROPERTY_INITIALIZER_NO_BACKING_FIELD by error<FirSourceElement, KtExpression>()
|
||||||
|
|||||||
@@ -215,6 +215,9 @@ object FirErrors {
|
|||||||
val ABSTRACT_PROPERTY_WITH_INITIALIZER by error0<FirSourceElement, KtExpression>()
|
val ABSTRACT_PROPERTY_WITH_INITIALIZER by error0<FirSourceElement, KtExpression>()
|
||||||
val PROPERTY_INITIALIZER_IN_INTERFACE by error0<FirSourceElement, KtExpression>()
|
val PROPERTY_INITIALIZER_IN_INTERFACE by error0<FirSourceElement, KtExpression>()
|
||||||
val PROPERTY_WITH_NO_TYPE_NO_INITIALIZER by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
val PROPERTY_WITH_NO_TYPE_NO_INITIALIZER by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
|
val MUST_BE_INITIALIZED by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
|
val MUST_BE_INITIALIZED_OR_BE_ABSTRACT by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
|
val EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
val BACKING_FIELD_IN_INTERFACE by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
val BACKING_FIELD_IN_INTERFACE by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
val EXTENSION_PROPERTY_WITH_BACKING_FIELD by error0<FirSourceElement, KtExpression>()
|
val EXTENSION_PROPERTY_WITH_BACKING_FIELD by error0<FirSourceElement, KtExpression>()
|
||||||
val PROPERTY_INITIALIZER_NO_BACKING_FIELD by error0<FirSourceElement, KtExpression>()
|
val PROPERTY_INITIALIZER_NO_BACKING_FIELD by error0<FirSourceElement, KtExpression>()
|
||||||
|
|||||||
@@ -22,13 +22,25 @@ abstract class EventOccurrencesRangeInfo<E : EventOccurrencesRangeInfo<E, K>, K
|
|||||||
map: PersistentMap<K, EventOccurrencesRange> = persistentMapOf()
|
map: PersistentMap<K, EventOccurrencesRange> = persistentMapOf()
|
||||||
) : ControlFlowInfo<E, K, EventOccurrencesRange>(map) {
|
) : ControlFlowInfo<E, K, EventOccurrencesRange>(map) {
|
||||||
|
|
||||||
override fun merge(other: E): E {
|
override fun merge(other: E): E =
|
||||||
|
operation(other, EventOccurrencesRange::or)
|
||||||
|
|
||||||
|
fun plus(other: E): E =
|
||||||
|
when {
|
||||||
|
isEmpty() -> other
|
||||||
|
other.isEmpty() ->
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
this as E
|
||||||
|
else -> operation(other, EventOccurrencesRange::plus)
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun operation(other: E, op: (EventOccurrencesRange, EventOccurrencesRange) -> EventOccurrencesRange): E {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
var result = this as E
|
var result = this as E
|
||||||
for (symbol in keys.union(other.keys)) {
|
for (symbol in keys.union(other.keys)) {
|
||||||
val kind1 = this[symbol] ?: EventOccurrencesRange.ZERO
|
val kind1 = this[symbol] ?: EventOccurrencesRange.ZERO
|
||||||
val kind2 = other[symbol] ?: EventOccurrencesRange.ZERO
|
val kind2 = other[symbol] ?: EventOccurrencesRange.ZERO
|
||||||
result = result.put(symbol, kind1 or kind2)
|
result = result.put(symbol, op.invoke(kind1, kind2))
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
+50
-15
@@ -19,9 +19,45 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
|||||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
|
||||||
|
internal fun isInsideExpectClass(containingClass: FirRegularClass, context: CheckerContext): Boolean =
|
||||||
|
isInsideSpecificClass(containingClass, context) { klass -> klass.isExpect }
|
||||||
|
|
||||||
|
internal fun isInsideExternalClass(containingClass: FirRegularClass, context: CheckerContext): Boolean =
|
||||||
|
isInsideSpecificClass(containingClass, context) { klass -> klass.isExternal }
|
||||||
|
|
||||||
// Note that the class that contains the currently visiting declaration will *not* be in the context's containing declarations *yet*.
|
// Note that the class that contains the currently visiting declaration will *not* be in the context's containing declarations *yet*.
|
||||||
internal fun isInsideExpectClass(containingDeclaration: FirRegularClass, context: CheckerContext): Boolean =
|
private inline fun isInsideSpecificClass(
|
||||||
containingDeclaration.isExpect || context.containingDeclarations.asReversed().any { it is FirRegularClass && it.isExpect }
|
containingClass: FirRegularClass,
|
||||||
|
context: CheckerContext,
|
||||||
|
specificStatus: (FirRegularClass) -> Boolean
|
||||||
|
): Boolean =
|
||||||
|
specificStatus.invoke(containingClass) ||
|
||||||
|
context.containingDeclarations.asReversed().any { it is FirRegularClass && specificStatus.invoke(it) }
|
||||||
|
|
||||||
|
internal fun FirMemberDeclaration.isEffectivelyExpect(
|
||||||
|
containingClass: FirRegularClass?,
|
||||||
|
modifierList: FirModifierList? = null,
|
||||||
|
context: CheckerContext,
|
||||||
|
): Boolean {
|
||||||
|
val isExpect = this.isExpect || modifierList?.modifiers?.any { it.token == KtTokens.EXPECT_KEYWORD } == true
|
||||||
|
if (isExpect) return true
|
||||||
|
|
||||||
|
return containingClass != null && isInsideExpectClass(containingClass, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun FirMemberDeclaration.isEffectivelyExternal(
|
||||||
|
containingClass: FirRegularClass?,
|
||||||
|
modifierList: FirModifierList? = null,
|
||||||
|
context: CheckerContext,
|
||||||
|
): Boolean {
|
||||||
|
val isExternal = this.isExternal || modifierList?.modifiers?.any { it.token == KtTokens.EXTERNAL_KEYWORD } == true
|
||||||
|
if (isExternal) return true
|
||||||
|
|
||||||
|
// NB: [MemberDescriptor.isEffectivelyExternal] checks property accessors for property and vice versa.
|
||||||
|
// But, raw FIR creation already did such upward/downward propagation of modifiers.
|
||||||
|
|
||||||
|
return containingClass != null && isInsideExternalClass(containingClass, context)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: check class too
|
// TODO: check class too
|
||||||
internal fun checkExpectDeclarationVisibilityAndBody(
|
internal fun checkExpectDeclarationVisibilityAndBody(
|
||||||
@@ -45,17 +81,19 @@ internal fun checkProperty(
|
|||||||
containingClass: FirRegularClass?,
|
containingClass: FirRegularClass?,
|
||||||
property: FirProperty,
|
property: FirProperty,
|
||||||
modifierList: FirModifierList?,
|
modifierList: FirModifierList?,
|
||||||
|
isInitialized: Boolean,
|
||||||
reporter: DiagnosticReporter,
|
reporter: DiagnosticReporter,
|
||||||
context: CheckerContext
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
checkPropertyInitializer(containingClass, modifierList, property, reporter, context)
|
checkPropertyInitializer(containingClass, property, modifierList, isInitialized, reporter, context)
|
||||||
checkPropertyAccessors(property, reporter, context)
|
checkPropertyAccessors(property, reporter, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkPropertyInitializer(
|
private fun checkPropertyInitializer(
|
||||||
containingClass: FirRegularClass?,
|
containingClass: FirRegularClass?,
|
||||||
modifierList: FirModifierList?,
|
|
||||||
property: FirProperty,
|
property: FirProperty,
|
||||||
|
modifierList: FirModifierList?,
|
||||||
|
isInitialized: Boolean,
|
||||||
reporter: DiagnosticReporter,
|
reporter: DiagnosticReporter,
|
||||||
context: CheckerContext
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
@@ -78,7 +116,7 @@ private fun checkPropertyInitializer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val isExpect = property.isExpect || modifierList?.modifiers?.any { it.token == KtTokens.EXPECT_KEYWORD } == true
|
val isExpect = property.isEffectivelyExpect(containingClass, modifierList, context)
|
||||||
|
|
||||||
when {
|
when {
|
||||||
property.initializer != null -> {
|
property.initializer != null -> {
|
||||||
@@ -112,18 +150,16 @@ private fun checkPropertyInitializer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val isExternal = property.isExternal || modifierList?.modifiers?.any { it.token == KtTokens.EXTERNAL_KEYWORD } == true
|
val isExternal = property.isEffectivelyExternal(containingClass, modifierList, context)
|
||||||
// TODO: need to analyze class anonymous initializer to see if the property is initialized there.
|
if (backingFieldRequired && !inInterface && !property.isLateInit && !isExpect && !isInitialized && !isExternal) {
|
||||||
val isUninitialized = false
|
|
||||||
if (backingFieldRequired && !inInterface && !property.isLateInit && !isExpect && isUninitialized && !isExternal) {
|
|
||||||
property.source?.let {
|
property.source?.let {
|
||||||
if (property.receiverTypeRef != null && !property.hasAccessorImplementation) {
|
if (property.receiverTypeRef != null && !property.hasAccessorImplementation) {
|
||||||
// reporter.reportOn(it, FirErrors.EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT, context)
|
reporter.reportOn(it, FirErrors.EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT, context)
|
||||||
} else {
|
} else { // TODO: can be suppressed not to report diagnostics about no body
|
||||||
if (containingClass != null || property.hasAccessorImplementation) {
|
if (containingClass == null || property.hasAccessorImplementation) {
|
||||||
// reporter.reportOn(it, FirErrors.MUST_BE_INITIALIZED, context)
|
reporter.reportOn(it, FirErrors.MUST_BE_INITIALIZED, context)
|
||||||
} else {
|
} else {
|
||||||
// reporter.reportOn(it, FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT, context)
|
reporter.reportOn(it, FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,5 +184,4 @@ private val FirProperty.hasAccessorImplementation: Boolean
|
|||||||
get() = (getter !is FirDefaultPropertyAccessor && getter?.hasBody == true) ||
|
get() = (getter !is FirDefaultPropertyAccessor && getter?.hasBody == true) ||
|
||||||
(setter !is FirDefaultPropertyAccessor && setter?.hasBody == true)
|
(setter !is FirDefaultPropertyAccessor && setter?.hasBody == true)
|
||||||
|
|
||||||
|
|
||||||
internal val FirClass<*>.canHaveOpenMembers: Boolean get() = modality() != Modality.FINAL || classKind == ClassKind.ENUM_CLASS
|
internal val FirClass<*>.canHaveOpenMembers: Boolean get() = modality() != Modality.FINAL || classKind == ClassKind.ENUM_CLASS
|
||||||
|
|||||||
+112
-4
@@ -5,9 +5,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||||
|
import org.jetbrains.kotlin.contracts.description.isDefinitelyVisited
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.cfa.PropertyInitializationInfo
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.cfa.PropertyInitializationInfoCollector
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
@@ -15,22 +19,126 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
|||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.NormalPath
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.dfa.controlFlowGraph
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
|
||||||
// See old FE's [DeclarationsChecker]
|
// See old FE's [DeclarationsChecker]
|
||||||
object FirMemberPropertyChecker : FirRegularClassChecker() {
|
object FirMemberPropertyChecker : FirRegularClassChecker() {
|
||||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
for (member in declaration.declarations) {
|
val memberPropertySymbols = declaration.declarations.filterIsInstance<FirProperty>().map { it.symbol }.toSet()
|
||||||
if (member is FirProperty) {
|
val initializedInConstructor =
|
||||||
checkProperty(declaration, member, context, reporter)
|
mutableMapOf<FirPropertySymbol, EventOccurrencesRange>().withDefault { EventOccurrencesRange.ZERO }
|
||||||
|
val initializedInInitOrOtherProperty =
|
||||||
|
mutableMapOf<FirPropertySymbol, EventOccurrencesRange>().withDefault { EventOccurrencesRange.ZERO }
|
||||||
|
|
||||||
|
// If all member properties have its own initializer, we don't need to collect property initialization info at all.
|
||||||
|
if (memberPropertySymbols.any { it.fir.initializer == null }) {
|
||||||
|
collectPropertyInitialization(declaration, memberPropertySymbols, initializedInConstructor, initializedInInitOrOtherProperty)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (propertySymbol in memberPropertySymbols) {
|
||||||
|
val property = propertySymbol.fir
|
||||||
|
val isInitialized =
|
||||||
|
property.initializer != null ||
|
||||||
|
initializedInConstructor.getValue(propertySymbol).isDefinitelyVisited() ||
|
||||||
|
initializedInInitOrOtherProperty.getValue(propertySymbol).isDefinitelyVisited()
|
||||||
|
checkProperty(declaration, property, isInitialized, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun collectPropertyInitialization(
|
||||||
|
klass: FirRegularClass,
|
||||||
|
memberPropertySymbols: Set<FirPropertySymbol>,
|
||||||
|
initializedInConstructor: MutableMap<FirPropertySymbol, EventOccurrencesRange>,
|
||||||
|
initializedInInitOrOtherProperty: MutableMap<FirPropertySymbol, EventOccurrencesRange>
|
||||||
|
) {
|
||||||
|
// A property is known to be initialized only if it is initialized
|
||||||
|
// 1) with its own initializing expression;
|
||||||
|
// 2) at every class constructor;
|
||||||
|
// 3) at any of class's anonymous initializers; or
|
||||||
|
// 4) at other property's initializing expression
|
||||||
|
|
||||||
|
// 2) Property can be initialized at constructors. Since it's unknown what constructor will be used, the property can be determined
|
||||||
|
// as initialized only if it is initialized at every constructor. We should consider a delegated constructor, e.g.,
|
||||||
|
// constructor() { x = ... }
|
||||||
|
// constructor(...): this() { ... } // x will be initialized via this() delegation
|
||||||
|
// We need to topologically sort constructors so that we can process delegated ones before the use sites.
|
||||||
|
|
||||||
|
// 3) Property can be initialized at any of class's anonymous initializers (all of initializers will be executed), e.g.,
|
||||||
|
// init { x = ... }
|
||||||
|
// ...
|
||||||
|
// init { y = ... }
|
||||||
|
|
||||||
|
// 4) Property can be initialized at other property's initializing expression too, e.g.,
|
||||||
|
// val initX = inlineMe { x = ... } // where inlineMe returns the value of the last expression of the lambda
|
||||||
|
|
||||||
|
// To handle the delegated constructor call, we need a cache from constructor to (analyzed) property init info.
|
||||||
|
val constructorToData =
|
||||||
|
mutableMapOf<FirConstructor, PropertyInitializationInfo>().withDefault { PropertyInitializationInfo.EMPTY }
|
||||||
|
|
||||||
|
fun collectInfoFromGraph(
|
||||||
|
graph: ControlFlowGraph,
|
||||||
|
map: MutableMap<FirPropertySymbol, EventOccurrencesRange>,
|
||||||
|
acc: (EventOccurrencesRange, EventOccurrencesRange) -> EventOccurrencesRange,
|
||||||
|
delegatedConstructor: FirConstructor? = null,
|
||||||
|
) {
|
||||||
|
val delegatedInfo = delegatedConstructor?.let { constructorToData.getValue(it) } ?: PropertyInitializationInfo.EMPTY
|
||||||
|
|
||||||
|
val data = PropertyInitializationInfoCollector(memberPropertySymbols).getData(graph)
|
||||||
|
val infoAtExitNode = data[graph.exitNode]?.get(NormalPath) ?: PropertyInitializationInfo.EMPTY
|
||||||
|
|
||||||
|
// NB: it's not [merge], which is conducted at merging points, such as loop condition or when conditions.
|
||||||
|
// Rather, delegated constructor call is the predecessor of the current constructor call, so we should accumulate.
|
||||||
|
val info = delegatedInfo.plus(infoAtExitNode)
|
||||||
|
|
||||||
|
if (graph.declaration is FirConstructor) {
|
||||||
|
constructorToData.putIfAbsent(graph.declaration as FirConstructor, info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (propertySymbol in memberPropertySymbols) {
|
||||||
|
if (map.containsKey(propertySymbol)) {
|
||||||
|
// Accumulation:
|
||||||
|
// range join for class constructors, range plus for class's anonymous initializers and property initializations
|
||||||
|
map[propertySymbol] = acc.invoke(map[propertySymbol]!!, info[propertySymbol] ?: EventOccurrencesRange.ZERO)
|
||||||
|
} else {
|
||||||
|
// Initial assignment.
|
||||||
|
// NB: we should not use `acc` here to not weaken ranges. For example, if we visit one and only constructor where
|
||||||
|
// a property of interest is correctly initialized (a.k.a. [EXACTLY_ONCE]), and if `acc` is ...Range::or,
|
||||||
|
// merging with the default [ZERO] makes the result [AT_MOST_ONCE], which will be regarded as uninitialized.
|
||||||
|
map[propertySymbol] = info[propertySymbol] ?: EventOccurrencesRange.ZERO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val constructorGraphs = klass.constructorsSortedByDelegation.mapNotNull { it.controlFlowGraphReference?.controlFlowGraph }
|
||||||
|
for (graph in constructorGraphs) {
|
||||||
|
collectInfoFromGraph(
|
||||||
|
graph,
|
||||||
|
initializedInConstructor,
|
||||||
|
EventOccurrencesRange::or,
|
||||||
|
(graph.declaration as? FirConstructor)?.delegatedThisConstructor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val initGraphs = klass.anonymousInitializers.mapNotNull { it.controlFlowGraphReference?.controlFlowGraph }
|
||||||
|
for (graph in initGraphs) {
|
||||||
|
collectInfoFromGraph(graph, initializedInInitOrOtherProperty, EventOccurrencesRange::plus)
|
||||||
|
}
|
||||||
|
|
||||||
|
val propertyInitGraphs = memberPropertySymbols.mapNotNull { it.fir.controlFlowGraphReference?.controlFlowGraph }
|
||||||
|
for (graph in propertyInitGraphs) {
|
||||||
|
collectInfoFromGraph(graph, initializedInInitOrOtherProperty, EventOccurrencesRange::plus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkProperty(
|
private fun checkProperty(
|
||||||
containingDeclaration: FirRegularClass,
|
containingDeclaration: FirRegularClass,
|
||||||
property: FirProperty,
|
property: FirProperty,
|
||||||
|
isInitialized: Boolean,
|
||||||
context: CheckerContext,
|
context: CheckerContext,
|
||||||
reporter: DiagnosticReporter
|
reporter: DiagnosticReporter
|
||||||
) {
|
) {
|
||||||
@@ -40,7 +148,7 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
|
|||||||
// So, our source of truth should be the full modifier list retrieved from the source.
|
// So, our source of truth should be the full modifier list retrieved from the source.
|
||||||
val modifierList = with(FirModifierList) { property.source.getModifierList() }
|
val modifierList = with(FirModifierList) { property.source.getModifierList() }
|
||||||
|
|
||||||
checkProperty(containingDeclaration, property, modifierList, reporter, context)
|
checkProperty(containingDeclaration, property, modifierList, isInitialized, reporter, context)
|
||||||
checkExpectDeclarationVisibilityAndBody(property, source, modifierList, reporter, context)
|
checkExpectDeclarationVisibilityAndBody(property, source, modifierList, reporter, context)
|
||||||
|
|
||||||
val hasAbstractModifier = modifierList?.modifiers?.any { it.token == KtTokens.ABSTRACT_KEYWORD } == true
|
val hasAbstractModifier = modifierList?.modifiers?.any { it.token == KtTokens.ABSTRACT_KEYWORD } == true
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ object FirTopLevelPropertyChecker : FirFileChecker() {
|
|||||||
// So, our source of truth should be the full modifier list retrieved from the source.
|
// So, our source of truth should be the full modifier list retrieved from the source.
|
||||||
val modifierList = with(FirModifierList) { source.getModifierList() }
|
val modifierList = with(FirModifierList) { source.getModifierList() }
|
||||||
|
|
||||||
checkProperty(null, property, modifierList, reporter, context)
|
checkProperty(null, property, modifierList, property.initializer != null, reporter, context)
|
||||||
checkExpectDeclarationVisibilityAndBody(property, source, modifierList, reporter, context)
|
checkExpectDeclarationVisibilityAndBody(property, source, modifierList, reporter, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-4
@@ -75,6 +75,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_SUPER_CLA
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_SUPER_INTERFACE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_SUPER_INTERFACE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_TYPE_PARAMETER_BOUND
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_TYPE_PARAMETER_BOUND
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXTENSION_PROPERTY_WITH_BACKING_FIELD
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXTENSION_PROPERTY_WITH_BACKING_FIELD
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FORBIDDEN_VARARG_PARAMETER_TYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FORBIDDEN_VARARG_PARAMETER_TYPE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUNCTION_DECLARATION_WITH_NO_NAME
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUNCTION_DECLARATION_WITH_NO_NAME
|
||||||
@@ -101,6 +102,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_COMPANION_OB
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NESTED_CLASS_NOT_ALLOWED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NESTED_CLASS_NOT_ALLOWED
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_VARARG_PARAMETERS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_VARARG_PARAMETERS
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_FINAL_MEMBER_IN_FINAL_CLASS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_FINAL_MEMBER_IN_FINAL_CLASS
|
||||||
@@ -471,16 +474,19 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
|||||||
map.put(PRIVATE_PROPERTY_IN_INTERFACE, "Abstract property in an interface cannot be private")
|
map.put(PRIVATE_PROPERTY_IN_INTERFACE, "Abstract property in an interface cannot be private")
|
||||||
|
|
||||||
map.put(ABSTRACT_PROPERTY_WITH_INITIALIZER, "Property with initializer cannot be abstract")
|
map.put(ABSTRACT_PROPERTY_WITH_INITIALIZER, "Property with initializer cannot be abstract")
|
||||||
|
|
||||||
map.put(EXTENSION_PROPERTY_WITH_BACKING_FIELD, "Extension property cannot be initialized because it has no backing field")
|
|
||||||
map.put(PROPERTY_INITIALIZER_NO_BACKING_FIELD, "Initializer is not allowed here because this property has no backing field")
|
|
||||||
|
|
||||||
map.put(PROPERTY_INITIALIZER_IN_INTERFACE, "Property initializers are not allowed in interfaces")
|
map.put(PROPERTY_INITIALIZER_IN_INTERFACE, "Property initializers are not allowed in interfaces")
|
||||||
map.put(
|
map.put(
|
||||||
PROPERTY_WITH_NO_TYPE_NO_INITIALIZER,
|
PROPERTY_WITH_NO_TYPE_NO_INITIALIZER,
|
||||||
"This property must either have a type annotation, be initialized or be delegated"
|
"This property must either have a type annotation, be initialized or be delegated"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
map.put(MUST_BE_INITIALIZED, "Property must be initialized")
|
||||||
|
map.put(MUST_BE_INITIALIZED_OR_BE_ABSTRACT, "Property must be initialized or be abstract")
|
||||||
|
map.put(EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT, "Extension property must have accessors or be abstract")
|
||||||
|
|
||||||
map.put(BACKING_FIELD_IN_INTERFACE, "Property in an interface cannot have a backing field")
|
map.put(BACKING_FIELD_IN_INTERFACE, "Property in an interface cannot have a backing field")
|
||||||
|
map.put(EXTENSION_PROPERTY_WITH_BACKING_FIELD, "Extension property cannot be initialized because it has no backing field")
|
||||||
|
map.put(PROPERTY_INITIALIZER_NO_BACKING_FIELD, "Initializer is not allowed here because this property has no backing field")
|
||||||
|
|
||||||
map.put(ABSTRACT_DELEGATED_PROPERTY, "Delegated property cannot be abstract")
|
map.put(ABSTRACT_DELEGATED_PROPERTY, "Delegated property cannot be abstract")
|
||||||
map.put(DELEGATED_PROPERTY_IN_INTERFACE, "Delegated properties are not allowed in interfaces")
|
map.put(DELEGATED_PROPERTY_IN_INTERFACE, "Delegated properties are not allowed in interfaces")
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.FirRegularClassBuilder
|
|||||||
import org.jetbrains.kotlin.fir.declarations.builder.FirTypeParameterBuilder
|
import org.jetbrains.kotlin.fir.declarations.builder.FirTypeParameterBuilder
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirFileImpl
|
import org.jetbrains.kotlin.fir.declarations.impl.FirFileImpl
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirRegularClassImpl
|
import org.jetbrains.kotlin.fir.declarations.impl.FirRegularClassImpl
|
||||||
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousObjectSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousObjectSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
@@ -117,8 +118,34 @@ val FirClassSymbol<*>.superConeTypes
|
|||||||
|
|
||||||
val FirClass<*>.superConeTypes get() = superTypeRefs.mapNotNull { it.coneTypeSafe<ConeClassLikeType>() }
|
val FirClass<*>.superConeTypes get() = superTypeRefs.mapNotNull { it.coneTypeSafe<ConeClassLikeType>() }
|
||||||
|
|
||||||
|
val FirClass<*>.anonymousInitializers: List<FirAnonymousInitializer>
|
||||||
|
get() = declarations.filterIsInstance<FirAnonymousInitializer>()
|
||||||
|
|
||||||
|
val FirClass<*>.constructors: List<FirConstructor>
|
||||||
|
get() = declarations.filterIsInstance<FirConstructor>()
|
||||||
|
|
||||||
|
val FirConstructor.delegatedThisConstructor: FirConstructor?
|
||||||
|
get() = delegatedConstructor?.takeIf { it.isThis }
|
||||||
|
?.let { (it.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol?.fir as? FirConstructor }
|
||||||
|
|
||||||
|
private object ConstructorDelegationComparator : Comparator<FirConstructor> {
|
||||||
|
override fun compare(p0: FirConstructor?, p1: FirConstructor?): Int {
|
||||||
|
if (p0 == null && p1 == null) return 0
|
||||||
|
if (p0 == null) return -1
|
||||||
|
if (p1 == null) return 1
|
||||||
|
if (p0.delegatedThisConstructor == p1) return 1
|
||||||
|
if (p1.delegatedThisConstructor == p0) return -1
|
||||||
|
// If neither is a delegation to each other, the order doesn't matter.
|
||||||
|
// Here we return 0 to preserve the original order.
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val FirClass<*>.constructorsSortedByDelegation: List<FirConstructor>
|
||||||
|
get() = constructors.sortedWith(ConstructorDelegationComparator)
|
||||||
|
|
||||||
fun FirClass<*>.getPrimaryConstructorIfAny(): FirConstructor? =
|
fun FirClass<*>.getPrimaryConstructorIfAny(): FirConstructor? =
|
||||||
declarations.filterIsInstance<FirConstructor>().firstOrNull()?.takeIf { it.isPrimary }
|
constructors.firstOrNull()?.takeIf { it.isPrimary }
|
||||||
|
|
||||||
fun FirRegularClass.collectEnumEntries(): Collection<FirEnumEntry> {
|
fun FirRegularClass.collectEnumEntries(): Collection<FirEnumEntry> {
|
||||||
assert(classKind == ClassKind.ENUM_CLASS)
|
assert(classKind == ClassKind.ENUM_CLASS)
|
||||||
|
|||||||
+3
@@ -4,6 +4,9 @@ compiler/testData/cli/jvm/firError.kt:5:13: error: x must be initialized before
|
|||||||
compiler/testData/cli/jvm/firError.kt:10:16: error: public subclass exposes its private supertype 'Private'
|
compiler/testData/cli/jvm/firError.kt:10:16: error: public subclass exposes its private supertype 'Private'
|
||||||
class Public : Private() {
|
class Public : Private() {
|
||||||
^
|
^
|
||||||
|
compiler/testData/cli/jvm/firError.kt:11:5: error: property must be initialized or be abstract
|
||||||
|
val x: Private
|
||||||
|
^
|
||||||
compiler/testData/cli/jvm/firError.kt:11:9: error: public property exposes its private type 'Private'
|
compiler/testData/cli/jvm/firError.kt:11:9: error: public property exposes its private type 'Private'
|
||||||
val x: Private
|
val x: Private
|
||||||
^
|
^
|
||||||
|
|||||||
+8
-8
@@ -1,17 +1,17 @@
|
|||||||
// FILE: b.kt
|
// FILE: b.kt
|
||||||
package MyPackage
|
package MyPackage
|
||||||
//properties
|
//properties
|
||||||
val a: Int
|
<!MUST_BE_INITIALIZED!>val a: Int<!>
|
||||||
val a1: Int = 1
|
val a1: Int = 1
|
||||||
abstract val a2: Int
|
abstract val a2: Int
|
||||||
abstract val a3: Int = 1
|
abstract val a3: Int = 1
|
||||||
|
|
||||||
var b: Int private set
|
<!MUST_BE_INITIALIZED!>var b: Int<!> private set
|
||||||
var b1: Int = 0; private set
|
var b1: Int = 0; private set
|
||||||
abstract var b2: Int private set
|
abstract var b2: Int private set
|
||||||
abstract var b3: Int = 0; private set
|
abstract var b3: Int = 0; private set
|
||||||
|
|
||||||
var c: Int set(v: Int) { field = v }
|
<!MUST_BE_INITIALIZED!>var c: Int<!> set(v: Int) { field = v }
|
||||||
var c1: Int = 0; set(v: Int) { field = v }
|
var c1: Int = 0; set(v: Int) { field = v }
|
||||||
abstract var c2: Int set(v: Int) { field = v }
|
abstract var c2: Int set(v: Int) { field = v }
|
||||||
abstract var c3: Int = 0; set(v: Int) { field = v }
|
abstract var c3: Int = 0; set(v: Int) { field = v }
|
||||||
@@ -28,19 +28,19 @@ package MyPackage
|
|||||||
abstract fun j() {}
|
abstract fun j() {}
|
||||||
|
|
||||||
//property accessors
|
//property accessors
|
||||||
var i: Int abstract get abstract set
|
<!MUST_BE_INITIALIZED!>var i: Int<!> abstract get abstract set
|
||||||
var i1: Int = 0; abstract get abstract set
|
var i1: Int = 0; abstract get abstract set
|
||||||
|
|
||||||
var j: Int get() = i; abstract set
|
<!MUST_BE_INITIALIZED!>var j: Int<!> get() = i; abstract set
|
||||||
var j1: Int = 0; get() = i; abstract set
|
var j1: Int = 0; get() = i; abstract set
|
||||||
|
|
||||||
var k: Int abstract set
|
<!MUST_BE_INITIALIZED!>var k: Int<!> abstract set
|
||||||
var k1: Int = 0; abstract set
|
var k1: Int = 0; abstract set
|
||||||
|
|
||||||
var l: Int abstract get abstract set
|
<!MUST_BE_INITIALIZED!>var l: Int<!> abstract get abstract set
|
||||||
var l1: Int = 0; abstract get abstract set
|
var l1: Int = 0; abstract get abstract set
|
||||||
|
|
||||||
var n: Int abstract get abstract set(v: Int) {}
|
<!MUST_BE_INITIALIZED!>var n: Int<!> abstract get abstract set(v: Int) {}
|
||||||
|
|
||||||
// FILE: c.kt
|
// FILE: c.kt
|
||||||
//creating an instance
|
//creating an instance
|
||||||
|
|||||||
@@ -2,17 +2,17 @@ package abstract
|
|||||||
|
|
||||||
abstract class MyAbstractClass() {
|
abstract class MyAbstractClass() {
|
||||||
//properties
|
//properties
|
||||||
val a: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val a: Int<!>
|
||||||
val a1: Int = 1
|
val a1: Int = 1
|
||||||
abstract val a2: Int
|
abstract val a2: Int
|
||||||
abstract val a3: Int = <!ABSTRACT_PROPERTY_WITH_INITIALIZER!>1<!>
|
abstract val a3: Int = <!ABSTRACT_PROPERTY_WITH_INITIALIZER!>1<!>
|
||||||
|
|
||||||
var b: Int private set
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var b: Int<!> private set
|
||||||
var b1: Int = 0; private set
|
var b1: Int = 0; private set
|
||||||
abstract var b2: Int <!PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY!>private<!> set
|
abstract var b2: Int <!PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY!>private<!> set
|
||||||
abstract var b3: Int = <!ABSTRACT_PROPERTY_WITH_INITIALIZER!>0<!>; <!PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY!>private<!> set
|
abstract var b3: Int = <!ABSTRACT_PROPERTY_WITH_INITIALIZER!>0<!>; <!PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY!>private<!> set
|
||||||
|
|
||||||
var c: Int set(v: Int) { field = v }
|
<!MUST_BE_INITIALIZED!>var c: Int<!> set(v: Int) { field = v }
|
||||||
var c1: Int = 0; set(v: Int) { field = v }
|
var c1: Int = 0; set(v: Int) { field = v }
|
||||||
abstract var c2: Int <!ABSTRACT_PROPERTY_WITH_SETTER!>set(v: Int) { field = v }<!>
|
abstract var c2: Int <!ABSTRACT_PROPERTY_WITH_SETTER!>set(v: Int) { field = v }<!>
|
||||||
abstract var c3: Int = <!ABSTRACT_PROPERTY_WITH_INITIALIZER!>0<!>; <!ABSTRACT_PROPERTY_WITH_SETTER!>set(v: Int) { field = v }<!>
|
abstract var c3: Int = <!ABSTRACT_PROPERTY_WITH_INITIALIZER!>0<!>; <!ABSTRACT_PROPERTY_WITH_SETTER!>set(v: Int) { field = v }<!>
|
||||||
@@ -29,17 +29,18 @@ abstract class MyAbstractClass() {
|
|||||||
<!ABSTRACT_FUNCTION_WITH_BODY!>abstract<!> fun j() {}
|
<!ABSTRACT_FUNCTION_WITH_BODY!>abstract<!> fun j() {}
|
||||||
|
|
||||||
//property accessors
|
//property accessors
|
||||||
var i: Int abstract get abstract set
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var i: Int<!> abstract get abstract set
|
||||||
var i1: Int = 0; abstract get abstract set
|
var i1: Int = 0; abstract get abstract set
|
||||||
|
|
||||||
var j: Int get() = i; abstract set
|
<!MUST_BE_INITIALIZED!>var j: Int<!> get() = i; abstract set
|
||||||
var j1: Int get() = i; abstract set
|
<!MUST_BE_INITIALIZED!>var j1: Int<!> get() = i; abstract set
|
||||||
|
|
||||||
var k: Int abstract set
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var k: Int<!> abstract set
|
||||||
var k1: Int = 0; abstract set
|
var k1: Int = 0; abstract set
|
||||||
|
|
||||||
var l: Int abstract get abstract set
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var l: Int<!> abstract get abstract set
|
||||||
var l1: Int = 0; abstract get abstract set
|
var l1: Int = 0; abstract get abstract set
|
||||||
|
|
||||||
var n: Int abstract get abstract set(v: Int) {}
|
<!MUST_BE_INITIALIZED!>var n: Int<!> abstract get abstract set(v: Int) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,17 +2,17 @@ package abstract
|
|||||||
|
|
||||||
class MyClass() {
|
class MyClass() {
|
||||||
//properties
|
//properties
|
||||||
val a: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val a: Int<!>
|
||||||
val a1: Int = 1
|
val a1: Int = 1
|
||||||
<!ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS!>abstract<!> val a2: Int
|
<!ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS!>abstract<!> val a2: Int
|
||||||
<!ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS!>abstract<!> val a3: Int = 1
|
<!ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS!>abstract<!> val a3: Int = 1
|
||||||
|
|
||||||
var b: Int private set
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var b: Int<!> private set
|
||||||
var b1: Int = 0; private set
|
var b1: Int = 0; private set
|
||||||
<!ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS!>abstract<!> var b2: Int private set
|
<!ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS!>abstract<!> var b2: Int private set
|
||||||
<!ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS!>abstract<!> var b3: Int = 0; private set
|
<!ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS!>abstract<!> var b3: Int = 0; private set
|
||||||
|
|
||||||
var c: Int set(v: Int) { field = v }
|
<!MUST_BE_INITIALIZED!>var c: Int<!> set(v: Int) { field = v }
|
||||||
var c1: Int = 0; set(v: Int) { field = v }
|
var c1: Int = 0; set(v: Int) { field = v }
|
||||||
<!ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS!>abstract<!> var c2: Int set(v: Int) { field = v }
|
<!ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS!>abstract<!> var c2: Int set(v: Int) { field = v }
|
||||||
<!ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS!>abstract<!> var c3: Int = 0; set(v: Int) { field = v }
|
<!ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS!>abstract<!> var c3: Int = 0; set(v: Int) { field = v }
|
||||||
@@ -29,17 +29,17 @@ class MyClass() {
|
|||||||
<!ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, ABSTRACT_FUNCTION_WITH_BODY!>abstract<!> fun j() {}
|
<!ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, ABSTRACT_FUNCTION_WITH_BODY!>abstract<!> fun j() {}
|
||||||
|
|
||||||
//property accessors
|
//property accessors
|
||||||
var i: Int abstract get abstract set
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var i: Int<!> abstract get abstract set
|
||||||
var i1: Int = 0; abstract get abstract set
|
var i1: Int = 0; abstract get abstract set
|
||||||
|
|
||||||
var j: Int get() = i; abstract set
|
<!MUST_BE_INITIALIZED!>var j: Int<!> get() = i; abstract set
|
||||||
var j1: Int = 0; get() = i; abstract set
|
var j1: Int = 0; get() = i; abstract set
|
||||||
|
|
||||||
var k: Int abstract set
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var k: Int<!> abstract set
|
||||||
var k1: Int = 0; abstract set
|
var k1: Int = 0; abstract set
|
||||||
|
|
||||||
var l: Int abstract get abstract set
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var l: Int<!> abstract get abstract set
|
||||||
var l1: Int = 0; abstract get abstract set
|
var l1: Int = 0; abstract get abstract set
|
||||||
|
|
||||||
var n: Int abstract get abstract set(v: Int) {}
|
<!MUST_BE_INITIALIZED!>var n: Int<!> abstract get abstract set(v: Int) {}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -19,7 +19,7 @@ class Foo() : WithPC0, <!SYNTAX!>this<!>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class WithCPI_Dup(x : Int) {
|
class WithCPI_Dup(x : Int) {
|
||||||
var x : Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var x : Int<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
class WithCPI(x : Int) {
|
class WithCPI(x : Int) {
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
// See KT-13997
|
|
||||||
|
|
||||||
class Foo {
|
|
||||||
var bar: Int // Ok
|
|
||||||
external get
|
|
||||||
external set
|
|
||||||
}
|
|
||||||
|
|
||||||
class Bar {
|
|
||||||
val foo: Int // Ok
|
|
||||||
external get
|
|
||||||
|
|
||||||
var baz: Int
|
|
||||||
external get
|
|
||||||
|
|
||||||
var gav: Int
|
|
||||||
external set
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// See KT-13997
|
// See KT-13997
|
||||||
|
|
||||||
class Foo {
|
class Foo {
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
class X {
|
|
||||||
val x : Int
|
|
||||||
}
|
|
||||||
|
|
||||||
open class Y() {
|
|
||||||
val x : Int = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
class Y1 {
|
|
||||||
val x : Int get() = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
class Z : Y() {
|
|
||||||
}
|
|
||||||
|
|
||||||
//KT-650 Prohibit creating class without constructor.
|
|
||||||
|
|
||||||
class MyIterable<T> : Iterable<T>
|
|
||||||
{
|
|
||||||
override fun iterator(): Iterator<T> = MyIterator()
|
|
||||||
|
|
||||||
inner class MyIterator : Iterator<T>
|
|
||||||
{
|
|
||||||
override fun hasNext(): Boolean = false
|
|
||||||
override fun next(): T {
|
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
class X {
|
class X {
|
||||||
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val x : Int<!>
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val x : Int<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
package bar
|
package bar
|
||||||
|
|
||||||
@file:foo
|
<!MUST_BE_INITIALIZED!>@file:foo
|
||||||
val prop
|
val prop<!>
|
||||||
|
|
||||||
@file:[bar baz]
|
@file:[bar baz]
|
||||||
fun func() {}
|
fun func() {}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ class My(val v: Int) {
|
|||||||
var y: Int
|
var y: Int
|
||||||
set(arg) { field = arg }
|
set(arg) { field = arg }
|
||||||
|
|
||||||
var z: Int
|
<!MUST_BE_INITIALIZED!>var z: Int<!>
|
||||||
set(arg) { field = arg }
|
set(arg) { field = arg }
|
||||||
|
|
||||||
// Ok: initializer available
|
// Ok: initializer available
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ abstract class My(val v: Int) {
|
|||||||
|
|
||||||
open var y: Int
|
open var y: Int
|
||||||
|
|
||||||
open var z: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>open var z: Int<!>
|
||||||
|
|
||||||
// Ok: initializer available
|
// Ok: initializer available
|
||||||
open var w: Int = v
|
open var w: Int = v
|
||||||
|
|||||||
Vendored
+4
-4
@@ -159,7 +159,7 @@ class AnonymousInitializers(var a: String, val b: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val o: String
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val o: String<!>
|
||||||
init {
|
init {
|
||||||
if (1 < 3) {
|
if (1 < 3) {
|
||||||
o = "a"
|
o = "a"
|
||||||
@@ -196,7 +196,7 @@ open class Open(a: Int, w: Int) {}
|
|||||||
|
|
||||||
class LocalValsVsProperties(val a: Int, w: Int) : Open(a, w) {
|
class LocalValsVsProperties(val a: Int, w: Int) : Open(a, w) {
|
||||||
val x : Int
|
val x : Int
|
||||||
val y : Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val y : Int<!>
|
||||||
init {
|
init {
|
||||||
x = 1
|
x = 1
|
||||||
val b = x
|
val b = x
|
||||||
@@ -279,7 +279,7 @@ fun foo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TestObjectExpression() {
|
class TestObjectExpression() {
|
||||||
val a : Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val a : Int<!>
|
||||||
fun foo() {
|
fun foo() {
|
||||||
val a = object {
|
val a = object {
|
||||||
val x : Int
|
val x : Int
|
||||||
@@ -306,7 +306,7 @@ class TestObjectExpression() {
|
|||||||
|
|
||||||
object TestObjectDeclaration {
|
object TestObjectDeclaration {
|
||||||
val x : Int
|
val x : Int
|
||||||
val y : Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val y : Int<!>
|
||||||
init {
|
init {
|
||||||
x = 1
|
x = 1
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -83,7 +83,7 @@ class My {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val top: Int
|
<!MUST_BE_INITIALIZED!>val top: Int<!>
|
||||||
|
|
||||||
fun init() {
|
fun init() {
|
||||||
top = 1
|
top = 1
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class A(val next: A? = null) {
|
class A(val next: A? = null) {
|
||||||
val x: String
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val x: String<!>
|
||||||
init {
|
init {
|
||||||
next?.x = "a"
|
next?.x = "a"
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Outer {
|
class Outer {
|
||||||
val outerProp: String
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val outerProp: String<!>
|
||||||
inner class Inner(inner: Inner, outer: Outer) {
|
inner class Inner(inner: Inner, outer: Outer) {
|
||||||
val innerProp: String
|
val innerProp: String
|
||||||
init {
|
init {
|
||||||
|
|||||||
@@ -4,17 +4,17 @@ package abstract
|
|||||||
enum class MyEnum() {
|
enum class MyEnum() {
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
//properties
|
//properties
|
||||||
val a: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val a: Int<!>
|
||||||
val a1: Int = 1
|
val a1: Int = 1
|
||||||
abstract val a2: Int
|
abstract val a2: Int
|
||||||
abstract val a3: Int = <!ABSTRACT_PROPERTY_WITH_INITIALIZER!>1<!>
|
abstract val a3: Int = <!ABSTRACT_PROPERTY_WITH_INITIALIZER!>1<!>
|
||||||
|
|
||||||
var b: Int private set
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var b: Int<!> private set
|
||||||
var b1: Int = 0; private set
|
var b1: Int = 0; private set
|
||||||
abstract var b2: Int <!PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY!>private<!> set
|
abstract var b2: Int <!PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY!>private<!> set
|
||||||
abstract var b3: Int = <!ABSTRACT_PROPERTY_WITH_INITIALIZER!>0<!>; <!PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY!>private<!> set
|
abstract var b3: Int = <!ABSTRACT_PROPERTY_WITH_INITIALIZER!>0<!>; <!PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY!>private<!> set
|
||||||
|
|
||||||
var c: Int set(v: Int) { field = v }
|
<!MUST_BE_INITIALIZED!>var c: Int<!> set(v: Int) { field = v }
|
||||||
var c1: Int = 0; set(v: Int) { field = v }
|
var c1: Int = 0; set(v: Int) { field = v }
|
||||||
abstract var c2: Int <!ABSTRACT_PROPERTY_WITH_SETTER!>set(v: Int) { field = v }<!>
|
abstract var c2: Int <!ABSTRACT_PROPERTY_WITH_SETTER!>set(v: Int) { field = v }<!>
|
||||||
abstract var c3: Int = <!ABSTRACT_PROPERTY_WITH_INITIALIZER!>0<!>; <!ABSTRACT_PROPERTY_WITH_SETTER!>set(v: Int) { field = v }<!>
|
abstract var c3: Int = <!ABSTRACT_PROPERTY_WITH_INITIALIZER!>0<!>; <!ABSTRACT_PROPERTY_WITH_SETTER!>set(v: Int) { field = v }<!>
|
||||||
@@ -31,17 +31,17 @@ enum class MyEnum() {
|
|||||||
<!ABSTRACT_FUNCTION_WITH_BODY!>abstract<!> fun j() {}
|
<!ABSTRACT_FUNCTION_WITH_BODY!>abstract<!> fun j() {}
|
||||||
|
|
||||||
//property accessors
|
//property accessors
|
||||||
var i: Int abstract get abstract set
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var i: Int<!> abstract get abstract set
|
||||||
var i1: Int = 0; abstract get abstract set
|
var i1: Int = 0; abstract get abstract set
|
||||||
|
|
||||||
var j: Int get() = i; abstract set
|
<!MUST_BE_INITIALIZED!>var j: Int<!> get() = i; abstract set
|
||||||
var j1: Int = 0; get() = i; abstract set
|
var j1: Int = 0; get() = i; abstract set
|
||||||
|
|
||||||
var k: Int abstract set
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var k: Int<!> abstract set
|
||||||
var k1: Int = 0; abstract set
|
var k1: Int = 0; abstract set
|
||||||
|
|
||||||
var l: Int abstract get abstract set
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var l: Int<!> abstract get abstract set
|
||||||
var l1: Int = 0; abstract get abstract set
|
var l1: Int = 0; abstract get abstract set
|
||||||
|
|
||||||
var n: Int abstract get abstract set(v: Int) {}
|
<!MUST_BE_INITIALIZED!>var n: Int<!> abstract get abstract set(v: Int) {}
|
||||||
}
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ fun test() {
|
|||||||
val Int.abs : Int
|
val Int.abs : Int
|
||||||
get() = if (this > 0) this else -this;
|
get() = if (this > 0) this else -this;
|
||||||
|
|
||||||
val <T> T.foo : T
|
<!EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT!>val <T> T.foo : T<!>
|
||||||
|
|
||||||
fun Int.foo() = this
|
fun Int.foo() = this
|
||||||
|
|
||||||
|
|||||||
-17
@@ -1,17 +0,0 @@
|
|||||||
package h
|
|
||||||
|
|
||||||
class Square() {
|
|
||||||
var size : Double =
|
|
||||||
<!UNRESOLVED_REFERENCE!>set<!>(<!UNRESOLVED_REFERENCE!>value<!>) {
|
|
||||||
<!SYNTAX!>$area<!> <!SYNTAX!>= size * size<!>
|
|
||||||
}
|
|
||||||
|
|
||||||
var area : Double
|
|
||||||
private set
|
|
||||||
}
|
|
||||||
|
|
||||||
fun main() {
|
|
||||||
val s = Square()
|
|
||||||
|
|
||||||
s.size = 2.0
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
package h
|
package h
|
||||||
|
|
||||||
class Square() {
|
class Square() {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
val <T : <!UNRESOLVED_REFERENCE!>KClass<T>.something<!>> abc
|
<!MUST_BE_INITIALIZED!>val <T : <!UNRESOLVED_REFERENCE!>KClass<T>.something<!>> abc<!>
|
||||||
|
|||||||
+11
-11
@@ -3,8 +3,8 @@ abstract class Test() {
|
|||||||
abstract val x1 : Int get
|
abstract val x1 : Int get
|
||||||
abstract val x2 : Int <!ABSTRACT_PROPERTY_WITH_GETTER!>get() = 1<!>
|
abstract val x2 : Int <!ABSTRACT_PROPERTY_WITH_GETTER!>get() = 1<!>
|
||||||
|
|
||||||
val a : Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val a : Int<!>
|
||||||
val b : Int get
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val b : Int<!> get
|
||||||
val c = 1
|
val c = 1
|
||||||
|
|
||||||
val c1 = 1
|
val c1 = 1
|
||||||
@@ -15,7 +15,7 @@ abstract class Test() {
|
|||||||
get() { return 1 }
|
get() { return 1 }
|
||||||
val c4 : Int
|
val c4 : Int
|
||||||
get() = 1
|
get() = 1
|
||||||
val c5 : Int
|
<!MUST_BE_INITIALIZED!>val c5 : Int<!>
|
||||||
get() = field + 1
|
get() = field + 1
|
||||||
|
|
||||||
abstract var y : Int
|
abstract var y : Int
|
||||||
@@ -26,19 +26,19 @@ abstract class Test() {
|
|||||||
abstract var y5 : Int <!ABSTRACT_PROPERTY_WITH_SETTER!>set(x) {}<!> <!ABSTRACT_PROPERTY_WITH_GETTER!>get() = 1<!>
|
abstract var y5 : Int <!ABSTRACT_PROPERTY_WITH_SETTER!>set(x) {}<!> <!ABSTRACT_PROPERTY_WITH_GETTER!>get() = 1<!>
|
||||||
abstract var y6 : Int <!ABSTRACT_PROPERTY_WITH_SETTER!>set(x) {}<!>
|
abstract var y6 : Int <!ABSTRACT_PROPERTY_WITH_SETTER!>set(x) {}<!>
|
||||||
|
|
||||||
var v : Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var v : Int<!>
|
||||||
var v1 : Int get
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var v1 : Int<!> get
|
||||||
var v2 : Int get set
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var v2 : Int<!> get set
|
||||||
var v3 : Int get() = 1; set
|
<!MUST_BE_INITIALIZED!>var v3 : Int<!> get() = 1; set
|
||||||
var v4 : Int get() = 1; set(x){}
|
var v4 : Int get() = 1; set(x){}
|
||||||
|
|
||||||
var v5 : Int get() = 1; set(x){field = x}
|
<!MUST_BE_INITIALIZED!>var v5 : Int<!> get() = 1; set(x){field = x}
|
||||||
var v6 : Int get() = field + 1; set(x){}
|
<!MUST_BE_INITIALIZED!>var v6 : Int<!> get() = field + 1; set(x){}
|
||||||
|
|
||||||
abstract val v7 : Int get
|
abstract val v7 : Int get
|
||||||
abstract var v8 : Int get set
|
abstract var v8 : Int get set
|
||||||
var v9 : Int set
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var v9 : Int<!> set
|
||||||
var v10 : Int get
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var v10 : Int<!> get
|
||||||
abstract val v11 : Int abstract get
|
abstract val v11 : Int abstract get
|
||||||
abstract var v12 : Int abstract get abstract set
|
abstract var v12 : Int abstract get abstract set
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ abstract class A() {
|
|||||||
abstract <!REDUNDANT_MODIFIER!>open<!> fun g()
|
abstract <!REDUNDANT_MODIFIER!>open<!> fun g()
|
||||||
<!INCOMPATIBLE_MODIFIERS!>final<!> <!INCOMPATIBLE_MODIFIERS!>open<!> fun h() {}
|
<!INCOMPATIBLE_MODIFIERS!>final<!> <!INCOMPATIBLE_MODIFIERS!>open<!> fun h() {}
|
||||||
|
|
||||||
open var r: String
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>open var r: String<!>
|
||||||
get
|
get
|
||||||
abstract protected set
|
abstract protected set
|
||||||
}
|
}
|
||||||
|
|||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
// !LANGUAGE: +MultiPlatformProjects
|
||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
fun <T> lazy(initializer: () -> T): Lazy<T> = <!UNRESOLVED_REFERENCE!>TODO<!>()
|
||||||
|
interface Lazy<out T> {
|
||||||
|
operator fun getValue(thisRef: Any?, property: KProperty<*>): T = <!UNRESOLVED_REFERENCE!>TODO<!>()
|
||||||
|
}
|
||||||
|
|
||||||
|
expect class OuterClass {
|
||||||
|
class NestedClass {
|
||||||
|
class DeepNested {
|
||||||
|
class Another {
|
||||||
|
fun f(s: String)
|
||||||
|
val p: Int
|
||||||
|
val c: Int = <!EXPECTED_PROPERTY_INITIALIZER!>1<!>
|
||||||
|
val a: Int by <!EXPECTED_DELEGATED_PROPERTY!>lazy { 1 }<!>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class InnerClass {
|
||||||
|
fun f(x: Int)
|
||||||
|
val p: String
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object
|
||||||
|
}
|
||||||
|
|
||||||
|
expect class OuterClassWithNamedCompanion {
|
||||||
|
companion object Factory
|
||||||
|
}
|
||||||
|
|
||||||
|
expect object OuterObject {
|
||||||
|
object NestedObject
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODULE: m2-jvm(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
|
||||||
|
actual class OuterClass {
|
||||||
|
actual class NestedClass {
|
||||||
|
actual class DeepNested {
|
||||||
|
actual class Another {
|
||||||
|
actual fun f(s: String) {}
|
||||||
|
actual val p: Int = 42
|
||||||
|
actual val c: Int = 2
|
||||||
|
actual val a: Int = 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual inner class InnerClass {
|
||||||
|
actual fun f(x: Int) {}
|
||||||
|
actual val p: String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
actual companion object
|
||||||
|
}
|
||||||
|
|
||||||
|
actual class OuterClassWithNamedCompanion {
|
||||||
|
actual companion object Factory
|
||||||
|
}
|
||||||
|
|
||||||
|
actual object OuterObject {
|
||||||
|
actual object NestedObject
|
||||||
|
}
|
||||||
+11
-1
@@ -1,7 +1,13 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// !LANGUAGE: +MultiPlatformProjects
|
// !LANGUAGE: +MultiPlatformProjects
|
||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
// MODULE: m1-common
|
// MODULE: m1-common
|
||||||
// FILE: common.kt
|
// FILE: common.kt
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
fun <T> lazy(initializer: () -> T): Lazy<T> = <!UNRESOLVED_REFERENCE!>TODO<!>()
|
||||||
|
interface Lazy<out T> {
|
||||||
|
operator fun getValue(thisRef: Any?, property: KProperty<*>): T = <!UNRESOLVED_REFERENCE!>TODO<!>()
|
||||||
|
}
|
||||||
|
|
||||||
expect class OuterClass {
|
expect class OuterClass {
|
||||||
class NestedClass {
|
class NestedClass {
|
||||||
@@ -9,6 +15,8 @@ expect class OuterClass {
|
|||||||
class Another {
|
class Another {
|
||||||
fun f(s: String)
|
fun f(s: String)
|
||||||
val p: Int
|
val p: Int
|
||||||
|
val c: Int = <!EXPECTED_PROPERTY_INITIALIZER, EXPECTED_PROPERTY_INITIALIZER{JVM}!>1<!>
|
||||||
|
val a: Int <!EXPECTED_DELEGATED_PROPERTY, EXPECTED_DELEGATED_PROPERTY{JVM}!>by lazy { 1 }<!>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,6 +46,8 @@ actual class OuterClass {
|
|||||||
actual class Another {
|
actual class Another {
|
||||||
actual fun f(s: String) {}
|
actual fun f(s: String) {}
|
||||||
actual val p: Int = 42
|
actual val p: Int = 42
|
||||||
|
actual val c: Int = 2
|
||||||
|
actual val a: Int = 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
@@ -1,6 +1,15 @@
|
|||||||
// -- Module: <m1-common> --
|
// -- Module: <m1-common> --
|
||||||
package
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ T> lazy(/*0*/ initializer: () -> T): Lazy<T>
|
||||||
|
|
||||||
|
public interface Lazy</*0*/ out T> {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open operator fun getValue(/*0*/ thisRef: kotlin.Any?, /*1*/ property: kotlin.reflect.KProperty<*>): T
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
public final expect class OuterClass {
|
public final expect class OuterClass {
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
@@ -31,6 +40,8 @@ public final expect class OuterClass {
|
|||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
public final expect class Another {
|
public final expect class Another {
|
||||||
|
public expect final val a: kotlin.Int
|
||||||
|
public expect final val c: kotlin.Int = 1
|
||||||
public expect final val p: kotlin.Int
|
public expect final val p: kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public final expect fun f(/*0*/ s: kotlin.String): kotlin.Unit
|
public final expect fun f(/*0*/ s: kotlin.String): kotlin.Unit
|
||||||
@@ -68,6 +79,15 @@ public expect object OuterObject {
|
|||||||
// -- Module: <m2-jvm> --
|
// -- Module: <m2-jvm> --
|
||||||
package
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ T> lazy(/*0*/ initializer: () -> T): Lazy<T>
|
||||||
|
|
||||||
|
public interface Lazy</*0*/ out T> {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open operator fun getValue(/*0*/ thisRef: kotlin.Any?, /*1*/ property: kotlin.reflect.KProperty<*>): T
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
public final actual class OuterClass {
|
public final actual class OuterClass {
|
||||||
public constructor OuterClass()
|
public constructor OuterClass()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
@@ -104,6 +124,8 @@ public final actual class OuterClass {
|
|||||||
|
|
||||||
public final actual class Another {
|
public final actual class Another {
|
||||||
public constructor Another()
|
public constructor Another()
|
||||||
|
public actual final val a: kotlin.Int = 3
|
||||||
|
public actual final val c: kotlin.Int = 2
|
||||||
public actual final val p: kotlin.Int = 42
|
public actual final val p: kotlin.Int = 42
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public final actual fun f(/*0*/ s: kotlin.String): kotlin.Unit
|
public final actual fun f(/*0*/ s: kotlin.String): kotlin.Unit
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class MyIllegalClass3() : MyTrait, MyAbstractClass() {
|
|||||||
|
|
||||||
class MyIllegalClass4() : MyTrait, MyAbstractClass() {
|
class MyIllegalClass4() : MyTrait, MyAbstractClass() {
|
||||||
fun foo() {}
|
fun foo() {}
|
||||||
val pr : Unit
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val pr : Unit<!>
|
||||||
override fun other() {}
|
override fun other() {}
|
||||||
override val otherPr : Int = 1
|
override val otherPr : Int = 1
|
||||||
}
|
}
|
||||||
|
|||||||
compiler/testData/diagnostics/tests/properties/extensionPropertyMustHaveAccessorsOrBeAbstract.fir.kt
Vendored
-25
@@ -1,25 +0,0 @@
|
|||||||
val String.test1: Int
|
|
||||||
var String.test2: Int
|
|
||||||
|
|
||||||
var String.test3: Int; public set
|
|
||||||
|
|
||||||
class C {
|
|
||||||
val String.test1: Int
|
|
||||||
var String.test2: Int
|
|
||||||
var String.test3: Int; public set
|
|
||||||
}
|
|
||||||
|
|
||||||
interface I {
|
|
||||||
val String.test1: Int
|
|
||||||
var String.test2: Int
|
|
||||||
var String.test3: Int; public set
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class A {
|
|
||||||
val String.test1: Int
|
|
||||||
var String.test2: Int
|
|
||||||
var String.test3: Int; public set
|
|
||||||
|
|
||||||
abstract val String.testA1: Int
|
|
||||||
abstract var String.testA2: Int
|
|
||||||
}
|
|
||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
<!EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT!>val String.test1: Int<!>
|
<!EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT!>val String.test1: Int<!>
|
||||||
<!EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT!>var String.test2: Int<!>
|
<!EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT!>var String.test2: Int<!>
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ var x
|
|||||||
q checkType { _<Int>() }
|
q checkType { _<Int>() }
|
||||||
}
|
}
|
||||||
|
|
||||||
var noSetter
|
<!MUST_BE_INITIALIZED!>var noSetter<!>
|
||||||
get() = 1
|
get() = 1
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
var x: Int
|
|
||||||
fun foo(f: Boolean) {
|
|
||||||
try {
|
|
||||||
if (f) {
|
|
||||||
x = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
fun bar() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
<!MUST_BE_INITIALIZED!>var x: Int<!>
|
<!MUST_BE_INITIALIZED!>var x: Int<!>
|
||||||
fun foo(f: Boolean) {
|
fun foo(f: Boolean) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Vendored
+1
-1
@@ -5,7 +5,7 @@ class A(val w: Char) {
|
|||||||
val z: Int
|
val z: Int
|
||||||
val v = -1
|
val v = -1
|
||||||
|
|
||||||
val uninitialized: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val uninitialized: Int<!>
|
||||||
val overinitialized: Int
|
val overinitialized: Int
|
||||||
|
|
||||||
constructor(): this('a') {
|
constructor(): this('a') {
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ class A {
|
|||||||
val z: Int
|
val z: Int
|
||||||
val v = -1
|
val v = -1
|
||||||
|
|
||||||
val uninitialized: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val uninitialized: Int<!>
|
||||||
val overinitialized: Int
|
val overinitialized: Int
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
class A0 {
|
class A0 {
|
||||||
val x: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val x: Int<!>
|
||||||
constructor() {
|
constructor() {
|
||||||
if (1 == 1) {
|
if (1 == 1) {
|
||||||
return
|
return
|
||||||
@@ -12,7 +12,7 @@ class A0 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class A1 {
|
class A1 {
|
||||||
val x: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val x: Int<!>
|
||||||
constructor() {
|
constructor() {
|
||||||
if (1 == 1) {
|
if (1 == 1) {
|
||||||
return
|
return
|
||||||
|
|||||||
Vendored
+1
-1
@@ -8,7 +8,7 @@ class A(val w: Int) {
|
|||||||
val v = -1
|
val v = -1
|
||||||
val useInitialized = useUnitialized + v + w
|
val useInitialized = useUnitialized + v + w
|
||||||
|
|
||||||
val uninitialized: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val uninitialized: Int<!>
|
||||||
|
|
||||||
constructor(): this(1) {
|
constructor(): this(1) {
|
||||||
x + y + v + uninitialized + w
|
x + y + v + uninitialized + w
|
||||||
|
|||||||
Vendored
+5
-5
@@ -9,7 +9,11 @@ class A {
|
|||||||
|
|
||||||
val useInitialized = useUnitialized + v
|
val useInitialized = useUnitialized + v
|
||||||
|
|
||||||
val uninitialized: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val uninitialized: Int<!>
|
||||||
|
|
||||||
|
constructor(x: String): this() {
|
||||||
|
x + y + v + uninitialized
|
||||||
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
x = 1
|
x = 1
|
||||||
@@ -30,10 +34,6 @@ class A {
|
|||||||
x + y + v + uninitialized
|
x + y + v + uninitialized
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(x: String): this() {
|
|
||||||
x + y + v + uninitialized
|
|
||||||
}
|
|
||||||
|
|
||||||
//anonymous
|
//anonymous
|
||||||
init {
|
init {
|
||||||
y
|
y
|
||||||
|
|||||||
+4
-4
@@ -11,6 +11,10 @@ class A {
|
|||||||
|
|
||||||
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val uninitialized: Int<!>
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val uninitialized: Int<!>
|
||||||
|
|
||||||
|
constructor(x: String): this() {
|
||||||
|
x + y + v + uninitialized
|
||||||
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
x = 1
|
x = 1
|
||||||
y = 2
|
y = 2
|
||||||
@@ -30,10 +34,6 @@ class A {
|
|||||||
x + y + v + <!UNINITIALIZED_VARIABLE!>uninitialized<!>
|
x + y + v + <!UNINITIALIZED_VARIABLE!>uninitialized<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(x: String): this() {
|
|
||||||
x + y + v + uninitialized
|
|
||||||
}
|
|
||||||
|
|
||||||
//anonymous
|
//anonymous
|
||||||
init {
|
init {
|
||||||
<!UNINITIALIZED_VARIABLE, UNINITIALIZED_VARIABLE!>y<!>
|
<!UNINITIALIZED_VARIABLE, UNINITIALIZED_VARIABLE!>y<!>
|
||||||
|
|||||||
+1
-1
@@ -3,5 +3,5 @@ expect val bar1 = <!EXPECTED_PROPERTY_INITIALIZER!>42<!>
|
|||||||
expect class Baz1
|
expect class Baz1
|
||||||
|
|
||||||
actual fun foo2() = 42
|
actual fun foo2() = 42
|
||||||
actual val bar2: Int
|
<!MUST_BE_INITIALIZED!>actual val bar2: Int<!>
|
||||||
actual interface Baz2
|
actual interface Baz2
|
||||||
|
|||||||
+1
-1
@@ -83,7 +83,7 @@ fun unknownRun(block: () -> Unit) = block()
|
|||||||
|
|
||||||
class DefiniteInitializationInInitSection {
|
class DefiniteInitializationInInitSection {
|
||||||
val x: Int
|
val x: Int
|
||||||
val y: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val y: Int<!>
|
||||||
|
|
||||||
init {
|
init {
|
||||||
myRun { x = 42 }
|
myRun { x = 42 }
|
||||||
|
|||||||
+1
-1
@@ -60,7 +60,7 @@ fun nestedIndefiniteAssignment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class InitializationForbiddenInNonInitSection {
|
class InitializationForbiddenInNonInitSection {
|
||||||
val x: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val x: Int<!>
|
||||||
|
|
||||||
fun setup() {
|
fun setup() {
|
||||||
myRun { x = 42 }
|
myRun { x = 42 }
|
||||||
|
|||||||
+2
-2
@@ -8,8 +8,8 @@ abstract class Base() {
|
|||||||
<!ABSTRACT_FUNCTION_WITH_BODY!>abstract<!> fun foo() = {}
|
<!ABSTRACT_FUNCTION_WITH_BODY!>abstract<!> fun foo() = {}
|
||||||
<!NON_ABSTRACT_FUNCTION_WITH_NO_BODY!>fun boo() : Unit<!>
|
<!NON_ABSTRACT_FUNCTION_WITH_NO_BODY!>fun boo() : Unit<!>
|
||||||
abstract val a = <!ABSTRACT_PROPERTY_WITH_INITIALIZER!>""<!>
|
abstract val a = <!ABSTRACT_PROPERTY_WITH_INITIALIZER!>""<!>
|
||||||
val b
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val b<!>
|
||||||
var d
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var d<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
class Impl : Base() {
|
class Impl : Base() {
|
||||||
|
|||||||
+4
-4
@@ -34,11 +34,11 @@ fun case_4() {
|
|||||||
|
|
||||||
// TESTCASE NUMBER: 5
|
// TESTCASE NUMBER: 5
|
||||||
class case_5 {
|
class case_5 {
|
||||||
val value_1: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val value_1: Int<!>
|
||||||
val value_2: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val value_2: Int<!>
|
||||||
val value_3: Int
|
val value_3: Int
|
||||||
var value_4: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var value_4: Int<!>
|
||||||
var value_5: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var value_5: Int<!>
|
||||||
init {
|
init {
|
||||||
funWithAtMostOnceCallsInPlace { value_1 = 1 }
|
funWithAtMostOnceCallsInPlace { value_1 = 1 }
|
||||||
funWithUnknownCallsInPlace { value_2 = 1 }
|
funWithUnknownCallsInPlace { value_2 = 1 }
|
||||||
|
|||||||
+1
-1
@@ -34,7 +34,7 @@ fun case_2(value_1: Any?) {
|
|||||||
|
|
||||||
// TESTCASE NUMBER: 3
|
// TESTCASE NUMBER: 3
|
||||||
class case_3(value_1: Any?) {
|
class case_3(value_1: Any?) {
|
||||||
var value_2: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var value_2: Int<!>
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (value_1 is String) {
|
if (value_1 is String) {
|
||||||
|
|||||||
+18
@@ -911,6 +911,24 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.MUST_BE_INITIALIZED) { firDiagnostic ->
|
||||||
|
MustBeInitializedImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT) { firDiagnostic ->
|
||||||
|
MustBeInitializedOrBeAbstractImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT) { firDiagnostic ->
|
||||||
|
ExtensionPropertyMustHaveAccessorsOrBeAbstractImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.BACKING_FIELD_IN_INTERFACE) { firDiagnostic ->
|
add(FirErrors.BACKING_FIELD_IN_INTERFACE) { firDiagnostic ->
|
||||||
BackingFieldInInterfaceImpl(
|
BackingFieldInInterfaceImpl(
|
||||||
firDiagnostic as FirPsiDiagnostic<*>,
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
|||||||
+12
@@ -645,6 +645,18 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = PropertyWithNoTypeNoInitializer::class
|
override val diagnosticClass get() = PropertyWithNoTypeNoInitializer::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class MustBeInitialized : KtFirDiagnostic<KtProperty>() {
|
||||||
|
override val diagnosticClass get() = MustBeInitialized::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class MustBeInitializedOrBeAbstract : KtFirDiagnostic<KtProperty>() {
|
||||||
|
override val diagnosticClass get() = MustBeInitializedOrBeAbstract::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ExtensionPropertyMustHaveAccessorsOrBeAbstract : KtFirDiagnostic<KtProperty>() {
|
||||||
|
override val diagnosticClass get() = ExtensionPropertyMustHaveAccessorsOrBeAbstract::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class BackingFieldInInterface : KtFirDiagnostic<KtProperty>() {
|
abstract class BackingFieldInInterface : KtFirDiagnostic<KtProperty>() {
|
||||||
override val diagnosticClass get() = BackingFieldInInterface::class
|
override val diagnosticClass get() = BackingFieldInInterface::class
|
||||||
}
|
}
|
||||||
|
|||||||
+21
@@ -1036,6 +1036,27 @@ internal class PropertyWithNoTypeNoInitializerImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class MustBeInitializedImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.MustBeInitialized(), KtAbstractFirDiagnostic<KtProperty> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class MustBeInitializedOrBeAbstractImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.MustBeInitializedOrBeAbstract(), KtAbstractFirDiagnostic<KtProperty> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ExtensionPropertyMustHaveAccessorsOrBeAbstractImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.ExtensionPropertyMustHaveAccessorsOrBeAbstract(), KtAbstractFirDiagnostic<KtProperty> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class BackingFieldInInterfaceImpl(
|
internal class BackingFieldInInterfaceImpl(
|
||||||
firDiagnostic: FirPsiDiagnostic<*>,
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
|
|||||||
+2
-1
@@ -11,4 +11,5 @@ class Y1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Z : Y() {
|
class Z : Y() {
|
||||||
}
|
}
|
||||||
|
// FIR_COMPARISON
|
||||||
@@ -52,4 +52,5 @@ class TestPCParameters(w : Int, <warning>x</warning> : Int, val y : Int, var z :
|
|||||||
|
|
||||||
fun foo() = <error>x</error>
|
fun foo() = <error>x</error>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// FIR_COMPARISON
|
||||||
Reference in New Issue
Block a user