Define equality for boolean selectors.
R=kevmoo@google.com
Review URL: https://codereview.chromium.org//1715553002 .
diff --git a/lib/boolean_selector.dart b/lib/boolean_selector.dart
index 92eedbd..790740f 100644
--- a/lib/boolean_selector.dart
+++ b/lib/boolean_selector.dart
@@ -15,6 +15,9 @@
/// operations. See [the README][] for full details.
///
/// [the README]: https://github.com/dart-lang/boolean_selector/blob/master/README.md
+///
+/// Boolean selectors support structural equality. Two selectors that have the
+/// same parsed structure are considered equal.
abstract class BooleanSelector {
/// A selector that accepts all inputs.
static const all = const All();
diff --git a/lib/src/ast.dart b/lib/src/ast.dart
index 26c09bf..13eb633 100644
--- a/lib/src/ast.dart
+++ b/lib/src/ast.dart
@@ -38,6 +38,10 @@
accept(Visitor visitor) => visitor.visitVariable(this);
String toString() => name;
+
+ bool operator==(other) => other is VariableNode && name == other.name;
+
+ int get hashCode => name.hashCode;
}
/// A negation expression.
@@ -56,6 +60,10 @@
String toString() => child is VariableNode || child is NotNode
? "!$child"
: "!($child)";
+
+ bool operator==(other) => other is NotNode && child == other.child;
+
+ int get hashCode => ~child.hashCode;
}
/// An or expression.
@@ -87,6 +95,11 @@
return "$string1 || $string2";
}
+
+ bool operator==(other) =>
+ other is OrNode && left == other.left && right == other.right;
+
+ int get hashCode => left.hashCode ^ right.hashCode;
}
/// An and expression.
@@ -118,6 +131,11 @@
return "$string1 && $string2";
}
+
+ bool operator==(other) =>
+ other is AndNode && left == other.left && right == other.right;
+
+ int get hashCode => left.hashCode ^ right.hashCode;
}
/// A ternary conditional expression.
@@ -149,6 +167,15 @@
var trueString = whenTrue is ConditionalNode ? "($whenTrue)" : whenTrue;
return "$conditionString ? $trueString : $whenFalse";
}
+
+ bool operator==(other) =>
+ other is ConditionalNode &&
+ condition == other.condition &&
+ whenTrue == other.whenTrue &&
+ whenFalse == other.whenFalse;
+
+ int get hashCode =>
+ condition.hashCode ^ whenTrue.hashCode ^ whenFalse.hashCode;
}
/// Like [FileSpan.expand], except if [start] and [end] are `null` or from
diff --git a/lib/src/impl.dart b/lib/src/impl.dart
index 6a40530..c920e52 100644
--- a/lib/src/impl.dart
+++ b/lib/src/impl.dart
@@ -53,4 +53,9 @@
}
String toString() => _selector.toString();
+
+ bool operator==(other) =>
+ other is BooleanSelectorImpl && _selector == other._selector;
+
+ int get hashCode => _selector.hashCode;
}
diff --git a/lib/src/intersection_selector.dart b/lib/src/intersection_selector.dart
index aa51bf9..8c15254 100644
--- a/lib/src/intersection_selector.dart
+++ b/lib/src/intersection_selector.dart
@@ -32,4 +32,11 @@
}
String toString() => "($_selector1) && ($_selector2)";
+
+ bool operator==(other) =>
+ other is IntersectionSelector &&
+ _selector1 == other._selector1 &&
+ _selector2 == other._selector2;
+
+ int get hashCode => _selector1.hashCode ^ _selector2.hashCode;
}
diff --git a/lib/src/union_selector.dart b/lib/src/union_selector.dart
index 6b6cf87..f513f6c 100644
--- a/lib/src/union_selector.dart
+++ b/lib/src/union_selector.dart
@@ -30,4 +30,11 @@
}
String toString() => "($_selector1) && ($_selector2)";
+
+ bool operator==(other) =>
+ other is UnionSelector &&
+ _selector1 == other._selector1 &&
+ _selector2 == other._selector2;
+
+ int get hashCode => _selector1.hashCode ^ _selector2.hashCode;
}
diff --git a/pubspec.yaml b/pubspec.yaml
index 2527dd5..9c0090b 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: boolean_selector
-version: 1.0.0-dev
+version: 1.0.0
description: A flexible syntax for boolean expressions.
author: Dart Team <misc@dartlang.org>
homepage: https://github.com/dart-lang/boolean_selector
diff --git a/test/equality_test.dart b/test/equality_test.dart
new file mode 100644
index 0000000..7ee527b
--- /dev/null
+++ b/test/equality_test.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+
+import 'package:boolean_selector/boolean_selector.dart';
+
+void main() {
+ test("variable", () {
+ _expectEqualsSelf("foo");
+ });
+
+ test("not", () {
+ _expectEqualsSelf("!foo");
+ });
+
+ test("or", () {
+ _expectEqualsSelf("foo || bar");
+ });
+
+ test("and", () {
+ _expectEqualsSelf("foo && bar");
+ });
+
+ test("conditional", () {
+ _expectEqualsSelf("foo ? bar : baz");
+ });
+
+ test("all", () {
+ expect(BooleanSelector.all, equals(BooleanSelector.all));
+ });
+
+ test("none", () {
+ expect(BooleanSelector.none, equals(BooleanSelector.none));
+ });
+
+ test("redundant parens don't matter", () {
+ expect(new BooleanSelector.parse("foo && (bar && baz)"),
+ equals(new BooleanSelector.parse("foo && (bar && baz)")));
+ });
+
+ test("meaningful parens do matter", () {
+ expect(new BooleanSelector.parse("(foo && bar) || baz"),
+ equals(new BooleanSelector.parse("foo && bar || baz")));
+ });
+}
+
+void _expectEqualsSelf(String selector) {
+ expect(new BooleanSelector.parse(selector),
+ equals(new BooleanSelector.parse(selector)));
+}