From 8f2deb4c6095acfeeebd7434cac16c7d3d6ff08b Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Thu, 18 Jun 2020 16:49:53 +0200 Subject: [PATCH] RegExp: don't warn about redundant nested character classes when negated (IDEA-242520) because class negation behaviour changed between JDK 8 and JDK 9 GitOrigin-RevId: eb9bf0c636d17a98aac1a40a7376c13c65ef4999 --- ...dundantNestedCharacterClassInspection.java | 11 +++++++--- ...antNestedCharacterClassInspectionTest.java | 20 ++++++++++++++++--- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/RegExpSupport/src/org/intellij/lang/regexp/inspection/RedundantNestedCharacterClassInspection.java b/RegExpSupport/src/org/intellij/lang/regexp/inspection/RedundantNestedCharacterClassInspection.java index 9712432912d5..1a894d148682 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/inspection/RedundantNestedCharacterClassInspection.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/inspection/RedundantNestedCharacterClassInspection.java @@ -38,9 +38,14 @@ public class RedundantNestedCharacterClassInspection extends LocalInspectionTool public void visitRegExpClass(RegExpClass regExpClass) { super.visitRegExpClass(regExpClass); final PsiElement parent = regExpClass.getParent(); + // In JDK 9 the behaviour of negated character classes was changed, so we can never warn about them + // JDK 8: [^a&&b] is the intersection of [^a] with [b], which equals [b] + // JDK 9: [^a&&b] is the intersection of [a] and [b] (which is nothing), inverted, which equals everything. + // see https://bugs.openjdk.java.net/browse/JDK-8189343 + // and http://mail.openjdk.java.net/pipermail/core-libs-dev/2011-June/006957.html if (parent instanceof RegExpClass) { final RegExpClass parentClass = (RegExpClass)parent; - if (parentClass.isNegated() == regExpClass.isNegated()) { + if (!parentClass.isNegated() && !regExpClass.isNegated()) { myHolder.registerProblem(regExpClass.getFirstChild(), RegExpBundle.message("inspection.warning.redundant.nested.character.class"), new RedundantNestedCharacterClassFix()); } @@ -48,8 +53,8 @@ public class RedundantNestedCharacterClassInspection extends LocalInspectionTool else if (parent instanceof RegExpIntersection) { final PsiElement grandParent = parent.getParent(); if (grandParent instanceof RegExpClass) { - final RegExpClass parentClass = (RegExpClass)grandParent; - if (parentClass.isNegated() == regExpClass.isNegated()) { + final RegExpClass grandparentClass = (RegExpClass)grandParent; + if (!grandparentClass.isNegated() && !regExpClass.isNegated()) { myHolder.registerProblem(regExpClass.getFirstChild(), RegExpBundle.message("inspection.warning.redundant.nested.character.class"), new RedundantNestedCharacterClassFix()); } diff --git a/RegExpSupport/test/org/intellij/lang/regexp/inspection/RedundantNestedCharacterClassInspectionTest.java b/RegExpSupport/test/org/intellij/lang/regexp/inspection/RedundantNestedCharacterClassInspectionTest.java index b7161e5154ff..b2d03ac48f11 100644 --- a/RegExpSupport/test/org/intellij/lang/regexp/inspection/RedundantNestedCharacterClassInspectionTest.java +++ b/RegExpSupport/test/org/intellij/lang/regexp/inspection/RedundantNestedCharacterClassInspectionTest.java @@ -8,6 +8,7 @@ import org.jetbrains.annotations.NotNull; /** * @author Bas Leijdekkers */ +@SuppressWarnings({"RegExpDuplicateCharacterInClass", "RegExpRedundantNestedCharacterClass"}) public class RedundantNestedCharacterClassInspectionTest extends RegExpInspectionTestCase { public void testConjunction() { @@ -21,12 +22,25 @@ public class RedundantNestedCharacterClassInspectionTest extends RegExpInspectio } public void testNegation() { - quickfixTest("[^*=[^&]]", "[^*=&]", - RegExpBundle.message("inspection.quick.fix.replace.redundant.character.class.with.contents")); + highlightTest("[^abc[^cde]]"); + // JDK 8: conjunction of inverted [abc] and inverted [cde], which equals inverted [c] + // JDK 9: the inverse of the conjunction of [abc] and inverted [cde], which equals the inverse of inverted [de], which is [de] } public void testNoWarn() { - highlightTest("[a-z&&[^aeouiy]]" ); + highlightTest("[a-z&&[^aeouiy]]" ); // intersection of [a-z] with [aeouiy] inverted, which equals the alphabet except vowels + } + + public void testNoWarn2() { + highlightTest("[^a[abc]]"); + // JDK 8: conjunction of inverted [a] and [abc], which equals [bc] + // JDK 9: inverted conjunction of [a] and [abc], which equals inverted [abc] + } + + public void testNegatedIntersection() { + highlightTest("[^a&&[^abc]]"); + // JDK 8: intersection of inverted [a] and inverted [abc], which equals inverted [abc] + // JDK 9: inverted intersection of [a] and inverted [abc], which equals inverted empty class, which matches everything }