Use enforceHasSpan on all parse results in tests

This commit is contained in:
Simon Binder 2019-10-27 11:51:09 +01:00
parent 591e1b2bff
commit a304d13927
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
13 changed files with 59 additions and 52 deletions

View File

@ -52,6 +52,10 @@ abstract class AstNode with HasMetaMixin {
/// all nodes. /// all nodes.
Token last; Token last;
/// Whether this ast node is synthetic, meaning that it doesn't appear in the
/// actual source.
bool synthetic;
/// The first index in the source that belongs to this node. Not set for all /// The first index in the source that belongs to this node. Not set for all
/// nodes. /// nodes.
int get firstPosition => first.span.start.offset; int get firstPosition => first.span.start.offset;

View File

@ -674,7 +674,7 @@ mixin CrudParser on ParserBase {
baseWindowName: baseWindowName, baseWindowName: baseWindowName,
partitionBy: partitionBy, partitionBy: partitionBy,
orderBy: orderBy, orderBy: orderBy,
frameSpec: spec ?? FrameSpec(), frameSpec: spec ?? (FrameSpec()..synthetic = true),
)..setSpan(leftParen, _previous); )..setSpan(leftParen, _previous);
} }

View File

@ -266,9 +266,8 @@ mixin ExpressionParser on ParserBase {
final selectStmt = _fullSelect(); // returns null if there's no select final selectStmt = _fullSelect(); // returns null if there's no select
if (selectStmt != null) { if (selectStmt != null) {
final stmt = select(noCompound: true) as SelectStatement;
_consume(TokenType.rightParen, 'Expected a closing bracket'); _consume(TokenType.rightParen, 'Expected a closing bracket');
return SubQuery(select: stmt)..setSpan(left, _previous); return SubQuery(select: selectStmt)..setSpan(left, _previous);
} else { } else {
final expr = expression(); final expr = expression();
_consume(TokenType.rightParen, 'Expected a closing bracket'); _consume(TokenType.rightParen, 'Expected a closing bracket');
@ -382,7 +381,8 @@ mixin ExpressionParser on ParserBase {
_consume(TokenType.leftParen, 'Expected opening parenthesis for tuple'); _consume(TokenType.leftParen, 'Expected opening parenthesis for tuple');
final expressions = <Expression>[]; final expressions = <Expression>[];
final subQuery = _fullSelect(); // if desired, attempt to parse select statement
final subQuery = orSubQuery ? _fullSelect() : null;
if (subQuery == null) { if (subQuery == null) {
// no sub query found. read expressions that form the tuple. // no sub query found. read expressions that form the tuple.
// tuples can be empty `()`, so only start parsing values when it's not // tuples can be empty `()`, so only start parsing values when it's not

View File

@ -1,6 +1,5 @@
import 'package:sqlparser/sqlparser.dart'; import 'package:sqlparser/sqlparser.dart';
import 'package:sqlparser/src/ast/ast.dart'; import 'package:sqlparser/src/ast/ast.dart';
import 'package:sqlparser/src/utils/ast_equality.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import '../common_data.dart'; import '../common_data.dart';
@ -118,11 +117,8 @@ void main() {
}); });
test('parses MAPPED BY constraints when in moor mode', () { test('parses MAPPED BY constraints when in moor mode', () {
const stmt = 'CREATE TABLE a (b NOT NULL MAPPED BY `Mapper()` PRIMARY KEY)'; testStatement(
final parsed = SqlEngine(useMoorExtensions: true).parse(stmt).rootNode; 'CREATE TABLE a (b NOT NULL MAPPED BY `Mapper()` PRIMARY KEY)',
enforceEqual(
parsed,
CreateTableStatement(tableName: 'a', columns: [ CreateTableStatement(tableName: 'a', columns: [
ColumnDefinition( ColumnDefinition(
columnName: 'b', columnName: 'b',
@ -134,15 +130,13 @@ void main() {
], ],
), ),
]), ]),
moorMode: true,
); );
}); });
test('parses JSON KEY constraints in moor mode', () { test('parses JSON KEY constraints in moor mode', () {
const stmt = 'CREATE TABLE a (b INTEGER JSON KEY "my_json_key")'; testStatement(
final parsed = SqlEngine(useMoorExtensions: true).parse(stmt).rootNode; 'CREATE TABLE a (b INTEGER JSON KEY "my_json_key")',
enforceEqual(
parsed,
CreateTableStatement( CreateTableStatement(
tableName: 'a', tableName: 'a',
columns: [ columns: [
@ -158,6 +152,7 @@ void main() {
), ),
], ],
), ),
moorMode: true,
); );
}); });
} }

