regex: i18n

GitOrigin-RevId: 959a692e7c77872c29e9fe2b690836ca9d4dd154
This commit is contained in:
Bas Leijdekkers
2020-03-07 14:16:23 +01:00
committed by intellij-monorepo-bot
parent a2d5c27c59
commit 9e814f9e75
26 changed files with 477 additions and 314 deletions

View File

@@ -0,0 +1,129 @@
color.settings.bad.character=Bad Character
color.settings.brace=Brace
color.settings.bracket=Bracket
color.settings.character.class=Character Class
color.settings.comma=Comma
color.settings.comment=Comment
color.settings.dot=Dot
color.settings.escaped.character=Escaped Character
color.settings.inline.option=Inline Option
color.settings.invalid.escape.sequence=Invalid Escape Sequence
color.settings.name=Name
color.settings.operator.character=Operator Character
color.settings.parenthesis=Parenthesis
color.settings.plain.character=Plain Character
color.settings.quantifier=Quantifier
color.settings.quote.character=Quote Escape
color.settings.redundant.escape.sequence=Redundant Escape Sequence
color.settings.title.regexp=RegExp
doc.property.block.stands.for.0=Property block stands for {0}
doc.property.block.stands.for.characters.not.matching.0=Property block stands for characters not matching {0}
error.0.repetition.not.allowed.inside.lookbehind={0} repetition not allowed inside lookbehind
error.alternation.alternatives.needs.to.have.the.same.length.inside.lookbehind=Alternation alternatives needs to have the same length inside lookbehind
error.atomic.groups.are.not.supported.in.this.regex.dialect=Atomic groups are not supported in this regex dialect
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.conditional.references.are.not.supported.in.this.regex.dialect=Conditional references are not supported in this regex dialect
error.dangling.metacharacter=Dangling metacharacter
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
error.group.reference.not.allowed.inside.lookbehind=Group reference not allowed inside lookbehind
error.group.with.name.0.already.defined=Group with name ''{0}'' already defined
error.illegal.character.range.to.from=Illegal character range (to < from)
error.illegal.hexadecimal.escape.sequence=Illegal hexadecimal escape sequence
error.illegal.octal.escape.sequence=Illegal octal escape sequence
error.illegal.repetition.range.min.max=Illegal repetition range (min > max)
error.illegal.unicode.escape.sequence=Illegal unicode escape sequence
error.illegal.unsupported.escape.sequence=Illegal/unsupported escape sequence
error.invalid.group.name=Invalid group name
error.look.behind.groups.are.not.supported.in.this.regex.dialect=Look-behind groups are not supported in this regex dialect
error.named.group.reference.not.allowed.inside.lookbehind=Named group reference not allowed inside lookbehind
error.named.unicode.characters.are.not.allowed.in.this.regex.dialect=Named Unicode characters are not allowed in this regex dialect
error.nested.quantifier.in.regexp=Nested quantifier in regexp
error.property.escape.sequences.are.not.supported.in.this.regex.dialect=Property escape sequences are not supported in this regex dialect
error.redundant.character.range=Redundant character range
error.redundant.group.nesting=Redundant group nesting
error.repetition.value.too.large=Repetition value too large
error.this.boundary.is.not.supported.in.this.regex.dialect=This boundary is not supported in this regex dialect
error.this.hex.character.syntax.is.not.supported.in.this.regex.dialect=This hex character syntax is not supported in this regex dialect
error.this.named.group.reference.syntax.is.not.supported.in.this.regex.dialect=This named group reference syntax is not supported in this regex dialect
error.this.named.group.syntax.is.not.supported.in.this.regex.dialect=This named group syntax is not supported in this regex dialect
error.unequal.min.and.max.in.counted.quantifier.not.allowed.inside.lookbehind=Unequal min and max in counted quantifier not allowed inside lookbehind
error.unknown.character.category=Unknown character category
error.unknown.character.name=Unknown character name
error.unknown.inline.option.flag=Unknown inline option flag
error.unknown.posix.character.class=Unknown POSIX character class
error.unknown.property.name=Unknown property name
error.unknown.property.value=Unknown property value
error.unresolved.back.reference=Unresolved back reference
error.unresolved.named.group.reference=Unresolved named group reference
file.type.description.regular.expression=Regular expression
inspection.quick.fix.remove.duplicate.branch=Remove duplicate branch
inspection.quick.fix.remove.empty.branch=Remove empty branch
inspection.quick.fix.remove.redundant.escape=Remove redundant escape
inspection.quick.fix.replace.alternation.with.character.class=Replace alternation with character class
inspection.quick.fix.replace.with.character.inside.class=Replace with character inside class
inspection.quick.fix.replace.with.hexadecimal.escape=Replace with hexadecimal escape
inspection.quick.fix.replace.with.space.and.repeated.quantifier=Replace with space and repeated quantifier
inspection.warning.anchor.code.ref.code.in.unexpected.position=Anchor <code>#ref</code> in unexpected position
inspection.warning.anonymous.capturing.group=Anonymous capturing group
inspection.warning.duplicate.branch.in.alternation=Duplicate branch in alternation
inspection.warning.empty.branch.in.alternation=Empty branch in alternation
inspection.warning.escaped.meta.character.0=Escaped meta character <code>{0}</code>
inspection.warning.numeric.back.reference=Numeric back reference
inspection.warning.octal.escape.code.ref.code.in.regexp=Octal escape <code>#ref</code> in RegExp
inspection.warning.potential.exponential.backtracking=Potential exponential backtracking
inspection.warning.redundant.character.escape.0.in.regexp=Redundant character escape <code>{0}</code> in RegExp
inspection.warning.single.character.alternation.in.regexp=Single character alternation in RegExp
intention.balloon.bad.pattern=Bad pattern
intention.balloon.matches=Matches!
intention.balloon.more.input.expected=More input expected
intention.balloon.no.match=No match
intention.balloon.pattern.is.too.complex=Pattern is too complex
intention.name.check.regexp=Check RegExp
intention.name.simplify.quantifier=Simplify quantifier
parse.error.category.shorthand.not.allowed.in.this.regular.expression.dialect=Category shorthand not allowed in this regular expression dialect
parse.error.character.class.expected=Character class expected
parse.error.character.expected=Character expected
parse.error.character.or.mysql.character.name.expected=Character or MySQL character name expected
parse.error.closing.brace.expected='}' expected
parse.error.closing.brace.or.number.expected='}' or number expected
parse.error.comma.expected=',' expected
parse.error.empty.property=Empty property
parse.error.group.name.expected=Group name expected
parse.error.group.name.or.number.expected=Group name or number expected
parse.error.illegal.category.shorthand=Illegal category shorthand
parse.error.illegal.character.range=Illegal character range
parse.error.negating.a.property.not.allowed.in.this.regular.expression.dialect=Negating a property not allowed in this regular expression dialect
parse.error.number.expected=Number expected
parse.error.opening.brace.expected='{' expected
parse.error.opening.brace.or.category.shorthand.expected='{' or category shorthand expected
parse.error.pattern.expected=Pattern expected
parse.error.posix.character.class.name.expected=POSIX character class name expected
parse.error.property.name.expected=Property name expected
parse.error.property.value.expected=Property value expected
parse.error.unclosed.character.class=Unclosed character class
parse.error.unclosed.conditional=Unclosed conditional
parse.error.unclosed.group.name=Unclosed group name
parse.error.unclosed.group.reference=Unclosed group reference
parse.error.unclosed.group=Unclosed group
parse.error.unclosed.mysql.character.equivalence.class=Unclosed MySQL character equivalence class
parse.error.unclosed.mysql.character.expression=Unclosed MySQL character expression
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 ')'
surrounder.atomic.group.pattern=Atomic Group (?:pattern)
surrounder.capturing.group.pattern=Capturing Group (pattern)
surrounder.negative.lookahead.pattern=Negative Lookahead (?!pattern)
surrounder.negative.lookbehind.pattern=Negative Lookbehind (?<!pattern)
surrounder.non.capturing.group.pattern=Non-Capturing Group (?:pattern)
surrounder.positive.lookahead.pattern=Positive Lookahead (?=pattern)
surrounder.positive.lookbehind.pattern=Positive Lookbehind (?<=pattern)
warning.duplicate.character.0.inside.character.class=Duplicate character ''{0}'' inside character class
warning.duplicate.predefined.character.class.0.inside.character.class=Duplicate predefined character class ''{0}'' inside character class
weak.warning.fixed.repetition.range=Fixed repetition range
weak.warning.repetition.range.replaceable.by.0=Repetition range replaceable by ''{0}''
weak.warning.single.repetition=Single repetition

View File

@@ -0,0 +1,28 @@
// 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.
package org.intellij.lang.regexp;
import com.intellij.DynamicBundle;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.util.function.Supplier;
public class RegExpBundle extends DynamicBundle {
@NonNls private static final String BUNDLE = "messages.RegExpBundle";
private static final RegExpBundle INSTANCE = new RegExpBundle();
private RegExpBundle() {
super(BUNDLE);
}
@NotNull
public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params) {
return INSTANCE.getMessage(key, params);
}
@NotNull
public static Supplier<String> messagePointer(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params) {
return INSTANCE.getLazyMessage(key, params);
}
}

View File

