diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiUtil.java
index aa5f0577011..1c03c85c407 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiUtil.java
+++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiUtil.java
@@ -333,8 +333,15 @@ public class KtPsiUtil {
}
public static boolean isTrueConstant(@Nullable KtExpression condition) {
- return (condition != null && condition.getNode().getElementType() == KtNodeTypes.BOOLEAN_CONSTANT &&
- condition.getNode().findChildByType(KtTokens.TRUE_KEYWORD) != null);
+ return isBooleanConstant(condition) && condition.getNode().findChildByType(KtTokens.TRUE_KEYWORD) != null;
+ }
+
+ public static boolean isFalseConstant(@Nullable KtExpression condition) {
+ return isBooleanConstant(condition) && condition.getNode().findChildByType(KtTokens.FALSE_KEYWORD) != null;
+ }
+
+ private static boolean isBooleanConstant(@Nullable KtExpression condition) {
+ return condition != null && condition.getNode().getElementType() == KtNodeTypes.BOOLEAN_CONSTANT;
}
public static boolean isAbstract(@NotNull KtDeclarationWithBody declaration) {
diff --git a/idea/resources/inspectionDescriptions/RedundantlIf.html b/idea/resources/inspectionDescriptions/RedundantlIf.html
new file mode 100644
index 00000000000..33098205189
--- /dev/null
+++ b/idea/resources/inspectionDescriptions/RedundantlIf.html
@@ -0,0 +1,21 @@
+
+
+Reports if statements which can be simplified to single return statements.
+
+ For example:
+
+ if (foo()) {
+ return true
+ } else {
+ return false
+ }
+
+ can be simplified to
+
+ return foo()
+
+
+
+
+
+
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 0fa0d686741..40b94719c76 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -1532,6 +1532,15 @@
language="kotlin"
/>
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantIfInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantIfInspection.kt
new file mode 100644
index 00000000000..82c8de26555
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantIfInspection.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2010-2016 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.*
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiElementVisitor
+import org.jetbrains.kotlin.psi.*
+
+class RedundantIfInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool {
+
+ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
+ return object : KtVisitorVoid() {
+ override fun visitIfExpression(expression: KtIfExpression) {
+ super.visitIfExpression(expression)
+
+ if (expression.condition != null && isRedundant(expression)) {
+ holder.registerProblem(expression,
+ "Redundant 'if' statement",
+ ProblemHighlightType.LIKE_UNUSED_SYMBOL,
+ RemoveRedundantIf)
+ }
+ }
+ }
+ }
+
+ private fun isRedundant(expression: KtIfExpression): Boolean {
+ val thenReturn = getReturnedExpression(expression.then) ?: return false
+ val elseReturn = getReturnedExpression(expression.`else`) ?: return false
+
+ if (KtPsiUtil.isTrueConstant(thenReturn) && KtPsiUtil.isFalseConstant(elseReturn)) {
+ return true
+ }
+
+ if (KtPsiUtil.isFalseConstant(thenReturn) && KtPsiUtil.isTrueConstant(elseReturn)) {
+ return true
+ }
+
+ return false
+ }
+
+ private fun getReturnedExpression(expression: KtExpression?) : KtExpression? {
+ when(expression) {
+ is KtReturnExpression -> return expression.returnedExpression
+ is KtBlockExpression -> {
+ val statement = expression.statements.singleOrNull() as? KtReturnExpression ?: return null
+ return statement.returnedExpression
+ }
+ else -> return null
+ }
+ }
+
+ private object RemoveRedundantIf : LocalQuickFix {
+ override fun getName() = "Remove redundant 'if' statement"
+ override fun getFamilyName() = name
+
+ override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
+ val element = descriptor.psiElement as KtIfExpression
+ element.replace(KtPsiFactory(element).createExpressionByPattern("return $0", element.condition!!.text));
+ }
+ }
+
+}
diff --git a/idea/testData/inspections/redundantIf/inspectionData/expected.xml b/idea/testData/inspections/redundantIf/inspectionData/expected.xml
new file mode 100644
index 00000000000..c9e8840c5a9
--- /dev/null
+++ b/idea/testData/inspections/redundantIf/inspectionData/expected.xml
@@ -0,0 +1,18 @@
+
+
+ redundantIf.kt
+ 2
+ light_idea_test_case
+
+ Redundant 'if' statement
+ Redundant 'if' statement
+
+
+ redundantIf.kt
+ 10
+ light_idea_test_case
+
+ Redundant 'if' statement
+ Redundant 'if' statement
+
+
diff --git a/idea/testData/inspections/redundantIf/inspectionData/inspections.test b/idea/testData/inspections/redundantIf/inspectionData/inspections.test
new file mode 100644
index 00000000000..a8d3dc04796
--- /dev/null
+++ b/idea/testData/inspections/redundantIf/inspectionData/inspections.test
@@ -0,0 +1 @@
+// INSPECTION_CLASS: org.jetbrains.kotlin.idea.inspections.RedundantIfInspection
diff --git a/idea/testData/inspections/redundantIf/redundantIf.kt b/idea/testData/inspections/redundantIf/redundantIf.kt
new file mode 100644
index 00000000000..08f7e19e7a1
--- /dev/null
+++ b/idea/testData/inspections/redundantIf/redundantIf.kt
@@ -0,0 +1,11 @@
+fun foo() {
+ if (value % 2 == 0) {
+ return true
+ } else {
+ return false
+ }
+}
+
+fun bar() {
+ if (value % 2 == 0) return true else return false
+}
diff --git a/idea/testData/quickfix/redundantIf/.inspection b/idea/testData/quickfix/redundantIf/.inspection
new file mode 100644
index 00000000000..31f12fbfa2f
--- /dev/null
+++ b/idea/testData/quickfix/redundantIf/.inspection
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.inspections.RedundantIfInspection
\ No newline at end of file
diff --git a/idea/testData/quickfix/redundantIf/simple.kt b/idea/testData/quickfix/redundantIf/simple.kt
new file mode 100644
index 00000000000..6f51f02b593
--- /dev/null
+++ b/idea/testData/quickfix/redundantIf/simple.kt
@@ -0,0 +1,8 @@
+// "Remove redundant 'if' statement" "true"
+fun bar() {
+ if (value % 2 == 0) {
+ return true
+ } else {
+ return false
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/quickfix/redundantIf/simplet.kt.after b/idea/testData/quickfix/redundantIf/simplet.kt.after
new file mode 100644
index 00000000000..085569e3557
--- /dev/null
+++ b/idea/testData/quickfix/redundantIf/simplet.kt.after
@@ -0,0 +1,4 @@
+// "Remove redundant 'if' statement" "true"
+fun bar() {
+ return value % 2 == 0
+}
\ 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 1e808d85295..90c74ccc155 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java
@@ -160,6 +160,12 @@ public class InspectionTestGenerated extends AbstractInspectionTest {
doTest(fileName);
}
+ @TestMetadata("redundantIf/inspectionData/inspections.test")
+ public void testRedundantIf_inspectionData_Inspections_test() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspections/redundantIf/inspectionData/inspections.test");
+ doTest(fileName);
+ }
+
@TestMetadata("redundantModalityModifier/inspectionData/inspections.test")
public void testRedundantModalityModifier_inspectionData_Inspections_test() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspections/redundantModalityModifier/inspectionData/inspections.test");
diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java
index f844006867c..102f3988ef9 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java
@@ -6383,6 +6383,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
}
}
+ @TestMetadata("idea/testData/quickfix/redundantIf")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class RedundantIf extends AbstractQuickFixTest {
+ public void testAllFilesPresentInRedundantIf() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/redundantIf"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
+ }
+
+ @TestMetadata("simple.kt")
+ public void testSimple() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/redundantIf/simple.kt");
+ doTest(fileName);
+ }
+ }
+
@TestMetadata("idea/testData/quickfix/redundantModalityModifier")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)