View File

@ -146,8 +146,8 @@ void main() {
final tokens = scanner.scanTokens(); final tokens = scanner.scanTokens();
final parser = Parser(tokens); final parser = Parser(tokens);
final expression = parser.expression(); final expression = parser.expression();
enforceHasSpan(expression);
enforceHasSpan(expression);
enforceEqual(expression, expected); enforceEqual(expression, expected);
}); });
}); });

View File

@ -1,5 +1,4 @@
import 'package:sqlparser/sqlparser.dart'; import 'package:sqlparser/sqlparser.dart';
import 'package:sqlparser/src/utils/ast_equality.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'utils.dart'; import 'utils.dart';
@ -19,12 +18,8 @@ all: SELECT /* COUNT(*), */ * FROM tbl WHERE $predicate;
void main() { void main() {
test('parses moor files', () { test('parses moor files', () {
final parsed = SqlEngine(useMoorExtensions: true).parseMoorFile(content); testMoorFile(
final file = parsed.rootNode; content,
enforceHasSpan(file);
enforceEqual(
file,
MoorFile([ MoorFile([
ImportStatement('other.dart'), ImportStatement('other.dart'),
ImportStatement('another.moor'), ImportStatement('another.moor'),

View File

@ -4,38 +4,35 @@ import 'package:sqlparser/src/reader/tokenizer/scanner.dart';
import 'package:sqlparser/src/utils/ast_equality.dart'; import 'package:sqlparser/src/utils/ast_equality.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'utils.dart';
void main() { void main() {
test('can parse multiple statements', () { test('can parse multiple statements', () {
final sql = 'a: UPDATE tbl SET a = b; b: SELECT * FROM tbl;'; final sql = 'a: UPDATE tbl SET a = b; b: SELECT * FROM tbl;';
final tokens = Scanner(sql).scanTokens();
final moorFile = Parser(tokens).moorFile();
final statements = moorFile.statements; testMoorFile(
sql,
enforceEqual( MoorFile([
statements[0], DeclaredStatement(
DeclaredStatement( 'a',
'a', UpdateStatement(
UpdateStatement( table: TableReference('tbl', null),
table: TableReference('tbl', null), set: [
set: [ SetComponent(
SetComponent( column: Reference(columnName: 'a'),
column: Reference(columnName: 'a'), expression: Reference(columnName: 'b'),
expression: Reference(columnName: 'b'), ),
), ],
], ),
), ),
), DeclaredStatement(
); 'b',
enforceEqual( SelectStatement(
statements[1], columns: [StarResultColumn(null)],
DeclaredStatement( from: [TableReference('tbl', null)],
'b', ),
SelectStatement(
columns: [StarResultColumn(null)],
from: [TableReference('tbl', null)],
), ),
), ]),
); );
}); });

View File

@ -63,6 +63,8 @@ void main() {
final tokens = scanner.scanTokens(); final tokens = scanner.scanTokens();
final parser = Parser(tokens); final parser = Parser(tokens);
final expression = parser.expression(); final expression = parser.expression();
enforceHasSpan(expression);
enforceEqual(expression, expected); enforceEqual(expression, expected);
}); });
}); });

View File

@ -6,6 +6,7 @@ import 'package:sqlparser/src/utils/ast_equality.dart';
import '../utils.dart'; import '../utils.dart';
void _enforceFrom(SelectStatement stmt, List<Queryable> expected) { void _enforceFrom(SelectStatement stmt, List<Queryable> expected) {
enforceHasSpan(stmt);
expect(stmt.from.length, expected.length); expect(stmt.from.length, expected.length);
for (var i = 0; i < stmt.from.length; i++) { for (var i = 0; i < stmt.from.length; i++) {

View File

@ -11,6 +11,7 @@ void main() {
.parse("SELECT * FROM test GROUP BY country HAVING country LIKE '%G%'") .parse("SELECT * FROM test GROUP BY country HAVING country LIKE '%G%'")
.rootNode as SelectStatement; .rootNode as SelectStatement;
enforceHasSpan(stmt);
return enforceEqual( return enforceEqual(
stmt.groupBy, stmt.groupBy,
GroupBy( GroupBy(

View File

@ -12,6 +12,7 @@ void main() {
.parse('SELECT * FROM test LIMIT 5 * 3') .parse('SELECT * FROM test LIMIT 5 * 3')
.rootNode as SelectStatement; .rootNode as SelectStatement;
enforceHasSpan(select);
enforceEqual( enforceEqual(
select.limit, select.limit,
Limit( Limit(
@ -29,6 +30,7 @@ void main() {
.parse('SELECT * FROM test LIMIT 10 OFFSET 2') .parse('SELECT * FROM test LIMIT 10 OFFSET 2')
.rootNode as SelectStatement; .rootNode as SelectStatement;
enforceHasSpan(select);
enforceEqual( enforceEqual(
select.limit, select.limit,
Limit( Limit(
@ -46,6 +48,7 @@ void main() {
.parse('SELECT * FROM test LIMIT 10, 2') .parse('SELECT * FROM test LIMIT 10, 2')
.rootNode as SelectStatement; .rootNode as SelectStatement;
enforceHasSpan(select);
enforceEqual( enforceEqual(
select.limit, select.limit,
Limit( Limit(

View File

@ -11,6 +11,7 @@ void main() {
.parse('SELECT * FROM tbl ORDER BY -a, b DESC') .parse('SELECT * FROM tbl ORDER BY -a, b DESC')
.rootNode as SelectStatement; .rootNode as SelectStatement;
enforceHasSpan(parsed);
enforceEqual( enforceEqual(
parsed.orderBy, parsed.orderBy,
OrderBy( OrderBy(

View File

@ -18,6 +18,14 @@ IdentifierToken identifier(String content) {
return IdentifierToken(false, fakeSpan(content)); return IdentifierToken(false, fakeSpan(content));
} }
void testMoorFile(String moorFile, MoorFile expected) {
final parsed =
SqlEngine(useMoorExtensions: true).parseMoorFile(moorFile).rootNode;
enforceHasSpan(parsed);
enforceEqual(parsed, expected);
}
void testStatement(String sql, AstNode expected, {bool moorMode = false}) { void testStatement(String sql, AstNode expected, {bool moorMode = false}) {
final parsed = SqlEngine(useMoorExtensions: moorMode).parse(sql).rootNode; final parsed = SqlEngine(useMoorExtensions: moorMode).parse(sql).rootNode;
enforceHasSpan(parsed); enforceHasSpan(parsed);
@ -38,9 +46,9 @@ void testAll(Map<String, AstNode> testCases) {
/// The parser should make sure [AstNode.hasSpan] is true on relevant nodes. /// The parser should make sure [AstNode.hasSpan] is true on relevant nodes.
void enforceHasSpan(AstNode node) { void enforceHasSpan(AstNode node) {
final problematic = [node] final problematic = [node].followedBy(node.allDescendants).firstWhere(
.followedBy(node.allDescendants) (node) => !node.hasSpan && !node.synthetic,
.firstWhere((node) => !node.hasSpan, orElse: () => null); orElse: () => null);
if (problematic != null) { if (problematic != null) {
throw ArgumentError('Node $problematic did not have a span'); throw ArgumentError('Node $problematic did not have a span');