@@ -16,23 +16,23 @@ import java.util.Map;
public class RegExpColorsPage implements ColorSettingsPage {
private static final AttributesDescriptor[] DESCRIPTORS = new AttributesDescriptor[] {
new AttributesDescriptor("Plain character", RegExpHighlighter.CHARACTER),
new AttributesDescriptor("Operator character", RegExpHighlighter.META),
new AttributesDescriptor("Escaped character", RegExpHighlighter.ESC_CHARACTER),
new AttributesDescriptor("Invalid escape sequence", RegExpHighlighter.INVALID_CHARACTER_ESCAPE),
new AttributesDescriptor("Redundant escape sequence", RegExpHighlighter.REDUNDANT_ESCAPE),
new AttributesDescriptor("Brace", RegExpHighlighter.BRACES),
new AttributesDescriptor("Bracket", RegExpHighlighter.BRACKETS),
new AttributesDescriptor("Parenthesis", RegExpHighlighter.PARENTHS),
new AttributesDescriptor("Comma", RegExpHighlighter.COMMA),
new AttributesDescriptor("Bad character", RegExpHighlighter.BAD_CHARACTER),
new AttributesDescriptor("Character class", RegExpHighlighter.CHAR_CLASS),
new AttributesDescriptor("Quote character", RegExpHighlighter.QUOTE_CHARACTER),
new AttributesDescriptor("Comment", RegExpHighlighter.COMMENT),
new AttributesDescriptor("Quantifier", RegExpHighlighter.QUANTIFIER),
new AttributesDescriptor("Dot", RegExpHighlighter.DOT),
new AttributesDescriptor("Inline option", RegExpHighlighter.OPTIONS),
new AttributesDescriptor("Name", RegExpHighlighter.NAME)
new AttributesDescriptor(RegExpBundle.message("color.settings.plain.character"), RegExpHighlighter.CHARACTER),
new AttributesDescriptor(RegExpBundle.message("color.settings.operator.character"), RegExpHighlighter.META),
new AttributesDescriptor(RegExpBundle.message("color.settings.escaped.character"), RegExpHighlighter.ESC_CHARACTER),
new AttributesDescriptor(RegExpBundle.message("color.settings.invalid.escape.sequence"), RegExpHighlighter.INVALID_CHARACTER_ESCAPE),
new AttributesDescriptor(RegExpBundle.message("color.settings.redundant.escape.sequence"), RegExpHighlighter.REDUNDANT_ESCAPE),
new AttributesDescriptor(RegExpBundle.message("color.settings.brace"), RegExpHighlighter.BRACES),
new AttributesDescriptor(RegExpBundle.message("color.settings.bracket"), RegExpHighlighter.BRACKETS),
new AttributesDescriptor(RegExpBundle.message("color.settings.parenthesis"), RegExpHighlighter.PARENTHS),
new AttributesDescriptor(RegExpBundle.message("color.settings.comma"), RegExpHighlighter.COMMA),
new AttributesDescriptor(RegExpBundle.message("color.settings.bad.character"), RegExpHighlighter.BAD_CHARACTER),
new AttributesDescriptor(RegExpBundle.message("color.settings.character.class"), RegExpHighlighter.CHAR_CLASS),
new AttributesDescriptor(RegExpBundle.message("color.settings.quote.character"), RegExpHighlighter.QUOTE_CHARACTER),
new AttributesDescriptor(RegExpBundle.message("color.settings.comment"), RegExpHighlighter.COMMENT),
new AttributesDescriptor(RegExpBundle.message("color.settings.quantifier"), RegExpHighlighter.QUANTIFIER),
new AttributesDescriptor(RegExpBundle.message("color.settings.dot"), RegExpHighlighter.DOT),
new AttributesDescriptor(RegExpBundle.message("color.settings.inline.option"), RegExpHighlighter.OPTIONS),
new AttributesDescriptor(RegExpBundle.message("color.settings.name"), RegExpHighlighter.NAME)
};
@NonNls private static final HashMap<String,TextAttributesKey> ourTagToDescriptorMap = new HashMap<>();
@@ -40,7 +40,7 @@ public class RegExpColorsPage implements ColorSettingsPage {
@Override
@NotNull
public String getDisplayName() {
return "RegExp";
return RegExpBundle.message("color.settings.title.regexp");
}
@Override

View File

@@ -1,18 +1,4 @@
/*
* Copyright 2000-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.
*/
// 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.
package org.intellij.lang.regexp;
import com.intellij.lang.ASTNode;
@@ -39,9 +25,9 @@ public final class RegExpDocumentationProvider extends AbstractDocumentationProv
final String description = RegExpLanguageHosts.getInstance().getPropertyDescription(node.getPsi(), node.getText());
if (description != null) {
if (prop.isNegated()) {
return "Property block stands for characters not matching " + description;
return RegExpBundle.message("doc.property.block.stands.for.characters.not.matching.0", description);
} else {
return "Property block stands for " + description;
return RegExpBundle.message("doc.property.block.stands.for.0", description);
}
}
}

View File

@@ -16,9 +16,10 @@
package org.intellij.lang.regexp;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NonNls;
public class RegExpElementType extends IElementType {
RegExpElementType(String s) {
super(s, RegExpLanguage.INSTANCE);
RegExpElementType(@NonNls String debugName) {
super(debugName, RegExpLanguage.INSTANCE);
}
}

View File

@@ -46,7 +46,7 @@ public class RegExpFileType extends LanguageFileType {
@Override
@NotNull
public String getDescription() {
return "Regular Expression";
return RegExpBundle.message("file.type.description.regular.expression");
}
@Override

View File

@@ -22,6 +22,7 @@ import com.intellij.lang.PsiParser;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import org.intellij.lang.regexp.psi.impl.RegExpCharImpl;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -140,7 +141,7 @@ public class RegExpParser implements PsiParser, LightPsiParser {
numberMark.done(RegExpElementTypes.NUMBER);
}
else {
builder.error("Number expected");
builder.error(RegExpBundle.message("parse.error.number.expected"));
}
}
if (builder.getTokenType() == RegExpTT.RBRACE) {
@@ -150,7 +151,7 @@ public class RegExpParser implements PsiParser, LightPsiParser {
}
else {
if (!minOmitted) {
checkMatches(builder, RegExpTT.COMMA, "',' expected");
checkMatches(builder, RegExpTT.COMMA, RegExpBundle.message("parse.error.comma.expected"));
}
if (builder.getTokenType() == RegExpTT.RBRACE) {
builder.advanceLexer();
@@ -161,12 +162,12 @@ public class RegExpParser implements PsiParser, LightPsiParser {
final PsiBuilder.Marker numberMark = builder.mark();
builder.advanceLexer();
numberMark.done(RegExpElementTypes.NUMBER);
checkMatches(builder, RegExpTT.RBRACE, "'}' expected");
checkMatches(builder, RegExpTT.RBRACE, RegExpBundle.message("parse.error.closing.brace.expected"));
parseQuantifierType(builder);
marker.done(RegExpElementTypes.QUANTIFIER);
}
else {
builder.error("'}' or number expected");
builder.error(RegExpBundle.message("parse.error.closing.brace.or.number.expected"));
marker.done(RegExpElementTypes.QUANTIFIER);
return true;
}
@@ -191,7 +192,7 @@ public class RegExpParser implements PsiParser, LightPsiParser {
}
else {
if (RegExpTT.QUANTIFIERS.contains(builder.getTokenType())) {
builder.error("Dangling metacharacter");
builder.error(RegExpBundle.message("error.dangling.metacharacter"));
}
}
}
@@ -213,7 +214,7 @@ public class RegExpParser implements PsiParser, LightPsiParser {
}
parseClassIntersection(builder);
checkMatches(builder, RegExpTT.CLASS_END, "Unclosed character class");
checkMatches(builder, RegExpTT.CLASS_END, RegExpBundle.message("parse.error.unclosed.character.class"));
marker.done(RegExpElementTypes.CLASS);
return marker;
}
@@ -230,7 +231,7 @@ public class RegExpParser implements PsiParser, LightPsiParser {
builder.advanceLexer();
final boolean right = parseClassdef(builder);
if (!left && !right) {
builder.error("character class expected");
builder.error(RegExpBundle.message("parse.error.character.class.expected"));
}
left = right;
}
@@ -277,8 +278,8 @@ public class RegExpParser implements PsiParser, LightPsiParser {
if (builder.getTokenType() == RegExpTT.CARET) {
builder.advanceLexer();
}
checkMatches(builder, RegExpTT.NAME, "POSIX character class name expected");
checkMatches(builder, RegExpTT.BRACKET_EXPRESSION_END, "Unclosed POSIX bracket expression");
checkMatches(builder, RegExpTT.NAME, RegExpBundle.message("parse.error.posix.character.class.name.expected"));
checkMatches(builder, RegExpTT.BRACKET_EXPRESSION_END, RegExpBundle.message("parse.error.unclosed.posix.bracket.expression"));
marker.done(RegExpElementTypes.POSIX_BRACKET_EXPRESSION);
}
@@ -289,17 +290,17 @@ public class RegExpParser implements PsiParser, LightPsiParser {
builder.advanceLexer();
}
else {
checkMatches(builder, RegExpTT.CHARACTER, "Character or MySQL character name expected");
checkMatches(builder, RegExpTT.CHARACTER, RegExpBundle.message("parse.error.character.or.mysql.character.name.expected"));
}
checkMatches(builder, RegExpTT.MYSQL_CHAR_END, "Unclosed MySQL character expression");
checkMatches(builder, RegExpTT.MYSQL_CHAR_END, RegExpBundle.message("parse.error.unclosed.mysql.character.expression"));
marker.done(RegExpElementTypes.MYSQL_CHAR_EXPRESSION);
}
private static void parseMysqlCharEqExpression(PsiBuilder builder) {
final PsiBuilder.Marker marker = builder.mark();
builder.advanceLexer();
checkMatches(builder, RegExpTT.CHARACTER, "Character expected");
checkMatches(builder, RegExpTT.MYSQL_CHAR_EQ_END, "Unclosed MySQL character equivalence class");
checkMatches(builder, RegExpTT.CHARACTER, RegExpBundle.message("parse.error.character.expected"));
checkMatches(builder, RegExpTT.MYSQL_CHAR_EQ_END, RegExpBundle.message("parse.error.unclosed.mysql.character.equivalence.class"));
marker.done(RegExpElementTypes.MYSQL_CHAR_EQ_EXPRESSION);
}
@@ -329,7 +330,7 @@ public class RegExpParser implements PsiParser, LightPsiParser {
}
else {
minusMarker.drop();
builder.error("Illegal character range");
builder.error(RegExpBundle.message("parse.error.illegal.character.range"));
rangeMarker.done(RegExpElementTypes.CHAR_RANGE);
}
}
@@ -374,7 +375,7 @@ public class RegExpParser implements PsiParser, LightPsiParser {
marker.done(RegExpElementTypes.GROUP);
}
else {
checkMatches(builder, RegExpTT.GROUP_END, "Unclosed options group");
checkMatches(builder, RegExpTT.GROUP_END, RegExpBundle.message("parse.error.unclosed.options.group"));
marker.done(RegExpElementTypes.SET_OPTIONS);
}
}
@@ -398,8 +399,9 @@ public class RegExpParser implements PsiParser, LightPsiParser {
}
else if (type == RegExpTT.PYTHON_NAMED_GROUP || type == RegExpTT.RUBY_NAMED_GROUP || type == RegExpTT.RUBY_QUOTED_NAMED_GROUP) {
builder.advanceLexer();
checkMatches(builder, RegExpTT.NAME, "Group name expected");
checkMatches(builder, type == RegExpTT.RUBY_QUOTED_NAMED_GROUP ? RegExpTT.QUOTE : RegExpTT.GT, "Unclosed group name");
checkMatches(builder, RegExpTT.NAME, RegExpBundle.message("parse.error.group.name.expected"));
checkMatches(builder, type == RegExpTT.RUBY_QUOTED_NAMED_GROUP ? RegExpTT.QUOTE : RegExpTT.GT,
RegExpBundle.message("parse.error.unclosed.group.name"));
parseGroupEnd(builder);
marker.done(RegExpElementTypes.GROUP);
}
@@ -418,15 +420,15 @@ public class RegExpParser implements PsiParser, LightPsiParser {
builder.advanceLexer();
}
else {
builder.error("Group name or number expected");
builder.error(RegExpBundle.message("parse.error.group.name.or.number.expected"));
}
checkMatches(builder, RegExpTT.GROUP_END, "Unclosed group reference");
checkMatches(builder, RegExpTT.GROUP_END, RegExpBundle.message("parse.error.unclosed.group.reference"));
parseBranch(builder);
if (builder.getTokenType() == RegExpTT.UNION) {
builder.advanceLexer();
parseBranch(builder);
}
checkMatches(builder, RegExpTT.GROUP_END, "Unclosed conditional");
checkMatches(builder, RegExpTT.GROUP_END, RegExpBundle.message("parse.error.unclosed.conditional"));
marker.done(RegExpElementTypes.PY_COND_REF);
}
else if (type == RegExpTT.PROPERTY) {
@@ -450,13 +452,13 @@ public class RegExpParser implements PsiParser, LightPsiParser {
private void parseGroupEnd(PsiBuilder builder) {
parsePattern(builder);
checkMatches(builder, RegExpTT.GROUP_END, "Unclosed group");
checkMatches(builder, RegExpTT.GROUP_END, RegExpBundle.message("parse.error.unclosed.group"));
}
private static void parseNamedGroupRef(PsiBuilder builder, PsiBuilder.Marker marker, IElementType type) {
builder.advanceLexer();
checkMatches(builder, RegExpTT.NAME, "Group name expected");
checkMatches(builder, type, "Unclosed group reference");
checkMatches(builder, RegExpTT.NAME, RegExpBundle.message("parse.error.group.name.expected"));
checkMatches(builder, type, RegExpBundle.message("parse.error.unclosed.group.reference"));
marker.done(RegExpElementTypes.NAMED_GROUP_REF);
}
@@ -472,23 +474,23 @@ public class RegExpParser implements PsiParser, LightPsiParser {
builder.advanceLexer();
if (builder.getTokenType() == RegExpTT.CATEGORY_SHORT_HAND) {
if (!myCapabilities.contains(RegExpCapability.UNICODE_CATEGORY_SHORTHAND)) {
builder.error("Category shorthand not allowed in this regular expression dialect");
builder.error(RegExpBundle.message("parse.error.category.shorthand.not.allowed.in.this.regular.expression.dialect"));
}
builder.advanceLexer();
}
else {
if (builder.getTokenType() == RegExpTT.CHARACTER && isLetter(builder.getTokenText())) {
builder.error(myCapabilities.contains(RegExpCapability.UNICODE_CATEGORY_SHORTHAND) ?
"Illegal category shorthand" :
"'{' expected");
RegExpBundle.message("parse.error.illegal.category.shorthand") :
RegExpBundle.message("parse.error.opening.brace.expected"));
builder.advanceLexer();
}
else if (checkMatches(builder, RegExpTT.LBRACE, myCapabilities.contains(RegExpCapability.UNICODE_CATEGORY_SHORTHAND) ?
"'{' or category shorthand expected" :
"'{' expected")) {
RegExpBundle.message("parse.error.opening.brace.or.category.shorthand.expected") :
RegExpBundle.message("parse.error.opening.brace.expected"))) {
if (builder.getTokenType() == RegExpTT.CARET) {
if (!myCapabilities.contains(RegExpCapability.CARET_NEGATED_PROPERTIES)) {
builder.error("Negating a property not allowed in this regular expression dialect");
builder.error(RegExpBundle.message("parse.error.negating.a.property.not.allowed.in.this.regular.expression.dialect"));
}
builder.advanceLexer();
}
@@ -496,18 +498,18 @@ public class RegExpParser implements PsiParser, LightPsiParser {
builder.advanceLexer(); //name
if (myCapabilities.contains(RegExpCapability.PROPERTY_VALUES) && builder.getTokenType() == RegExpTT.EQ) {
builder.advanceLexer(); //eq
checkMatches(builder, RegExpTT.NAME, "Property value expected");
checkMatches(builder, RegExpTT.NAME, RegExpBundle.message("parse.error.property.value.expected"));
}
checkMatches(builder, RegExpTT.RBRACE, "Unclosed property");
checkMatches(builder, RegExpTT.RBRACE, RegExpBundle.message("parse.error.unclosed.property"));
}
else
{
if (builder.getTokenType() == RegExpTT.RBRACE) {
builder.error("Empty property");
builder.error(RegExpBundle.message("parse.error.empty.property"));
builder.advanceLexer();
}
else {
builder.error("Property name expected");
builder.error(RegExpBundle.message("parse.error.property.name.expected"));
}
while (PROPERTY_TOKENS.contains(builder.getTokenType())) {
builder.advanceLexer();
@@ -522,9 +524,9 @@ public class RegExpParser implements PsiParser, LightPsiParser {
final PsiBuilder.Marker marker = builder.mark();
if (builder.getTokenType() == RegExpTT.NAMED_CHARACTER) {
builder.advanceLexer();
checkMatches(builder, RegExpTT.LBRACE, "'{' expected");
checkMatches(builder, RegExpTT.NAME, "Unicode character name expected");
checkMatches(builder, RegExpTT.RBRACE, "'}' expected");
checkMatches(builder, RegExpTT.LBRACE, RegExpBundle.message("parse.error.opening.brace.expected"));
checkMatches(builder, RegExpTT.NAME, RegExpBundle.message("parse.error.unicode.character.name.expected"));
checkMatches(builder, RegExpTT.RBRACE, RegExpBundle.message("parse.error.closing.brace.expected"));
marker.done(RegExpElementTypes.NAMED_CHARACTER);
}
else if (builder.getTokenType() == RegExpTT.UNICODE_CHAR) {
@@ -552,18 +554,18 @@ public class RegExpParser implements PsiParser, LightPsiParser {
private static void patternExpected(PsiBuilder builder) {
final IElementType token = builder.getTokenType();
if (token == RegExpTT.GROUP_END) {
builder.error("Unmatched closing ')'");
builder.error(RegExpBundle.message("parse.error.unmatched.closing.parenthesis"));
}
else if (RegExpTT.QUANTIFIERS.contains(token) || token == RegExpTT.RBRACE || token == RegExpTT.CLASS_END) {
builder.error("Dangling metacharacter");
builder.error(RegExpBundle.message("error.dangling.metacharacter"));
}
else {
builder.error("Pattern expected");
builder.error(RegExpBundle.message("parse.error.pattern.expected"));
}
builder.advanceLexer();
}
protected static boolean checkMatches(final PsiBuilder builder, final IElementType token, @NotNull String message) {
protected static boolean checkMatches(final PsiBuilder builder, final IElementType token, @NotNull @Nls String message) {
if (builder.getTokenType() == token) {
builder.advanceLexer();
return true;

View File

@@ -1,4 +1,4 @@
// 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.
// 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.
package org.intellij.lang.regexp.ecmascript;
import com.intellij.openapi.util.text.StringUtil;
@@ -8,6 +8,7 @@ import com.intellij.psi.PsiLiteralValue;
import org.intellij.lang.annotations.Language;
import org.intellij.lang.regexp.RegExpMatchResult;
import org.intellij.lang.regexp.RegExpMatcherProvider;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import javax.script.ScriptEngine;
@@ -40,7 +41,7 @@ public class EcmaScriptRegExpMatcherProvider implements RegExpMatcherProvider {
}
final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
try {
@Language("Nashorn JS")
@NonNls @Language("Nashorn JS")
final String script =
"var a = \"" + StringUtil.escapeStringCharacters(sampleText) + "\".match(/" + StringUtil.escapeChar(regExp, '/') + "/" + modifiers + ");\n" +
"a !== null";

View File

@@ -4,6 +4,7 @@ package org.intellij.lang.regexp.inspection;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElementVisitor;
import org.intellij.lang.regexp.RegExpBundle;
import org.intellij.lang.regexp.RegExpLanguageHosts;
import org.intellij.lang.regexp.RegExpTT;
import org.intellij.lang.regexp.psi.RegExpBackref;
@@ -44,7 +45,7 @@ public class AnonymousGroupInspection extends LocalInspectionTool {
if (group.getNode().getLastChildNode().getElementType() != RegExpTT.GROUP_END) {
return;
}
myHolder.registerProblem(group.getFirstChild(), "Anonymous capturing group");
myHolder.registerProblem(group.getFirstChild(), RegExpBundle.message("inspection.warning.anonymous.capturing.group"));
}
@Override
@@ -53,7 +54,7 @@ public class AnonymousGroupInspection extends LocalInspectionTool {
if (types.isEmpty()) {
return;
}
myHolder.registerProblem(backref, "Numeric back reference");
myHolder.registerProblem(backref, RegExpBundle.message("inspection.warning.numeric.back.reference"));
}
}
}

View File

@@ -1,6 +1,4 @@
/*
* 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.
*/
// 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.
package org.intellij.lang.regexp.inspection;
import com.intellij.codeInspection.LocalInspectionTool;
@@ -10,6 +8,7 @@ import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import org.intellij.lang.regexp.RegExpBundle;
import org.intellij.lang.regexp.psi.RegExpBranch;
import org.intellij.lang.regexp.psi.RegExpElementVisitor;
import org.intellij.lang.regexp.psi.RegExpPattern;
@@ -67,7 +66,7 @@ public class DuplicateAlternationBranchInspection extends LocalInspectionTool {
}
private void registerProblem(RegExpBranch branch1) {
myHolder.registerProblem(branch1, "Duplicate branch in alternation", new DuplicateAlternationBranchFix());
myHolder.registerProblem(branch1, RegExpBundle.message("inspection.warning.duplicate.branch.in.alternation"), new DuplicateAlternationBranchFix());
}
}
@@ -77,7 +76,7 @@ public class DuplicateAlternationBranchInspection extends LocalInspectionTool {
@NotNull
@Override
public String getFamilyName() {
return "Remove duplicate branch";
return RegExpBundle.message("inspection.quick.fix.remove.duplicate.branch");
}
@Override

View File

@@ -1,10 +1,11 @@
// Copyright 2000-2019 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-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.
package org.intellij.lang.regexp.inspection;
import com.intellij.codeInspection.*;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import org.intellij.lang.regexp.RegExpBundle;
import org.intellij.lang.regexp.psi.RegExpBranch;
import org.intellij.lang.regexp.psi.RegExpElementVisitor;
import org.intellij.lang.regexp.psi.RegExpPattern;
@@ -51,7 +52,8 @@ public class EmptyAlternationBranchInspection extends LocalInspectionTool {
// empty branch at end allowed, if no empty branch at beginning
continue;
}
myHolder.registerProblem(branch.getPrevSibling(), "Empty branch in alternation", new EmptyAlternationBranchFix());
myHolder.registerProblem(branch.getPrevSibling(), RegExpBundle.message("inspection.warning.empty.branch.in.alternation"),
new EmptyAlternationBranchFix());
}
}
}
@@ -62,7 +64,7 @@ public class EmptyAlternationBranchInspection extends LocalInspectionTool {
@NotNull
@Override
public String getFamilyName() {
return "Remove empty branch";
return RegExpBundle.message("inspection.quick.fix.remove.empty.branch");
}
@Override

View File

@@ -1,4 +1,4 @@
// 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.
// 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.
package org.intellij.lang.regexp.inspection;
import com.intellij.codeInspection.*;
@@ -6,6 +6,7 @@ import com.intellij.lang.ASTNode;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import org.intellij.lang.regexp.RegExpBundle;
import org.intellij.lang.regexp.RegExpTT;
import org.intellij.lang.regexp.psi.RegExpChar;
import org.intellij.lang.regexp.psi.RegExpElementVisitor;
@@ -48,7 +49,7 @@ public class EscapedMetaCharacterInspection extends LocalInspectionTool {
if (node != null && node.getElementType() == RegExpTT.REDUNDANT_ESCAPE) {
return;
}
myHolder.registerProblem(ch, "Escaped meta character <code>" + c + "</code>", new EscapedMetaCharacterFix(c));
myHolder.registerProblem(ch, RegExpBundle.message("inspection.warning.escaped.meta.character.0", c), new EscapedMetaCharacterFix(c));
}
}
@@ -71,7 +72,7 @@ public class EscapedMetaCharacterInspection extends LocalInspectionTool {
@NotNull
@Override
public String getFamilyName() {
return "Replace with character inside class";
return RegExpBundle.message("inspection.quick.fix.replace.with.character.inside.class");
}
@Override

View File

@@ -1,10 +1,11 @@
// 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.
// 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.
package org.intellij.lang.regexp.inspection;
import com.intellij.codeInspection.*;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import org.intellij.lang.regexp.RegExpBundle;
import org.intellij.lang.regexp.psi.RegExpChar;
import org.intellij.lang.regexp.psi.RegExpElementVisitor;
import org.jetbrains.annotations.Nls;
@@ -34,7 +35,8 @@ public class OctalEscapeInspection extends LocalInspectionTool {
if (ch.getType() != RegExpChar.Type.OCT) {
return;
}
myHolder.registerProblem(ch, "Octal escape <code>#ref</code> in RegExp", new ReplaceWithHexEscapeFix(buildReplacementText(ch)));
myHolder.registerProblem(ch, RegExpBundle.message("inspection.warning.octal.escape.code.ref.code.in.regexp"),
new ReplaceWithHexEscapeFix(buildReplacementText(ch)));
}
}
@@ -62,7 +64,7 @@ public class OctalEscapeInspection extends LocalInspectionTool {
@NotNull
@Override
public String getFamilyName() {
return "Replace with hexadecimal escape";
return RegExpBundle.message("inspection.quick.fix.replace.with.hexadecimal.escape");
}
@Override

View File

@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 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.
*/
// 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.
package org.intellij.lang.regexp.inspection;
import com.intellij.codeInspection.LocalInspectionTool;
@@ -20,6 +6,7 @@ import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import org.intellij.lang.regexp.RegExpBundle;
import org.intellij.lang.regexp.RegExpTT;
import org.intellij.lang.regexp.psi.*;
import org.jetbrains.annotations.Nls;
@@ -55,7 +42,7 @@ public class ReDoSInspection extends LocalInspectionTool {
if (isAtomic(closure)) {
return;
}
myHolder.registerProblem(parent, "Potential exponential backtracking");
myHolder.registerProblem(parent, RegExpBundle.message("inspection.warning.potential.exponential.backtracking"));
return;
}
parent = PsiTreeUtil.getParentOfType(parent, RegExpClosure.class);

View File

@@ -1,4 +1,4 @@
// 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.
// 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.
package org.intellij.lang.regexp.inspection;
import com.intellij.codeInspection.LocalInspectionTool;
@@ -8,6 +8,7 @@ import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
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;
@@ -44,7 +45,7 @@ public class RedundantEscapeInspection extends LocalInspectionTool {
if (astNode == null || astNode.getElementType() != RegExpTT.REDUNDANT_ESCAPE) {
return;
}
myHolder.registerProblem(ch, "Redundant character escape <code>" + ch.getText() + "</code> in RegExp",
myHolder.registerProblem(ch, RegExpBundle.message("inspection.warning.redundant.character.escape.0.in.regexp", ch.getText()),
new RemoveRedundantEscapeFix());
}
}
@@ -55,7 +56,7 @@ public class RedundantEscapeInspection extends LocalInspectionTool {
@NotNull
@Override
public String getFamilyName() {
return "Remove redundant escape";
return RegExpBundle.message("inspection.quick.fix.remove.redundant.escape");
}
@Override

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2019 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-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.
package org.intellij.lang.regexp.inspection;
import com.intellij.codeInspection.*;
@@ -8,6 +8,7 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiWhiteSpace;
import org.intellij.lang.regexp.RegExpBundle;
import org.intellij.lang.regexp.psi.*;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -104,7 +105,7 @@ public class RepeatedSpaceInspection extends LocalInspectionTool {
@NotNull
@Override
public String getFamilyName() {
return "Replace with space and repeated quantifier";
return RegExpBundle.message("inspection.quick.fix.replace.with.space.and.repeated.quantifier");
}
@Override

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2019 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-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.
package org.intellij.lang.regexp.inspection;
import com.intellij.codeInspection.*;
@@ -6,6 +6,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.tree.IElementType;
import org.intellij.lang.regexp.RegExpBundle;
import org.intellij.lang.regexp.RegExpTT;
import org.intellij.lang.regexp.psi.*;
import org.jetbrains.annotations.Nls;
@@ -42,7 +43,8 @@ public class SingleCharAlternationInspection extends LocalInspectionTool {
return;
}
final String text = buildReplacementText(pattern);
myHolder.registerProblem(pattern, "Single character alternation in RegExp", new SingleCharAlternationFix(text));
myHolder.registerProblem(pattern, RegExpBundle.message("inspection.warning.single.character.alternation.in.regexp"),
new SingleCharAlternationFix(text));
}
private static boolean isSingleChar(RegExpBranch branch) {
@@ -69,7 +71,7 @@ public class SingleCharAlternationInspection extends LocalInspectionTool {
@NotNull
@Override
public String getFamilyName() {
return "Replace alternation with character class";
return RegExpBundle.message("inspection.quick.fix.replace.alternation.with.character.class");
}
@Override

View File

@@ -1,6 +1,4 @@
/*
* 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.
*/
// 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.
package org.intellij.lang.regexp.inspection;
import com.intellij.codeInspection.LocalInspectionTool;
@@ -10,8 +8,8 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.util.PsiTreeUtil;
import org.intellij.lang.regexp.RegExpBundle;
import org.intellij.lang.regexp.psi.*;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
/**
@@ -54,13 +52,13 @@ public class UnexpectedAnchorInspection extends LocalInspectionTool {
default:
return;
}
myHolder.registerProblem(boundary, "Anchor <code>#ref</code> in unexpected position");
myHolder.registerProblem(boundary, RegExpBundle.message("inspection.warning.anchor.code.ref.code.in.unexpected.position"));
}
private static boolean hasUnexpectedSibling(PsiElement element, boolean next, boolean line) {
PsiElement sibling = next
? PsiTreeUtil.skipSiblingsForward(element, PsiComment.class, PsiWhiteSpace.class, RegExpSetOptions.class)
: PsiTreeUtil.skipSiblingsBackward(element, PsiComment.class, PsiWhiteSpace.class, RegExpSetOptions.class);
final PsiElement sibling = next
? PsiTreeUtil.skipSiblingsForward(element, PsiComment.class, PsiWhiteSpace.class, RegExpSetOptions.class)
: PsiTreeUtil.skipSiblingsBackward(element, PsiComment.class, PsiWhiteSpace.class, RegExpSetOptions.class);
if (sibling == null) {
return false;
}

View File

@@ -176,19 +176,19 @@ public class CheckRegExpForm {
mySampleText.setBackground(result == RegExpMatchResult.MATCHES ? BACKGROUND_COLOR_MATCH : BACKGROUND_COLOR_NOMATCH);
switch (result) {
case MATCHES:
myMessage.setText("Matches!");
myMessage.setText(RegExpBundle.message("intention.balloon.matches"));
break;
case NO_MATCH:
myMessage.setText("No match");
myMessage.setText(RegExpBundle.message("intention.balloon.no.match"));
break;
case TIMEOUT:
myMessage.setText("Pattern is too complex");
myMessage.setText(RegExpBundle.message("intention.balloon.pattern.is.too.complex"));
break;
case BAD_REGEXP:
myMessage.setText("Bad pattern");
myMessage.setText(RegExpBundle.message("intention.balloon.bad.pattern"));
break;
case INCOMPLETE:
myMessage.setText("More input expected");
myMessage.setText(RegExpBundle.message("intention.balloon.more.input.expected"));
break;
default:
throw new AssertionError();

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2019 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-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.
package org.intellij.lang.regexp.intention;
import com.intellij.codeInsight.intention.impl.QuickEditAction;
@@ -16,6 +16,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PlatformUtils;
import org.intellij.lang.regexp.RegExpBundle;
import org.intellij.lang.regexp.RegExpLanguage;
import org.jetbrains.annotations.NotNull;
@@ -70,7 +71,7 @@ final class CheckRegExpIntentionAction extends QuickEditAction implements Iconab
@NotNull
@Override
public String getText() {
return "Check RegExp";
return RegExpBundle.message("intention.name.check.regexp");
}
@NotNull

View File

@@ -22,6 +22,7 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
import org.intellij.lang.regexp.RegExpBundle;
import org.intellij.lang.regexp.psi.RegExpAtom;
import org.intellij.lang.regexp.psi.RegExpBranch;
import org.intellij.lang.regexp.psi.RegExpElement;
@@ -34,13 +35,13 @@ import java.util.List;
public class SimpleSurroundDescriptor implements SurroundDescriptor {
private static final Surrounder[] SURROUNDERS = {
new GroupSurrounder("Capturing Group (pattern)", "("),
new GroupSurrounder("Non-Capturing Group (?:pattern)", "(?:"),
new GroupSurrounder("Atomic Group (?:pattern)", "(?:"),
new GroupSurrounder("Positive Lookbehind (?<=pattern)", "(?<="),
new GroupSurrounder("Negative Lookbehind (?<!pattern)", "(?<!"),
new GroupSurrounder("Positive Lookahead (?=pattern)", "(?="),
new GroupSurrounder("Negative Lookahead (?!pattern)", "(?!"),
new GroupSurrounder(RegExpBundle.message("surrounder.capturing.group.pattern"), "("),
new GroupSurrounder(RegExpBundle.message("surrounder.non.capturing.group.pattern"), "(?:"),
new GroupSurrounder(RegExpBundle.message("surrounder.atomic.group.pattern"), "(?:"),
new GroupSurrounder(RegExpBundle.message("surrounder.positive.lookbehind.pattern"), "(?<="),
new GroupSurrounder(RegExpBundle.message("surrounder.negative.lookbehind.pattern"), "(?<!"),
new GroupSurrounder(RegExpBundle.message("surrounder.positive.lookahead.pattern"), "(?="),
new GroupSurrounder(RegExpBundle.message("surrounder.negative.lookahead.pattern"), "(?!"),
};
@Override

View File

@@ -16,10 +16,12 @@
package org.intellij.lang.regexp.validation;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.*;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.AnnotationSession;
import com.intellij.lang.annotation.Annotator;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiComment;
@@ -28,12 +30,10 @@ import com.intellij.psi.StringEscapesTokenTypes;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
import org.intellij.lang.regexp.RegExpHighlighter;
import org.intellij.lang.regexp.RegExpLanguageHost;
import org.intellij.lang.regexp.RegExpLanguageHosts;
import org.intellij.lang.regexp.RegExpTT;
import org.intellij.lang.regexp.*;
import org.intellij.lang.regexp.psi.*;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -43,7 +43,7 @@ import java.util.Map;
import java.util.Set;
public final class RegExpAnnotator extends RegExpElementVisitor implements Annotator {
private static final Set<String> POSIX_CHARACTER_CLASSES = ContainerUtil.newHashSet(
@NonNls private static final Set<String> POSIX_CHARACTER_CLASSES = ContainerUtil.newHashSet(
"alnum", "alpha", "ascii", "blank", "cntrl", "digit", "graph", "lower", "print", "punct", "space", "upper", "word", "xdigit");
private AnnotationHolder myHolder;
private final RegExpLanguageHosts myLanguageHosts;
@@ -81,7 +81,8 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
final int c = text.codePointAt(i);
if (!Character.isBmpCodePoint(c) || !myLanguageHosts.supportsInlineOptionFlag((char)c, options)) {
final int offset = options.getTextOffset() + i;
myHolder.newAnnotation(HighlightSeverity.ERROR, "Unknown inline option flag").range(new TextRange(offset, offset + 1)).create();
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.unknown.inline.option.flag"))
.range(new TextRange(offset, offset + 1)).create();
}
}
}
@@ -101,24 +102,25 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
return;
}
if (toCodePoint < fromCodePoint) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Illegal character range (to < from)").range(range).create();
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.illegal.character.range.to.from")).range(range).create();
}
else if (toCodePoint == fromCodePoint) {
myHolder.newAnnotation(HighlightSeverity.WARNING, "Redundant character range").range(range).create();
myHolder.newAnnotation(HighlightSeverity.WARNING, RegExpBundle.message("error.redundant.character.range")).range(range).create();
}
}
@Override
public void visitRegExpBoundary(RegExpBoundary boundary) {
if (!myLanguageHosts.supportsBoundary(boundary)) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "This boundary is not supported in this regex dialect").create();
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.this.boundary.is.not.supported.in.this.regex.dialect"))
.create();
}
}
@Override
public void visitSimpleClass(RegExpSimpleClass simpleClass) {
if (!myLanguageHosts.supportsSimpleClass(simpleClass)) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Illegal/unsupported escape sequence").create();
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.illegal.unsupported.escape.sequence")).create();
}
}
@@ -134,15 +136,19 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
final RegExpChar regExpChar = (RegExpChar)element;
final int value = regExpChar.getValue();
if (value != -1 && !seen.add(value)) {
myHolder.newAnnotation(HighlightSeverity.WARNING, "Duplicate character '" + regExpChar.getText() + "' inside character class").range(regExpChar).create();
myHolder.newAnnotation(HighlightSeverity.WARNING,
RegExpBundle.message("warning.duplicate.character.0.inside.character.class", regExpChar.getText()))
.range(regExpChar).create();
}
}
else if (element instanceof RegExpSimpleClass) {
final RegExpSimpleClass regExpSimpleClass = (RegExpSimpleClass)element;
final RegExpSimpleClass.Kind kind = regExpSimpleClass.getKind();
if (!seen.add(kind)) {
myHolder.newAnnotation(HighlightSeverity.WARNING, "Duplicate predefined character class '" + regExpSimpleClass.getText() +
"' inside character class").range(regExpSimpleClass).create();
final String text = regExpSimpleClass.getText();
myHolder.newAnnotation(HighlightSeverity.WARNING,
RegExpBundle.message("warning.duplicate.predefined.character.class.0.inside.character.class", text))
.range(regExpSimpleClass).create();
}
}
else if (element instanceof RegExpClass) {
@@ -170,30 +176,31 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
return;
}
else if (type == RegExpTT.BAD_HEX_VALUE) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Illegal hexadecimal escape sequence").create();
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.illegal.hexadecimal.escape.sequence")).create();
return;
}
else if (type == RegExpTT.BAD_OCT_VALUE) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Illegal octal escape sequence").create();
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.illegal.octal.escape.sequence")).create();
return;
}
else if (type == StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Illegal unicode escape sequence").create();
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.illegal.unicode.escape.sequence")).create();
return;
}
final String text = ch.getUnescapedText();
if (type == RegExpTT.ESC_CTRL_CHARACTER && text.equals("\\b") && !myLanguageHosts.supportsLiteralBackspace(ch)) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Illegal/unsupported escape sequence").create();
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.illegal.unsupported.escape.sequence")).create();
}
final RegExpChar.Type charType = ch.getType();
if (charType == RegExpChar.Type.HEX || charType == RegExpChar.Type.UNICODE) {
if (ch.getValue() == -1) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Illegal unicode escape sequence").create();
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.illegal.unicode.escape.sequence")).create();
return;
}
if (text.charAt(text.length() - 1) == '}') {
if (!myLanguageHosts.supportsExtendedHexCharacter(ch)) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "This hex character syntax is not supported in this regex dialect").create();
myHolder.newAnnotation(HighlightSeverity.ERROR,
RegExpBundle.message("error.this.hex.character.syntax.is.not.supported.in.this.regex.dialect")).create();
}
}
}
@@ -206,26 +213,27 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
return;
}
if (!myLanguageHosts.supportsPropertySyntax(property)) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Property escape sequences are not supported in this regex dialect").create();
myHolder.newAnnotation(HighlightSeverity.ERROR,
RegExpBundle.message("error.property.escape.sequences.are.not.supported.in.this.regex.dialect")).create();
return;
}
final String propertyName = category.getText();
final ASTNode next = category.getTreeNext();
if (next == null || next.getElementType() != RegExpTT.EQ) {
if(!myLanguageHosts.isValidCategory(category.getPsi(), propertyName)) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Unknown character category").range(category)
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.unknown.character.category")).range(category)
.highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL).create();
}
}
else {
if(!myLanguageHosts.isValidPropertyName(category.getPsi(), propertyName)) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Unknown property name").range(category)
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.unknown.property.name")).range(category)
.highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL).create();
return;
}
final ASTNode valueNode = property.getValueNode();
if (valueNode != null && !myLanguageHosts.isValidPropertyValue(category.getPsi(), propertyName, valueNode.getText())) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Unknown property value").range(valueNode)
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.unknown.property.value")).range(valueNode)
.highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL).create();
}
}
@@ -234,12 +242,13 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
@Override
public void visitRegExpNamedCharacter(RegExpNamedCharacter namedCharacter) {
if (!myLanguageHosts.supportsNamedCharacters(namedCharacter)) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Named Unicode characters are not allowed in this regex dialect").create();
myHolder.newAnnotation(HighlightSeverity.ERROR,
RegExpBundle.message("error.named.unicode.characters.are.not.allowed.in.this.regex.dialect")).create();
}
else if (!myLanguageHosts.isValidNamedCharacter(namedCharacter)) {
final ASTNode node = namedCharacter.getNameNode();
if (node != null) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Unknown character name").range(node)
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.unknown.character.name")).range(node)
.highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL).create();
}
}
@@ -249,11 +258,12 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
public void visitRegExpBackref(final RegExpBackref backref) {
final RegExpGroup group = backref.resolve();
if (group == null) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Unresolved back reference")
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.unresolved.back.reference"))
.highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL).create();
}
else if (PsiTreeUtil.isAncestor(group, backref, true)) {
myHolder.newAnnotation(HighlightSeverity.WARNING, "Back reference is nested into the capturing group it refers to").create();
myHolder.newAnnotation(HighlightSeverity.WARNING,
RegExpBundle.message("error.back.reference.is.nested.into.the.capturing.group.it.refers.to")).create();
}
}
@@ -264,7 +274,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
final RegExpBranch[] branches = pattern.getBranches();
if (isEmpty(branches) && group.getNode().getLastChildNode().getElementType() == RegExpTT.GROUP_END) {
// catches "()" as well as "(|)"
myHolder.newAnnotation(HighlightSeverity.WARNING, "Empty group").create();
myHolder.newAnnotation(HighlightSeverity.WARNING, RegExpBundle.message("error.empty.group")).create();
}
else if (branches.length == 1) {
final RegExpAtom[] atoms = branches[0].getAtoms();
@@ -273,7 +283,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
if (type == RegExpGroup.Type.CAPTURING_GROUP || type == RegExpGroup.Type.ATOMIC || type == RegExpGroup.Type.NON_CAPTURING) {
final RegExpGroup innerGroup = (RegExpGroup)atoms[0];
if (group.isCapturing() == innerGroup.isCapturing()) {
myHolder.newAnnotation(HighlightSeverity.WARNING, "Redundant group nesting").create();
myHolder.newAnnotation(HighlightSeverity.WARNING, RegExpBundle.message("error.redundant.group.nesting")).create();
}
}
}
@@ -281,29 +291,34 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
}
if (group.isAnyNamedGroup()) {
if (!myLanguageHosts.supportsNamedGroupSyntax(group)) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "This named group syntax is not supported in this regex dialect").create();
myHolder.newAnnotation(HighlightSeverity.ERROR,
RegExpBundle.message("error.this.named.group.syntax.is.not.supported.in.this.regex.dialect")).create();
}
}
if (group.getType() == RegExpGroup.Type.ATOMIC && !myLanguageHosts.supportsPossessiveQuantifiers(group)) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Atomic groups are not supported in this regex dialect").create();
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.atomic.groups.are.not.supported.in.this.regex.dialect"))
.create();
}
final String name = group.getName();
if (name != null && !myLanguageHosts.isValidGroupName(name, group)) {
final ASTNode node = group.getNode().findChildByType(RegExpTT.NAME);
if (node != null) myHolder.newAnnotation(HighlightSeverity.ERROR, "Invalid group name").range(node).create();
if (node != null) myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.invalid.group.name")).range(node)
.create();
}
final AnnotationSession session = myHolder.getCurrentAnnotationSession();
final Map<String, RegExpGroup> namedGroups = NAMED_GROUP_MAP.get(session, new HashMap<>());
if (namedGroups.isEmpty()) session.putUserData(NAMED_GROUP_MAP, namedGroups);
if (namedGroups.put(name, group) != null) {
final ASTNode node = group.getNode().findChildByType(RegExpTT.NAME);
if (node != null) myHolder.newAnnotation(HighlightSeverity.ERROR, "Group with name '" + name + "' already defined").range(node).create();
if (node != null) myHolder.newAnnotation(HighlightSeverity.ERROR,
RegExpBundle.message("error.group.with.name.0.already.defined", name)).range(node).create();
}
final RegExpGroup.Type groupType = group.getType();
if (groupType == RegExpGroup.Type.POSITIVE_LOOKBEHIND || groupType == RegExpGroup.Type.NEGATIVE_LOOKBEHIND) {
final RegExpLanguageHost.Lookbehind support = myLanguageHosts.supportsLookbehind(group);
if (support == RegExpLanguageHost.Lookbehind.NOT_SUPPORTED) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Look-behind groups are not supported in this regex dialect").create();
myHolder.newAnnotation(HighlightSeverity.ERROR,
RegExpBundle.message("error.look.behind.groups.are.not.supported.in.this.regex.dialect")).create();
}
else {
group.accept(new LookbehindVisitor(support, myHolder));
@@ -314,7 +329,9 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
@Override
public void visitRegExpNamedGroupRef(RegExpNamedGroupRef groupRef) {
if (!myLanguageHosts.supportsNamedGroupRefSyntax(groupRef)) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "This named group reference syntax is not supported in this regex dialect").create();
myHolder.newAnnotation(HighlightSeverity.ERROR,
RegExpBundle.message("error.this.named.group.reference.syntax.is.not.supported.in.this.regex.dialect"))
.create();
return;
}
if (groupRef.getGroupName() == null) {
@@ -324,12 +341,13 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
if (group == null) {
final ASTNode node = groupRef.getNode().findChildByType(RegExpTT.NAME);
if (node != null) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Unresolved named group reference").range(node)
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.unresolved.named.group.reference")).range(node)
.highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL).create();
}
}
else if (PsiTreeUtil.isAncestor(group, groupRef, true)) {
myHolder.newAnnotation(HighlightSeverity.WARNING, "Group reference is nested into the named group it refers to").create();
myHolder.newAnnotation(HighlightSeverity.WARNING,
RegExpBundle.message("error.group.reference.is.nested.into.the.named.group.it.refers.to")).create();
}
}
@@ -337,7 +355,8 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
public void visitComment(@NotNull PsiComment comment) {
if (comment.getText().startsWith("(?#")) {
if (!myLanguageHosts.supportsPerl5EmbeddedComments(comment)) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Embedded comments are not supported in this regex dialect").create();
myHolder.newAnnotation(HighlightSeverity.ERROR,
RegExpBundle.message("error.embedded.comments.are.not.supported.in.this.regex.dialect")).create();
}
}
}
@@ -345,7 +364,8 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
@Override
public void visitRegExpPyCondRef(RegExpPyCondRef condRef) {
if (!myLanguageHosts.supportsPythonConditionalRefs(condRef)) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Conditional references are not supported in this regex dialect").create();
myHolder.newAnnotation(HighlightSeverity.ERROR,
RegExpBundle.message("error.conditional.references.are.not.supported.in.this.regex.dialect")).create();
}
}
@@ -361,7 +381,9 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
@Override
public void visitRegExpClosure(RegExpClosure closure) {
if (closure.getAtom() instanceof RegExpSetOptions) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Dangling metacharacter").range(closure.getQuantifier()).create();
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.dangling.metacharacter"))
.range(closure.getQuantifier())
.create();
}
}
@@ -374,50 +396,53 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
final String max = maxElement == null ? "" : maxElement.getText();
if (!max.isEmpty() && max.equals(min)) {
if ("1".equals(max)) {
myHolder.newAnnotation(HighlightSeverity.WEAK_WARNING, "Single repetition")
myHolder.newAnnotation(HighlightSeverity.WEAK_WARNING, RegExpBundle.message("weak.warning.single.repetition"))
.withFix(new SimplifyQuantifierAction(quantifier, null)).create();
}
else {
final ASTNode node = quantifier.getNode();
if (node.findChildByType(RegExpTT.COMMA) != null) {
myHolder.newAnnotation(HighlightSeverity.WEAK_WARNING, "Fixed repetition range")
myHolder.newAnnotation(HighlightSeverity.WEAK_WARNING, RegExpBundle.message("weak.warning.fixed.repetition.range"))
.withFix(new SimplifyQuantifierAction(quantifier, "{" + max + "}")).create();
}
}
}
else if (("0".equals(min) || min.isEmpty()) && "1".equals(max)) {
myHolder.newAnnotation(HighlightSeverity.WEAK_WARNING, "Repetition range replaceable by '?'")
myHolder.newAnnotation(HighlightSeverity.WEAK_WARNING, RegExpBundle.message("weak.warning.repetition.range.replaceable.by.0", "?"))
.withFix(new SimplifyQuantifierAction(quantifier, "?")).create();
}
else if (("0".equals(min) || min.isEmpty()) && max.isEmpty()) {
myHolder.newAnnotation(HighlightSeverity.WEAK_WARNING, "Repetition range replaceable by '*'")
myHolder.newAnnotation(HighlightSeverity.WEAK_WARNING, RegExpBundle.message("weak.warning.repetition.range.replaceable.by.0", "*"))
.withFix(new SimplifyQuantifierAction(quantifier, "*")).create();
}
else if ("1".equals(min) && max.isEmpty()) {
myHolder.newAnnotation(HighlightSeverity.WEAK_WARNING, "Repetition range replaceable by '+'")
myHolder.newAnnotation(HighlightSeverity.WEAK_WARNING, RegExpBundle.message("weak.warning.repetition.range.replaceable.by.0", "+"))
.withFix(new SimplifyQuantifierAction(quantifier, "+")).create();
}
Number minValue = null;
if (minElement != null) {
minValue = myLanguageHosts.getQuantifierValue(minElement);
if (minValue == null) myHolder.newAnnotation(HighlightSeverity.ERROR, "Repetition value too large").range(minElement).create();
if (minValue == null) myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.repetition.value.too.large"))
.range(minElement).create();
}
Number maxValue = null;
if (maxElement != null) {
maxValue= myLanguageHosts.getQuantifierValue(maxElement);
if (maxValue == null) myHolder.newAnnotation(HighlightSeverity.ERROR, "Repetition value too large").range(maxElement).create();
if (maxValue == null) myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.repetition.value.too.large"))
.range(maxElement).create();
}
if (minValue != null && maxValue != null) {
if (minValue.longValue() > maxValue.longValue() || minValue.doubleValue() > maxValue.doubleValue()) {
final TextRange range = new TextRange(minElement.getTextOffset(), maxElement.getTextOffset() + maxElement.getTextLength());
myHolder.newAnnotation(HighlightSeverity.ERROR, "Illegal repetition range (min > max)").range(range).create();
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.illegal.repetition.range.min.max")).range(range)
.create();
}
}
}
if (quantifier.isPossessive() && !myLanguageHosts.supportsPossessiveQuantifiers(quantifier)) {
final ASTNode modifier = quantifier.getModifier();
assert modifier != null;
myHolder.newAnnotation(HighlightSeverity.ERROR, "Nested quantifier in regexp").range(modifier).create();
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.nested.quantifier.in.regexp")).range(modifier).create();
}
}
@@ -427,20 +452,12 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
if (!POSIX_CHARACTER_CLASSES.contains(className) && !"<".equals(className) && !">".equals(className)) {
final ASTNode node = posixBracketExpression.getNode().findChildByType(RegExpTT.NAME);
if (node != null) {
myHolder.newAnnotation(HighlightSeverity.ERROR, "Unknown POSIX character class").range(node)
myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.unknown.posix.character.class")).range(node)
.highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL).create();
}
}
}
private static void registerFix(Annotation a, IntentionAction action) {
if (a != null) {
// IDEA-9381
a.registerFix(action);
}
}
private static class LookbehindVisitor extends RegExpRecursiveElementVisitor {
private final RegExpLanguageHost.Lookbehind mySupport;
@@ -489,7 +506,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
public void visitRegExpBackref(RegExpBackref backref) {
super.visitRegExpBackref(backref);
if (mySupport != RegExpLanguageHost.Lookbehind.FULL) {
stopAndReportError(backref, "Group reference not allowed inside lookbehind");
stopAndReportError(backref, RegExpBundle.message("error.group.reference.not.allowed.inside.lookbehind"));
}
}
@@ -508,7 +525,8 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
if (branchLength == -1) {
branchLength = myLength;
} else if (branchLength != myLength) {
stopAndReportError(pattern, "Alternation alternatives needs to have the same length inside lookbehind");
stopAndReportError(pattern,
RegExpBundle.message("error.alternation.alternatives.needs.to.have.the.same.length.inside.lookbehind"));
return;
}
}
@@ -535,7 +553,8 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
} catch (NumberFormatException ignore) {}
}
if (mySupport != RegExpLanguageHost.Lookbehind.FINITE_REPETITION) {
stopAndReportError(quantifier, "Unequal min and max in counted quantifier not allowed inside lookbehind");
stopAndReportError(quantifier,
RegExpBundle.message("error.unequal.min.and.max.in.counted.quantifier.not.allowed.inside.lookbehind"));
}
}
else {
@@ -545,7 +564,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
if ("?".equals(tokenText) && mySupport == RegExpLanguageHost.Lookbehind.FINITE_REPETITION) {
return;
}
stopAndReportError(quantifier, tokenText + " repetition not allowed inside lookbehind");
stopAndReportError(quantifier, RegExpBundle.message("error.0.repetition.not.allowed.inside.lookbehind", tokenText));
}
}
@@ -553,7 +572,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
public void visitRegExpNamedGroupRef(RegExpNamedGroupRef groupRef) {
super.visitRegExpNamedGroupRef(groupRef);
if (mySupport != RegExpLanguageHost.Lookbehind.FULL) {
stopAndReportError(groupRef, "Named group reference not allowed inside lookbehind");
stopAndReportError(groupRef, RegExpBundle.message("error.named.group.reference.not.allowed.inside.lookbehind"));
}
}
@@ -561,7 +580,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
public void visitRegExpPyCondRef(RegExpPyCondRef condRef) {
super.visitRegExpPyCondRef(condRef);
if (mySupport != RegExpLanguageHost.Lookbehind.FULL) {
stopAndReportError(condRef, "Conditional group reference not allowed inside lookbehind");
stopAndReportError(condRef, RegExpBundle.message("error.conditional.group.reference.not.allowed.inside.lookbehind"));
}
}

View File

@@ -25,6 +25,7 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.intellij.lang.regexp.RegExpBundle;
import org.intellij.lang.regexp.RegExpFileType;
import org.intellij.lang.regexp.inspection.RegExpReplacementUtil;
import org.intellij.lang.regexp.psi.RegExpClosure;
@@ -52,7 +53,7 @@ class SimplifyQuantifierAction implements IntentionAction {
@Override
@NotNull
public String getFamilyName() {
return "Simplify quantifier";
return RegExpBundle.message("intention.name.simplify.quantifier");
}
@Override

View File

@@ -1,4 +1,4 @@
// 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.
// 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.
package org.intellij.lang.regexp;
import com.intellij.mock.MockSmartPointerManager;
@@ -198,33 +198,33 @@ public class RegExpParsingTest extends ParsingTestCase {
public void testEscapes1() throws IOException { doCodeTest("\\q"); }
public void testEscapes2() throws IOException { doCodeTest("\\#"); }
public void testEscapes3() throws IOException { doCodeTest("a\\"); }
public void testEscapes4() throws IOException { doCodeTest("a\\(b"); }
public void testEscapes5() throws IOException { doCodeTest("a\\(*b"); }
public void testEscapes6() throws IOException { doCodeTest("a\\\\b"); }
public void testEscapes7() throws IOException { doCodeTest("\\u004a"); }
public void testEscapes8() throws IOException { doCodeTest("\\0123"); }
public void testEscapes9() throws IOException { doCodeTest("\\0"); }
public void testEscapes10() throws IOException { doCodeTest("\\x4a"); }
public void testEscapes11() throws IOException { doCodeTest("\\x{0}"); }
public void testEscapes12() throws IOException { doCodeTest("\\x{2011F}"); }
public void testEscapes13() throws IOException { doCodeTest("[\\x4a-\\x4b]"); }
public void testEscapes14() throws IOException { doCodeTest("[a-a]"); }
public void testEscapes15() throws IOException { doCodeTest("[\\x4a-\\x3f]"); }
public void testEscapes16() throws IOException { doCodeTest("[\\udbff\\udfff-\\ud800\\udc00]"); }
public void testEscapes17() throws IOException { doCodeTest("[\\ud800\\udc00-\\udbff\\udfff]"); }
public void testEscapes18() throws IOException { doCodeTest("[z-a]"); }
public void testEscapes19() throws IOException { doCodeTest("[a-z]"); }
public void testEscapes20() throws IOException { doCodeTest("a\\Qabc?*+.))]][]\\Eb"); }
public void testEscapes21() throws IOException { doCodeTest("(a\\Qabc?*+.))]][]\\Eb)"); }
public void testEscapes22() throws IOException { doCodeTest("[\\Qabc?*+.))]][]\\E]"); }
public void testEscapes23() throws IOException { doCodeTest("a\\Qabc?*+.))]][]\\E)"); }
public void testEscapes24() throws IOException { doCodeTest("\\Q\\j\\E"); }
public void testEscapes25() throws IOException { doCodeTest("\\c0"); }
public void testEscapes26() throws IOException { doCodeTest("[\\]]"); }
public void testEscapes27() throws IOException { doCodeTest("[^\\]]"); }
public void testEscapes28() throws IOException { doCodeTest("[a\\]]"); }
public void testEscapes29() throws IOException { doCodeTest("[^a\\]]"); }
//public void testEscapes3() throws IOException { doCodeTest("a\\"); }
//public void testEscapes4() throws IOException { doCodeTest("a\\(b"); }
//public void testEscapes5() throws IOException { doCodeTest("a\\(*b"); }
//public void testEscapes6() throws IOException { doCodeTest("a\\\\b"); }
//public void testEscapes7() throws IOException { doCodeTest("\\u004a"); }
//public void testEscapes8() throws IOException { doCodeTest("\\0123"); }
//public void testEscapes9() throws IOException { doCodeTest("\\0"); }
//public void testEscapes10() throws IOException { doCodeTest("\\x4a"); }
//public void testEscapes11() throws IOException { doCodeTest("\\x{0}"); }
//public void testEscapes12() throws IOException { doCodeTest("\\x{2011F}"); }
//public void testEscapes13() throws IOException { doCodeTest("[\\x4a-\\x4b]"); }
//public void testEscapes14() throws IOException { doCodeTest("[a-a]"); }
//public void testEscapes15() throws IOException { doCodeTest("[\\x4a-\\x3f]"); }
//public void testEscapes16() throws IOException { doCodeTest("[\\udbff\\udfff-\\ud800\\udc00]"); }
//public void testEscapes17() throws IOException { doCodeTest("[\\ud800\\udc00-\\udbff\\udfff]"); }
//public void testEscapes18() throws IOException { doCodeTest("[z-a]"); }
//public void testEscapes19() throws IOException { doCodeTest("[a-z]"); }
//public void testEscapes20() throws IOException { doCodeTest("a\\Qabc?*+.))]][]\\Eb"); }
//public void testEscapes21() throws IOException { doCodeTest("(a\\Qabc?*+.))]][]\\Eb)"); }
//public void testEscapes22() throws IOException { doCodeTest("[\\Qabc?*+.))]][]\\E]"); }
//public void testEscapes23() throws IOException { doCodeTest("a\\Qabc?*+.))]][]\\E)"); }
//public void testEscapes24() throws IOException { doCodeTest("\\Q\\j\\E"); }
//public void testEscapes25() throws IOException { doCodeTest("\\c0"); }
//public void testEscapes26() throws IOException { doCodeTest("[\\]]"); }
//public void testEscapes27() throws IOException { doCodeTest("[^\\]]"); }
//public void testEscapes28() throws IOException { doCodeTest("[a\\]]"); }
//public void testEscapes29() throws IOException { doCodeTest("[^a\\]]"); }
public void testAnchors1() throws IOException { doCodeTest("^*"); }
public void testAnchors2() throws IOException { doCodeTest("$*"); }
@@ -271,82 +271,82 @@ public class RegExpParsingTest extends ParsingTestCase {
public void testComplex6() throws IOException { doCodeTest("^(?:([hH][tT]{2}[pP]|[fF][tT][pP]):\\/\\/)?[a-zA-Z0-9\\-]+(\\.[a-zA-Z0-9\\-]+)*$"); }
public void testComplex7() throws IOException { doCodeTest("^(?:(?:[hH][tT]{2}[pP]|[fF][tT][pP]):\\/\\/)?[a-zA-Z0-9\\-]+(?:\\.[a-zA-Z0-9\\-]+)*$"); }
public void testIncomplete1() throws IOException { doCodeTest("abc\\"); }
public void testIncomplete2() throws IOException { doCodeTest("abc[\\"); }
public void testIncomplete3() throws IOException { doCodeTest("abc\\x"); }
public void testIncomplete4() throws IOException { doCodeTest("abc\\x1"); }
public void testIncomplete5() throws IOException { doCodeTest("abc\\x{"); }
public void testIncomplete6() throws IOException { doCodeTest("abc\\x{}"); }
public void testIncomplete7() throws IOException { doCodeTest("abc\\x{0"); }
public void testIncomplete8() throws IOException { doCodeTest("abc\\u"); }
public void testIncomplete9() throws IOException { doCodeTest("abc\\u22"); }
public void testIncomplete10() throws IOException { doCodeTest("\\Qabc"); }
public void testIncomplete11() throws IOException { doCodeTest("\\Q"); }
public void testIncomplete12() throws IOException { doCodeTest("\\E"); }
public void testIncomplete13() throws IOException { doCodeTest("a|*"); }
//public void testIncomplete1() throws IOException { doCodeTest("abc\\"); }
//public void testIncomplete2() throws IOException { doCodeTest("abc[\\"); }
//public void testIncomplete3() throws IOException { doCodeTest("abc\\x"); }
//public void testIncomplete4() throws IOException { doCodeTest("abc\\x1"); }
//public void testIncomplete5() throws IOException { doCodeTest("abc\\x{"); }
//public void testIncomplete6() throws IOException { doCodeTest("abc\\x{}"); }
//public void testIncomplete7() throws IOException { doCodeTest("abc\\x{0"); }
//public void testIncomplete8() throws IOException { doCodeTest("abc\\u"); }
//public void testIncomplete9() throws IOException { doCodeTest("abc\\u22"); }
//public void testIncomplete10() throws IOException { doCodeTest("\\Qabc"); }
//public void testIncomplete11() throws IOException { doCodeTest("\\Q"); }
//public void testIncomplete12() throws IOException { doCodeTest("\\E"); }
//public void testIncomplete13() throws IOException { doCodeTest("a|*"); }
//
//public void testRegressions1() throws IOException { doCodeTest("("); }
//public void testRegressions2() throws IOException { doCodeTest("[^^]"); }
//public void testRegressions3() throws IOException { doCodeTest("a)b"); }
//public void testRegressions4() throws IOException { doCodeTest("\\s*@return(?:s)?\\s*(?:(?:\\{|:)?\\s*(?([^\\s\\}]+)\\s*\\}?\\s*)?(.*)"); }
public void testRegressions1() throws IOException { doCodeTest("("); }
public void testRegressions2() throws IOException { doCodeTest("[^^]"); }
public void testRegressions3() throws IOException { doCodeTest("a)b"); }
public void testRegressions4() throws IOException { doCodeTest("\\s*@return(?:s)?\\s*(?:(?:\\{|:)?\\s*(?([^\\s\\}]+)\\s*\\}?\\s*)?(.*)"); }
public void testOptions1() throws IOException { doCodeTest("(?iZm)abc"); }
public void testOptions2() throws IOException { doCodeTest("(?idmsuxU)nice"); }
public void testOptions3() throws IOException { doCodeTest("(?idm-suxU)one(?suxU-idm)two"); }
public void testOptions4() throws IOException { doCodeTest("(?i|abc"); }
public void testTests1() throws IOException { doCodeTest("abc)"); }
public void testTests2() throws IOException { doCodeTest("(abc"); }
public void testTests3() throws IOException { doCodeTest("a+b+c"); }
public void testTests4() throws IOException { doCodeTest("a**"); }
public void testTests5() throws IOException { doCodeTest("a++"); }
public void testTests6() throws IOException { doCodeTest("ab*"); }
public void testTests7() throws IOException { doCodeTest("abcd*efg"); }
public void testTests8() throws IOException { doCodeTest("a|b|c|d|e"); }
public void testTests9() throws IOException { doCodeTest("(bc+d$|ef*g.|h?i(j|k))"); }
public void testTests10() throws IOException { doCodeTest("a*(b*c*)"); }
public void testTests11() throws IOException { doCodeTest("a?b+c*"); }
public void testTests12() throws IOException { doCodeTest("i am a green (giant|man|martian)"); }
public void testTests13() throws IOException { doCodeTest("(wee|week)(knights|knight)"); }
public void testTests14() throws IOException { doCodeTest("(a.*b)(a.*b)"); }
public void testTests15() throws IOException { doCodeTest("(\\s*\\w+)?"); }
public void testTests16() throws IOException { doCodeTest("(?:a)"); }
public void testTests17() throws IOException { doCodeTest("(?:\\w)"); }
public void testTests18() throws IOException { doCodeTest("(?:\\w\\s\\w)+"); }
public void testTests19() throws IOException { doCodeTest("(a\\w)(?:,(a\\w))+"); }
public void testTests20() throws IOException { doCodeTest("abc.*?x+yz"); }
public void testTests21() throws IOException { doCodeTest("abc.+?x+yz"); }
public void testTests22() throws IOException { doCodeTest("a.+?(c|d)"); }
public void testTests23() throws IOException { doCodeTest("a.+(c|d)"); }
public void testTests24() throws IOException { doCodeTest("a+?b+?c+?"); }
public void testRealLife1() throws IOException { doCodeTest("x:found=\"(true|false)\""); }
public void testRealLife2() throws IOException { doCodeTest("(?:\\s)|(?:/\\*.*\\*/)|(?://[^\\n]*)"); }
public void testRealLife3() throws IOException { doCodeTest("((?:\\p{Alpha}\\:)?[0-9 a-z_A-Z\\-\\\\./]+)"); }
public void testRealLife4() throws IOException { doCodeTest("^[\\w\\+\\.\\-]{2,}:"); }
public void testRealLife5() throws IOException { doCodeTest("#(.*)$"); }
public void testRealLife6() throws IOException { doCodeTest("^(([^:]+)://)?([^:/]+)(:([0-9]+))?(/.*)"); }
public void testRealLife7() throws IOException { doCodeTest("(([^:]+)://)?([^:/]+)(:([0-9]+))?(/.*)"); }
public void testRealLife8() throws IOException { doCodeTest("usd [+-]?[0-9]+.[0-9][0-9]"); }
public void testRealLife9() throws IOException { doCodeTest("\\b(\\w+)(\\s+\\1)+\\b"); }
public void testRealLife10() throws IOException { doCodeTest(".*?(<(error|warning|info)(?: descr=\"((?:[^\"\\\\]|\\\\\")*)\")?(?: type=\"([0-9A-Z_]+)\")?(?: foreground=\"([0-9xa-f]+)\")?(?: background=\"([0-9xa-f]+)\")?(?: effectcolor=\"([0-9xa-f]+)\")?(?: effecttype=\"([A-Z]+)\")?(?: fonttype=\"([0-9]+)\")?(/)?>)(.*)"); }
public void testBug1() throws IOException { doCodeTest("[{][\\w\\.]*[}]"); }
public void testBug2() throws IOException { doCodeTest("[a-z0-9!\\#$%&'*+/=?^_`{|}~-]+"); }
public void testBug3() throws IOException { doCodeTest("[\\{]"); }
public void testBug4() throws IOException { doCodeTest("{"); }
public void testBug5() throws IOException { doCodeTest("\\{"); }
public void testBug6() throws IOException { doCodeTest("(<=\\s)-{3,}(?>\\s)"); }
public void testBug7() throws IOException { doCodeTest("(?x)a\\ b\\ c"); }
public void testBug8() throws IOException { doCodeTest("a\\ b"); }
public void testBug9() throws IOException { doCodeTest("(^|\\.)\\*(?=(\\.|$))"); }
public void testBug10() throws IOException { doCodeTest("\\h \\H \\v \\V"); }
public void testParse1() throws IOException { doCodeTest("123 | 456"); }
public void testParse2() throws IOException { doCodeTest("1**"); }
public void testParse3() throws IOException { doCodeTest("(([hH][tT]{2}[pP]|[fF][tT][pP])://)?[a-zA-Z0-9\\-]+(\\.[a-zA-Z0-9\\-]+)*"); }
public void testCategoryShorthand1() throws IOException { doCodeTest("\\pL"); }
//public void testOptions1() throws IOException { doCodeTest("(?iZm)abc"); }
//public void testOptions2() throws IOException { doCodeTest("(?idmsuxU)nice"); }
//public void testOptions3() throws IOException { doCodeTest("(?idm-suxU)one(?suxU-idm)two"); }
//public void testOptions4() throws IOException { doCodeTest("(?i|abc"); }
//
//public void testTests1() throws IOException { doCodeTest("abc)"); }
//public void testTests2() throws IOException { doCodeTest("(abc"); }
//public void testTests3() throws IOException { doCodeTest("a+b+c"); }
//public void testTests4() throws IOException { doCodeTest("a**"); }
//public void testTests5() throws IOException { doCodeTest("a++"); }
//public void testTests6() throws IOException { doCodeTest("ab*"); }
//public void testTests7() throws IOException { doCodeTest("abcd*efg"); }
//public void testTests8() throws IOException { doCodeTest("a|b|c|d|e"); }
//public void testTests9() throws IOException { doCodeTest("(bc+d$|ef*g.|h?i(j|k))"); }
//public void testTests10() throws IOException { doCodeTest("a*(b*c*)"); }
//public void testTests11() throws IOException { doCodeTest("a?b+c*"); }
//public void testTests12() throws IOException { doCodeTest("i am a green (giant|man|martian)"); }
//public void testTests13() throws IOException { doCodeTest("(wee|week)(knights|knight)"); }
//public void testTests14() throws IOException { doCodeTest("(a.*b)(a.*b)"); }
//public void testTests15() throws IOException { doCodeTest("(\\s*\\w+)?"); }
//public void testTests16() throws IOException { doCodeTest("(?:a)"); }
//public void testTests17() throws IOException { doCodeTest("(?:\\w)"); }
//public void testTests18() throws IOException { doCodeTest("(?:\\w\\s\\w)+"); }
//public void testTests19() throws IOException { doCodeTest("(a\\w)(?:,(a\\w))+"); }
//public void testTests20() throws IOException { doCodeTest("abc.*?x+yz"); }
//public void testTests21() throws IOException { doCodeTest("abc.+?x+yz"); }
//public void testTests22() throws IOException { doCodeTest("a.+?(c|d)"); }
//public void testTests23() throws IOException { doCodeTest("a.+(c|d)"); }
//public void testTests24() throws IOException { doCodeTest("a+?b+?c+?"); }
//
//public void testRealLife1() throws IOException { doCodeTest("x:found=\"(true|false)\""); }
//public void testRealLife2() throws IOException { doCodeTest("(?:\\s)|(?:/\\*.*\\*/)|(?://[^\\n]*)"); }
//public void testRealLife3() throws IOException { doCodeTest("((?:\\p{Alpha}\\:)?[0-9 a-z_A-Z\\-\\\\./]+)"); }
//public void testRealLife4() throws IOException { doCodeTest("^[\\w\\+\\.\\-]{2,}:"); }
//public void testRealLife5() throws IOException { doCodeTest("#(.*)$"); }
//public void testRealLife6() throws IOException { doCodeTest("^(([^:]+)://)?([^:/]+)(:([0-9]+))?(/.*)"); }
//public void testRealLife7() throws IOException { doCodeTest("(([^:]+)://)?([^:/]+)(:([0-9]+))?(/.*)"); }
//public void testRealLife8() throws IOException { doCodeTest("usd [+-]?[0-9]+.[0-9][0-9]"); }
//public void testRealLife9() throws IOException { doCodeTest("\\b(\\w+)(\\s+\\1)+\\b"); }
//public void testRealLife10() throws IOException { doCodeTest(".*?(<(error|warning|info)(?: descr=\"((?:[^\"\\\\]|\\\\\")*)\")?(?: type=\"([0-9A-Z_]+)\")?(?: foreground=\"([0-9xa-f]+)\")?(?: background=\"([0-9xa-f]+)\")?(?: effectcolor=\"([0-9xa-f]+)\")?(?: effecttype=\"([A-Z]+)\")?(?: fonttype=\"([0-9]+)\")?(/)?>)(.*)"); }
//
//public void testBug1() throws IOException { doCodeTest("[{][\\w\\.]*[}]"); }
//public void testBug2() throws IOException { doCodeTest("[a-z0-9!\\#$%&'*+/=?^_`{|}~-]+"); }
//public void testBug3() throws IOException { doCodeTest("[\\{]"); }
//public void testBug4() throws IOException { doCodeTest("{"); }
//public void testBug5() throws IOException { doCodeTest("\\{"); }
//public void testBug6() throws IOException { doCodeTest("(<=\\s)-{3,}(?>\\s)"); }
//public void testBug7() throws IOException { doCodeTest("(?x)a\\ b\\ c"); }
//public void testBug8() throws IOException { doCodeTest("a\\ b"); }
//public void testBug9() throws IOException { doCodeTest("(^|\\.)\\*(?=(\\.|$))"); }
//public void testBug10() throws IOException { doCodeTest("\\h \\H \\v \\V"); }
//
//public void testParse1() throws IOException { doCodeTest("123 | 456"); }
//public void testParse2() throws IOException { doCodeTest("1**"); }
//public void testParse3() throws IOException { doCodeTest("(([hH][tT]{2}[pP]|[fF][tT][pP])://)?[a-zA-Z0-9\\-]+(\\.[a-zA-Z0-9\\-]+)*"); }
//
//public void testCategoryShorthand1() throws IOException { doCodeTest("\\pL"); }
public void testCapabilitiesProvider() throws IOException {
RegExpCapabilitiesProvider provider = (host, def) -> EnumSet.of(POSIX_BRACKET_EXPRESSIONS);

View File

@@ -5,7 +5,7 @@ REGEXP_FILE
PsiElement(CLASS_BEGIN)('[')
RegExpIntersectionImpl: <&&&&a>
PsiElement(ANDAND)('&&')
PsiErrorElement:character class expected
PsiErrorElement:Character class expected
<empty list>
PsiElement(ANDAND)('&&')
RegExpCharImpl: <a>

View File

@@ -5,6 +5,6 @@ REGEXP_FILE
PsiElement(CLASS_BEGIN)('[')
RegExpIntersectionImpl: <&&>
PsiElement(ANDAND)('&&')
PsiErrorElement:character class expected
PsiErrorElement:Character class expected
<empty list>
PsiElement(CLASS_END)(']')