drift/sqlparser/test/parser/utils.dart

91 lines
2.4 KiB
Dart

import 'package:collection/collection.dart' show IterableExtension;
import 'package:source_span/source_span.dart';
import 'package:sqlparser/sqlparser.dart';
import 'package:sqlparser/src/utils/ast_equality.dart';
import 'package:test/test.dart';
export 'package:sqlparser/src/reader/tokenizer/token.dart';
final defaultSpan = fakeSpan('fake');
Token token(TokenType type) {
return Token(type, defaultSpan);
}
StringLiteralToken stringLiteral(String value) {
return StringLiteralToken(value, defaultSpan);
}
InlineDartToken inlineDart(String dartCode) {
return InlineDartToken(fakeSpan('`$dartCode`'));
}
IdentifierToken identifier(String content) {
return IdentifierToken(false, fakeSpan(content));
}
DriftFile parseDrift(String content) {
return SqlEngine(EngineOptions(driftOptions: const DriftSqlOptions()))
.parseDriftFile(content)
.rootNode as DriftFile;
}
void testDriftFile(String driftFile, DriftFile expected) {
final parsed = parseDrift(driftFile);
enforceHasSpan(parsed);
enforceEqual(parsed, expected);
}
void testStatement(String sql, AstNode expected, {bool driftMode = false}) {
final result = SqlEngine(EngineOptions(
driftOptions: driftMode ? const DriftSqlOptions() : null))
.parse(sql);
expect(result.errors, isEmpty);
final parsed = result.rootNode;
enforceHasSpan(parsed);
enforceEqual(parsed, expected);
}
void expectParseError(
String sql, {
dynamic message = anything,
dynamic span = anything,
}) {
final result = SqlEngine().parse(sql);
expect(result.errors, [isParsingError(message: message, span: span)]);
}
TypeMatcher<ParsingError> isParsingError({
dynamic message = anything,
dynamic span = anything,
}) {
return isA<ParsingError>()
.having((e) => e.message, 'message', wrapMatcher(message))
.having((e) => e.token.span.text, 'span', wrapMatcher(span));
}
FileSpan fakeSpan(String content) {
return SourceFile.fromString(content).span(0);
}
void testAll(Map<String, AstNode> testCases) {
testCases.forEach((sql, expected) {
test('with $sql', () {
testStatement(sql, expected);
});
});
}
/// The parser should make sure [AstNode.hasSpan] is true on relevant nodes.
void enforceHasSpan(AstNode node) {
final problematic = [node]
.followedBy(node.allDescendants)
.firstWhereOrNull((node) => !node.hasSpan && !node.synthetic);
if (problematic != null) {
throw ArgumentError('Node $problematic did not have a span');
}
}