Reduce usages of covariant

This commit is contained in:
Simon Binder 2020-11-23 18:53:37 +01:00
parent f872152a75
commit a73b9334b6
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
34 changed files with 699 additions and 419 deletions

View File

@ -1,9 +1,9 @@
import 'package:collection/collection.dart';
import 'package:meta/meta.dart';
import 'package:source_span/source_span.dart';
import 'package:sqlparser/src/analysis/analysis.dart';
import 'package:sqlparser/src/reader/syntactic_entity.dart';
import 'package:sqlparser/src/reader/tokenizer/token.dart';
import 'package:sqlparser/src/utils/ast_equality.dart';
import 'package:sqlparser/src/utils/meta.dart';
part 'clauses/limit.dart';
@ -167,7 +167,16 @@ abstract class AstNode with HasMetaMixin implements SyntacticEntity {
/// Whether the content of this node is equal to the [other] node of the same
/// type. The "content" refers to anything stored only in this node, children
/// are ignored.
bool contentEquals(covariant AstNode other);
@nonVirtual
bool contentEquals(AstNode other) {
final checker = EqualityEnforcingVisitor(this, considerChildren: false);
try {
checker.visit(other, null);
return true;
} on NotEqualException {
return false;
}
}
@override
String toString() {

View File

@ -33,7 +33,4 @@ class Limit extends AstNode implements LimitBase {
// If using a comma, the count is followed by an optional offset
return [count, if (offset != null) offset];
}
@override
bool contentEquals(Limit other) => true;
}

View File

@ -26,11 +26,6 @@ class OrderBy extends AstNode implements OrderByBase {
@override
Iterable<AstNode> get childNodes => terms;
@override
bool contentEquals(OrderBy other) {
return true;
}
}
enum OrderingMode { ascending, descending }
@ -59,9 +54,4 @@ class OrderingTerm extends AstNode implements OrderingTermBase {
@override
Iterable<AstNode> get childNodes => [expression];
@override
bool contentEquals(OrderingTerm other) {
return other.orderingMode == orderingMode && other.nulls == nulls;
}
}

View File

@ -29,9 +29,6 @@ class UpsertClause extends AstNode implements HasWhereClause {
action,
];
}
@override
bool contentEquals(UpsertClause other) => true;
}
abstract class UpsertAction extends AstNode {}
@ -47,9 +44,6 @@ class DoNothing extends UpsertAction {
@override
Iterable<AstNode> get childNodes => const [];
@override
bool contentEquals(DoNothing other) => true;
}
class DoUpdate extends UpsertAction implements HasWhereClause {
@ -72,7 +66,4 @@ class DoUpdate extends UpsertAction implements HasWhereClause {
@override
Iterable<AstNode> get childNodes => [...set, if (where != null) where];
@override
bool contentEquals(DoUpdate other) => true;
}

View File

@ -22,9 +22,6 @@ class WithClause extends AstNode {
@override
Iterable<AstNode> get childNodes => ctes;
@override
bool contentEquals(WithClause other) => other.recursive == recursive;
}
class CommonTableExpression extends AstNode with ResultSet {
@ -57,11 +54,6 @@ class CommonTableExpression extends AstNode with ResultSet {
@override
Iterable<AstNode> get childNodes => [as];
@override
bool contentEquals(CommonTableExpression other) {
return other.cteTableName == cteTableName;
}
@override
List<Column> get resolvedColumns {
final columnsOfSelect = as.resolvedColumns;

View File

@ -55,11 +55,6 @@ class TableReference extends TableOrSubquery
return visitor.visitTableReference(this, arg);
}
@override
bool contentEquals(TableReference other) {
return other.tableName == tableName && other.as == as;
}
@override
void transformChildren<A>(Transformer<A> transformer, A arg) {}
@ -93,11 +88,6 @@ class SelectStatementAsSource extends TableOrSubquery implements Renamable {
void transformChildren<A>(Transformer<A> transformer, A arg) {
statement = transformer.transformChild(statement, this, arg);
}
@override
bool contentEquals(SelectStatementAsSource other) {
return other.as == as;
}
}
/// https://www.sqlite.org/syntax/join-clause.html
@ -120,11 +110,6 @@ class JoinClause extends Queryable {
@override
Iterable<AstNode> get childNodes => [primary, ...joins];
@override
bool contentEquals(JoinClause other) {
return true; // equality is defined by child nodes
}
}
enum JoinOperator {
@ -156,27 +141,6 @@ class Join extends AstNode {
];
}
@override
bool contentEquals(Join other) {
if (other.natural != natural || other.operator != operator) {
return false;
}
if (constraint is OnConstraint) {
return other.constraint is OnConstraint;
} else if (constraint is UsingConstraint) {
final typedConstraint = constraint as UsingConstraint;
if (other.constraint is! UsingConstraint) {
return false;
}
final typedOther = other.constraint as UsingConstraint;
return const ListEquality()
.equals(typedConstraint.columnNames, typedOther.columnNames);
}
return true;
}
@override
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
return visitor.visitJoin(this, arg);
@ -238,9 +202,4 @@ class TableValuedFunction extends Queryable
@override
bool get visibleToChildren => false;
@override
bool contentEquals(TableValuedFunction other) {
return other.name == name;
}
}

View File

@ -28,7 +28,4 @@ class Tuple extends Expression {
@override
List<Expression> get childNodes => expressions;
@override
bool contentEquals(Tuple other) => true;
}

View File

@ -62,11 +62,6 @@ class AggregateExpression extends Expression
if (windowDefinition != null) windowDefinition,
];
}
@override
bool contentEquals(AggregateExpression other) {
return other.name == name && other.windowName == windowName;
}
}
/// A window declaration that appears in a `SELECT` statement like
@ -107,11 +102,6 @@ class WindowDefinition extends AstNode {
@override
Iterable<AstNode> get childNodes =>
[...partitionBy, if (orderBy != null) orderBy, frameSpec];
@override
bool contentEquals(WindowDefinition other) {
return other.baseWindowName == baseWindowName;
}
}
class FrameSpec extends AstNode {
@ -148,14 +138,6 @@ class FrameSpec extends AstNode {
if (start.isExpressionOffset) start.offset,
if (end.isExpressionOffset) end.offset,
];
@override
bool contentEquals(FrameSpec other) {
return other.type == type &&
other.excludeMode == excludeMode &&
other.start == start &&
other.end == end;
}
}
/// Defines how a [FrameBoundary] count rows or groups. See

