diff --git a/idea/resources/inspectionDescriptions/RedundantCompanionReference.html b/idea/resources/inspectionDescriptions/RedundantCompanionReference.html
new file mode 100644
index 00000000000..fc4250288bb
--- /dev/null
+++ b/idea/resources/inspectionDescriptions/RedundantCompanionReference.html
@@ -0,0 +1,17 @@
+
+
+This inspection reports redundant Companion reference, for example:
+
+
+
+class A {
+ companion object {
+ fun create() = "Hello"
+ }
+}
+fun test() {
+ val s = A.Companion.create() // redundant Companion reference
+}
+
+
+
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 42b1bafd1bc..a29c1cc0526 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -2746,6 +2746,15 @@
language="kotlin"
/>
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantCompanionReferenceInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantCompanionReferenceInspection.kt
new file mode 100644
index 00000000000..62cdb233971
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantCompanionReferenceInspection.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-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.LocalQuickFix
+import com.intellij.codeInspection.ProblemDescriptor
+import com.intellij.codeInspection.ProblemHighlightType
+import com.intellij.codeInspection.ProblemsHolder
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiElementVisitor
+import org.jetbrains.kotlin.idea.references.mainReference
+import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
+import org.jetbrains.kotlin.resolve.DescriptorUtils
+
+class RedundantCompanionReferenceInspection : AbstractKotlinInspection() {
+ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
+ return referenceExpressionVisitor(fun(expression) {
+
+ val descriptor = (expression.mainReference.resolve() as? KtObjectDeclaration)?.descriptor ?: return
+ if (!DescriptorUtils.isCompanionObject(descriptor)) return
+
+ val parent = expression.getStrictParentOfType() ?: return
+ if (expression == parent.receiverExpression && expression.text == descriptor.containingDeclaration?.name?.asString()) return
+ if (expression == parent.selectorExpression && parent.parent !is KtDotQualifiedExpression) return
+
+ holder.registerProblem(
+ expression,
+ "Redundant Companion reference",
+ ProblemHighlightType.LIKE_UNUSED_SYMBOL,
+ RemoveRedundantCompanionReferenceFix()
+ )
+ })
+ }
+}
+
+private class RemoveRedundantCompanionReferenceFix : LocalQuickFix {
+ override fun getName() = "Remove redundant Companion reference"
+
+ override fun getFamilyName() = name
+
+ override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
+ val expression = descriptor.psiElement as? KtReferenceExpression ?: return
+ val parent = expression.getStrictParentOfType() ?: return
+ val selector = parent.selectorExpression ?: return
+ val receiver = parent.receiverExpression
+ if (expression == receiver) parent.replace(selector) else parent.replace(receiver)
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/redundantCompanionReference/.inspection b/idea/testData/inspectionsLocal/redundantCompanionReference/.inspection
new file mode 100644
index 00000000000..e9affe4e724
--- /dev/null
+++ b/idea/testData/inspectionsLocal/redundantCompanionReference/.inspection
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.inspections.RedundantCompanionReferenceInspection
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/redundantCompanionReference/basic.kt b/idea/testData/inspectionsLocal/redundantCompanionReference/basic.kt
new file mode 100644
index 00000000000..a249c7d559a
--- /dev/null
+++ b/idea/testData/inspectionsLocal/redundantCompanionReference/basic.kt
@@ -0,0 +1,9 @@
+class C {
+ companion object {
+ fun create() = C()
+ }
+}
+
+fun test() {
+ C.Companion.create()
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/redundantCompanionReference/basic.kt.after b/idea/testData/inspectionsLocal/redundantCompanionReference/basic.kt.after
new file mode 100644
index 00000000000..b60b16ac507
--- /dev/null
+++ b/idea/testData/inspectionsLocal/redundantCompanionReference/basic.kt.after
@@ -0,0 +1,9 @@
+class C {
+ companion object {
+ fun create() = C()
+ }
+}
+
+fun test() {
+ C.create()
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/redundantCompanionReference/directCompanion.kt b/idea/testData/inspectionsLocal/redundantCompanionReference/directCompanion.kt
new file mode 100644
index 00000000000..3ff8434f01b
--- /dev/null
+++ b/idea/testData/inspectionsLocal/redundantCompanionReference/directCompanion.kt
@@ -0,0 +1,8 @@
+class C {
+ companion object {
+ fun create() = C()
+ }
+ fun test() {
+ Companion.create()
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/redundantCompanionReference/directCompanion.kt.after b/idea/testData/inspectionsLocal/redundantCompanionReference/directCompanion.kt.after
new file mode 100644
index 00000000000..c7fcdacd27c
--- /dev/null
+++ b/idea/testData/inspectionsLocal/redundantCompanionReference/directCompanion.kt.after
@@ -0,0 +1,8 @@
+class C {
+ companion object {
+ fun create() = C()
+ }
+ fun test() {
+ create()
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/redundantCompanionReference/functionReference.kt b/idea/testData/inspectionsLocal/redundantCompanionReference/functionReference.kt
new file mode 100644
index 00000000000..86649604a4e
--- /dev/null
+++ b/idea/testData/inspectionsLocal/redundantCompanionReference/functionReference.kt
@@ -0,0 +1,8 @@
+// PROBLEM: none
+class C {
+ companion object {
+ fun foo() {}
+ }
+}
+
+fun test() = C.Companion::foo
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/redundantCompanionReference/notCompanion.kt b/idea/testData/inspectionsLocal/redundantCompanionReference/notCompanion.kt
new file mode 100644
index 00000000000..77ae62c8e8e
--- /dev/null
+++ b/idea/testData/inspectionsLocal/redundantCompanionReference/notCompanion.kt
@@ -0,0 +1,10 @@
+// PROBLEM: none
+class C {
+ companion object {
+ fun create() = C()
+ }
+}
+
+fun test() {
+ C.create()
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/redundantCompanionReference/onlyCompanion.kt b/idea/testData/inspectionsLocal/redundantCompanionReference/onlyCompanion.kt
new file mode 100644
index 00000000000..77b3af409ec
--- /dev/null
+++ b/idea/testData/inspectionsLocal/redundantCompanionReference/onlyCompanion.kt
@@ -0,0 +1,10 @@
+// PROBLEM: none
+class C {
+ companion object {
+ fun create() = C()
+ }
+}
+
+fun test() {
+ C.Companion
+}
\ 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 f94fb23b9a8..3b29c7c7afe 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
@@ -2515,6 +2515,45 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
}
}
+ @TestMetadata("idea/testData/inspectionsLocal/redundantCompanionReference")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class RedundantCompanionReference extends AbstractLocalInspectionTest {
+ public void testAllFilesPresentInRedundantCompanionReference() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/redundantCompanionReference"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("basic.kt")
+ public void testBasic() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantCompanionReference/basic.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("directCompanion.kt")
+ public void testDirectCompanion() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantCompanionReference/directCompanion.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("functionReference.kt")
+ public void testFunctionReference() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantCompanionReference/functionReference.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("notCompanion.kt")
+ public void testNotCompanion() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantCompanionReference/notCompanion.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("onlyCompanion.kt")
+ public void testOnlyCompanion() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/redundantCompanionReference/onlyCompanion.kt");
+ doTest(fileName);
+ }
+ }
+
@TestMetadata("idea/testData/inspectionsLocal/redundantExplicitType")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)