RegExp: don't report \{ as redundant escape and add option to not report \} and \] (IDEA-243874, WEB-54046, PY-47380)

GitOrigin-RevId: 1ce7073269aaa2a1cd843765f97820bca8155747
This commit is contained in:
Bas Leijdekkers
2021-12-20 10:55:08 +00:00
committed by intellij-monorepo-bot
parent d24901c574
commit ccc210eeb2
4 changed files with 38 additions and 5 deletions
@@ -2,6 +2,11 @@
<body>
Reports character escapes that are replaceable with the unescaped character without a change in meaning.
Note that inside the square brackets of a character class, many escapes are unnecessary that would be necessary outside of a character class.
<p>
This inspection doesn't warn on opening curly braces (<code>{</code>) outside of character classes (<code>[]</code>).
Removing the escape before an opening curly brace can cause confusion,
even though this is allowed in e.g. the Javascript and Python regex dialects.
It would also make the regex pattern less portable, because many other dialects don't allow unescaped curly braces as characters.
<p><b>Example:</b></p>
<pre><code>
\-\;[\.]
@@ -11,6 +16,10 @@ Note that inside the square brackets of a character class, many escapes are unne
-;[.]
</code></pre>
<!-- tooltip end -->
<p>
Use the <b>Ignore escaped closing brackets '}' and ']'</b> option
to specify if '\}' and '\]' should be reported when they are not inside a character class
and they are allowed to be unescaped by the RegExp dialect.
<p><small>New in 2017.3</small>
</body>
</html>
@@ -26,7 +26,7 @@ error.atomic.groups.are.not.supported.in.this.regex.dialect=Atomic groups are no
error.back.reference.is.nested.into.the.capturing.group.it.refers.to=Back reference is nested into the capturing group it refers to
error.conditional.group.reference.not.allowed.inside.lookbehind=Conditional group reference not allowed inside lookbehind
error.conditionals.are.not.supported.in.this.regex.dialect=Conditionals are not supported in this regex dialect
error.dangling.metacharacter=Dangling metacharacter
error.dangling.metacharacter=Dangling quantifier ''{0}''
error.embedded.comments.are.not.supported.in.this.regex.dialect=Embedded comments are not supported in this regex dialect
error.empty.group=Empty group
error.group.reference.is.nested.into.the.named.group.it.refers.to=Group reference is nested into the named group it refers to
@@ -77,6 +77,7 @@ inspection.name.redundant.nested.character.class=Redundant nested character clas
inspection.name.single.character.alternation=Single character alternation
inspection.name.suspicious.backref=Suspicious back reference
inspection.name.unnecessary.non.capturing.group=Unnecessary non-capturing group
inspection.option.ignore.escaped.closing.brackets=Ignore escaped closing brackets '}' and ']'
inspection.quick.fix.remove.duplicate.0.from.character.class=Remove duplicate ''{0}'' from character class
inspection.quick.fix.remove.duplicate.branch=Remove duplicate branch
inspection.quick.fix.remove.duplicate.element.from.character.class=Remove duplicate element from character class
@@ -137,7 +138,7 @@ parse.error.unclosed.options.group=Unclosed options group
parse.error.unclosed.posix.bracket.expression=Unclosed POSIX bracket expression
parse.error.unclosed.property=Unclosed property
parse.error.unicode.character.name.expected=Unicode character name expected
parse.error.unmatched.closing.parenthesis=Unmatched closing ')'
parse.error.unmatched.closing.bracket=Unmatched closing ''{0}''
surrounder.atomic.group.pattern=Atomic Group (?:pattern)
surrounder.capturing.group.pattern=Capturing Group (pattern)
surrounder.negative.lookahead.pattern=Negative Lookahead (?!pattern)
@@ -1,10 +1,11 @@
// Copyright 2000-2020 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.
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.intellij.lang.regexp.inspection;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
@@ -12,22 +13,34 @@ import org.intellij.lang.regexp.RegExpBundle;
import org.intellij.lang.regexp.RegExpLanguageHosts;
import org.intellij.lang.regexp.RegExpTT;
import org.intellij.lang.regexp.psi.RegExpChar;
import org.intellij.lang.regexp.psi.RegExpClass;
import org.intellij.lang.regexp.psi.RegExpElementVisitor;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
/**
* @author Bas Leijdekkers
*/
public class RegExpRedundantEscapeInspection extends LocalInspectionTool {
public boolean ignoreEscapedMetaCharacters = false;
@Override
public @Nullable JComponent createOptionsPanel() {
return new SingleCheckboxOptionsPanel(RegExpBundle.message("inspection.option.ignore.escaped.closing.brackets"),
this, "ignoreEscapedMetaCharacters");
}
@NotNull
@Override
public RegExpElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
return new RedundantEscapeVisitor(holder);
}
private static class RedundantEscapeVisitor extends RegExpElementVisitor {
private class RedundantEscapeVisitor extends RegExpElementVisitor {
private final ProblemsHolder myHolder;
@@ -41,6 +54,12 @@ public class RegExpRedundantEscapeInspection extends LocalInspectionTool {
if (!text.startsWith("\\") || !RegExpLanguageHosts.getInstance().isRedundantEscape(ch, text)) {
return;
}
if (text.equals("\\{") && !(ch.getParent() instanceof RegExpClass)) {
return;
}
if (ignoreEscapedMetaCharacters && (text.equals("\\}") || text.equals("\\]")) && !(ch.getParent() instanceof RegExpClass)) {
return;
}
final ASTNode astNode = ch.getNode().getFirstChildNode();
if (astNode == null || astNode.getElementType() != RegExpTT.REDUNDANT_ESCAPE) {
return;
@@ -1,4 +1,4 @@
// Copyright 2000-2020 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.
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.intellij.lang.regexp.inspection;
import com.intellij.codeInspection.LocalInspectionTool;
@@ -33,6 +33,10 @@ public class RedundantEscapeInspectionTest extends RegExpInspectionTestCase {
highlightTest("<warning descr=\"Redundant character escape '\\#' in RegExp\">\\#</warning>(?x)\\#");
}
public void testCurlyBrace() {
highlightTest("\\{TEST}", RegExpFileType.forLanguage(EcmaScriptRegexpLanguage.INSTANCE));
}
@NotNull
@Override
protected LocalInspectionTool getInspection() {