regexp: parser test coverage and remove dead code

This commit is contained in:
Bas Leijdekkers
2016-12-05 16:38:26 +01:00
parent df13b92ff4
commit 4b7013730e
9 changed files with 94 additions and 28 deletions
@@ -30,10 +30,6 @@ public class RegExpParser implements PsiParser {
private static final TokenSet PROPERTY_TOKENS = TokenSet.create(RegExpTT.NUMBER, RegExpTT.COMMA, RegExpTT.NAME, RegExpTT.RBRACE);
private final EnumSet<RegExpCapability> myCapabilities;
public RegExpParser() {
myCapabilities = EnumSet.noneOf(RegExpCapability.class);
}
public RegExpParser(EnumSet<RegExpCapability> capabilities) {
myCapabilities = capabilities;
}
@@ -82,7 +78,6 @@ public class RegExpParser implements PsiParser {
/**
* BRANCH ::= ATOM BRANCH | ""
*/
@SuppressWarnings({"StatementWithEmptyBody"})
private boolean parseBranch(PsiBuilder builder) {
final PsiBuilder.Marker marker = builder.mark();
@@ -97,7 +92,8 @@ public class RegExpParser implements PsiParser {
return false;
}
while (parseAtom(builder)) ;
//noinspection StatementWithEmptyBody
while (parseAtom(builder)) {}
marker.done(RegExpElementTypes.BRANCH);
return true;
@@ -141,10 +137,6 @@ public class RegExpParser implements PsiParser {
if (minOmitted) {
builder.advanceLexer();
}
else if (builder.getTokenType() != RegExpTT.NUMBER && myCapabilities.contains(RegExpCapability.DANGLING_METACHARACTERS)) {
marker.done(RegExpTT.CHARACTER);
return true;
}
else {
checkMatches(builder, RegExpTT.NUMBER, "Number expected");
}
@@ -214,37 +206,26 @@ public class RegExpParser implements PsiParser {
if (builder.getTokenType() == RegExpTT.CARET) {
builder.advanceLexer();
}
// DEFLIST
if (parseClassIntersection(builder)) {
while (RegExpTT.CHARACTERS.contains(builder.getTokenType()) ||
builder.getTokenType() == RegExpTT.CHAR_CLASS ||
builder.getTokenType() == RegExpTT.CLASS_BEGIN ||
builder.getTokenType() == RegExpTT.PROPERTY ||
builder.getTokenType() == RegExpTT.BRACKET_EXPRESSION_BEGIN) {
parseClassIntersection(builder);
}
}
parseClassIntersection(builder);
checkMatches(builder, RegExpTT.CLASS_END, "Unclosed character class");
marker.done(RegExpElementTypes.CLASS);
return marker;
}
private boolean parseClassIntersection(PsiBuilder builder) {
private void parseClassIntersection(PsiBuilder builder) {
final PsiBuilder.Marker marker = builder.mark();
parseClassdef(builder);
if (RegExpTT.ANDAND != builder.getTokenType()) {
marker.drop();
return true;
return;
}
while (RegExpTT.ANDAND == builder.getTokenType()) {
builder.advanceLexer();
parseClassdef(builder);
}
marker.done(RegExpElementTypes.INTERSECTION);
return true;
}
private boolean parseClassdef(PsiBuilder builder) {
@@ -463,10 +444,6 @@ public class RegExpParser implements PsiParser {
marker.drop();
return parseClass(builder);
}
else if (type == RegExpTT.LBRACE && myCapabilities.contains(RegExpCapability.DANGLING_METACHARACTERS)) {
builder.advanceLexer();
marker.done(RegExpElementTypes.CHAR);
}
else {
marker.drop();
return null;
@@ -49,6 +49,10 @@ public class RegExpParserDefinition implements ParserDefinition {
CAPABILITIES.add(capability);
Disposer.register(parentDisposable, () -> CAPABILITIES.remove(capability));
}
else {
CAPABILITIES.remove(capability);
Disposer.register(parentDisposable, () -> CAPABILITIES.add(capability));
}
}
@NotNull
@@ -188,6 +188,7 @@ public class RegExpParsingTest extends ParsingTestCase {
public void testGroups37() throws IOException { doCodeTest("(?P=name)"); }
public void testGroups38() throws IOException { doCodeTest("\\g'name'"); }
public void testGroups39() throws IOException { doCodeTest("(?(name)yes-pattern|no-pattern)"); }
public void testGroups40() throws IOException { doCodeTest("(?(name)yes-pattern|{"); }
public void testEscapes1() throws IOException { doCodeTest("\\q"); }
public void testEscapes2() throws IOException { doCodeTest("\\#"); }
@@ -243,6 +244,7 @@ public class RegExpParsingTest extends ParsingTestCase {
public void testNamedchars11() throws IOException { doCodeTest("[:^xdigit:]+"); }
public void testNamedchars12() throws IOException { doCodeTest("\\p{InArabic Extended-A}"); }
public void testNamedchars13() throws IOException { doCodeTest("\\N{Mahjong Tile Winter}"); }
public void testNamedchars14() throws IOException { doCodeTest("[\\N{Mahjong Tile Winter}]"); }
public void testBackrefs1() throws IOException { doCodeTest("(ac*)c*d[ac]*\\1"); }
public void testBackrefs2() throws IOException { doCodeTest("(.)=\\1"); }
@@ -336,14 +338,40 @@ public class RegExpParsingTest extends ParsingTestCase {
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 testPosixBracketExpression1() throws IOException {
RegExpParserDefinition.setTestCapability(RegExpCapability.POSIX_BRACKET_EXPRESSIONS, getTestRootDisposable());
doCodeTest("[[:alpha:]]");
}
public void testPosixBracketExpression2() throws IOException {
RegExpParserDefinition.setTestCapability(RegExpCapability.POSIX_BRACKET_EXPRESSIONS, getTestRootDisposable());
doCodeTest("[[:^alpha:]]");
}
public void testCategoryShorthand1() throws IOException {
doCodeTest("\\pL");
}
public void testCategoryShorthand2() throws IOException {
RegExpParserDefinition.setTestCapability(RegExpCapability.UNICODE_CATEGORY_SHORTHAND, getTestRootDisposable());
doCodeTest("\\pL");
}
public void testOmitNumberInQuantifier() throws IOException {
RegExpParserDefinition.setTestCapability(RegExpCapability.OMIT_NUMBERS_IN_QUANTIFIERS, getTestRootDisposable());
doCodeTest("a{,3}");
}
public void testDanglingMetaCharacter1() throws IOException {
RegExpParserDefinition.setTestCapability(RegExpCapability.DANGLING_METACHARACTERS, getTestRootDisposable());
doCodeTest("{");
}
public void testDanglingMetaCharacter2() throws IOException {
RegExpParserDefinition.setTestCapability(RegExpCapability.DANGLING_METACHARACTERS, getTestRootDisposable());
doCodeTest("a{a");
}
public void testDanglingMetaCharacters3() throws IOException {
RegExpParserDefinition.setTestCapability(RegExpCapability.DANGLING_METACHARACTERS, getTestRootDisposable());
doCodeTest("{{E1:\\s*(?P<ref>([^\\n]+\\+)?[0-9]+)( *\\|[^\\n]*)?}}");
@@ -0,0 +1,6 @@
REGEXP_FILE
RegExpPatternImpl: <\pL>
RegExpBranchImpl: <\pL>
RegExpPropertyImpl: <\pL>
PsiElement(PROPERTY)('\p')
PsiElement(CATEGORY_SHORT_HAND)('L')
@@ -0,0 +1,8 @@
REGEXP_FILE
RegExpPatternImpl: <\pL>
RegExpBranchImpl: <\pL>
RegExpPropertyImpl: <\pL>
PsiElement(PROPERTY)('\p')
PsiErrorElement:Category shorthand not allowed in this regular expression dialect
<empty list>
PsiElement(CATEGORY_SHORT_HAND)('L')
@@ -0,0 +1,11 @@
REGEXP_FILE
RegExpPatternImpl: <[\N{Mahjong Tile Winter}]>
RegExpBranchImpl: <[\N{Mahjong Tile Winter}]>
RegExpClassImpl: <[\N{Mahjong Tile Winter}]>
PsiElement(CLASS_BEGIN)('[')
RegExpNamedCharacterImpl: <\N{Mahjong Tile Winter}>
PsiElement(NAMED_CHARACTER)('\N')
PsiElement(LBRACE)('{')
PsiElement(NAME)('Mahjong Tile Winter')
PsiElement(RBRACE)('}')
PsiElement(CLASS_END)(']')
@@ -0,0 +1,11 @@
REGEXP_FILE
RegExpPatternImpl: <a{,3}>
RegExpBranchImpl: <a{,3}>
RegExpClosureImpl: <a{,3}>
RegExpCharImpl: <a>
PsiElement(CHARACTER)('a')
RegExpQuantifierImpl: <{,3}>
PsiElement(LBRACE)('{')
PsiElement(COMMA)(',')
PsiElement(NUMBER)('3')
PsiElement(RBRACE)('}')
@@ -0,0 +1,10 @@
REGEXP_FILE
RegExpPatternImpl: <[[:alpha:]]>
RegExpBranchImpl: <[[:alpha:]]>
RegExpClassImpl: <[[:alpha:]]>
PsiElement(CLASS_BEGIN)('[')
RegExpPosixBracketExpressionImpl: <[:alpha:]>
PsiElement(BRACKET_EXPRESSION_BEGIN)('[:')
PsiElement(NAME)('alpha')
PsiElement(BRACKET_EXPRESSION_END)(':]')
PsiElement(CLASS_END)(']')
@@ -0,0 +1,11 @@
REGEXP_FILE
RegExpPatternImpl: <[[:^alpha:]]>
RegExpBranchImpl: <[[:^alpha:]]>
RegExpClassImpl: <[[:^alpha:]]>
PsiElement(CLASS_BEGIN)('[')
RegExpPosixBracketExpressionImpl: <[:^alpha:]>
PsiElement(BRACKET_EXPRESSION_BEGIN)('[:')
PsiElement(CARET)('^')
PsiElement(NAME)('alpha')
PsiElement(BRACKET_EXPRESSION_END)(':]')
PsiElement(CLASS_END)(']')