diff --git a/java/java-impl/src/META-INF/JavaPlugin.xml b/java/java-impl/src/META-INF/JavaPlugin.xml
index b46fccb69669..db996ce19f1c 100644
--- a/java/java-impl/src/META-INF/JavaPlugin.xml
+++ b/java/java-impl/src/META-INF/JavaPlugin.xml
@@ -1189,6 +1189,7 @@
+
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/CaseJoinLinesHandler.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/CaseJoinLinesHandler.java
new file mode 100644
index 000000000000..1597da88339c
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/CaseJoinLinesHandler.java
@@ -0,0 +1,37 @@
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.application.options.CodeStyle;
+import com.intellij.codeInsight.daemon.impl.analysis.HighlightingFeature;
+import com.intellij.lang.java.JavaLanguage;
+import com.intellij.openapi.editor.Document;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtil;
+import org.jetbrains.annotations.NotNull;
+
+public class CaseJoinLinesHandler implements JoinLinesHandlerDelegate {
+ @Override
+ public int tryJoinLines(@NotNull final Document document, @NotNull final PsiFile psiFile, final int start, final int end) {
+ if (!HighlightingFeature.ENHANCED_SWITCH.isAvailable(psiFile)) return -1;
+ PsiElement elementAtStartLineEnd = psiFile.findElementAt(start);
+ PsiElement elementAtNextLineStart = psiFile.findElementAt(end);
+ if (elementAtStartLineEnd == null || elementAtNextLineStart == null) return -1;
+ if (!PsiUtil.isJavaToken(elementAtStartLineEnd, JavaTokenType.COLON)) return -1;
+ if (!(elementAtNextLineStart instanceof PsiKeyword) ||
+ ((PsiKeyword)elementAtNextLineStart).getTokenType() != JavaTokenType.CASE_KEYWORD) {
+ return -1;
+ }
+ PsiSwitchLabelStatement firstLabel = PsiTreeUtil.getParentOfType(elementAtStartLineEnd, PsiSwitchLabelStatement.class);
+ if (firstLabel == null) return -1;
+ PsiSwitchLabelStatement secondLabel = PsiTreeUtil.getParentOfType(elementAtNextLineStart, PsiSwitchLabelStatement.class);
+ if (secondLabel == null || secondLabel == firstLabel) return -1;
+ PsiElement nextToken = PsiTreeUtil.skipWhitespacesForward(elementAtNextLineStart);
+ if (nextToken == null) return -1;
+ int replaceStart = elementAtStartLineEnd.getTextRange().getStartOffset();
+ int replaceEnd = nextToken.getTextRange().getStartOffset();
+ boolean spaceAfterComma = CodeStyle.getSettings(psiFile).getCommonSettings(JavaLanguage.INSTANCE).SPACE_AFTER_COMMA;
+ document.replaceString(replaceStart, replaceEnd, "," + (spaceAfterComma ? " " : ""));
+ return replaceStart;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/joinLines/CaseLabels.java b/java/java-tests/testData/codeInsight/joinLines/CaseLabels.java
new file mode 100644
index 000000000000..667568977271
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/joinLines/CaseLabels.java
@@ -0,0 +1,12 @@
+class A {
+ void test(int x) {
+ switch (x) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ System.out.println("hello");
+ default:
+ }
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/joinLines/CaseLabels2.java b/java/java-tests/testData/codeInsight/joinLines/CaseLabels2.java
new file mode 100644
index 000000000000..c4cf6a8c5a9f
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/joinLines/CaseLabels2.java
@@ -0,0 +1,10 @@
+class A {
+ void test(int x) {
+ switch (x) {
+ case 0:
+ case /*hello*/ 1,2,3:
+ System.out.println("hello");
+ default:
+ }
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/joinLines/CaseLabels2_after.java b/java/java-tests/testData/codeInsight/joinLines/CaseLabels2_after.java
new file mode 100644
index 000000000000..aee126c0f295
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/joinLines/CaseLabels2_after.java
@@ -0,0 +1,9 @@
+class A {
+ void test(int x) {
+ switch (x) {
+ case 0,/*hello*/ 1,2,3:
+ System.out.println("hello");
+ default:
+ }
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/joinLines/CaseLabels_after.java b/java/java-tests/testData/codeInsight/joinLines/CaseLabels_after.java
new file mode 100644
index 000000000000..a93e14a9128c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/joinLines/CaseLabels_after.java
@@ -0,0 +1,10 @@
+class A {
+ void test(int x) {
+ switch (x) {
+ case 0, 1, 2:
+ case 3:
+ System.out.println("hello");
+ default:
+ }
+ }
+}
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 958619d68c4b..de7dda15d666 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java
+++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java
@@ -290,6 +290,13 @@ public class JoinLinesTest extends LightJavaCodeInsightTestCase {
public void testJoinFields2() {doTest(3);}
public void testJoinFields3() {doTest();}
+ public void testCaseLabels() {doTest();}
+ public void testCaseLabels2() {
+ CommonCodeStyleSettings settings = getJavaSettings();
+ settings.SPACE_AFTER_COMMA = false;
+ doTest();
+ }
+
private void doTest() {
doTest(".java");
}