Add Inspection for lateinit var overrides another lateinit var

#KT-30775 Fixed
This commit is contained in:
Toshiaki Kameyama
2019-05-29 03:44:54 +03:00
committed by Mikhail Glukhikh
parent fbd992f8c7
commit 4b4be07942
8 changed files with 100 additions and 0 deletions
@@ -3408,6 +3408,15 @@
language="kotlin"
/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.LateinitVarOverridesLateinitVarInspection"
displayName="lateinit var property overrides lateinit var property"
groupPath="Kotlin"
groupName="Probable bugs"
enabledByDefault="true"
level="WARNING"
language="kotlin"
/>
<referenceImporter implementation="org.jetbrains.kotlin.idea.quickfix.KotlinReferenceImporter"/>
<fileType.fileViewProviderFactory filetype="KJSM" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
@@ -0,0 +1,6 @@
<html>
<body>
This inspection reports when one lateinit var property overrides another lateinit var property.
An instance of a subclass will have two fields for the single property and the one from a superclass remains effectively unused.
</body>
</html>
@@ -0,0 +1,32 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.ProblemsHolder
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.classOrObjectRecursiveVisitor
class LateinitVarOverridesLateinitVarInspection : AbstractKotlinInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = classOrObjectRecursiveVisitor(fun(klass) {
for (declaration in klass.declarations) {
val property = declaration as? KtProperty ?: continue
if (!property.hasModifier(KtTokens.OVERRIDE_KEYWORD) || !property.hasModifier(KtTokens.LATEINIT_KEYWORD) || !property.isVar) {
continue
}
val identifier = property.nameIdentifier ?: continue
val descriptor = property.resolveToDescriptorIfAny() ?: continue
if (descriptor.overriddenDescriptors.any { (it as? PropertyDescriptor)?.let { d -> d.isLateInit && d.isVar } == true }) {
holder.registerProblem(
identifier,
"lateinit var overrides lateinit var"
)
}
}
})
}
@@ -0,0 +1 @@
org.jetbrains.kotlin.idea.inspections.LateinitVarOverridesLateinitVarInspection
@@ -0,0 +1,8 @@
// FIX: none
open class A1 {
open lateinit var a: String
}
class A2 : A1() {
override lateinit var <caret>a: String
}
@@ -0,0 +1,8 @@
// PROBLEM: none
open class A1 {
open var a: String = ""
}
class A2 : A1() {
override lateinit var <caret>a: String
}
@@ -0,0 +1,8 @@
// PROBLEM: none
open class A1 {
open lateinit var a: String
}
class A2 : A1() {
override var <caret>a: String = ""
}
@@ -4475,6 +4475,34 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
}
}
@TestMetadata("idea/testData/inspectionsLocal/lateinitVarOverridesLateinitVar")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class LateinitVarOverridesLateinitVar extends AbstractLocalInspectionTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInLateinitVarOverridesLateinitVar() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/lateinitVarOverridesLateinitVar"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
}
@TestMetadata("basic.kt")
public void testBasic() throws Exception {
runTest("idea/testData/inspectionsLocal/lateinitVarOverridesLateinitVar/basic.kt");
}
@TestMetadata("notLateinit.kt")
public void testNotLateinit() throws Exception {
runTest("idea/testData/inspectionsLocal/lateinitVarOverridesLateinitVar/notLateinit.kt");
}
@TestMetadata("notLateinit2.kt")
public void testNotLateinit2() throws Exception {
runTest("idea/testData/inspectionsLocal/lateinitVarOverridesLateinitVar/notLateinit2.kt");
}
}
@TestMetadata("idea/testData/inspectionsLocal/leakingThis")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)