Painless: Fix Semicolon Regression (#33212)
Trailers (statements following something like an if statement) that don't use brackets currently require a semicolon even if they're the last statement. This is a regression caused by (#29566) and noted by (#33193). This change fixes the regression and adds a test for the broken case.
This commit is contained in:
parent
e9b0807c67
commit
a381749aac
|
@ -22,7 +22,7 @@ parser grammar PainlessParser;
|
||||||
options { tokenVocab=PainlessLexer; }
|
options { tokenVocab=PainlessLexer; }
|
||||||
|
|
||||||
source
|
source
|
||||||
: function* statement* dstatement? EOF
|
: function* statement* EOF
|
||||||
;
|
;
|
||||||
|
|
||||||
function
|
function
|
||||||
|
@ -35,7 +35,7 @@ parameters
|
||||||
|
|
||||||
statement
|
statement
|
||||||
: rstatement
|
: rstatement
|
||||||
| dstatement SEMICOLON
|
| dstatement ( SEMICOLON | EOF )
|
||||||
;
|
;
|
||||||
|
|
||||||
// Note we use a predicate on the if/else case here to prevent the
|
// Note we use a predicate on the if/else case here to prevent the
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
// ANTLR GENERATED CODE: DO NOT EDIT
|
// ANTLR GENERATED CODE: DO NOT EDIT
|
||||||
package org.elasticsearch.painless.antlr;
|
package org.elasticsearch.painless.antlr;
|
||||||
|
|
||||||
import org.antlr.v4.runtime.CharStream;
|
|
||||||
import org.antlr.v4.runtime.Lexer;
|
import org.antlr.v4.runtime.Lexer;
|
||||||
import org.antlr.v4.runtime.RuleContext;
|
import org.antlr.v4.runtime.CharStream;
|
||||||
import org.antlr.v4.runtime.RuntimeMetaData;
|
import org.antlr.v4.runtime.Token;
|
||||||
import org.antlr.v4.runtime.Vocabulary;
|
import org.antlr.v4.runtime.TokenStream;
|
||||||
import org.antlr.v4.runtime.VocabularyImpl;
|
import org.antlr.v4.runtime.*;
|
||||||
import org.antlr.v4.runtime.atn.ATN;
|
import org.antlr.v4.runtime.atn.*;
|
||||||
import org.antlr.v4.runtime.atn.ATNDeserializer;
|
|
||||||
import org.antlr.v4.runtime.atn.LexerATNSimulator;
|
|
||||||
import org.antlr.v4.runtime.atn.PredictionContextCache;
|
|
||||||
import org.antlr.v4.runtime.dfa.DFA;
|
import org.antlr.v4.runtime.dfa.DFA;
|
||||||
|
import org.antlr.v4.runtime.misc.*;
|
||||||
|
|
||||||
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
|
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
|
||||||
abstract class PainlessLexer extends Lexer {
|
abstract class PainlessLexer extends Lexer {
|
||||||
|
@ -21,16 +17,16 @@ abstract class PainlessLexer extends Lexer {
|
||||||
protected static final PredictionContextCache _sharedContextCache =
|
protected static final PredictionContextCache _sharedContextCache =
|
||||||
new PredictionContextCache();
|
new PredictionContextCache();
|
||||||
public static final int
|
public static final int
|
||||||
WS=1, COMMENT=2, LBRACK=3, RBRACK=4, LBRACE=5, RBRACE=6, LP=7, RP=8, DOT=9,
|
WS=1, COMMENT=2, LBRACK=3, RBRACK=4, LBRACE=5, RBRACE=6, LP=7, RP=8, DOT=9,
|
||||||
NSDOT=10, COMMA=11, SEMICOLON=12, IF=13, IN=14, ELSE=15, WHILE=16, DO=17,
|
NSDOT=10, COMMA=11, SEMICOLON=12, IF=13, IN=14, ELSE=15, WHILE=16, DO=17,
|
||||||
FOR=18, CONTINUE=19, BREAK=20, RETURN=21, NEW=22, TRY=23, CATCH=24, THROW=25,
|
FOR=18, CONTINUE=19, BREAK=20, RETURN=21, NEW=22, TRY=23, CATCH=24, THROW=25,
|
||||||
THIS=26, INSTANCEOF=27, BOOLNOT=28, BWNOT=29, MUL=30, DIV=31, REM=32,
|
THIS=26, INSTANCEOF=27, BOOLNOT=28, BWNOT=29, MUL=30, DIV=31, REM=32,
|
||||||
ADD=33, SUB=34, LSH=35, RSH=36, USH=37, LT=38, LTE=39, GT=40, GTE=41,
|
ADD=33, SUB=34, LSH=35, RSH=36, USH=37, LT=38, LTE=39, GT=40, GTE=41,
|
||||||
EQ=42, EQR=43, NE=44, NER=45, BWAND=46, XOR=47, BWOR=48, BOOLAND=49, BOOLOR=50,
|
EQ=42, EQR=43, NE=44, NER=45, BWAND=46, XOR=47, BWOR=48, BOOLAND=49, BOOLOR=50,
|
||||||
COND=51, COLON=52, ELVIS=53, REF=54, ARROW=55, FIND=56, MATCH=57, INCR=58,
|
COND=51, COLON=52, ELVIS=53, REF=54, ARROW=55, FIND=56, MATCH=57, INCR=58,
|
||||||
DECR=59, ASSIGN=60, AADD=61, ASUB=62, AMUL=63, ADIV=64, AREM=65, AAND=66,
|
DECR=59, ASSIGN=60, AADD=61, ASUB=62, AMUL=63, ADIV=64, AREM=65, AAND=66,
|
||||||
AXOR=67, AOR=68, ALSH=69, ARSH=70, AUSH=71, OCTAL=72, HEX=73, INTEGER=74,
|
AXOR=67, AOR=68, ALSH=69, ARSH=70, AUSH=71, OCTAL=72, HEX=73, INTEGER=74,
|
||||||
DECIMAL=75, STRING=76, REGEX=77, TRUE=78, FALSE=79, NULL=80, TYPE=81,
|
DECIMAL=75, STRING=76, REGEX=77, TRUE=78, FALSE=79, NULL=80, TYPE=81,
|
||||||
ID=82, DOTINTEGER=83, DOTID=84;
|
ID=82, DOTINTEGER=83, DOTID=84;
|
||||||
public static final int AFTER_DOT = 1;
|
public static final int AFTER_DOT = 1;
|
||||||
public static String[] modeNames = {
|
public static String[] modeNames = {
|
||||||
|
@ -38,39 +34,39 @@ abstract class PainlessLexer extends Lexer {
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final String[] ruleNames = {
|
public static final String[] ruleNames = {
|
||||||
"WS", "COMMENT", "LBRACK", "RBRACK", "LBRACE", "RBRACE", "LP", "RP", "DOT",
|
"WS", "COMMENT", "LBRACK", "RBRACK", "LBRACE", "RBRACE", "LP", "RP", "DOT",
|
||||||
"NSDOT", "COMMA", "SEMICOLON", "IF", "IN", "ELSE", "WHILE", "DO", "FOR",
|
"NSDOT", "COMMA", "SEMICOLON", "IF", "IN", "ELSE", "WHILE", "DO", "FOR",
|
||||||
"CONTINUE", "BREAK", "RETURN", "NEW", "TRY", "CATCH", "THROW", "THIS",
|
"CONTINUE", "BREAK", "RETURN", "NEW", "TRY", "CATCH", "THROW", "THIS",
|
||||||
"INSTANCEOF", "BOOLNOT", "BWNOT", "MUL", "DIV", "REM", "ADD", "SUB", "LSH",
|
"INSTANCEOF", "BOOLNOT", "BWNOT", "MUL", "DIV", "REM", "ADD", "SUB", "LSH",
|
||||||
"RSH", "USH", "LT", "LTE", "GT", "GTE", "EQ", "EQR", "NE", "NER", "BWAND",
|
"RSH", "USH", "LT", "LTE", "GT", "GTE", "EQ", "EQR", "NE", "NER", "BWAND",
|
||||||
"XOR", "BWOR", "BOOLAND", "BOOLOR", "COND", "COLON", "ELVIS", "REF", "ARROW",
|
"XOR", "BWOR", "BOOLAND", "BOOLOR", "COND", "COLON", "ELVIS", "REF", "ARROW",
|
||||||
"FIND", "MATCH", "INCR", "DECR", "ASSIGN", "AADD", "ASUB", "AMUL", "ADIV",
|
"FIND", "MATCH", "INCR", "DECR", "ASSIGN", "AADD", "ASUB", "AMUL", "ADIV",
|
||||||
"AREM", "AAND", "AXOR", "AOR", "ALSH", "ARSH", "AUSH", "OCTAL", "HEX",
|
"AREM", "AAND", "AXOR", "AOR", "ALSH", "ARSH", "AUSH", "OCTAL", "HEX",
|
||||||
"INTEGER", "DECIMAL", "STRING", "REGEX", "TRUE", "FALSE", "NULL", "TYPE",
|
"INTEGER", "DECIMAL", "STRING", "REGEX", "TRUE", "FALSE", "NULL", "TYPE",
|
||||||
"ID", "DOTINTEGER", "DOTID"
|
"ID", "DOTINTEGER", "DOTID"
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final String[] _LITERAL_NAMES = {
|
private static final String[] _LITERAL_NAMES = {
|
||||||
null, null, null, "'{'", "'}'", "'['", "']'", "'('", "')'", "'.'", "'?.'",
|
null, null, null, "'{'", "'}'", "'['", "']'", "'('", "')'", "'.'", "'?.'",
|
||||||
"','", "';'", "'if'", "'in'", "'else'", "'while'", "'do'", "'for'", "'continue'",
|
"','", "';'", "'if'", "'in'", "'else'", "'while'", "'do'", "'for'", "'continue'",
|
||||||
"'break'", "'return'", "'new'", "'try'", "'catch'", "'throw'", "'this'",
|
"'break'", "'return'", "'new'", "'try'", "'catch'", "'throw'", "'this'",
|
||||||
"'instanceof'", "'!'", "'~'", "'*'", "'/'", "'%'", "'+'", "'-'", "'<<'",
|
"'instanceof'", "'!'", "'~'", "'*'", "'/'", "'%'", "'+'", "'-'", "'<<'",
|
||||||
"'>>'", "'>>>'", "'<'", "'<='", "'>'", "'>='", "'=='", "'==='", "'!='",
|
"'>>'", "'>>>'", "'<'", "'<='", "'>'", "'>='", "'=='", "'==='", "'!='",
|
||||||
"'!=='", "'&'", "'^'", "'|'", "'&&'", "'||'", "'?'", "':'", "'?:'", "'::'",
|
"'!=='", "'&'", "'^'", "'|'", "'&&'", "'||'", "'?'", "':'", "'?:'", "'::'",
|
||||||
"'->'", "'=~'", "'==~'", "'++'", "'--'", "'='", "'+='", "'-='", "'*='",
|
"'->'", "'=~'", "'==~'", "'++'", "'--'", "'='", "'+='", "'-='", "'*='",
|
||||||
"'/='", "'%='", "'&='", "'^='", "'|='", "'<<='", "'>>='", "'>>>='", null,
|
"'/='", "'%='", "'&='", "'^='", "'|='", "'<<='", "'>>='", "'>>>='", null,
|
||||||
null, null, null, null, null, "'true'", "'false'", "'null'"
|
null, null, null, null, null, "'true'", "'false'", "'null'"
|
||||||
};
|
};
|
||||||
private static final String[] _SYMBOLIC_NAMES = {
|
private static final String[] _SYMBOLIC_NAMES = {
|
||||||
null, "WS", "COMMENT", "LBRACK", "RBRACK", "LBRACE", "RBRACE", "LP", "RP",
|
null, "WS", "COMMENT", "LBRACK", "RBRACK", "LBRACE", "RBRACE", "LP", "RP",
|
||||||
"DOT", "NSDOT", "COMMA", "SEMICOLON", "IF", "IN", "ELSE", "WHILE", "DO",
|
"DOT", "NSDOT", "COMMA", "SEMICOLON", "IF", "IN", "ELSE", "WHILE", "DO",
|
||||||
"FOR", "CONTINUE", "BREAK", "RETURN", "NEW", "TRY", "CATCH", "THROW",
|
"FOR", "CONTINUE", "BREAK", "RETURN", "NEW", "TRY", "CATCH", "THROW",
|
||||||
"THIS", "INSTANCEOF", "BOOLNOT", "BWNOT", "MUL", "DIV", "REM", "ADD",
|
"THIS", "INSTANCEOF", "BOOLNOT", "BWNOT", "MUL", "DIV", "REM", "ADD",
|
||||||
"SUB", "LSH", "RSH", "USH", "LT", "LTE", "GT", "GTE", "EQ", "EQR", "NE",
|
"SUB", "LSH", "RSH", "USH", "LT", "LTE", "GT", "GTE", "EQ", "EQR", "NE",
|
||||||
"NER", "BWAND", "XOR", "BWOR", "BOOLAND", "BOOLOR", "COND", "COLON", "ELVIS",
|
"NER", "BWAND", "XOR", "BWOR", "BOOLAND", "BOOLOR", "COND", "COLON", "ELVIS",
|
||||||
"REF", "ARROW", "FIND", "MATCH", "INCR", "DECR", "ASSIGN", "AADD", "ASUB",
|
"REF", "ARROW", "FIND", "MATCH", "INCR", "DECR", "ASSIGN", "AADD", "ASUB",
|
||||||
"AMUL", "ADIV", "AREM", "AAND", "AXOR", "AOR", "ALSH", "ARSH", "AUSH",
|
"AMUL", "ADIV", "AREM", "AAND", "AXOR", "AOR", "ALSH", "ARSH", "AUSH",
|
||||||
"OCTAL", "HEX", "INTEGER", "DECIMAL", "STRING", "REGEX", "TRUE", "FALSE",
|
"OCTAL", "HEX", "INTEGER", "DECIMAL", "STRING", "REGEX", "TRUE", "FALSE",
|
||||||
"NULL", "TYPE", "ID", "DOTINTEGER", "DOTID"
|
"NULL", "TYPE", "ID", "DOTINTEGER", "DOTID"
|
||||||
};
|
};
|
||||||
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
|
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -261,10 +261,6 @@ public final class Walker extends PainlessParserBaseVisitor<ANode> {
|
||||||
statements.add((AStatement)visit(statement));
|
statements.add((AStatement)visit(statement));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.dstatement() != null) {
|
|
||||||
statements.add((AStatement)visit(ctx.dstatement()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SSource(scriptClassInfo, settings, sourceName, debugStream, (MainMethodReserved)reserved.pop(),
|
return new SSource(scriptClassInfo, settings, sourceName, debugStream, (MainMethodReserved)reserved.pop(),
|
||||||
location(ctx), functions, globals, statements);
|
location(ctx), functions, globals, statements);
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,4 +129,8 @@ public class BasicAPITests extends ScriptTestCase {
|
||||||
assertEquals(5, exec("org.elasticsearch.painless.FeatureTest ft = new org.elasticsearch.painless.FeatureTest();" +
|
assertEquals(5, exec("org.elasticsearch.painless.FeatureTest ft = new org.elasticsearch.painless.FeatureTest();" +
|
||||||
"ft.z = 5; return ft.z;"));
|
"ft.z = 5; return ft.z;"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testNoSemicolon() {
|
||||||
|
assertEquals(true, exec("def x = true; if (x) return x"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -278,6 +278,6 @@ public class RegexTests extends ScriptTestCase {
|
||||||
IllegalArgumentException e = expectScriptThrows(IllegalArgumentException.class, () -> {
|
IllegalArgumentException e = expectScriptThrows(IllegalArgumentException.class, () -> {
|
||||||
exec("/asdf/b", false); // Not picky so we get a non-assertion error
|
exec("/asdf/b", false); // Not picky so we get a non-assertion error
|
||||||
});
|
});
|
||||||
assertEquals("invalid sequence of tokens near ['b'].", e.getMessage());
|
assertEquals("unexpected token ['b'] was expecting one of [{<EOF>, ';'}].", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -255,7 +255,7 @@ public class WhenThingsGoWrongTests extends ScriptTestCase {
|
||||||
// We don't want PICKY here so we get the normal error message
|
// We don't want PICKY here so we get the normal error message
|
||||||
exec("def i = 1} return 1", emptyMap(), emptyMap(), null, false);
|
exec("def i = 1} return 1", emptyMap(), emptyMap(), null, false);
|
||||||
});
|
});
|
||||||
assertEquals("invalid sequence of tokens near ['}'].", e.getMessage());
|
assertEquals("unexpected token ['}'] was expecting one of [{<EOF>, ';'}].", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBadBoxingCast() {
|
public void testBadBoxingCast() {
|
||||||
|
|
Loading…
Reference in New Issue