diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/VisitorWrappers.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/VisitorWrappers.kt
index 4039a4a1394..5fb93c920f2 100644
--- a/compiler/psi/src/org/jetbrains/kotlin/psi/VisitorWrappers.kt
+++ b/compiler/psi/src/org/jetbrains/kotlin/psi/VisitorWrappers.kt
@@ -417,3 +417,12 @@ fun returnExpressionVisitor(block: (KtReturnExpression) -> Unit) =
block(returnExpression)
}
}
+
+
+fun delegatedSuperTypeEntry(block: (KtDelegatedSuperTypeEntry) -> Unit) =
+ object : KtVisitorVoid() {
+ override fun visitDelegatedSuperTypeEntry(delegatedSuperTypeEntry: KtDelegatedSuperTypeEntry) {
+ super.visitDelegatedSuperTypeEntry(delegatedSuperTypeEntry)
+ block(delegatedSuperTypeEntry)
+ }
+ }
diff --git a/idea/resources/inspectionDescriptions/DelegationToVarProperty.html b/idea/resources/inspectionDescriptions/DelegationToVarProperty.html
new file mode 100644
index 00000000000..512098fd8a5
--- /dev/null
+++ b/idea/resources/inspectionDescriptions/DelegationToVarProperty.html
@@ -0,0 +1,6 @@
+
+
+This inspection reports delegation to var property.
+In fact, only starting value of var property is used for delegation so it's not recommended to do so.
+
+
diff --git a/idea/src/META-INF/plugin-common.xml b/idea/src/META-INF/plugin-common.xml
index 6c6f3723a53..69ed76bfccf 100644
--- a/idea/src/META-INF/plugin-common.xml
+++ b/idea/src/META-INF/plugin-common.xml
@@ -3084,6 +3084,15 @@
language="kotlin"
/>
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/DelegationToVarPropertyInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/DelegationToVarPropertyInspection.kt
new file mode 100644
index 00000000000..3a2b78b2c28
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/inspections/DelegationToVarPropertyInspection.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
+ * that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.idea.inspections
+
+import com.intellij.codeInspection.*
+import com.intellij.openapi.project.Project
+import org.jetbrains.kotlin.idea.quickfix.ChangeVariableMutabilityFix
+import org.jetbrains.kotlin.idea.references.mainReference
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.psi.KtParameter
+import org.jetbrains.kotlin.psi.delegatedSuperTypeEntry
+
+class DelegationToVarPropertyInspection : AbstractKotlinInspection() {
+ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) =
+ delegatedSuperTypeEntry(fun(delegatedSuperTypeEntry) {
+ val parameter = delegatedSuperTypeEntry.delegateExpression?.mainReference?.resolve() as? KtParameter ?: return
+ if (parameter.valOrVarKeyword?.node?.elementType != KtTokens.VAR_KEYWORD) return
+ holder.registerProblem(
+ parameter,
+ "Delegating to 'var' property does not take its changes into account",
+ ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
+ IntentionWrapper(ChangeVariableMutabilityFix(parameter, false), parameter.containingFile),
+ RemoveVarKeyword()
+ )
+ })
+}
+
+private class RemoveVarKeyword : LocalQuickFix {
+ override fun getName() = "Remove var"
+
+ override fun getFamilyName() = name
+
+ override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
+ (descriptor.psiElement as? KtParameter)?.valOrVarKeyword?.delete()
+
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/delegationToVarProperty/.inspection b/idea/testData/inspectionsLocal/delegationToVarProperty/.inspection
new file mode 100644
index 00000000000..19832897511
--- /dev/null
+++ b/idea/testData/inspectionsLocal/delegationToVarProperty/.inspection
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.inspections.DelegationToVarPropertyInspection
diff --git a/idea/testData/inspectionsLocal/delegationToVarProperty/parameter.kt b/idea/testData/inspectionsLocal/delegationToVarProperty/parameter.kt
new file mode 100644
index 00000000000..eff596e4ee6
--- /dev/null
+++ b/idea/testData/inspectionsLocal/delegationToVarProperty/parameter.kt
@@ -0,0 +1,9 @@
+// PROBLEM: none
+interface A {
+ fun foo()
+}
+class B : A {
+ override fun foo() {
+ }
+}
+class C(b: B) : A by b
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/delegationToVarProperty/valParameter.kt b/idea/testData/inspectionsLocal/delegationToVarProperty/valParameter.kt
new file mode 100644
index 00000000000..f65b1f28ba3
--- /dev/null
+++ b/idea/testData/inspectionsLocal/delegationToVarProperty/valParameter.kt
@@ -0,0 +1,8 @@
+// PROBLEM: none
+interface A {
+ fun foo()
+}
+class B : A {
+ override fun foo() {}
+}
+class C(val b: B) : A by b
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/delegationToVarProperty/varParameter.kt b/idea/testData/inspectionsLocal/delegationToVarProperty/varParameter.kt
new file mode 100644
index 00000000000..7449b8cdc64
--- /dev/null
+++ b/idea/testData/inspectionsLocal/delegationToVarProperty/varParameter.kt
@@ -0,0 +1,8 @@
+// FIX: Change to val
+interface A {
+ fun foo()
+}
+class B : A {
+ override fun foo() {}
+}
+class C(var b: B) : A by b
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/delegationToVarProperty/varParameter.kt.after b/idea/testData/inspectionsLocal/delegationToVarProperty/varParameter.kt.after
new file mode 100644
index 00000000000..79835a5fccc
--- /dev/null
+++ b/idea/testData/inspectionsLocal/delegationToVarProperty/varParameter.kt.after
@@ -0,0 +1,8 @@
+// FIX: Change to val
+interface A {
+ fun foo()
+}
+class B : A {
+ override fun foo() {}
+}
+class C(val b: B) : A by b
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/delegationToVarProperty/varParameter2.kt b/idea/testData/inspectionsLocal/delegationToVarProperty/varParameter2.kt
new file mode 100644
index 00000000000..ca9c76510a3
--- /dev/null
+++ b/idea/testData/inspectionsLocal/delegationToVarProperty/varParameter2.kt
@@ -0,0 +1,8 @@
+// FIX: Remove var
+interface A {
+ fun foo()
+}
+class B : A {
+ override fun foo() {}
+}
+class C(var b: B) : A by b
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/delegationToVarProperty/varParameter2.kt.after b/idea/testData/inspectionsLocal/delegationToVarProperty/varParameter2.kt.after
new file mode 100644
index 00000000000..4ae150a2761
--- /dev/null
+++ b/idea/testData/inspectionsLocal/delegationToVarProperty/varParameter2.kt.after
@@ -0,0 +1,8 @@
+// FIX: Remove var
+interface A {
+ fun foo()
+}
+class B : A {
+ override fun foo() {}
+}
+class C(b: B) : A by b
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
index 93853fff690..ff9fe1fb22e 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
@@ -2115,6 +2115,39 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
}
}
+ @TestMetadata("idea/testData/inspectionsLocal/delegationToVarProperty")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class DelegationToVarProperty extends AbstractLocalInspectionTest {
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
+ }
+
+ public void testAllFilesPresentInDelegationToVarProperty() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/delegationToVarProperty"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("parameter.kt")
+ public void testParameter() throws Exception {
+ runTest("idea/testData/inspectionsLocal/delegationToVarProperty/parameter.kt");
+ }
+
+ @TestMetadata("valParameter.kt")
+ public void testValParameter() throws Exception {
+ runTest("idea/testData/inspectionsLocal/delegationToVarProperty/valParameter.kt");
+ }
+
+ @TestMetadata("varParameter.kt")
+ public void testVarParameter() throws Exception {
+ runTest("idea/testData/inspectionsLocal/delegationToVarProperty/varParameter.kt");
+ }
+
+ @TestMetadata("varParameter2.kt")
+ public void testVarParameter2() throws Exception {
+ runTest("idea/testData/inspectionsLocal/delegationToVarProperty/varParameter2.kt");
+ }
+ }
+
@TestMetadata("idea/testData/inspectionsLocal/deprecatedCallableAddReplaceWith")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)