From 909007d984b3fb211e719c8228fe296a12d10d67 Mon Sep 17 00:00:00 2001 From: Kirill Rakhman Date: Sun, 22 Jan 2017 13:45:58 +0100 Subject: [PATCH] Add inspection for private primary constructors in data classes Fixes #KT-15709 --- .../DataClassPrivateConstructor.html | 5 ++ idea/src/META-INF/plugin.xml | 8 +++ .../DataClassPrivateConstructorInspection.kt | 49 +++++++++++++++++++ .../inspectionData/expected.xml | 10 ++++ .../inspectionData/inspections.test | 1 + .../dataClassPrivateConstructor/test.kt | 3 ++ .../codeInsight/InspectionTestGenerated.java | 6 +++ 7 files changed, 82 insertions(+) create mode 100644 idea/resources/inspectionDescriptions/DataClassPrivateConstructor.html create mode 100644 idea/src/org/jetbrains/kotlin/idea/inspections/DataClassPrivateConstructorInspection.kt create mode 100644 idea/testData/inspections/dataClassPrivateConstructor/inspectionData/expected.xml create mode 100644 idea/testData/inspections/dataClassPrivateConstructor/inspectionData/inspections.test create mode 100644 idea/testData/inspections/dataClassPrivateConstructor/test.kt diff --git a/idea/resources/inspectionDescriptions/DataClassPrivateConstructor.html b/idea/resources/inspectionDescriptions/DataClassPrivateConstructor.html new file mode 100644 index 00000000000..50aea769751 --- /dev/null +++ b/idea/resources/inspectionDescriptions/DataClassPrivateConstructor.html @@ -0,0 +1,5 @@ + + +This inspection reports private constructors of data classes because they are always exposed via the generated 'copy' method. + + \ No newline at end of file diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 6a1ffc2377c..217c072da93 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -2029,6 +2029,14 @@ language="kotlin" /> + + diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/DataClassPrivateConstructorInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/DataClassPrivateConstructorInspection.kt new file mode 100644 index 00000000000..32079af53c7 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/DataClassPrivateConstructorInspection.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.inspections + +import com.intellij.codeInspection.ProblemHighlightType +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.psi.PsiElementVisitor +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.KtPrimaryConstructor +import org.jetbrains.kotlin.psi.KtVisitorVoid +import org.jetbrains.kotlin.psi.psiUtil.containingClass +import org.jetbrains.kotlin.psi.psiUtil.isPrivate + +class DataClassPrivateConstructorInspection : AbstractKotlinInspection() { + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { + return object : KtVisitorVoid() { + override fun visitPrimaryConstructor(constructor: KtPrimaryConstructor) { + super.visitPrimaryConstructor(constructor) + + if (constructor.containingClass()?.isData() == true && constructor.isPrivate()) { + val keyword = constructor.modifierList?.getModifier(KtTokens.PRIVATE_KEYWORD) ?: return + val problemDescriptor = holder.manager.createProblemDescriptor( + keyword, + keyword, + "Private data class constructor is exposed via the generated 'copy' method.", + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + isOnTheFly + ) + + holder.registerProblem(problemDescriptor) + } + } + } + } +} \ No newline at end of file diff --git a/idea/testData/inspections/dataClassPrivateConstructor/inspectionData/expected.xml b/idea/testData/inspections/dataClassPrivateConstructor/inspectionData/expected.xml new file mode 100644 index 00000000000..169ed3e459c --- /dev/null +++ b/idea/testData/inspections/dataClassPrivateConstructor/inspectionData/expected.xml @@ -0,0 +1,10 @@ + + + test.kt + 1 + light_idea_test_case + + Private data class constructor is exposed via the 'copy' method + Private data class constructor is exposed via the generated 'copy' method. + + \ No newline at end of file diff --git a/idea/testData/inspections/dataClassPrivateConstructor/inspectionData/inspections.test b/idea/testData/inspections/dataClassPrivateConstructor/inspectionData/inspections.test new file mode 100644 index 00000000000..1543baa1f49 --- /dev/null +++ b/idea/testData/inspections/dataClassPrivateConstructor/inspectionData/inspections.test @@ -0,0 +1 @@ +// INSPECTION_CLASS: org.jetbrains.kotlin.idea.inspections.DataClassPrivateConstructorInspection \ No newline at end of file diff --git a/idea/testData/inspections/dataClassPrivateConstructor/test.kt b/idea/testData/inspections/dataClassPrivateConstructor/test.kt new file mode 100644 index 00000000000..c8b77d23f7f --- /dev/null +++ b/idea/testData/inspections/dataClassPrivateConstructor/test.kt @@ -0,0 +1,3 @@ +data class Foo private constructor(val foo: String) +class Foo private constructor(val foo: String) +data class Foo2(val foo: String) \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java index abe2f9c9bb2..3384700d62d 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java @@ -173,6 +173,12 @@ public class InspectionTestGenerated extends AbstractInspectionTest { doTest(fileName); } + @TestMetadata("dataClassPrivateConstructor/inspectionData/inspections.test") + public void testDataClassPrivateConstructor_inspectionData_Inspections_test() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspections/dataClassPrivateConstructor/inspectionData/inspections.test"); + doTest(fileName); + } + @TestMetadata("dynamic/js/inspectionData/inspections.test") public void testDynamic_js_inspectionData_Inspections_test() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspections/dynamic/js/inspectionData/inspections.test");