diff --git a/java/java-impl/src/META-INF/JavaPlugin.xml b/java/java-impl/src/META-INF/JavaPlugin.xml
index d97256c1ed35..8efaadb02394 100644
--- a/java/java-impl/src/META-INF/JavaPlugin.xml
+++ b/java/java-impl/src/META-INF/JavaPlugin.xml
@@ -406,6 +406,7 @@
order="before explicitlyImported"/>
+
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/NestedIfJoinLinesHandler.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/NestedIfJoinLinesHandler.java
new file mode 100644
index 000000000000..5e839ceaa0a5
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/NestedIfJoinLinesHandler.java
@@ -0,0 +1,64 @@
+// 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 file.
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.siyeh.ig.psiutils.CommentTracker;
+import com.siyeh.ig.psiutils.ControlFlowUtils;
+import com.siyeh.ig.psiutils.ParenthesesUtils;
+import org.jetbrains.annotations.NotNull;
+
+import static com.intellij.util.ObjectUtils.tryCast;
+
+/**
+ *
{@code
+ * if(a) {
+ * if(b) {
+ * ...
+ * }
+ * }
+ * =>
+ * if(a && b) {
+ * ...
+ * }
+ * }
+ */
+public class NestedIfJoinLinesHandler implements JoinLinesHandlerDelegate {
+ @Override
+ public int tryJoinLines(@NotNull final Document document, @NotNull final PsiFile psiFile, final int start, final int end) {
+ PsiJavaToken elementAtStartLineEnd = tryCast(psiFile.findElementAt(start), PsiJavaToken.class);
+ PsiElement nextLineElement = psiFile.findElementAt(end);
+ if (elementAtStartLineEnd == null || nextLineElement == null) return CANNOT_JOIN;
+ PsiIfStatement outerIf = null;
+ if (elementAtStartLineEnd.getTokenType().equals(JavaTokenType.RPARENTH)) {
+ outerIf = tryCast(elementAtStartLineEnd.getParent(), PsiIfStatement.class);
+ } else if(elementAtStartLineEnd.getTokenType().equals(JavaTokenType.LBRACE)) {
+ PsiCodeBlock block = tryCast(elementAtStartLineEnd.getParent(), PsiCodeBlock.class);
+ if (block != null) {
+ PsiBlockStatement blockStatement = tryCast(block.getParent(), PsiBlockStatement.class);
+ if (blockStatement != null) {
+ outerIf = tryCast(blockStatement.getParent(), PsiIfStatement.class);
+ if (outerIf == null || outerIf.getThenBranch() != blockStatement) return CANNOT_JOIN;
+ }
+ }
+ }
+ if (outerIf == null || outerIf.getElseBranch() != null) return CANNOT_JOIN;
+ PsiIfStatement innerIf = tryCast(ControlFlowUtils.stripBraces(outerIf.getThenBranch()), PsiIfStatement.class);
+ if (!PsiTreeUtil.isAncestor(innerIf, nextLineElement, false)) return CANNOT_JOIN;
+ if (innerIf.getThenBranch() == null || innerIf.getElseBranch() != null) return CANNOT_JOIN;
+
+ PsiExpression outerCondition = outerIf.getCondition();
+ if (outerCondition == null) return CANNOT_JOIN;
+ PsiExpression innerCondition = innerIf.getCondition();
+ if (innerCondition == null) return CANNOT_JOIN;
+
+ CommentTracker ct = new CommentTracker();
+ String childConditionText = ParenthesesUtils.getText(ct.markUnchanged(innerCondition), ParenthesesUtils.OR_PRECEDENCE);
+ String parentConditionText = ParenthesesUtils.getText(ct.markUnchanged(outerCondition), ParenthesesUtils.OR_PRECEDENCE);
+
+ PsiBinaryExpression newCondition = (PsiBinaryExpression)ct.replace(outerCondition, parentConditionText + "&&" + childConditionText);
+ ct.replaceAndRestoreComments(outerIf.getThenBranch(), innerIf.getThenBranch());
+ return newCondition.getOperationSign().getTextRange().getStartOffset();
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/joinLines/IfChain.java b/java/java-tests/testData/codeInsight/joinLines/IfChain.java
new file mode 100644
index 000000000000..0b3422feefd0
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/joinLines/IfChain.java
@@ -0,0 +1,9 @@
+class Foo {
+ void test(int a, int b) {
+ if(a > 0) {
+ if(b < 0) {
+ System.out.println(a+b);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/joinLines/IfChainElse.java b/java/java-tests/testData/codeInsight/joinLines/IfChainElse.java
new file mode 100644
index 000000000000..43aa552571e1
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/joinLines/IfChainElse.java
@@ -0,0 +1,11 @@
+class Foo {
+ void test(int a, int b) {
+ if(a > 0) {
+ if(b < 0) {
+ System.out.println(a+b);
+ } else {
+ System.out.println(a-b);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/joinLines/IfChainElse_after.java b/java/java-tests/testData/codeInsight/joinLines/IfChainElse_after.java
new file mode 100644
index 000000000000..262acca60791
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/joinLines/IfChainElse_after.java
@@ -0,0 +1,9 @@
+class Foo {
+ void test(int a, int b) {
+ if(a > 0) if(b < 0) {
+ System.out.println(a+b);
+ } else {
+ System.out.println(a-b);
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/joinLines/IfChainNoBraces.java b/java/java-tests/testData/codeInsight/joinLines/IfChainNoBraces.java
new file mode 100644
index 000000000000..bf81d2875f79
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/joinLines/IfChainNoBraces.java
@@ -0,0 +1,6 @@
+class Foo {
+ void test(int a, int b) {
+ if(a > 0)
+ if (b < 0) System.out.println(a + b);
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/joinLines/IfChainNoBraces_after.java b/java/java-tests/testData/codeInsight/joinLines/IfChainNoBraces_after.java
new file mode 100644
index 000000000000..18b49845703d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/joinLines/IfChainNoBraces_after.java
@@ -0,0 +1,5 @@
+class Foo {
+ void test(int a, int b) {
+ if(a > 0 && b < 0) System.out.println(a + b);
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/joinLines/IfChain_after.java b/java/java-tests/testData/codeInsight/joinLines/IfChain_after.java
new file mode 100644
index 000000000000..b67ba027537d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/joinLines/IfChain_after.java
@@ -0,0 +1,7 @@
+class Foo {
+ void test(int a, int b) {
+ if(a > 0 && b < 0) {
+ System.out.println(a+b);
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java
index b05b2e8e758d..384d12390b04 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java
+++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java
@@ -50,6 +50,10 @@ public class JoinLinesTest extends LightCodeInsightTestCase {
public void testDeclarationAndReassignmentWithCall() { doTest(); }
public void testAssignmentAndReassignmentWithCall() { doTest(); }
+ public void testIfChain() { doTest(); }
+ public void testIfChainNoBraces() { doTest(); }
+ public void testIfChainElse() { doTest(); }
+
public void testSCR3493() {
CommonCodeStyleSettings settings = getJavaSettings();
boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER;