From ba0e36cdb1039273a541875c4698e78685164ea9 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 25 Oct 2016 15:15:35 +0300 Subject: [PATCH] (1.1 only) Var can be val: correct handling of delegated local variables #KT-14409 Fixed --- .../kotlin/idea/inspections/CanBeValInspection.kt | 13 ++++++++++--- .../canBeVal/inspectionData/expected.xml | 9 +++++++++ idea/testData/inspections/canBeVal/withDelegate.kt | 6 ++++++ .../inspections/canBeVal/withReadOnlyDelegate.kt | 6 ++++++ 4 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 idea/testData/inspections/canBeVal/withDelegate.kt create mode 100644 idea/testData/inspections/canBeVal/withReadOnlyDelegate.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/CanBeValInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/CanBeValInspection.kt index 672fe39c1e9..bf4fb20cfb3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/CanBeValInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/CanBeValInspection.kt @@ -49,7 +49,10 @@ class CanBeValInspection : AbstractKotlinInspection() { when (declaration) { is KtProperty -> { - if (declaration.isVar && declaration.isLocal && canBeVal(declaration, declaration.hasInitializer(), listOf(declaration))) { + if (declaration.isVar && declaration.isLocal && + canBeVal(declaration, + declaration.hasInitializer() || declaration.hasDelegateExpression(), + listOf(declaration))) { reportCanBeVal(declaration) } } @@ -63,13 +66,17 @@ class CanBeValInspection : AbstractKotlinInspection() { } } - private fun canBeVal(declaration: KtVariableDeclaration, hasInitializer: Boolean, allDeclarations: Collection): Boolean { + private fun canBeVal( + declaration: KtVariableDeclaration, + hasInitializerOrDelegate: Boolean, + allDeclarations: Collection + ): Boolean { if (allDeclarations.all { ReferencesSearch.search(it, it.useScope).none() }) { // do not report for unused var's (otherwise we'll get it highlighted immediately after typing the declaration return false } - if (hasInitializer) { + if (hasInitializerOrDelegate) { val hasWriteUsages = ReferencesSearch.search(declaration, declaration.useScope).any { (it as? KtSimpleNameReference)?.element?.readWriteAccess(useResolveForReadWrite = true)?.isWrite == true } diff --git a/idea/testData/inspections/canBeVal/inspectionData/expected.xml b/idea/testData/inspections/canBeVal/inspectionData/expected.xml index 5ab6a2c1487..265fcba97d2 100644 --- a/idea/testData/inspections/canBeVal/inspectionData/expected.xml +++ b/idea/testData/inspections/canBeVal/inspectionData/expected.xml @@ -79,4 +79,13 @@ Local 'var' is never modified and can be declared as 'val' Variable is never modified and can be declared immutable using 'val' + + + withReadOnlyDelegate.kt + 4 + light_idea_test_case + + Local 'var' is never modified and can be declared as 'val' + Variable is never modified and can be declared immutable using 'val' + diff --git a/idea/testData/inspections/canBeVal/withDelegate.kt b/idea/testData/inspections/canBeVal/withDelegate.kt new file mode 100644 index 00000000000..6456fc04903 --- /dev/null +++ b/idea/testData/inspections/canBeVal/withDelegate.kt @@ -0,0 +1,6 @@ +// WITH_RUNTIME + +fun foo() { + var s: String by Delegates.notNull() + s = "" +} diff --git a/idea/testData/inspections/canBeVal/withReadOnlyDelegate.kt b/idea/testData/inspections/canBeVal/withReadOnlyDelegate.kt new file mode 100644 index 00000000000..088ffb8e92c --- /dev/null +++ b/idea/testData/inspections/canBeVal/withReadOnlyDelegate.kt @@ -0,0 +1,6 @@ +// WITH_RUNTIME + +fun foo() { + var s: String by lazy { "Hello!" } + s.hashCode() +}