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");