View File

@ -22,9 +22,6 @@ class CaseExpression extends Expression {
@override
Iterable<AstNode> get childNodes =>
[if (base != null) base, ...whens, if (elseExpr != null) elseExpr];
@override
bool contentEquals(CaseExpression other) => true;
}
class WhenComponent extends AstNode {
@ -46,7 +43,4 @@ class WhenComponent extends AstNode {
@override
Iterable<AstNode> get childNodes => [when, then];
@override
bool contentEquals(WhenComponent other) => true;
}

View File

@ -19,9 +19,4 @@ class CastExpression extends Expression {
@override
Iterable<AstNode> get childNodes => [operand];
@override
bool contentEquals(CastExpression other) {
return other.typeName == typeName;
}
}

View File

@ -40,11 +40,6 @@ class FunctionExpression extends Expression
Iterable<AstNode> get childNodes {
return [parameters];
}
@override
bool contentEquals(FunctionExpression other) {
return other.name == name;
}
}
/// Marker interface for anything that can be inside the parentheses after a
@ -67,11 +62,6 @@ class StarFunctionParameter extends FunctionParameters {
@override
Iterable<AstNode> get childNodes => const Iterable.empty();
@override
bool contentEquals(StarFunctionParameter other) {
return true;
}
}
class ExprFunctionParameters extends FunctionParameters {
@ -92,9 +82,4 @@ class ExprFunctionParameters extends FunctionParameters {
@override
List<AstNode> get childNodes => parameters;
@override
bool contentEquals(ExprFunctionParameters other) {
return other.distinct == distinct;
}
}

View File

@ -30,9 +30,6 @@ class NullLiteral<T> extends Literal {
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
return visitor.visitNullLiteral(this, arg);
}
@override
bool contentEquals(NullLiteral other) => true;
}
class NumericLiteral extends Literal<num> {
@ -47,9 +44,6 @@ class NumericLiteral extends Literal<num> {
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
return visitor.visitNumericLiteral(this, arg);
}
@override
bool contentEquals(NumericLiteral other) => other.value == value;
}
class BooleanLiteral extends Literal<bool> {
@ -67,11 +61,6 @@ class BooleanLiteral extends Literal<bool> {
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
return visitor.visitBooleanLiteral(this, arg);
}
@override
bool contentEquals(BooleanLiteral other) {
return other.value == value;
}
}
class StringLiteral extends Literal {
@ -91,11 +80,6 @@ class StringLiteral extends Literal {
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
return visitor.visitStringLiteral(this, arg);
}
@override
bool contentEquals(StringLiteral other) {
return other.isBinary == isBinary && other.value == value;
}
}
enum TimeConstantKind { currentTime, currentDate, currentTimestamp }
@ -110,11 +94,6 @@ class TimeConstantLiteral extends Literal {
return visitor.visitTimeConstantLiteral(this, arg);
}
@override
bool contentEquals(TimeConstantLiteral other) {
return other.kind == kind;
}
@override
dynamic get value => throw UnimplementedError('TimeConstantLiteral.value');
}

View File

