From 4da9a101cff78006055045aa83d87769d3c40a0c Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 26 Sep 2016 11:17:42 +0300 Subject: [PATCH] UNNECESSARY_LATEINIT warning introduced #KT-13295 Fixed (cherry picked from commit 88f9938) --- .../jetbrains/kotlin/diagnostics/Errors.java | 3 +- .../diagnostics/PositioningStrategies.kt | 2 + .../rendering/DefaultErrorMessages.java | 1 + .../kotlin/resolve/DeclarationsChecker.kt | 7 +- .../lateinitWithConstructor.kt | 9 +++ .../lateinitWithConstructor.txt | 9 +++ .../lateinitWithErroneousDelegation.kt | 11 +++ .../lateinitWithErroneousDelegation.txt | 10 +++ .../unnecessaryLateinit/lateinitWithInit.kt | 7 ++ .../unnecessaryLateinit/lateinitWithInit.txt | 9 +++ .../lateinitWithMultipleConstructors.kt | 13 ++++ .../lateinitWithMultipleConstructors.txt | 10 +++ ...itWithMultipleConstructorsAndDelegation.kt | 15 ++++ ...tWithMultipleConstructorsAndDelegation.txt | 11 +++ .../lateinitWithPlusAssign.kt | 10 +++ .../lateinitWithPlusAssign.txt | 9 +++ ...nitWithPrimaryConstructorAndConstructor.kt | 9 +++ ...itWithPrimaryConstructorAndConstructor.txt | 10 +++ .../unnecessaryLateinit/normalLateinit.kt | 7 ++ .../unnecessaryLateinit/normalLateinit.txt | 10 +++ .../normalLateinitWithTwoConstructors.kt | 9 +++ .../normalLateinitWithTwoConstructors.txt | 10 +++ .../secondaryConstructorDelegateItself.kt | 13 ++++ .../secondaryConstructorDelegateItself.txt | 10 +++ .../secondaryConstructorDelegateLoop.kt | 18 +++++ .../secondaryConstructorDelegateLoop.txt | 12 +++ .../checkers/DiagnosticsTestGenerated.java | 75 +++++++++++++++++++ 27 files changed, 316 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithConstructor.kt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithConstructor.txt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithErroneousDelegation.kt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithErroneousDelegation.txt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithInit.kt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithInit.txt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructors.kt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructors.txt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructorsAndDelegation.kt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructorsAndDelegation.txt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPlusAssign.kt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPlusAssign.txt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPrimaryConstructorAndConstructor.kt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPrimaryConstructorAndConstructor.txt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinit.kt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinit.txt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinitWithTwoConstructors.kt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinitWithTwoConstructors.txt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateItself.kt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateItself.txt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateLoop.kt create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateLoop.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 7465375966e..847d04c7998 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -407,6 +407,7 @@ public interface Errors { DiagnosticFactory0 MUST_BE_INITIALIZED = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); DiagnosticFactory0 MUST_BE_INITIALIZED_OR_BE_ABSTRACT = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); + DiagnosticFactory0 UNNECESSARY_LATEINIT = DiagnosticFactory0.create(WARNING, LATEINIT_MODIFIER); DiagnosticFactory0 EXTENSION_PROPERTY_WITH_BACKING_FIELD = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 PROPERTY_INITIALIZER_NO_BACKING_FIELD = DiagnosticFactory0.create(ERROR); @@ -827,7 +828,7 @@ public interface Errors { INVISIBLE_MEMBER, NON_PUBLIC_CALL_FROM_PUBLIC_INLINE, INVISIBLE_REFERENCE, INVISIBLE_SETTER); ImmutableSet> UNUSED_ELEMENT_DIAGNOSTICS = ImmutableSet.of( UNUSED_VARIABLE, UNUSED_PARAMETER, ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE, VARIABLE_WITH_REDUNDANT_INITIALIZER, - UNUSED_LAMBDA_EXPRESSION, USELESS_CAST, UNUSED_VALUE, USELESS_ELVIS); + UNUSED_LAMBDA_EXPRESSION, USELESS_CAST, UNUSED_VALUE, USELESS_ELVIS, UNNECESSARY_LATEINIT); ImmutableSet> TYPE_INFERENCE_ERRORS = ImmutableSet.of( TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER, TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS, TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index f607fa56037..b2d7bedaebf 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -201,6 +201,8 @@ object PositioningStrategies { @JvmField val PRIVATE_MODIFIER: PositioningStrategy = modifierSetPosition(KtTokens.PRIVATE_KEYWORD) + @JvmField val LATEINIT_MODIFIER: PositioningStrategy = modifierSetPosition(KtTokens.LATEINIT_KEYWORD) + @JvmField val VARIANCE_MODIFIER: PositioningStrategy = modifierSetPosition(KtTokens.IN_KEYWORD, KtTokens.OUT_KEYWORD) @JvmField val FOR_REDECLARATION: PositioningStrategy = object : PositioningStrategy() { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 7ed83e59d18..cf1f83127a3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -229,6 +229,7 @@ public class DefaultErrorMessages { MAP.put(BACKING_FIELD_IN_INTERFACE, "Property in an interface cannot have a backing field"); 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(UNNECESSARY_LATEINIT, "Lateinit is unnecessary: definitely initialized in constructors"); MAP.put(PROPERTY_INITIALIZER_IN_INTERFACE, "Property initializers are not allowed in interfaces"); MAP.put(PRIVATE_PROPERTY_IN_INTERFACE, "Abstract property in an interface cannot be private"); MAP.put(EXTENSION_PROPERTY_WITH_BACKING_FIELD, "Extension property cannot be initialized because it has no backing field"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt index 25277b365ea..4eeb316c76a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt @@ -657,8 +657,8 @@ class DeclarationsChecker( } } else { - if (backingFieldRequired && !inTrait && !propertyDescriptor.isLateInit && - trace.bindingContext.get(BindingContext.IS_UNINITIALIZED, propertyDescriptor) ?: false) { + val isUninitialized = trace.bindingContext.get(BindingContext.IS_UNINITIALIZED, propertyDescriptor) ?: false + if (backingFieldRequired && !inTrait && !propertyDescriptor.isLateInit && isUninitialized) { if (containingDeclaration !is ClassDescriptor || hasAccessorImplementation) { trace.report(MUST_BE_INITIALIZED.on(property)) } @@ -669,6 +669,9 @@ class DeclarationsChecker( else if (property.typeReference == null) { trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property)) } + if (backingFieldRequired && !inTrait && propertyDescriptor.isLateInit && !isUninitialized) { + trace.report(UNNECESSARY_LATEINIT.on(property)) + } } } diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithConstructor.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithConstructor.kt new file mode 100644 index 00000000000..e9d68bf0713 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithConstructor.kt @@ -0,0 +1,9 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +class Foo { + lateinit var bar: String + + constructor(baz: Int) { + bar = "" + } +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithConstructor.txt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithConstructor.txt new file mode 100644 index 00000000000..2a4a066261e --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithConstructor.txt @@ -0,0 +1,9 @@ +package + +public final class Foo { + public constructor Foo(/*0*/ baz: kotlin.Int) + public final lateinit var bar: kotlin.String + 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 toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithErroneousDelegation.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithErroneousDelegation.kt new file mode 100644 index 00000000000..36b4329af77 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithErroneousDelegation.kt @@ -0,0 +1,11 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +class Foo { + lateinit var x: String + + constructor() { + x = "Foo" + } + + constructor(x: String, y: String): this(y.hashCode()) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithErroneousDelegation.txt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithErroneousDelegation.txt new file mode 100644 index 00000000000..e2fc5a5a4f8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithErroneousDelegation.txt @@ -0,0 +1,10 @@ +package + +public final class Foo { + public constructor Foo() + public constructor Foo(/*0*/ x: kotlin.String, /*1*/ y: kotlin.String) + public final lateinit var x: kotlin.String + 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 toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithInit.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithInit.kt new file mode 100644 index 00000000000..72d069f6218 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithInit.kt @@ -0,0 +1,7 @@ +class Foo { + lateinit var bar: String + + init { + bar = "" + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithInit.txt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithInit.txt new file mode 100644 index 00000000000..0c41df4bc85 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithInit.txt @@ -0,0 +1,9 @@ +package + +public final class Foo { + public constructor Foo() + public final lateinit var bar: kotlin.String + 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 toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructors.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructors.kt new file mode 100644 index 00000000000..ef2eac39181 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructors.kt @@ -0,0 +1,13 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +class Foo { + lateinit var bar: String + + constructor() { + bar = "" + } + + constructor(baz: Int) { + bar = "" + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructors.txt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructors.txt new file mode 100644 index 00000000000..2fca0f86a78 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructors.txt @@ -0,0 +1,10 @@ +package + +public final class Foo { + public constructor Foo() + public constructor Foo(/*0*/ baz: kotlin.Int) + public final lateinit var bar: kotlin.String + 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 toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructorsAndDelegation.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructorsAndDelegation.kt new file mode 100644 index 00000000000..4664b6a5da1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructorsAndDelegation.kt @@ -0,0 +1,15 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +class Foo { + lateinit var bar: String + + constructor() { + bar = "" + } + + constructor(a: Int) : this() { + } + + constructor(a: Int, b: Int) : this(a) { + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructorsAndDelegation.txt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructorsAndDelegation.txt new file mode 100644 index 00000000000..b12c86957c1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructorsAndDelegation.txt @@ -0,0 +1,11 @@ +package + +public final class Foo { + public constructor Foo() + public constructor Foo(/*0*/ a: kotlin.Int) + public constructor Foo(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int) + public final lateinit var bar: kotlin.String + 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 toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPlusAssign.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPlusAssign.kt new file mode 100644 index 00000000000..1a7b5dd5573 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPlusAssign.kt @@ -0,0 +1,10 @@ +class Foo { + // Erroneous case: after lateinit removal, we'll have error at 'bar += baz', not here + // However, looks like we must have error at 'bar += baz' even with lateinit + // because nobody can initialize this 'bar' before constructor is called + lateinit var bar: String + + constructor(baz: Int) { + bar += baz + } +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPlusAssign.txt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPlusAssign.txt new file mode 100644 index 00000000000..2a4a066261e --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPlusAssign.txt @@ -0,0 +1,9 @@ +package + +public final class Foo { + public constructor Foo(/*0*/ baz: kotlin.Int) + public final lateinit var bar: kotlin.String + 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 toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPrimaryConstructorAndConstructor.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPrimaryConstructorAndConstructor.kt new file mode 100644 index 00000000000..d1d946dbf1a --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPrimaryConstructorAndConstructor.kt @@ -0,0 +1,9 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +class Foo() { + lateinit var bar: String + + constructor(baz: Int) : this() { + bar = "" + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPrimaryConstructorAndConstructor.txt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPrimaryConstructorAndConstructor.txt new file mode 100644 index 00000000000..2fca0f86a78 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPrimaryConstructorAndConstructor.txt @@ -0,0 +1,10 @@ +package + +public final class Foo { + public constructor Foo() + public constructor Foo(/*0*/ baz: kotlin.Int) + public final lateinit var bar: kotlin.String + 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 toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinit.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinit.kt new file mode 100644 index 00000000000..abee30f6f36 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinit.kt @@ -0,0 +1,7 @@ +class Foo { + lateinit var bar: String + + fun init() { + bar = "" + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinit.txt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinit.txt new file mode 100644 index 00000000000..d895dd7f70f --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinit.txt @@ -0,0 +1,10 @@ +package + +public final class Foo { + public constructor Foo() + public final lateinit var bar: kotlin.String + 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 final fun init(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinitWithTwoConstructors.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinitWithTwoConstructors.kt new file mode 100644 index 00000000000..2c54f35a1f5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinitWithTwoConstructors.kt @@ -0,0 +1,9 @@ +class Foo { + lateinit var x: String + + constructor(y: String) { + x = y + } + + constructor() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinitWithTwoConstructors.txt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinitWithTwoConstructors.txt new file mode 100644 index 00000000000..f2ae473b4ff --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinitWithTwoConstructors.txt @@ -0,0 +1,10 @@ +package + +public final class Foo { + public constructor Foo() + public constructor Foo(/*0*/ y: kotlin.String) + public final lateinit var x: kotlin.String + 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 toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateItself.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateItself.kt new file mode 100644 index 00000000000..18ca8d05c47 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateItself.kt @@ -0,0 +1,13 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +class Foo { + lateinit var bar: String + + constructor() { + bar = "" + } + + constructor(a: Int) : this(a) { + bar = "a" + } +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateItself.txt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateItself.txt new file mode 100644 index 00000000000..3b404cf36da --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateItself.txt @@ -0,0 +1,10 @@ +package + +public final class Foo { + public constructor Foo() + public constructor Foo(/*0*/ a: kotlin.Int) + public final lateinit var bar: kotlin.String + 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 toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateLoop.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateLoop.kt new file mode 100644 index 00000000000..fad28f5b3c1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateLoop.kt @@ -0,0 +1,18 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +class Foo { + lateinit var bar: String + + constructor() { + bar = "" + } + + constructor(a: Int) : this(a, 0, 0) { + } + + constructor(a: Int, b: Int) : this(a) { + } + + constructor(a: Int, b: Int, c: Int) : this(a, b) { + } +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateLoop.txt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateLoop.txt new file mode 100644 index 00000000000..99a56fd2772 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateLoop.txt @@ -0,0 +1,12 @@ +package + +public final class Foo { + public constructor Foo() + public constructor Foo(/*0*/ a: kotlin.Int) + public constructor Foo(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int) + public constructor Foo(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int, /*2*/ c: kotlin.Int) + public final lateinit var bar: kotlin.String + 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 toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 25794246394..c39697add0d 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -3881,6 +3881,81 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } } + + @TestMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class UnnecessaryLateinit extends AbstractDiagnosticsTest { + public void testAllFilesPresentInUnnecessaryLateinit() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("lateinitWithConstructor.kt") + public void testLateinitWithConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithConstructor.kt"); + doTest(fileName); + } + + @TestMetadata("lateinitWithErroneousDelegation.kt") + public void testLateinitWithErroneousDelegation() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithErroneousDelegation.kt"); + doTest(fileName); + } + + @TestMetadata("lateinitWithInit.kt") + public void testLateinitWithInit() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithInit.kt"); + doTest(fileName); + } + + @TestMetadata("lateinitWithMultipleConstructors.kt") + public void testLateinitWithMultipleConstructors() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructors.kt"); + doTest(fileName); + } + + @TestMetadata("lateinitWithMultipleConstructorsAndDelegation.kt") + public void testLateinitWithMultipleConstructorsAndDelegation() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithMultipleConstructorsAndDelegation.kt"); + doTest(fileName); + } + + @TestMetadata("lateinitWithPlusAssign.kt") + public void testLateinitWithPlusAssign() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPlusAssign.kt"); + doTest(fileName); + } + + @TestMetadata("lateinitWithPrimaryConstructorAndConstructor.kt") + public void testLateinitWithPrimaryConstructorAndConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/lateinitWithPrimaryConstructorAndConstructor.kt"); + doTest(fileName); + } + + @TestMetadata("normalLateinit.kt") + public void testNormalLateinit() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinit.kt"); + doTest(fileName); + } + + @TestMetadata("normalLateinitWithTwoConstructors.kt") + public void testNormalLateinitWithTwoConstructors() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/normalLateinitWithTwoConstructors.kt"); + doTest(fileName); + } + + @TestMetadata("secondaryConstructorDelegateItself.kt") + public void testSecondaryConstructorDelegateItself() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateItself.kt"); + doTest(fileName); + } + + @TestMetadata("secondaryConstructorDelegateLoop.kt") + public void testSecondaryConstructorDelegateLoop() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/unnecessaryLateinit/secondaryConstructorDelegateLoop.kt"); + doTest(fileName); + } + } } @TestMetadata("compiler/testData/diagnostics/tests/controlStructures")