regexes in reference expressions

This commit is contained in:
Maxim.Medvedev
2011-12-12 12:55:40 +04:00
parent d9be85aa38
commit dd477bf1ad
13 changed files with 164 additions and 87 deletions
@@ -115,11 +115,12 @@ public class ArgumentList implements GroovyElementTypes {
marker.done(ARGUMENT_LABEL);
return true;
}
else if (ParserUtils.lookAhead(builder, mIDENT, mCOLON) ||
TokenSets.KEYWORDS.contains(builder.getTokenType()) ||
mSTRING_LITERAL.equals(builder.getTokenType()) ||
mGSTRING_LITERAL.equals(builder.getTokenType()) ||
mREGEX_LITERAL.equals(builder.getTokenType())) {
final IElementType type = builder.getTokenType();
if (ParserUtils.lookAhead(builder, mIDENT, mCOLON) ||
TokenSets.KEYWORDS.contains(type) ||
mSTRING_LITERAL.equals(type) ||
mGSTRING_LITERAL.equals(type)) {
builder.advanceLexer();
if (mCOLON.equals(builder.getTokenType())) {
marker.done(ARGUMENT_LABEL);
@@ -130,12 +131,14 @@ public class ArgumentList implements GroovyElementTypes {
return false;
}
}
else if (mGSTRING_BEGIN.equals(builder.getTokenType()) ||
mREGEX_BEGIN.equals(builder.getTokenType()) ||
TokenSets.NUMBERS.contains(builder.getTokenType()) ||
mLBRACK.equals(builder.getTokenType()) ||
mLPAREN.equals(builder.getTokenType()) ||
mLCURLY.equals(builder.getTokenType())) {
if (mGSTRING_BEGIN.equals(type) ||
mREGEX_BEGIN.equals(type) ||
mDOLLAR_SLASH_REGEX_BEGIN.equals(type) ||
TokenSets.NUMBERS.contains(type) ||
mLBRACK.equals(type) ||
mLPAREN.equals(type) ||
mLCURLY.equals(type)) {
PrimaryExpression.parsePrimaryExpression(builder, parser);
if (mCOLON.equals(builder.getTokenType())) {
marker.done(ARGUMENT_LABEL);
@@ -146,11 +149,8 @@ public class ArgumentList implements GroovyElementTypes {
return false;
}
}
else {
marker.drop();
return false;
}
marker.drop();
return false;
}
}
@@ -26,6 +26,7 @@ import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.parser.GroovyParser;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.blocks.OpenOrClosableBlock;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.arguments.ArgumentList;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.primary.DollarSlashRegexConstructorExpression;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.primary.PrimaryExpression;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.primary.RegexConstructorExpression;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.primary.StringConstructorExpression;
@@ -227,17 +228,15 @@ public class PathExpression implements GroovyElementTypes {
}
final IElementType tokenType = builder.getTokenType();
if (mREGEX_LITERAL.equals(tokenType)) {
ParserUtils.eatElement(builder, REGEX);
return PATH_PROPERTY_REFERENCE;
}
if (mGSTRING_BEGIN.equals(tokenType)) {
StringConstructorExpression.parse(builder, parser);
return PATH_PROPERTY_REFERENCE;
}
if (mREGEX_BEGIN.equals(tokenType)) {
RegexConstructorExpression.parse(builder, parser);
return PATH_PROPERTY_REFERENCE;
return RegexConstructorExpression.parse(builder, parser) ? PATH_PROPERTY_REFERENCE : REFERENCE_EXPRESSION;
}
if (mDOLLAR_SLASH_REGEX_BEGIN.equals(tokenType)) {
return DollarSlashRegexConstructorExpression.parse(builder, parser) ? PATH_PROPERTY_REFERENCE : REFERENCE_EXPRESSION;
}
if (mLCURLY.equals(tokenType)) {
OpenOrClosableBlock.parseOpenBlock(builder, parser);
@@ -16,52 +16,40 @@
package org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.primary;
import com.intellij.lang.PsiBuilder;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.plugins.groovy.GroovyBundle;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyElementType;
import org.jetbrains.plugins.groovy.lang.parser.GroovyParser;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.blocks.OpenOrClosableBlock;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.arithmetic.PathExpression;
import org.jetbrains.plugins.groovy.lang.parser.parsing.util.ParserUtils;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mDOLLAR;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mDOLLAR_SLASH_REGEX_BEGIN;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mDOLLAR_SLASH_REGEX_CONTENT;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mDOLLAR_SLASH_REGEX_END;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mIDENT;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mLCURLY;
import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.*;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*;
import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.GSTRING_INJECTION;
import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.REGEX;
/**
* @author Max Medvedev
*/
public class DollarSlashRegexConstructorExpression {
public static GroovyElementType parse(PsiBuilder builder, GroovyParser parser) {
private static final Logger LOG = Logger.getInstance(DollarSlashRegexConstructorExpression.class);
PsiBuilder.Marker sMarker = builder.mark();
if (ParserUtils.getToken(builder, mDOLLAR_SLASH_REGEX_BEGIN)) {
public static boolean parse(PsiBuilder builder, GroovyParser parser) {
PsiBuilder.Marker marker = builder.mark();
final boolean result = ParserUtils.getToken(builder, mDOLLAR_SLASH_REGEX_BEGIN);
LOG.assertTrue(result);
boolean inj = false;
ParserUtils.getToken(builder, mDOLLAR_SLASH_REGEX_CONTENT);
while (parseInjection(builder, parser)) {
inj = true;
ParserUtils.getToken(builder, mDOLLAR_SLASH_REGEX_CONTENT);
if (!parseInjection(builder, parser)) {
if (!ParserUtils.getToken(builder, mDOLLAR_SLASH_REGEX_END)) {
builder.error(GroovyBundle.message("dollar.slash.end.expected"));
}
sMarker.done(REGEX);
return REGEX;
}
else {
while (ParserUtils.getToken(builder, mDOLLAR_SLASH_REGEX_CONTENT)) {
if (!parseInjection(builder, parser)) break;
}
if (!ParserUtils.getToken(builder, mDOLLAR_SLASH_REGEX_END)) {
builder.error(GroovyBundle.message("dollar.slash.end.expected"));
}
sMarker.done(REGEX);
return REGEX;
}
}
else {
sMarker.drop();
return WRONGWAY;
if (!ParserUtils.getToken(builder, mDOLLAR_SLASH_REGEX_END)) {
builder.error(GroovyBundle.message("dollar.slash.end.expected"));
}
marker.done(REGEX);
return inj;
}
/**
@@ -69,10 +69,12 @@ public class PrimaryExpression implements GroovyElementTypes {
return StringConstructorExpression.parse(builder, parser);
}
if (mREGEX_BEGIN == tokenType) {
return RegexConstructorExpression.parse(builder, parser);
RegexConstructorExpression.parse(builder, parser);
return REGEX;
}
if (mDOLLAR_SLASH_REGEX_BEGIN == tokenType) {
return DollarSlashRegexConstructorExpression.parse(builder, parser);
DollarSlashRegexConstructorExpression.parse(builder, parser);
return REGEX;
}
if (mLBRACK == tokenType) {
return ListOrMapConstructorExpression.parse(builder, parser);
@@ -83,10 +85,7 @@ public class PrimaryExpression implements GroovyElementTypes {
if (mLCURLY == tokenType) {
return OpenOrClosableBlock.parseClosableBlock(builder, parser);
}
if (tokenType == mSTRING_LITERAL ||
tokenType == mGSTRING_LITERAL ||
tokenType == mREGEX_LITERAL ||
tokenType == mDOLLAR_SLASH_REGEX_LITERAL) {
if (tokenType == mSTRING_LITERAL || tokenType == mGSTRING_LITERAL) {
return ParserUtils.eatElement(builder, literalsAsRefExprs ? REFERENCE_EXPRESSION : LITERAL);
}
if (TokenSets.CONSTANTS.contains(tokenType)) {
@@ -17,8 +17,8 @@
package org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.primary;
import com.intellij.lang.PsiBuilder;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.plugins.groovy.GroovyBundle;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyElementType;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.parser.GroovyParser;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.blocks.OpenOrClosableBlock;
@@ -29,34 +29,28 @@ import org.jetbrains.plugins.groovy.lang.parser.parsing.util.ParserUtils;
* @author ilyas
*/
public class RegexConstructorExpression implements GroovyElementTypes {
private static final Logger LOG = Logger.getInstance(RegexConstructorExpression.class);
public static GroovyElementType parse(PsiBuilder builder, GroovyParser parser) {
/**
* @return true if there are any injections
*/
public static boolean parse(PsiBuilder builder, GroovyParser parser) {
PsiBuilder.Marker marker = builder.mark();
final boolean result = ParserUtils.getToken(builder, mREGEX_BEGIN);
LOG.assertTrue(result);
PsiBuilder.Marker sMarker = builder.mark();
if (ParserUtils.getToken(builder, mREGEX_BEGIN)) {
boolean inj = false;
ParserUtils.getToken(builder, mREGEX_CONTENT);
while (parseInjection(builder, parser)) {
inj = true;
ParserUtils.getToken(builder, mREGEX_CONTENT);
if (!parseInjection(builder, parser)) {
if (!ParserUtils.getToken(builder, mREGEX_END)) {
builder.error(GroovyBundle.message("regex.end.expected"));
}
sMarker.done(REGEX);
return REGEX;
}
else {
while (ParserUtils.getToken(builder, mREGEX_CONTENT)) {
if (!parseInjection(builder, parser)) break;
}
if (!ParserUtils.getToken(builder, mREGEX_END)) {
builder.error(GroovyBundle.message("regex.end.expected"));
}
sMarker.done(REGEX);
return REGEX;
}
}
else {
sMarker.drop();
return WRONGWAY;
if (!ParserUtils.getToken(builder, mREGEX_END)) {
builder.error(GroovyBundle.message("regex.end.expected"));
}
marker.done(REGEX);
return inj;
}
/**
@@ -17,6 +17,7 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.path;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
@@ -30,6 +31,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrRefer
* @author ilyas
*/
public class GrPropertySelectionImpl extends GrReferenceExpressionImpl implements GrPropertySelection {
private static final Logger LOG = Logger.getInstance(GrPropertySelectionImpl.class);
public GrPropertySelectionImpl(@NotNull ASTNode node) {
super(node);
@@ -70,7 +72,7 @@ public class GrPropertySelectionImpl extends GrReferenceExpressionImpl implement
@Override
public PsiElement getReferenceNameElement() {
final PsiElement last = getLastChild();
assert last != null;
LOG.assertTrue(last!=null);
return last;
}
@@ -133,6 +133,7 @@ public class ExpressionsParsingTest extends GroovyParsingTestCase {
public void testpath$path8() throws Throwable { doTest(); }
public void testpath$path9() throws Throwable { doTest(); }
public void testpath$path10() throws Throwable {doTest(); }
public void testpath$regexp() {doTest()}
public void testpath$typeVsExpr() {doTest();}
public void testreferences$ref1() throws Throwable { doTest(); }
public void testreferences$ref2() throws Throwable { doTest(); }
@@ -159,6 +160,8 @@ public class ExpressionsParsingTest extends GroovyParsingTestCase {
public void testregex$regex2() throws Throwable { doTest(); }
public void testregex$regex20() throws Throwable { doTest(); }
public void testregex$regex21() throws Throwable { doTest(); }
public void testregex$regex22() throws Throwable { doTest(); }
public void testregex$regex23() throws Throwable { doTest(); }
public void testregex$regex3() throws Throwable { doTest(); }
public void testregex$regex33() throws Throwable { doTest(); }
public void testregex$regex4() throws Throwable { doTest(); }
@@ -0,0 +1,44 @@
a.$/dfg/$./fg/."sfg"./${a}/.$/df$g/$
-----
Groovy script
Property selection
Property selection
Reference expression
Reference expression
Reference expression
Reference expression
PsiElement(identifier)('a')
PsiElement(.)('.')
Compound regular expression
PsiElement($/ regex begin)('$/')
PsiElement($/ regex content)('dfg')
PsiElement($/ regex end)('/$')
PsiElement(.)('.')
Compound regular expression
PsiElement(regex begin)('/')
PsiElement(regex content)('fg')
PsiElement(regex end)('/')
PsiElement(.)('.')
PsiElement(Gstring)('"sfg"')
PsiElement(.)('.')
Compound regular expression
PsiElement(regex begin)('/')
GString injection
PsiElement($)('$')
Closable block
PsiElement({)('{')
Parameter list
<empty list>
Reference expression
PsiElement(identifier)('a')
PsiElement(})('}')
PsiElement(regex end)('/')
PsiElement(.)('.')
Compound regular expression
PsiElement($/ regex begin)('$/')
PsiElement($/ regex content)('df')
GString injection
PsiElement($)('$')
Reference expression
PsiElement(identifier)('g')
PsiElement($/ regex end)('/$')
@@ -36,7 +36,7 @@ Groovy script
Parameter list
<empty list>
Method call
Property selection
Reference expression
Reference expression
PsiElement(identifier)('frg')
PsiElement(.)('.')
@@ -0,0 +1,24 @@
/${1}${2}/
-----
Groovy script
Compound regular expression
PsiElement(regex begin)('/')
GString injection
PsiElement($)('$')
Closable block
PsiElement({)('{')
Parameter list
<empty list>
Literal
PsiElement(Integer)('1')
PsiElement(})('}')
GString injection
PsiElement($)('$')
Closable block
PsiElement({)('{')
Parameter list
<empty list>
Literal
PsiElement(Integer)('2')
PsiElement(})('}')
PsiElement(regex end)('/')
@@ -0,0 +1,24 @@
$/${1}${2}/$
-----
Groovy script
Compound regular expression
PsiElement($/ regex begin)('$/')
GString injection
PsiElement($)('$')
Closable block
PsiElement({)('{')
Parameter list
<empty list>
Literal
PsiElement(Integer)('1')
PsiElement(})('}')
GString injection
PsiElement($)('$')
Closable block
PsiElement({)('{')
Parameter list
<empty list>
Literal
PsiElement(Integer)('2')
PsiElement(})('}')
PsiElement($/ regex end)('/$')
@@ -52,7 +52,7 @@ Groovy script
Parameter list
<empty list>
Method call
Property selection
Reference expression
Reference expression
PsiElement(identifier)('frg')
PsiElement(.)('.')
@@ -53,7 +53,7 @@ Groovy script
Parameter list
<empty list>
Method call
Property selection
Reference expression
Reference expression
PsiElement(identifier)('frg')
PsiElement(.)('.')