@ -26,11 +26,6 @@ class Reference extends Expression with ReferenceOwner {
@override
Iterable<AstNode> get childNodes => const [];
@override
bool contentEquals(Reference other) {
return other.tableName == tableName && other.columnName == columnName;
}
@override
String toString() {
if (tableName != null) {

View File

@ -18,11 +18,6 @@ class UnaryExpression extends Expression {
@override
Iterable<AstNode> get childNodes => [inner];
@override
bool contentEquals(UnaryExpression other) {
return other.operator.type == operator.type;
}
}
class CollateExpression extends UnaryExpression {
@ -40,12 +35,6 @@ class CollateExpression extends UnaryExpression {
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
return visitor.visitCollateExpression(this, arg);
}
@override
bool contentEquals(CollateExpression other) {
return super.contentEquals(other) &&
other.collateFunction.type == collateFunction.type;
}
}
class BinaryExpression extends Expression {
@ -68,11 +57,6 @@ class BinaryExpression extends Expression {
@override
Iterable<AstNode> get childNodes => [left, right];
@override
bool contentEquals(BinaryExpression other) {
return other.operator.type == operator.type;
}
}
/// A like, glob, match or regexp expression.
@ -104,9 +88,6 @@ class StringComparisonExpression extends Expression {
@override
Iterable<AstNode> get childNodes => [left, right, if (escape != null) escape];
@override
bool contentEquals(StringComparisonExpression other) => other.not == not;
}
/// `(NOT)? $left IS $right`
@ -130,11 +111,6 @@ class IsExpression extends Expression {
@override
Iterable<AstNode> get childNodes => [left, right];
@override
bool contentEquals(IsExpression other) {
return other.negated == negated;
}
}
class IsNullExpression extends Expression {
@ -157,11 +133,6 @@ class IsNullExpression extends Expression {
@override
Iterable<AstNode> get childNodes => [operand];
@override
bool contentEquals(IsNullExpression other) {
return other.negated == negated;
}
}
/// `$check BETWEEN $lower AND $upper`
@ -187,9 +158,6 @@ class BetweenExpression extends Expression {
@override
List<Expression> get childNodes => [check, lower, upper];
@override
bool contentEquals(BetweenExpression other) => other.not == not;
}
/// `$left$ IN $inside`.
@ -219,9 +187,6 @@ class InExpression extends Expression {
left = transformer.transformChild(left, this, arg);
inside = transformer.transformChild(inside, this, arg);
}
@override
bool contentEquals(InExpression other) => other.not == not;
}
class Parentheses extends Expression {
@ -245,7 +210,4 @@ class Parentheses extends Expression {
@override
Iterable<AstNode> get childNodes => [expression];
@override
bool contentEquals(Parentheses other) => true;
}

View File

@ -19,9 +19,6 @@ class SubQuery extends Expression {
@override
Iterable<AstNode> get childNodes => [select];
@override
bool contentEquals(SubQuery other) => true;
}
class ExistsExpression extends Expression {
@ -41,7 +38,4 @@ class ExistsExpression extends Expression {
@override
Iterable<AstNode> get childNodes => [select];
@override
bool contentEquals(ExistsExpression other) => true;
}

View File

@ -23,11 +23,6 @@ class NumberedVariable extends Expression with Variable {
@override
Iterable<AstNode> get childNodes => const [];
@override
bool contentEquals(NumberedVariable other) {
return other.explicitIndex == explicitIndex;
}
}
class ColonNamedVariable extends Expression with Variable {
@ -46,9 +41,4 @@ class ColonNamedVariable extends Expression with Variable {
@override
Iterable<AstNode> get childNodes => [];
@override
bool contentEquals(ColonNamedVariable other) {
return other.name == name;
}
}

View File

@ -36,11 +36,6 @@ class DeclaredStatement extends Statement implements PartOfMoorFile {
@override
Iterable<AstNode> get childNodes =>
[statement, if (parameters != null) ...parameters];
@override
bool contentEquals(DeclaredStatement other) {
return other.identifier == identifier && other.as == as;
}
}
/// How a statement was declared in a moor file.
@ -123,11 +118,6 @@ class VariableTypeHint extends StatementParameter {
void transformChildren<A>(Transformer<A> transformer, A arg) {
variable = transformer.transformChild(variable, this, arg);
}
@override
bool contentEquals(VariableTypeHint other) {
return other.typeName == typeName;
}
}
/// Set a default value for a dart placeholder.
@ -150,11 +140,6 @@ class DartPlaceholderDefaultValue extends StatementParameter {
@override
Iterable<AstNode> get childNodes => [defaultValue];
@override
bool contentEquals(DartPlaceholderDefaultValue other) {
return other.variableName == variableName;
}
@override
void transformChildren<A>(Transformer<A> transformer, A arg) {
defaultValue = transformer.transformChild(defaultValue, this, arg);

View File

@ -18,9 +18,4 @@ class ImportStatement extends Statement implements PartOfMoorFile {
@override
final Iterable<AstNode> childNodes = const [];
@override
bool contentEquals(ImportStatement other) {
return other.importedFile == importedFile;
}
}

View File

@ -31,13 +31,6 @@ abstract class DartPlaceholder extends AstNode {
return visitor.visitDartPlaceholder(this, arg);
}
bool _dartEquals(covariant DartPlaceholder other) => true;
@override
bool contentEquals(DartPlaceholder other) {
return other.name == name && other._dartEquals(other);
}
T when<T>(
{T Function(DartExpressionPlaceholder) isExpression,
T Function(DartLimitPlaceholder) isLimit,

View File

@ -28,7 +28,4 @@ class MoorFile extends AstNode {
/// Returns the imports defined in this file.
Iterable<ImportStatement> get imports =>
childNodes.whereType<ImportStatement>();
@override
bool contentEquals(MoorFile other) => true;
}

View File

@ -17,11 +17,6 @@ class NestedStarResultColumn extends ResultColumn {
@override
void transformChildren<A>(Transformer<A> transformer, A arg) {}
@override
bool contentEquals(NestedStarResultColumn other) {
return other.tableName == tableName;
}
@override
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
return visitor.visitMoorNestedStarResultColumn(this, arg);

View File

@ -28,11 +28,6 @@ class ColumnDefinition extends AstNode {
@override
Iterable<AstNode> get childNodes => constraints;
@override
bool contentEquals(ColumnDefinition other) {
return other.columnName == columnName && other.typeName == typeName;
}
/// Finds a constraint of type [T], or null, if none is set.
T findConstraint<T extends ColumnConstraint>() {
final typedConstraints = constraints.whereType<T>().iterator;
@ -87,14 +82,6 @@ abstract class ColumnConstraint extends AstNode {
throw Exception('Did not expect $runtimeType as a ColumnConstraint');
}
}
@visibleForOverriding
bool _equalToConstraint(covariant ColumnConstraint other);
@override
bool contentEquals(ColumnConstraint other) {
return other.name == name && _equalToConstraint(other);
}
}
enum ConflictClause { rollback, abort, fail, ignore, replace }
@ -105,9 +92,6 @@ class NullColumnConstraint extends ColumnConstraint {
NullColumnConstraint(String name, {this.$null}) : super(name);
@override
bool _equalToConstraint(NullColumnConstraint other) => true;
@override
Iterable<AstNode> get childNodes => const Iterable.empty();
@ -128,9 +112,6 @@ class NotNull extends ColumnConstraint {
@override
void transformChildren<A>(Transformer<A> transformer, A arg) {}
@override
bool _equalToConstraint(NotNull other) => onConflict == other.onConflict;
}
class PrimaryKeyColumn extends ColumnConstraint {
@ -147,13 +128,6 @@ class PrimaryKeyColumn extends ColumnConstraint {
@override
void transformChildren<A>(Transformer<A> transformer, A arg) {}
@override
bool _equalToConstraint(PrimaryKeyColumn other) {
return other.autoIncrement == autoIncrement &&
other.mode == mode &&
other.onConflict == onConflict;
}
}
class UniqueColumn extends ColumnConstraint {
@ -166,11 +140,6 @@ class UniqueColumn extends ColumnConstraint {
@override
void transformChildren<A>(Transformer<A> transformer, A arg) {}
@override
bool _equalToConstraint(UniqueColumn other) {
return other.onConflict == onConflict;
}
}
class CheckColumn extends ColumnConstraint {
@ -185,9 +154,6 @@ class CheckColumn extends ColumnConstraint {
void transformChildren<A>(Transformer<A> transformer, A arg) {
expression = transformer.transformChild(expression, this, arg);
}
@override
bool _equalToConstraint(CheckColumn other) => true;
}
class Default extends ColumnConstraint {
@ -202,9 +168,6 @@ class Default extends ColumnConstraint {
void transformChildren<A>(Transformer<A> transformer, A arg) {
expression = transformer.transformChild(expression, this, arg);
}
@override
bool _equalToConstraint(Default other) => true;
}
class CollateConstraint extends ColumnConstraint {
@ -217,9 +180,6 @@ class CollateConstraint extends ColumnConstraint {
@override
void transformChildren<A>(Transformer<A> transformer, A arg) {}
@override
bool _equalToConstraint(CollateConstraint other) => true;
}
class ForeignKeyColumnConstraint extends ColumnConstraint {
@ -227,9 +187,6 @@ class ForeignKeyColumnConstraint extends ColumnConstraint {
ForeignKeyColumnConstraint(String name, this.clause) : super(name);
@override
bool _equalToConstraint(ForeignKeyColumnConstraint other) => true;
@override
Iterable<AstNode> get childNodes => [clause];
@ -247,11 +204,6 @@ class MappedBy extends ColumnConstraint {
MappedBy(String name, this.mapper) : super(name);
@override
bool _equalToConstraint(MappedBy other) {
return other.mapper.dartCode == mapper.dartCode;
}
@override
final Iterable<AstNode> childNodes = const [];
@ -272,11 +224,6 @@ class JsonKey extends ColumnConstraint {
JsonKey(String name, this.jsonNameToken) : super(name);
@override
bool _equalToConstraint(JsonKey other) {
return other.jsonKey == jsonKey;
}
@override
void transformChildren<A>(Transformer<A> transformer, A arg) {}
}

View File

@ -35,11 +35,6 @@ class ForeignKeyClause extends AstNode {
...columnNames,
if (deferrable != null) deferrable,
];
@override
bool contentEquals(ForeignKeyClause other) {
return other.onDelete == onDelete && other.onUpdate == onUpdate;
}
}
enum InitialDeferrableMode {
@ -69,11 +64,6 @@ class DeferrableClause extends AstNode {
@override
Iterable<AstNode> get childNodes => const Iterable.empty();
@override
bool contentEquals(DeferrableClause other) {
return other.not == not && other.declaredInitially == declaredInitially;
}
@override
void transformChildren<A>(Transformer<A> transformer, A arg) {}
}
@ -89,13 +79,7 @@ abstract class TableConstraint extends AstNode {
return visitor.visitTableConstraint(this, arg);
}
@override
bool contentEquals(TableConstraint other) {
return other.name == name && _constraintEquals(other);
}
@visibleForOverriding
bool _constraintEquals(covariant TableConstraint other);
bool constraintEquals(covariant TableConstraint other);
}
class KeyClause extends TableConstraint {
@ -112,7 +96,7 @@ class KeyClause extends TableConstraint {
: super(name);
@override
bool _constraintEquals(KeyClause other) {
bool constraintEquals(KeyClause other) {
return other.isPrimaryKey == isPrimaryKey && other.onConflict == onConflict;
}
@ -131,7 +115,7 @@ class CheckTable extends TableConstraint {
CheckTable(String name, this.expression) : super(name);
@override
bool _constraintEquals(CheckTable other) => true;
bool constraintEquals(CheckTable other) => true;
@override
void transformChildren<A>(Transformer<A> transformer, A arg) {
@ -151,7 +135,7 @@ class ForeignKeyTableConstraint extends TableConstraint {
: super(name);
@override
bool _constraintEquals(ForeignKeyTableConstraint other) => true;
bool constraintEquals(ForeignKeyTableConstraint other) => true;
@override
void transformChildren<A>(Transformer<A> transformer, A arg) {

View File

@ -20,7 +20,4 @@ class Block extends AstNode {
@override
Iterable<AstNode> get childNodes => statements;
@override
bool contentEquals(Block other) => true;
}

View File

@ -38,11 +38,6 @@ class CreateIndexStatement extends Statement
@override
Iterable<AstNode> get childNodes =>
[on, ...columns, if (where != null) where];
@override
bool contentEquals(CreateIndexStatement other) {
return other.indexName == indexName;
}
}
/// Note that this class matches the productions listed at https://www.sqlite.org/syntax/indexed-column.html
@ -70,7 +65,4 @@ class IndexedColumn extends AstNode {
void transformChildren<A>(Transformer<A> transformer, A arg) {
expression = transformer.transformChild(expression, this, arg);
}
@override
bool contentEquals(IndexedColumn other) => other.ordering == ordering;
}

View File

@ -51,14 +51,6 @@ class CreateTableStatement extends TableInducingStatement {
@override
Iterable<AstNode> get childNodes => [...columns, ...tableConstraints];
@override
bool contentEquals(CreateTableStatement other) {
return other.ifNotExists == ifNotExists &&
other.tableName == tableName &&
other.withoutRowId == withoutRowId &&
other.overriddenDataClassName == overriddenDataClassName;
}
}
class CreateVirtualTableStatement extends TableInducingStatement {
@ -94,12 +86,4 @@ class CreateVirtualTableStatement extends TableInducingStatement {
@override
Iterable<AstNode> get childNodes => const [];
@override
bool contentEquals(CreateVirtualTableStatement other) {
return other.ifNotExists == ifNotExists &&
other.tableName == tableName &&
other.moduleName == moduleName &&
const ListEquality().equals(other.argumentContent, argumentContent);
}
}

View File

@ -46,13 +46,6 @@ class CreateTriggerStatement extends Statement implements CreatingStatement {
if (when != null) when,
action,
];
@override
bool contentEquals(CreateTriggerStatement other) {
return other.ifNotExists == ifNotExists &&
other.triggerName == triggerName &&
other.mode == mode;
}
}
enum TriggerMode { before, after, insteadOf }
@ -74,9 +67,6 @@ abstract class TriggerTarget extends AstNode {
/// Whether this target introduces the "old" table reference in the sub-scope
/// of the create trigger statement.
bool get introducesOld;
@override
bool contentEquals(TriggerTarget other) => true;
}
class DeleteTarget extends TriggerTarget {

View File

@ -32,11 +32,4 @@ class CreateViewStatement extends Statement implements CreatingStatement {
@override
Iterable<AstNode> get childNodes => [query];
@override
bool contentEquals(CreateViewStatement other) {
return other.ifNotExists == ifNotExists &&
other.viewName == viewName &&
const ListEquality().equals(other.columns, columns);
}
}

View File

@ -30,7 +30,4 @@ class DeleteStatement extends CrudStatement
from,
if (where != null) where,
];
@override
bool contentEquals(DeleteStatement other) => true;
}

View File

@ -56,11 +56,6 @@ class InsertStatement extends CrudStatement implements HasPrimarySource {
source,
if (upsert != null) upsert
];
@override
bool contentEquals(InsertStatement other) {
return other.mode == mode && other.source.runtimeType == source.runtimeType;
}
}
abstract class InsertSource extends AstNode {
@ -94,9 +89,6 @@ class ValuesSource extends InsertSource {
return visitor.visitValuesSource(this, arg);
}
@override
bool contentEquals(ValuesSource other) => true;
@override
void transformChildren<A>(Transformer<A> transformer, A arg) {
transformer.transformChildren(values, this, arg);
@ -117,9 +109,6 @@ class SelectInsertSource extends InsertSource {
return visitor.visitSelectInsertSource(this, arg);
}
@override
bool contentEquals(SelectInsertSource other) => true;
@override
void transformChildren<A>(Transformer<A> transformer, A arg) {
stmt = transformer.transformChild(stmt, this, arg);
@ -136,9 +125,6 @@ class DefaultValues extends InsertSource {
return visitor.visitDefaultValues(this, arg);
}
@override
bool contentEquals(DefaultValues other) => true;
@override
void transformChildren<A>(Transformer<A> transformer, A arg) {}
}

View File

@ -10,9 +10,6 @@ class InvalidStatement extends Statement {
@override
Iterable<AstNode> get childNodes => const Iterable.empty();
@override
bool contentEquals(InvalidStatement other) => true;
@override
void transformChildren<A>(Transformer<A> transformer, A arg) {}
}

View File

@ -72,11 +72,6 @@ class SelectStatement extends BaseSelectStatement
if (orderBy != null) orderBy,
];
}
@override
bool contentEquals(SelectStatement other) {
return other.distinct == distinct;
}
}
class CompoundSelectStatement extends BaseSelectStatement {
@ -109,12 +104,6 @@ class CompoundSelectStatement extends BaseSelectStatement {
base = transformer.transformChild(base, this, arg);
transformer.transformChildren(additional, this, arg);
}
@override
bool contentEquals(CompoundSelectStatement other) {
// this class doesn't contain anything but child nodes
return true;
}
}
/// A select statement of the form `VALUES (expr-list), ..., (expr-list-N)`.
@ -137,9 +126,6 @@ class ValuesSelectStatement extends BaseSelectStatement
@override
Iterable<AstNode> get childNodes => values;
@override
bool contentEquals(ValuesSelectStatement other) => true;
}
abstract class ResultColumn extends AstNode {}
@ -157,11 +143,6 @@ class StarResultColumn extends ResultColumn {
@override
void transformChildren<A>(Transformer<A> transformer, A arg) {}
@override
bool contentEquals(StarResultColumn other) {
return other.tableName == tableName;
}
@override
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
return visitor.visitStarResultColumn(this, arg);
@ -191,11 +172,6 @@ class ExpressionResultColumn extends ResultColumn
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
return visitor.visitExpressionResultColumn(this, arg);
}
@override
bool contentEquals(ExpressionResultColumn other) {
return other.as == as;
}
}
class GroupBy extends AstNode {
@ -218,11 +194,6 @@ class GroupBy extends AstNode {
@override
Iterable<AstNode> get childNodes => [...by, if (having != null) having];
@override
bool contentEquals(GroupBy other) {
return true; // Defined via child nodes
}
}
enum CompoundSelectMode {
@ -256,7 +227,4 @@ class CompoundSelectPart extends AstNode {
void transformChildren<A>(Transformer<A> transformer, A arg) {
select = transformer.transformChild(select, this, arg);
}
@override
bool contentEquals(CompoundSelectPart other) => mode == other.mode;
}

View File

@ -54,11 +54,6 @@ class UpdateStatement extends CrudStatement
if (where != null) where,
];
@override
bool contentEquals(UpdateStatement other) {
return other.or == or;
}
static FailureMode failureModeFromToken(TokenType token) {
return _tokensToMode[token];
}
@ -83,7 +78,4 @@ class SetComponent extends AstNode {
@override
Iterable<AstNode> get childNodes => [column, expression];
@override
bool contentEquals(SetComponent other) => true;
}

View File

@ -1,16 +1,693 @@
import 'package:collection/collection.dart';
import 'package:sqlparser/src/ast/ast.dart';
/// Visitor enforcing the equality of two ast nodes.
class EqualityEnforcingVisitor implements AstVisitor<void, void> {
// The current ast node. Visitor methods will compare the node they receive to
// this one.
AstNode _current;
// Whether to check for deep equality too.
final bool _considerChildren;
/// Creates a visitor enforcing equality to the given node.
///
/// The [visit] methods of this visitor will throw an [NotEqualException]
/// if they receive a node that is different to the node passed here.
///
/// When [considerChildren] is true (the default), it also considers child
/// nodes, thus enforcing deep equality.
EqualityEnforcingVisitor(this._current, {bool considerChildren = true})
: _considerChildren = considerChildren;
void _check(AstNode childOfCurrent, AstNode childOfOther) {
if (identical(childOfCurrent, childOfOther)) return;
if ((childOfCurrent == null) != (childOfOther == null)) {
throw NotEqualException('$childOfCurrent and $childOfOther');
}
// Both non nullable here
final savedCurrent = _current;
_current = childOfCurrent;
visit(childOfOther, null);
_current = savedCurrent;
}
void _checkChildren(AstNode other) {
if (!_considerChildren) return;
final currentChildren = _current.childNodes.iterator;
final otherChildren = other.childNodes.iterator;
// always move both iterators
while (currentChildren.moveNext() & otherChildren.moveNext()) {
_check(currentChildren.current, otherChildren.current);
}
if (currentChildren.moveNext() || otherChildren.moveNext()) {
throw NotEqualException(
"$_current and $other don't have an equal amount of children");
}
}
Null /*Never*/ _notEqual(AstNode other) {
throw NotEqualException('$_current and $other');
}
T _currentAs<T extends AstNode>(T context) {
final current = _current;
if (current is T) return current;
_notEqual(context);
return null;
}
void _assert(bool contentEqual, AstNode context) {
if (!contentEqual) _notEqual(context);
}
@override
void visitAggregateExpression(AggregateExpression e, void arg) {
final current = _currentAs<AggregateExpression>(e);
_assert(current.name == e.name && current.windowName == e.windowName, e);
_checkChildren(e);
}
@override
void visitBetweenExpression(BetweenExpression e, void arg) {
final current = _currentAs<BetweenExpression>(e);
_assert(current.not == e.not, e);
_checkChildren(e);
}
@override
void visitBinaryExpression(BinaryExpression e, void arg) {
final current = _currentAs<BinaryExpression>(e);
_assert(current.operator.type == e.operator.type, e);
_checkChildren(e);
}
@override
void visitBlock(Block block, void arg) {
_currentAs<Block>(block);
_checkChildren(block);
}
@override
void visitBooleanLiteral(BooleanLiteral e, void arg) {
final current = _currentAs<BooleanLiteral>(e);
_assert(current.value == e.value, e);
_checkChildren(e);
}
@override
void visitCaseExpression(CaseExpression e, void arg) {
_currentAs<CaseExpression>(e);
_checkChildren(e);
}
@override
void visitCastExpression(CastExpression e, void arg) {
final current = _currentAs<CastExpression>(e);
_assert(current.typeName == e.typeName, e);
_checkChildren(e);
}
@override
void visitCollateExpression(CollateExpression e, void arg) {
final current = _currentAs<CollateExpression>(e);
_assert(current.collateFunction.type == e.collateFunction.type, e);
_checkChildren(e);
}
@override
void visitColumnConstraint(ColumnConstraint e, void arg) {
final current = _currentAs<ColumnConstraint>(e);
_assert(current.name == e.name, e);
if (e is NotNull) {
_assert(current is NotNull && current.onConflict == e.onConflict, e);
} else if (e is PrimaryKeyColumn) {
_assert(
current is PrimaryKeyColumn &&
current.autoIncrement == e.autoIncrement &&
current.mode == e.mode &&
current.onConflict == e.onConflict,
e);
} else if (e is UniqueColumn) {
_assert(current is UniqueColumn && current.onConflict == e.onConflict, e);
} else if (e is CheckColumn) {
_assert(current is CheckColumn, e);
} else if (e is MappedBy) {
_assert(
current is MappedBy && current.mapper.dartCode == e.mapper.dartCode,
e);
} else if (e is JsonKey) {
_assert(current is JsonKey && current.jsonKey == e.jsonKey, e);
} else {
_assert(current.runtimeType == e.runtimeType, e);
}
_checkChildren(e);
}
@override
void visitColumnDefinition(ColumnDefinition e, void arg) {
final current = _currentAs<ColumnDefinition>(e);
_assert(
current.columnName == e.columnName && current.typeName == e.typeName,
e);
_checkChildren(e);
}
@override
void visitCommonTableExpression(CommonTableExpression e, void arg) {
final current = _currentAs<CommonTableExpression>(e);
_assert(current.cteTableName == e.cteTableName, e);
_checkChildren(e);
}
@override
void visitCompoundSelectPart(CompoundSelectPart e, void arg) {
final current = _currentAs<CompoundSelectPart>(e);
_assert(current.mode == e.mode, e);
_checkChildren(e);
}
@override
void visitCompoundSelectStatement(CompoundSelectStatement e, void arg) {
_currentAs<CompoundSelectStatement>(e);
_checkChildren(e);
}
@override
void visitCreateIndexStatement(CreateIndexStatement e, void arg) {
final current = _currentAs<CreateIndexStatement>(e);
_assert(
current.indexName == e.indexName &&
current.unique == e.unique &&
current.ifNotExists == e.ifNotExists,
e);
_checkChildren(e);
}
@override
void visitCreateTableStatement(CreateTableStatement e, void arg) {
final current = _currentAs<CreateTableStatement>(e);
_assert(
current.ifNotExists == e.ifNotExists &&
current.tableName == e.tableName &&
current.withoutRowId == e.withoutRowId &&
current.overriddenDataClassName == e.overriddenDataClassName,
e);
_checkChildren(e);
}
@override
void visitCreateTriggerStatement(CreateTriggerStatement e, void arg) {
final current = _currentAs<CreateTriggerStatement>(e);
_assert(
current.ifNotExists == e.ifNotExists &&
current.triggerName == e.triggerName &&
current.mode == e.mode,
e);
_checkChildren(e);
}
@override
void visitCreateViewStatement(CreateViewStatement e, void arg) {
final current = _currentAs<CreateViewStatement>(e);
_assert(
current.ifNotExists == e.ifNotExists &&
current.viewName == e.viewName &&
const ListEquality().equals(current.columns, e.columns),
e);
_checkChildren(e);
}
@override
void visitCreateVirtualTableStatement(
CreateVirtualTableStatement e, void arg) {
final current = _currentAs<CreateVirtualTableStatement>(e);
_assert(
current.ifNotExists == e.ifNotExists &&
current.tableName == e.tableName &&
current.moduleName == e.moduleName &&
const ListEquality()
.equals(current.argumentContent, e.argumentContent),
e);
_checkChildren(e);
}
@override
void visitDartPlaceholder(DartPlaceholder e, void arg) {
final current = _currentAs<DartPlaceholder>(e);
_assert(current.name == e.name && current.runtimeType == e.runtimeType, e);
_checkChildren(e);
}
@override
void visitDefaultValues(DefaultValues e, void arg) {
_currentAs<DefaultValues>(e);
_checkChildren(e);
}
@override
void visitDeferrableClause(DeferrableClause e, void arg) {
final current = _currentAs<DeferrableClause>(e);
_assert(
current.not == e.not &&
current.declaredInitially == e.declaredInitially,
e);
_checkChildren(e);
}
@override
void visitDeleteStatement(DeleteStatement e, void arg) {
_currentAs<DeleteStatement>(e);
_checkChildren(e);
}
@override
void visitDeleteTriggerTarget(DeleteTarget e, void arg) {
_currentAs<DeleteTarget>(e);
_checkChildren(e);
}
@override
void visitDoNothing(DoNothing e, void arg) {
_currentAs<DoNothing>(e);
_checkChildren(e);
}
@override
void visitDoUpdate(DoUpdate e, void arg) {
_currentAs<DoUpdate>(e);
_checkChildren(e);
}
@override
void visitExists(ExistsExpression e, void arg) {
_currentAs<ExistsExpression>(e);
_checkChildren(e);
}
@override
void visitExpressionFunctionParameters(ExprFunctionParameters e, void arg) {
final current = _currentAs<ExprFunctionParameters>(e);
_assert(current.distinct == e.distinct, e);
_checkChildren(e);
}
@override
void visitExpressionResultColumn(ExpressionResultColumn e, void arg) {
final current = _currentAs<ExpressionResultColumn>(e);
_assert(current.as == e.as, e);
_checkChildren(e);
}
@override
void visitForeignKeyClause(ForeignKeyClause e, void arg) {
final current = _currentAs<ForeignKeyClause>(e);
_assert(
current.onDelete == e.onDelete && current.onUpdate == e.onUpdate, e);
_checkChildren(e);
}
@override
void visitFrameSpec(FrameSpec e, void arg) {
final current = _currentAs<FrameSpec>(e);
_assert(
current.type == e.type &&
current.excludeMode == e.excludeMode &&
current.start == e.start &&
e.end == e.end,
e);
_checkChildren(e);
}
@override
void visitFunction(FunctionExpression e, void arg) {
final current = _currentAs<FunctionExpression>(e);
_assert(current.name == e.name, e);
_checkChildren(e);
}
@override
void visitGroupBy(GroupBy e, void arg) {
_currentAs<GroupBy>(e);
_checkChildren(e);
}
@override
void visitInExpression(InExpression e, void arg) {
final current = _currentAs<InExpression>(e);
_assert(current.not == e.not, e);
_checkChildren(e);
}
@override
void visitIndexedColumn(IndexedColumn e, void arg) {
final current = _currentAs<IndexedColumn>(e);
_assert(current.ordering == e.ordering, e);
_checkChildren(e);
}
@override
void visitInsertStatement(InsertStatement e, void arg) {
final current = _currentAs<InsertStatement>(e);
_assert(current.mode == e.mode, e);
_checkChildren(e);
}
@override
void visitInsertTriggerTarget(InsertTarget e, void arg) {
_currentAs<InsertTarget>(e);
_checkChildren(e);
}
@override
void visitInvalidStatement(InvalidStatement e, void arg) {
_currentAs<InvalidStatement>(e);
_checkChildren(e);
}
@override
void visitIsExpression(IsExpression e, void arg) {
final current = _currentAs<IsExpression>(e);
_assert(current.negated == e.negated, e);
_checkChildren(e);
}
@override
void visitIsNullExpression(IsNullExpression e, void arg) {
final current = _currentAs<IsNullExpression>(e);
_assert(current.negated == e.negated, e);
_checkChildren(e);
}
@override
void visitJoin(Join e, void arg) {
final current = _currentAs<Join>(e);
if (current.natural != e.natural || current.operator != e.operator) {
_notEqual(e);
}
final constraint = current.constraint;
if (constraint is OnConstraint) {
_assert(e.constraint is OnConstraint, e);
} else if (constraint is UsingConstraint) {
if (e.constraint is! UsingConstraint) {
_notEqual(e);
}
final typedOther = e.constraint as UsingConstraint;
_assert(
const ListEquality()
.equals(constraint.columnNames, typedOther.columnNames),
e);
}
_checkChildren(e);
}
@override
void visitJoinClause(JoinClause e, void arg) {
_currentAs<JoinClause>(e);
_checkChildren(e);
}
@override
void visitLimit(Limit e, void arg) {
_currentAs<Limit>(e);
_checkChildren(e);
}
@override
void visitMoorDeclaredStatement(DeclaredStatement e, void arg) {
final current = _currentAs<DeclaredStatement>(e);
_assert(current.identifier == e.identifier && current.as == e.as, e);
_checkChildren(e);
}
@override
void visitMoorFile(MoorFile e, void arg) {
_currentAs<MoorFile>(e);
_checkChildren(e);
}
@override
void visitMoorImportStatement(ImportStatement e, void arg) {
final current = _currentAs<ImportStatement>(e);
_assert(current.importedFile == e.importedFile, e);
_checkChildren(e);
}
@override
void visitMoorNestedStarResultColumn(NestedStarResultColumn e, void arg) {
final current = _currentAs<NestedStarResultColumn>(e);
_assert(current.tableName == e.tableName, e);
_checkChildren(e);
}
@override
void visitMoorStatementParameter(StatementParameter e, void arg) {
if (e is VariableTypeHint) {
final current = _currentAs<VariableTypeHint>(e);
_assert(current.typeName == e.typeName, e);
} else if (e is DartPlaceholderDefaultValue) {
final current = _currentAs<DartPlaceholderDefaultValue>(e);
_assert(current.variableName == e.variableName, e);
}
_checkChildren(e);
}
@override
void visitNamedVariable(ColonNamedVariable e, void arg) {
final current = _currentAs<ColonNamedVariable>(e);
_assert(current.name == e.name, e);
_checkChildren(e);
}
@override
void visitNullLiteral(NullLiteral e, void arg) {
_currentAs<NullLiteral>(e);
_checkChildren(e);
}
@override
void visitNumberedVariable(NumberedVariable e, void arg) {
final current = _currentAs<NumberedVariable>(e);
_assert(current.explicitIndex == e.explicitIndex, e);
_checkChildren(e);
}
@override
void visitNumericLiteral(NumericLiteral e, void arg) {
final current = _currentAs<NumericLiteral>(e);
_assert(current.value == e.value, e);
_checkChildren(e);
}
@override
void visitOrderBy(OrderBy e, void arg) {
_currentAs<OrderBy>(e);
_checkChildren(e);
}
@override
void visitOrderingTerm(OrderingTerm e, void arg) {
final current = _currentAs<OrderingTerm>(e);
_assert(
current.orderingMode == e.orderingMode && current.nulls == e.nulls, e);
_checkChildren(e);
}
@override
void visitParentheses(Parentheses e, void arg) {
_currentAs<Parentheses>(e);
_checkChildren(e);
}
@override
void visitReference(Reference e, void arg) {
final current = _currentAs<Reference>(e);
_assert(
current.tableName == e.tableName && current.columnName == e.columnName,
e);
_checkChildren(e);
}
@override
void visitSelectInsertSource(SelectInsertSource e, void arg) {
_currentAs<SelectInsertSource>(e);
_checkChildren(e);
}
@override
void visitSelectStatement(SelectStatement e, void arg) {
final current = _currentAs<SelectStatement>(e);
_assert(current.distinct == e.distinct, e);
_checkChildren(e);
}
@override
void visitSelectStatementAsSource(SelectStatementAsSource e, void arg) {
final current = _currentAs<SelectStatementAsSource>(e);
_assert(current.as == e.as, e);
_checkChildren(e);
}
@override
void visitSetComponent(SetComponent e, void arg) {
_currentAs<SetComponent>(e);
_checkChildren(e);
}
@override
void visitStarFunctionParameter(StarFunctionParameter e, void arg) {
_currentAs<StarFunctionParameter>(e);
_checkChildren(e);
}
@override
void visitStarResultColumn(StarResultColumn e, void arg) {
final current = _currentAs<StarResultColumn>(e);
_assert(current.tableName == e.tableName, e);
_checkChildren(e);
}
@override
void visitStringComparison(StringComparisonExpression e, void arg) {
final current = _currentAs<StringComparisonExpression>(e);
_assert(current.not == e.not, e);
_checkChildren(e);
}
@override
void visitStringLiteral(StringLiteral e, void arg) {
final current = _currentAs<StringLiteral>(e);
_assert(current.value == e.value, e);
_checkChildren(e);
}
@override
void visitSubQuery(SubQuery e, void arg) {
_currentAs<SubQuery>(e);
_checkChildren(e);
}
@override
void visitTableConstraint(TableConstraint e, void arg) {
final current = _currentAs<TableConstraint>(e);
_assert(current.name == e.name && e.constraintEquals(current), e);
_checkChildren(e);
}
@override
void visitTableReference(TableReference e, void arg) {
final current = _currentAs<TableReference>(e);
_assert(current.tableName == e.tableName && current.as == e.as, e);
_checkChildren(e);
}
@override
void visitTableValuedFunction(TableValuedFunction e, void arg) {
final current = _currentAs<TableValuedFunction>(e);
_assert(current.name == e.name, e);
_checkChildren(e);
}
@override
void visitTimeConstantLiteral(TimeConstantLiteral e, void arg) {
final current = _currentAs<TimeConstantLiteral>(e);
_assert(current.kind == e.kind, e);
_checkChildren(e);
}
@override
void visitTuple(Tuple e, void arg) {
_currentAs<Tuple>(e);
_checkChildren(e);
}
@override
void visitUnaryExpression(UnaryExpression e, void arg) {
final current = _currentAs<UnaryExpression>(e);
_assert(current.operator.type == e.operator.type, e);
_checkChildren(e);
}
@override
void visitUpdateStatement(UpdateStatement e, void arg) {
final current = _currentAs<UpdateStatement>(e);
_assert(current.or == e.or, e);
_checkChildren(e);
}
@override
void visitUpdateTriggerTarget(UpdateTarget e, void arg) {
_currentAs<UpdateTarget>(e);
_checkChildren(e);
}
@override
void visitUpsertClause(UpsertClause e, void arg) {
_currentAs<UpsertClause>(e);
_checkChildren(e);
}
@override
void visitValuesSelectStatement(ValuesSelectStatement e, void arg) {
_currentAs<ValuesSelectStatement>(e);
_checkChildren(e);
}
@override
void visitValuesSource(ValuesSource e, void arg) {
_currentAs<ValuesSource>(e);
_checkChildren(e);
}
@override
void visitWhen(WhenComponent e, void arg) {
_currentAs<WhenComponent>(e);
_checkChildren(e);
}
@override
void visitWindowDefinition(WindowDefinition e, void arg) {
final current = _currentAs<WindowDefinition>(e);
_assert(current.baseWindowName == e.baseWindowName, e);
_checkChildren(e);
}
@override
void visitWithClause(WithClause e, void arg) {
final current = _currentAs<WithClause>(e);
_assert(current.recursive == e.recursive, e);
_checkChildren(e);
}
}
/// Checks whether [a] and [b] are equal. If they aren't, throws an exception.
void enforceEqual(AstNode a, AstNode b) {
if (a.runtimeType != b.runtimeType) {
throw ArgumentError('Not equal: First was $a, second $b');
}
EqualityEnforcingVisitor(a).visit(b, null);
}
if (!a.contentEquals(b)) {
throw ArgumentError('Content not equal: $a and $b');
}
/// Thrown by the [EqualityEnforcingVisitor] when two nodes were determined to
/// be non-equal.
class NotEqualException implements Exception {
final String message;
return enforceEqualIterable(a.childNodes, b.childNodes);
NotEqualException(this.message);
@override
String toString() {
return 'Not equal: $message';
}
}
void enforceEqualIterable(Iterable<AstNode> a, Iterable<AstNode> b) {