Fix newly enforced package:pedantic lints (#19)
- always_declare_return_types
- annotate_overrides
- prefer_conditional_assignment
- prefer_if_null_operators
- prefer_single_quotes
- use_function_type_syntax_for_parameters
Drop unused author field from pubspec.
Simplify dependency on `string_scanner` since older versions aren't
supported on the Dart 2 SDK and so wouldn't be picked up even with a
wide constraint.
diff --git a/example/example.dart b/example/example.dart
index 35548e4..a4f7879 100644
--- a/example/example.dart
+++ b/example/example.dart
@@ -1,6 +1,6 @@
import 'package:boolean_selector/boolean_selector.dart';
void main(List<String> args) {
- var selector = BooleanSelector.parse("(x && y) || z");
+ var selector = BooleanSelector.parse('(x && y) || z');
print(selector.evaluate((variable) => args.contains(variable)));
}
diff --git a/lib/boolean_selector.dart b/lib/boolean_selector.dart
index adc36b3..e32eb40 100644
--- a/lib/boolean_selector.dart
+++ b/lib/boolean_selector.dart
@@ -54,5 +54,5 @@
///
/// The [isDefined] function should return `true` for any variables that are
/// considered valid, and `false` for any invalid or undefined variables.
- void validate(bool isDefined(String variable));
+ void validate(bool Function(String variable) isDefined);
}
diff --git a/lib/src/all.dart b/lib/src/all.dart
index f4b2c1f..d634b9f 100644
--- a/lib/src/all.dart
+++ b/lib/src/all.dart
@@ -8,17 +8,23 @@
class All implements BooleanSelector {
// TODO(nweiz): Stop explicitly providing a type argument when sdk#32412 is
// fixed.
+ @override
final variables = const <String>[];
const All();
+ @override
bool evaluate(semantics) => true;
+ @override
BooleanSelector intersection(BooleanSelector other) => other;
+ @override
BooleanSelector union(BooleanSelector other) => this;
- void validate(bool isDefined(String variable)) {}
+ @override
+ void validate(bool Function(String variable) isDefined) {}
- String toString() => "<all>";
+ @override
+ String toString() => '<all>';
}
diff --git a/lib/src/ast.dart b/lib/src/ast.dart
index c532535..1408ffd 100644
--- a/lib/src/ast.dart
+++ b/lib/src/ast.dart
@@ -21,52 +21,65 @@
Iterable<String> get variables;
/// Calls the appropriate [Visitor] method on [this] and returns the result.
- accept(Visitor visitor);
+ dynamic accept(Visitor visitor);
}
/// A single variable.
class VariableNode implements Node {
+ @override
final FileSpan span;
/// The variable name.
final String name;
+ @override
Iterable<String> get variables => [name];
VariableNode(this.name, [this.span]);
- accept(Visitor visitor) => visitor.visitVariable(this);
+ @override
+ dynamic accept(Visitor visitor) => visitor.visitVariable(this);
+ @override
String toString() => name;
+ @override
bool operator ==(other) => other is VariableNode && name == other.name;
+ @override
int get hashCode => name.hashCode;
}
/// A negation expression.
class NotNode implements Node {
+ @override
final FileSpan span;
/// The expression being negated.
final Node child;
+ @override
Iterable<String> get variables => child.variables;
NotNode(this.child, [this.span]);
- accept(Visitor visitor) => visitor.visitNot(this);
+ @override
+ dynamic accept(Visitor visitor) => visitor.visitNot(this);
+ @override
String toString() =>
- child is VariableNode || child is NotNode ? "!$child" : "!($child)";
+ child is VariableNode || child is NotNode ? '!$child' : '!($child)';
+ @override
bool operator ==(other) => other is NotNode && child == other.child;
+ @override
int get hashCode => ~child.hashCode;
}
/// An or expression.
class OrNode implements Node {
+ @override
FileSpan get span => _expandSafe(left.span, right.span);
/// The left-hand branch of the expression.
@@ -75,6 +88,7 @@
/// The right-hand branch of the expression.
final Node right;
+ @override
Iterable<String> get variables sync* {
yield* left.variables;
yield* right.variables;
@@ -82,24 +96,29 @@
OrNode(this.left, this.right);
- accept(Visitor visitor) => visitor.visitOr(this);
+ @override
+ dynamic accept(Visitor visitor) => visitor.visitOr(this);
+ @override
String toString() {
- var string1 = left is AndNode || left is ConditionalNode ? "($left)" : left;
+ var string1 = left is AndNode || left is ConditionalNode ? '($left)' : left;
var string2 =
- right is AndNode || right is ConditionalNode ? "($right)" : right;
+ right is AndNode || right is ConditionalNode ? '($right)' : right;
- return "$string1 || $string2";
+ return '$string1 || $string2';
}
+ @override
bool operator ==(other) =>
other is OrNode && left == other.left && right == other.right;
+ @override
int get hashCode => left.hashCode ^ right.hashCode;
}
/// An and expression.
class AndNode implements Node {
+ @override
FileSpan get span => _expandSafe(left.span, right.span);
/// The left-hand branch of the expression.
@@ -108,6 +127,7 @@
/// The right-hand branch of the expression.
final Node right;
+ @override
Iterable<String> get variables sync* {
yield* left.variables;
yield* right.variables;
@@ -115,24 +135,29 @@
AndNode(this.left, this.right);
- accept(Visitor visitor) => visitor.visitAnd(this);
+ @override
+ dynamic accept(Visitor visitor) => visitor.visitAnd(this);
+ @override
String toString() {
- var string1 = left is OrNode || left is ConditionalNode ? "($left)" : left;
+ var string1 = left is OrNode || left is ConditionalNode ? '($left)' : left;
var string2 =
- right is OrNode || right is ConditionalNode ? "($right)" : right;
+ right is OrNode || right is ConditionalNode ? '($right)' : right;
- return "$string1 && $string2";
+ return '$string1 && $string2';
}
+ @override
bool operator ==(other) =>
other is AndNode && left == other.left && right == other.right;
+ @override
int get hashCode => left.hashCode ^ right.hashCode;
}
/// A ternary conditional expression.
class ConditionalNode implements Node {
+ @override
FileSpan get span => _expandSafe(condition.span, whenFalse.span);
/// The condition expression to check.
@@ -144,6 +169,7 @@
/// The branch to run if the condition is false.
final Node whenFalse;
+ @override
Iterable<String> get variables sync* {
yield* condition.variables;
yield* whenTrue.variables;
@@ -152,21 +178,25 @@
ConditionalNode(this.condition, this.whenTrue, this.whenFalse);
- accept(Visitor visitor) => visitor.visitConditional(this);
+ @override
+ dynamic accept(Visitor visitor) => visitor.visitConditional(this);
+ @override
String toString() {
var conditionString =
- condition is ConditionalNode ? "($condition)" : condition;
- var trueString = whenTrue is ConditionalNode ? "($whenTrue)" : whenTrue;
- return "$conditionString ? $trueString : $whenFalse";
+ condition is ConditionalNode ? '($condition)' : condition;
+ var trueString = whenTrue is ConditionalNode ? '($whenTrue)' : whenTrue;
+ return '$conditionString ? $trueString : $whenFalse';
}
+ @override
bool operator ==(other) =>
other is ConditionalNode &&
condition == other.condition &&
whenTrue == other.whenTrue &&
whenFalse == other.whenFalse;
+ @override
int get hashCode =>
condition.hashCode ^ whenTrue.hashCode ^ whenFalse.hashCode;
}
diff --git a/lib/src/evaluator.dart b/lib/src/evaluator.dart
index fa02f74..c15c0ca 100644
--- a/lib/src/evaluator.dart
+++ b/lib/src/evaluator.dart
@@ -18,16 +18,21 @@
? semantics.toSet().contains
: semantics as _Semantics;
+ @override
bool visitVariable(VariableNode node) => _semantics(node.name);
+ @override
bool visitNot(NotNode node) => !node.child.accept(this);
+ @override
bool visitOr(OrNode node) =>
node.left.accept(this) || node.right.accept(this);
+ @override
bool visitAnd(AndNode node) =>
node.left.accept(this) && node.right.accept(this);
+ @override
bool visitConditional(ConditionalNode node) => node.condition.accept(this)
? node.whenTrue.accept(this)
: node.whenFalse.accept(this);
diff --git a/lib/src/impl.dart b/lib/src/impl.dart
index 49e0f5f..3cd87c8 100644
--- a/lib/src/impl.dart
+++ b/lib/src/impl.dart
@@ -28,10 +28,13 @@
BooleanSelectorImpl._(this._selector);
+ @override
Iterable<String> get variables => _selector.variables;
+ @override
bool evaluate(semantics) => _selector.accept(Evaluator(semantics));
+ @override
BooleanSelector intersection(BooleanSelector other) {
if (other == BooleanSelector.all) return this;
if (other == BooleanSelector.none) return other;
@@ -40,6 +43,7 @@
: IntersectionSelector(this, other);
}
+ @override
BooleanSelector union(BooleanSelector other) {
if (other == BooleanSelector.all) return other;
if (other == BooleanSelector.none) return this;
@@ -48,14 +52,18 @@
: UnionSelector(this, other);
}
- void validate(bool isDefined(String variable)) {
+ @override
+ void validate(bool Function(String variable) isDefined) {
_selector.accept(Validator(isDefined));
}
+ @override
String toString() => _selector.toString();
+ @override
bool operator ==(other) =>
other is BooleanSelectorImpl && _selector == other._selector;
+ @override
int get hashCode => _selector.hashCode;
}
diff --git a/lib/src/intersection_selector.dart b/lib/src/intersection_selector.dart
index ef6bfdd..6c1d314 100644
--- a/lib/src/intersection_selector.dart
+++ b/lib/src/intersection_selector.dart
@@ -10,6 +10,7 @@
final BooleanSelector _selector1;
final BooleanSelector _selector2;
+ @override
Iterable<String> get variables sync* {
yield* _selector1.variables;
yield* _selector2.variables;
@@ -17,25 +18,32 @@
IntersectionSelector(this._selector1, this._selector2);
+ @override
bool evaluate(semantics) =>
_selector1.evaluate(semantics) && _selector2.evaluate(semantics);
+ @override
BooleanSelector intersection(BooleanSelector other) =>
IntersectionSelector(this, other);
+ @override
BooleanSelector union(BooleanSelector other) => UnionSelector(this, other);
- void validate(bool isDefined(String variable)) {
+ @override
+ void validate(bool Function(String variable) isDefined) {
_selector1.validate(isDefined);
_selector2.validate(isDefined);
}
- String toString() => "($_selector1) && ($_selector2)";
+ @override
+ String toString() => '($_selector1) && ($_selector2)';
+ @override
bool operator ==(other) =>
other is IntersectionSelector &&
_selector1 == other._selector1 &&
_selector2 == other._selector2;
+ @override
int get hashCode => _selector1.hashCode ^ _selector2.hashCode;
}
diff --git a/lib/src/none.dart b/lib/src/none.dart
index 637f185..1fc616f 100644
--- a/lib/src/none.dart
+++ b/lib/src/none.dart
@@ -8,17 +8,23 @@
class None implements BooleanSelector {
// TODO(nweiz): Stop explicitly providing a type argument when sdk#32412 is
// fixed.
+ @override
final variables = const <String>[];
const None();
+ @override
bool evaluate(semantics) => false;
+ @override
BooleanSelector intersection(BooleanSelector other) => this;
+ @override
BooleanSelector union(BooleanSelector other) => other;
- void validate(bool isDefined(String variable)) {}
+ @override
+ void validate(bool Function(String) isDefined) {}
- String toString() => "<none>";
+ @override
+ String toString() => '<none>';
}
diff --git a/lib/src/parser.dart b/lib/src/parser.dart
index 91a2663..1a0a73b 100644
--- a/lib/src/parser.dart
+++ b/lib/src/parser.dart
@@ -28,7 +28,7 @@
if (_scanner.peek().type != TokenType.endOfFile) {
throw SourceSpanFormatException(
- "Expected end of input.", _scanner.peek().span);
+ 'Expected end of input.', _scanner.peek().span);
}
return selector;
@@ -97,7 +97,7 @@
return VariableNode((token as IdentifierToken).name, token.span);
default:
- throw SourceSpanFormatException("Expected expression.", token.span);
+ throw SourceSpanFormatException('Expected expression.', token.span);
}
}
}
diff --git a/lib/src/scanner.dart b/lib/src/scanner.dart
index 729c483..6325175 100644
--- a/lib/src/scanner.dart
+++ b/lib/src/scanner.dart
@@ -9,19 +9,19 @@
/// A regular expression matching both whitespace and single-line comments.
///
/// This will only match if consumes at least one character.
-final _whitespaceAndSingleLineComments = RegExp(r"([ \t\n]+|//[^\n]*(\n|$))+");
+final _whitespaceAndSingleLineComments = RegExp(r'([ \t\n]+|//[^\n]*(\n|$))+');
/// A regular expression matching the body of a multi-line comment, after `/*`
/// but before `*/` or a nested `/*`.
///
/// This will only match if it consumes at least one character.
-final _multiLineCommentBody = RegExp(r"([^/*]|/[^*]|\*[^/])+");
+final _multiLineCommentBody = RegExp(r'([^/*]|/[^*]|\*[^/])+');
/// A regular expression matching a hyphenated identifier.
///
/// This is like a standard Dart identifier, except that it can also contain
/// hyphens.
-final _hyphenatedIdentifier = RegExp(r"[a-zA-Z_-][a-zA-Z0-9_-]*");
+final _hyphenatedIdentifier = RegExp(r'[a-zA-Z_-][a-zA-Z0-9_-]*');
/// A scanner that converts a boolean selector string into a stream of tokens.
class Scanner {
@@ -40,17 +40,14 @@
///
/// Throws a [StateError] if a [TokenType.endOfFile] token has already been
/// consumed.
- Token peek() {
- if (_next == null) _next = _getNext();
- return _next;
- }
+ Token peek() => _next ??= _getNext();
/// Consumes and returns the next token in the stream.
///
/// Throws a [StateError] if a [TokenType.endOfFile] token has already been
/// consumed.
Token next() {
- var token = _next == null ? _getNext() : _next;
+ var token = _next ?? _getNext();
_endOfFileEmitted = token.type == TokenType.endOfFile;
_next = null;
return token;
@@ -69,7 +66,7 @@
/// Scan and return the next token in the stream.
Token _getNext() {
- if (_endOfFileEmitted) throw StateError("No more tokens.");
+ if (_endOfFileEmitted) throw StateError('No more tokens.');
_consumeWhitespace();
if (_scanner.isDone) {
@@ -111,7 +108,7 @@
/// This validates that the next two characters are `||`.
Token _scanOr() {
var start = _scanner.state;
- _scanner.expect("||");
+ _scanner.expect('||');
return Token(TokenType.or, _scanner.spanFrom(start));
}
@@ -120,13 +117,13 @@
/// This validates that the next two characters are `&&`.
Token _scanAnd() {
var start = _scanner.state;
- _scanner.expect("&&");
+ _scanner.expect('&&');
return Token(TokenType.and, _scanner.spanFrom(start));
}
/// Scans and returns an identifier token.
Token _scanIdentifier() {
- _scanner.expect(_hyphenatedIdentifier, name: "expression");
+ _scanner.expect(_hyphenatedIdentifier, name: 'expression');
return IdentifierToken(_scanner.lastMatch[0], _scanner.lastSpan);
}
@@ -143,12 +140,12 @@
///
/// Returns whether or not a comment was consumed.
bool _multiLineComment() {
- if (!_scanner.scan("/*")) return false;
+ if (!_scanner.scan('/*')) return false;
while (_scanner.scan(_multiLineCommentBody) || _multiLineComment()) {
// Do nothing.
}
- _scanner.expect("*/");
+ _scanner.expect('*/');
return true;
}
diff --git a/lib/src/token.dart b/lib/src/token.dart
index 908d8a9..19e6864 100644
--- a/lib/src/token.dart
+++ b/lib/src/token.dart
@@ -21,7 +21,9 @@
/// A token representing an identifier.
class IdentifierToken implements Token {
+ @override
final type = TokenType.identifier;
+ @override
final FileSpan span;
/// The name of the identifier.
@@ -29,42 +31,44 @@
IdentifierToken(this.name, this.span);
+ @override
String toString() => 'identifier "$name"';
}
/// An enumeration of types of tokens.
class TokenType {
/// A `(` character.
- static const leftParen = TokenType._("left paren");
+ static const leftParen = TokenType._('left paren');
/// A `)` character.
- static const rightParen = TokenType._("right paren");
+ static const rightParen = TokenType._('right paren');
/// A `||` sequence.
- static const or = TokenType._("or");
+ static const or = TokenType._('or');
/// A `&&` sequence.
- static const and = TokenType._("and");
+ static const and = TokenType._('and');
/// A `!` character.
- static const not = TokenType._("not");
+ static const not = TokenType._('not');
/// A `?` character.
- static const questionMark = TokenType._("question mark");
+ static const questionMark = TokenType._('question mark');
/// A `:` character.
- static const colon = TokenType._("colon");
+ static const colon = TokenType._('colon');
/// A named identifier.
- static const identifier = TokenType._("identifier");
+ static const identifier = TokenType._('identifier');
/// The end of the selector.
- static const endOfFile = TokenType._("end of file");
+ static const endOfFile = TokenType._('end of file');
/// The name of the token type.
final String name;
const TokenType._(this.name);
+ @override
String toString() => name;
}
diff --git a/lib/src/union_selector.dart b/lib/src/union_selector.dart
index a3a9b0a..c985be9 100644
--- a/lib/src/union_selector.dart
+++ b/lib/src/union_selector.dart
@@ -12,28 +12,36 @@
UnionSelector(this._selector1, this._selector2);
+ @override
List<String> get variables =>
_selector1.variables.toList()..addAll(_selector2.variables);
+ @override
bool evaluate(semantics) =>
_selector1.evaluate(semantics) || _selector2.evaluate(semantics);
+ @override
BooleanSelector intersection(BooleanSelector other) =>
IntersectionSelector(this, other);
+ @override
BooleanSelector union(BooleanSelector other) => UnionSelector(this, other);
- void validate(bool isDefined(String variable)) {
+ @override
+ void validate(bool Function(String variable) isDefined) {
_selector1.validate(isDefined);
_selector2.validate(isDefined);
}
- String toString() => "($_selector1) && ($_selector2)";
+ @override
+ String toString() => '($_selector1) && ($_selector2)';
+ @override
bool operator ==(other) =>
other is UnionSelector &&
_selector1 == other._selector1 &&
_selector2 == other._selector2;
+ @override
int get hashCode => _selector1.hashCode ^ _selector2.hashCode;
}
diff --git a/lib/src/validator.dart b/lib/src/validator.dart
index deea1ef..a7f49f2 100644
--- a/lib/src/validator.dart
+++ b/lib/src/validator.dart
@@ -15,8 +15,9 @@
Validator(this._isDefined);
+ @override
void visitVariable(VariableNode node) {
if (_isDefined(node.name)) return;
- throw SourceSpanFormatException("Undefined variable.", node.span);
+ throw SourceSpanFormatException('Undefined variable.', node.span);
}
}
diff --git a/lib/src/visitor.dart b/lib/src/visitor.dart
index 4bc0436..d0efe72 100644
--- a/lib/src/visitor.dart
+++ b/lib/src/visitor.dart
@@ -20,22 +20,27 @@
abstract class RecursiveVisitor implements Visitor {
const RecursiveVisitor();
+ @override
void visitVariable(VariableNode node) {}
+ @override
void visitNot(NotNode node) {
node.child.accept(this);
}
+ @override
void visitOr(OrNode node) {
node.left.accept(this);
node.right.accept(this);
}
+ @override
void visitAnd(AndNode node) {
node.left.accept(this);
node.right.accept(this);
}
+ @override
void visitConditional(ConditionalNode node) {
node.condition.accept(this);
node.whenTrue.accept(this);
diff --git a/pubspec.yaml b/pubspec.yaml
index 4b4a313..ba9a4b8 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,9 +1,8 @@
name: boolean_selector
-version: 1.0.5
+version: 1.0.6-dev
description: >-
A flexible syntax for boolean expressions, based on a simplified version of
Dart's expression syntax.
-author: Dart Team <misc@dartlang.org>
homepage: https://github.com/dart-lang/boolean_selector
environment:
@@ -11,7 +10,7 @@
dependencies:
source_span: ^1.0.0
- string_scanner: '>=0.1.1 <2.0.0'
+ string_scanner: ^1.0.0
dev_dependencies:
pedantic: ^1.0.0
diff --git a/test/equality_test.dart b/test/equality_test.dart
index 4470cfd..b0d2500 100644
--- a/test/equality_test.dart
+++ b/test/equality_test.dart
@@ -7,42 +7,42 @@
import 'package:boolean_selector/boolean_selector.dart';
void main() {
- test("variable", () {
- _expectEqualsSelf("foo");
+ test('variable', () {
+ _expectEqualsSelf('foo');
});
- test("not", () {
- _expectEqualsSelf("!foo");
+ test('not', () {
+ _expectEqualsSelf('!foo');
});
- test("or", () {
- _expectEqualsSelf("foo || bar");
+ test('or', () {
+ _expectEqualsSelf('foo || bar');
});
- test("and", () {
- _expectEqualsSelf("foo && bar");
+ test('and', () {
+ _expectEqualsSelf('foo && bar');
});
- test("conditional", () {
- _expectEqualsSelf("foo ? bar : baz");
+ test('conditional', () {
+ _expectEqualsSelf('foo ? bar : baz');
});
- test("all", () {
+ test('all', () {
expect(BooleanSelector.all, equals(BooleanSelector.all));
});
- test("none", () {
+ test('none', () {
expect(BooleanSelector.none, equals(BooleanSelector.none));
});
test("redundant parens don't matter", () {
- expect(BooleanSelector.parse("foo && (bar && baz)"),
- equals(BooleanSelector.parse("foo && (bar && baz)")));
+ expect(BooleanSelector.parse('foo && (bar && baz)'),
+ equals(BooleanSelector.parse('foo && (bar && baz)')));
});
- test("meaningful parens do matter", () {
- expect(BooleanSelector.parse("(foo && bar) || baz"),
- equals(BooleanSelector.parse("foo && bar || baz")));
+ test('meaningful parens do matter', () {
+ expect(BooleanSelector.parse('(foo && bar) || baz'),
+ equals(BooleanSelector.parse('foo && bar || baz')));
});
}
diff --git a/test/evaluate_test.dart b/test/evaluate_test.dart
index d6961ec..9df5fdc 100644
--- a/test/evaluate_test.dart
+++ b/test/evaluate_test.dart
@@ -7,41 +7,41 @@
import 'package:boolean_selector/boolean_selector.dart';
void main() {
- group("operator:", () {
- test("conditional", () {
- _expectEval("true ? true : false", true);
- _expectEval("true ? false : true", false);
- _expectEval("false ? true : false", false);
- _expectEval("false ? false : true", true);
+ group('operator:', () {
+ test('conditional', () {
+ _expectEval('true ? true : false', true);
+ _expectEval('true ? false : true', false);
+ _expectEval('false ? true : false', false);
+ _expectEval('false ? false : true', true);
});
- test("or", () {
- _expectEval("true || true", true);
- _expectEval("true || false", true);
- _expectEval("false || true", true);
- _expectEval("false || false", false);
+ test('or', () {
+ _expectEval('true || true', true);
+ _expectEval('true || false', true);
+ _expectEval('false || true', true);
+ _expectEval('false || false', false);
});
- test("and", () {
- _expectEval("true && true", true);
- _expectEval("true && false", false);
- _expectEval("false && true", false);
- _expectEval("false && false", false);
+ test('and', () {
+ _expectEval('true && true', true);
+ _expectEval('true && false', false);
+ _expectEval('false && true', false);
+ _expectEval('false && false', false);
});
- test("not", () {
- _expectEval("!true", false);
- _expectEval("!false", true);
+ test('not', () {
+ _expectEval('!true', false);
+ _expectEval('!false', true);
});
});
- test("with a semantics function", () {
- _expectEval("foo", false,
- semantics: (String variable) => variable.contains("a"));
- _expectEval("bar", true,
- semantics: (String variable) => variable.contains("a"));
- _expectEval("baz", true,
- semantics: (String variable) => variable.contains("a"));
+ test('with a semantics function', () {
+ _expectEval('foo', false,
+ semantics: (String variable) => variable.contains('a'));
+ _expectEval('bar', true,
+ semantics: (String variable) => variable.contains('a'));
+ _expectEval('baz', true,
+ semantics: (String variable) => variable.contains('a'));
});
}
@@ -58,5 +58,5 @@
/// By default, "true" is true and all other variables are "false".
bool _eval(String expression, {semantics}) {
var selector = BooleanSelector.parse(expression);
- return selector.evaluate(semantics ?? ["true"]);
+ return selector.evaluate(semantics ?? ['true']);
}
diff --git a/test/parser_test.dart b/test/parser_test.dart
index 43af40f..5a1bd83 100644
--- a/test/parser_test.dart
+++ b/test/parser_test.dart
@@ -20,230 +20,230 @@
final _isNotNode = TypeMatcher<NotNode>();
void main() {
- group("parses a conditional expression", () {
- test("with identifiers", () {
- var node = _parse(" a ? b : c ");
- expect(node.toString(), equals("a ? b : c"));
+ group('parses a conditional expression', () {
+ test('with identifiers', () {
+ var node = _parse(' a ? b : c ');
+ expect(node.toString(), equals('a ? b : c'));
- expect(node.span.text, equals("a ? b : c"));
+ expect(node.span.text, equals('a ? b : c'));
expect(node.span.start.offset, equals(2));
expect(node.span.end.offset, equals(11));
});
- test("with nested ors", () {
+ test('with nested ors', () {
// Should parse as "(a || b) ? (c || d) : (e || f)".
// Should not parse as "a || (b ? (c || d) : (e || f))".
// Should not parse as "((a || b) ? (c || d) : e) || f".
// Should not parse as "a || (b ? (c || d) : e) || f".
- _expectToString("a || b ? c || d : e || f", "a || b ? c || d : e || f");
+ _expectToString('a || b ? c || d : e || f', 'a || b ? c || d : e || f');
});
- test("with a conditional expression as branch 1", () {
+ test('with a conditional expression as branch 1', () {
// Should parse as "a ? (b ? c : d) : e".
- var node = _parse("a ? b ? c : d : e");
+ var node = _parse('a ? b ? c : d : e');
expect(node, _isConditionalNode);
- expect(node.condition, _isVar("a"));
- expect(node.whenFalse, _isVar("e"));
+ expect(node.condition, _isVar('a'));
+ expect(node.whenFalse, _isVar('e'));
expect(node.whenTrue, _isConditionalNode);
- expect(node.whenTrue.condition, _isVar("b"));
- expect(node.whenTrue.whenTrue, _isVar("c"));
- expect(node.whenTrue.whenFalse, _isVar("d"));
+ expect(node.whenTrue.condition, _isVar('b'));
+ expect(node.whenTrue.whenTrue, _isVar('c'));
+ expect(node.whenTrue.whenFalse, _isVar('d'));
});
- test("with a conditional expression as branch 2", () {
+ test('with a conditional expression as branch 2', () {
// Should parse as "a ? b : (c ? d : e)".
// Should not parse as "(a ? b : c) ? d : e".
- var node = _parse("a ? b : c ? d : e");
+ var node = _parse('a ? b : c ? d : e');
expect(node, _isConditionalNode);
- expect(node.condition, _isVar("a"));
- expect(node.whenTrue, _isVar("b"));
+ expect(node.condition, _isVar('a'));
+ expect(node.whenTrue, _isVar('b'));
expect(node.whenFalse, _isConditionalNode);
- expect(node.whenFalse.condition, _isVar("c"));
- expect(node.whenFalse.whenTrue, _isVar("d"));
- expect(node.whenFalse.whenFalse, _isVar("e"));
+ expect(node.whenFalse.condition, _isVar('c'));
+ expect(node.whenFalse.whenTrue, _isVar('d'));
+ expect(node.whenFalse.whenFalse, _isVar('e'));
});
- group("which must have", () {
- test("an expression after the ?", () {
- expect(() => _parse("a ?"), throwsFormatException);
- expect(() => _parse("a ? && b"), throwsFormatException);
+ group('which must have', () {
+ test('an expression after the ?', () {
+ expect(() => _parse('a ?'), throwsFormatException);
+ expect(() => _parse('a ? && b'), throwsFormatException);
});
- test("a :", () {
- expect(() => _parse("a ? b"), throwsFormatException);
- expect(() => _parse("a ? b && c"), throwsFormatException);
+ test('a :', () {
+ expect(() => _parse('a ? b'), throwsFormatException);
+ expect(() => _parse('a ? b && c'), throwsFormatException);
});
- test("an expression after the :", () {
- expect(() => _parse("a ? b :"), throwsFormatException);
- expect(() => _parse("a ? b : && c"), throwsFormatException);
+ test('an expression after the :', () {
+ expect(() => _parse('a ? b :'), throwsFormatException);
+ expect(() => _parse('a ? b : && c'), throwsFormatException);
});
});
});
- group("parses an or expression", () {
- test("with identifiers", () {
- var node = _parse(" a || b ");
+ group('parses an or expression', () {
+ test('with identifiers', () {
+ var node = _parse(' a || b ');
expect(node, _isOrNode);
- expect(node.left, _isVar("a"));
- expect(node.right, _isVar("b"));
+ expect(node.left, _isVar('a'));
+ expect(node.right, _isVar('b'));
- expect(node.span.text, equals("a || b"));
+ expect(node.span.text, equals('a || b'));
expect(node.span.start.offset, equals(2));
expect(node.span.end.offset, equals(8));
});
- test("with nested ands", () {
+ test('with nested ands', () {
// Should parse as "(a && b) || (c && d)".
// Should not parse as "a && (b || c) && d".
- var node = _parse("a && b || c && d");
+ var node = _parse('a && b || c && d');
expect(node, _isOrNode);
expect(node.left, _isAndNode);
- expect(node.left.left, _isVar("a"));
- expect(node.left.right, _isVar("b"));
+ expect(node.left.left, _isVar('a'));
+ expect(node.left.right, _isVar('b'));
expect(node.right, _isAndNode);
- expect(node.right.left, _isVar("c"));
- expect(node.right.right, _isVar("d"));
+ expect(node.right.left, _isVar('c'));
+ expect(node.right.right, _isVar('d'));
});
- test("with trailing ors", () {
+ test('with trailing ors', () {
// Should parse as "a || (b || (c || d))", although it doesn't affect the
// semantics.
- var node = _parse("a || b || c || d");
+ var node = _parse('a || b || c || d');
- for (var variable in ["a", "b", "c"]) {
+ for (var variable in ['a', 'b', 'c']) {
expect(node, _isOrNode);
expect(node.left, _isVar(variable));
node = node.right;
}
- expect(node, _isVar("d"));
+ expect(node, _isVar('d'));
});
- test("which must have an expression after the ||", () {
- expect(() => _parse("a ||"), throwsFormatException);
- expect(() => _parse("a || && b"), throwsFormatException);
+ test('which must have an expression after the ||', () {
+ expect(() => _parse('a ||'), throwsFormatException);
+ expect(() => _parse('a || && b'), throwsFormatException);
});
});
- group("parses an and expression", () {
- test("with identifiers", () {
- var node = _parse(" a && b ");
+ group('parses an and expression', () {
+ test('with identifiers', () {
+ var node = _parse(' a && b ');
expect(node, _isAndNode);
- expect(node.left, _isVar("a"));
- expect(node.right, _isVar("b"));
+ expect(node.left, _isVar('a'));
+ expect(node.right, _isVar('b'));
- expect(node.span.text, equals("a && b"));
+ expect(node.span.text, equals('a && b'));
expect(node.span.start.offset, equals(2));
expect(node.span.end.offset, equals(8));
});
- test("with nested nots", () {
+ test('with nested nots', () {
// Should parse as "(!a) && (!b)", obviously.
// Should not parse as "!(a && (!b))".
- var node = _parse("!a && !b");
+ var node = _parse('!a && !b');
expect(node, _isAndNode);
expect(node.left, _isNotNode);
- expect(node.left.child, _isVar("a"));
+ expect(node.left.child, _isVar('a'));
expect(node.right, _isNotNode);
- expect(node.right.child, _isVar("b"));
+ expect(node.right.child, _isVar('b'));
});
- test("with trailing ands", () {
+ test('with trailing ands', () {
// Should parse as "a && (b && (c && d))", although it doesn't affect the
// semantics since .
- var node = _parse("a && b && c && d");
+ var node = _parse('a && b && c && d');
- for (var variable in ["a", "b", "c"]) {
+ for (var variable in ['a', 'b', 'c']) {
expect(node, _isAndNode);
expect(node.left, _isVar(variable));
node = node.right;
}
- expect(node, _isVar("d"));
+ expect(node, _isVar('d'));
});
- test("which must have an expression after the &&", () {
- expect(() => _parse("a &&"), throwsFormatException);
- expect(() => _parse("a && && b"), throwsFormatException);
+ test('which must have an expression after the &&', () {
+ expect(() => _parse('a &&'), throwsFormatException);
+ expect(() => _parse('a && && b'), throwsFormatException);
});
});
- group("parses a not expression", () {
- test("with an identifier", () {
- var node = _parse(" ! a ");
+ group('parses a not expression', () {
+ test('with an identifier', () {
+ var node = _parse(' ! a ');
expect(node, _isNotNode);
- expect(node.child, _isVar("a"));
+ expect(node.child, _isVar('a'));
- expect(node.span.text, equals("! a"));
+ expect(node.span.text, equals('! a'));
expect(node.span.start.offset, equals(2));
expect(node.span.end.offset, equals(5));
});
- test("with a parenthesized expression", () {
- var node = _parse("!(a || b)");
+ test('with a parenthesized expression', () {
+ var node = _parse('!(a || b)');
expect(node, _isNotNode);
expect(node.child, _isOrNode);
- expect(node.child.left, _isVar("a"));
- expect(node.child.right, _isVar("b"));
+ expect(node.child.left, _isVar('a'));
+ expect(node.child.right, _isVar('b'));
});
- test("with a nested not", () {
- var node = _parse("!!a");
+ test('with a nested not', () {
+ var node = _parse('!!a');
expect(node, _isNotNode);
expect(node.child, _isNotNode);
- expect(node.child.child, _isVar("a"));
+ expect(node.child.child, _isVar('a'));
});
- test("which must have an expression after the !", () {
- expect(() => _parse("!"), throwsFormatException);
- expect(() => _parse("! && a"), throwsFormatException);
+ test('which must have an expression after the !', () {
+ expect(() => _parse('!'), throwsFormatException);
+ expect(() => _parse('! && a'), throwsFormatException);
});
});
- group("parses a parenthesized expression", () {
- test("with an identifier", () {
- var node = _parse("(a)");
- expect(node, _isVar("a"));
+ group('parses a parenthesized expression', () {
+ test('with an identifier', () {
+ var node = _parse('(a)');
+ expect(node, _isVar('a'));
});
- test("controls precedence", () {
+ test('controls precedence', () {
// Without parentheses, this would parse as "(a || b) ? c : d".
- var node = _parse("a || (b ? c : d)");
+ var node = _parse('a || (b ? c : d)');
expect(node, _isOrNode);
- expect(node.left, _isVar("a"));
+ expect(node.left, _isVar('a'));
expect(node.right, _isConditionalNode);
- expect(node.right.condition, _isVar("b"));
- expect(node.right.whenTrue, _isVar("c"));
- expect(node.right.whenFalse, _isVar("d"));
+ expect(node.right.condition, _isVar('b'));
+ expect(node.right.whenTrue, _isVar('c'));
+ expect(node.right.whenFalse, _isVar('d'));
});
- group("which must have", () {
- test("an expression within the ()", () {
- expect(() => _parse("()"), throwsFormatException);
- expect(() => _parse("( && a )"), throwsFormatException);
+ group('which must have', () {
+ test('an expression within the ()', () {
+ expect(() => _parse('()'), throwsFormatException);
+ expect(() => _parse('( && a )'), throwsFormatException);
});
- test("a matching )", () {
- expect(() => _parse("( a"), throwsFormatException);
+ test('a matching )', () {
+ expect(() => _parse('( a'), throwsFormatException);
});
});
});
- group("disallows", () {
- test("an empty selector", () {
- expect(() => _parse(""), throwsFormatException);
+ group('disallows', () {
+ test('an empty selector', () {
+ expect(() => _parse(''), throwsFormatException);
});
- test("too many expressions", () {
- expect(() => _parse("a b"), throwsFormatException);
+ test('too many expressions', () {
+ expect(() => _parse('a b'), throwsFormatException);
});
});
}
@@ -258,7 +258,7 @@
'is a variable named "$name"');
void _expectToString(String selector, [String result]) {
- if (result == null) result = selector;
+ result ??= selector;
expect(_toString(selector), equals(result),
reason: 'Expected toString of "$selector" to be "$result".');
}
diff --git a/test/scanner_test.dart b/test/scanner_test.dart
index fafe31a..c684278 100644
--- a/test/scanner_test.dart
+++ b/test/scanner_test.dart
@@ -8,16 +8,16 @@
import 'package:boolean_selector/src/token.dart';
void main() {
- group("peek()", () {
- test("returns the next token without consuming it", () {
- var scanner = Scanner("( )");
+ group('peek()', () {
+ test('returns the next token without consuming it', () {
+ var scanner = Scanner('( )');
expect(scanner.peek().type, equals(TokenType.leftParen));
expect(scanner.peek().type, equals(TokenType.leftParen));
expect(scanner.peek().type, equals(TokenType.leftParen));
});
- test("returns an end-of-file token at the end of a file", () {
- var scanner = Scanner("( )");
+ test('returns an end-of-file token at the end of a file', () {
+ var scanner = Scanner('( )');
scanner.next();
scanner.next();
@@ -27,8 +27,8 @@
expect(token.span.end.offset, equals(3));
});
- test("throws a StateError if called after end-of-file was consumed", () {
- var scanner = Scanner("( )");
+ test('throws a StateError if called after end-of-file was consumed', () {
+ var scanner = Scanner('( )');
scanner.next();
scanner.next();
scanner.next();
@@ -36,16 +36,16 @@
});
});
- group("next()", () {
- test("consumes and returns the next token", () {
- var scanner = Scanner("( )");
+ group('next()', () {
+ test('consumes and returns the next token', () {
+ var scanner = Scanner('( )');
expect(scanner.next().type, equals(TokenType.leftParen));
expect(scanner.peek().type, equals(TokenType.rightParen));
expect(scanner.next().type, equals(TokenType.rightParen));
});
- test("returns an end-of-file token at the end of a file", () {
- var scanner = Scanner("( )");
+ test('returns an end-of-file token at the end of a file', () {
+ var scanner = Scanner('( )');
scanner.next();
scanner.next();
@@ -55,8 +55,8 @@
expect(token.span.end.offset, equals(3));
});
- test("throws a StateError if called after end-of-file was consumed", () {
- var scanner = Scanner("( )");
+ test('throws a StateError if called after end-of-file was consumed', () {
+ var scanner = Scanner('( )');
scanner.next();
scanner.next();
scanner.next();
@@ -64,21 +64,21 @@
});
});
- group("scan()", () {
- test("consumes a matching token and returns true", () {
- var scanner = Scanner("( )");
+ group('scan()', () {
+ test('consumes a matching token and returns true', () {
+ var scanner = Scanner('( )');
expect(scanner.scan(TokenType.leftParen), isTrue);
expect(scanner.peek().type, equals(TokenType.rightParen));
});
test("doesn't consume a matching token and returns false", () {
- var scanner = Scanner("( )");
+ var scanner = Scanner('( )');
expect(scanner.scan(TokenType.questionMark), isFalse);
expect(scanner.peek().type, equals(TokenType.leftParen));
});
- test("throws a StateError called after end-of-file was consumed", () {
- var scanner = Scanner("( )");
+ test('throws a StateError called after end-of-file was consumed', () {
+ var scanner = Scanner('( )');
scanner.next();
scanner.next();
scanner.next();
@@ -86,67 +86,67 @@
});
});
- group("scans a simple token:", () {
- test("left paren", () => _expectSimpleScan("(", TokenType.leftParen));
- test("right paren", () => _expectSimpleScan(")", TokenType.rightParen));
- test("or", () => _expectSimpleScan("||", TokenType.or));
- test("and", () => _expectSimpleScan("&&", TokenType.and));
- test("not", () => _expectSimpleScan("!", TokenType.not));
- test("question mark", () => _expectSimpleScan("?", TokenType.questionMark));
- test("colon", () => _expectSimpleScan(":", TokenType.colon));
+ group('scans a simple token:', () {
+ test('left paren', () => _expectSimpleScan('(', TokenType.leftParen));
+ test('right paren', () => _expectSimpleScan(')', TokenType.rightParen));
+ test('or', () => _expectSimpleScan('||', TokenType.or));
+ test('and', () => _expectSimpleScan('&&', TokenType.and));
+ test('not', () => _expectSimpleScan('!', TokenType.not));
+ test('question mark', () => _expectSimpleScan('?', TokenType.questionMark));
+ test('colon', () => _expectSimpleScan(':', TokenType.colon));
});
- group("scans an identifier that", () {
- test("is simple", () {
- var token = _scan(" foo ");
- expect(token.name, equals("foo"));
- expect(token.span.text, equals("foo"));
+ group('scans an identifier that', () {
+ test('is simple', () {
+ var token = _scan(' foo ');
+ expect(token.name, equals('foo'));
+ expect(token.span.text, equals('foo'));
expect(token.span.start.offset, equals(3));
expect(token.span.end.offset, equals(6));
});
- test("is a single character", () {
- var token = _scan("f");
- expect(token.name, equals("f"));
+ test('is a single character', () {
+ var token = _scan('f');
+ expect(token.name, equals('f'));
});
- test("has a leading underscore", () {
- var token = _scan("_foo");
- expect(token.name, equals("_foo"));
+ test('has a leading underscore', () {
+ var token = _scan('_foo');
+ expect(token.name, equals('_foo'));
});
- test("has a leading dash", () {
- var token = _scan("-foo");
- expect(token.name, equals("-foo"));
+ test('has a leading dash', () {
+ var token = _scan('-foo');
+ expect(token.name, equals('-foo'));
});
- test("contains an underscore", () {
- var token = _scan("foo_bar");
- expect(token.name, equals("foo_bar"));
+ test('contains an underscore', () {
+ var token = _scan('foo_bar');
+ expect(token.name, equals('foo_bar'));
});
- test("contains a dash", () {
- var token = _scan("foo-bar");
- expect(token.name, equals("foo-bar"));
+ test('contains a dash', () {
+ var token = _scan('foo-bar');
+ expect(token.name, equals('foo-bar'));
});
- test("is capitalized", () {
- var token = _scan("FOO");
- expect(token.name, equals("FOO"));
+ test('is capitalized', () {
+ var token = _scan('FOO');
+ expect(token.name, equals('FOO'));
});
- test("contains numbers", () {
- var token = _scan("foo123");
- expect(token.name, equals("foo123"));
+ test('contains numbers', () {
+ var token = _scan('foo123');
+ expect(token.name, equals('foo123'));
});
});
- test("scans an empty selector", () {
- expect(_scan("").type, equals(TokenType.endOfFile));
+ test('scans an empty selector', () {
+ expect(_scan('').type, equals(TokenType.endOfFile));
});
- test("scans multiple tokens", () {
- var scanner = Scanner("(foo && bar)");
+ test('scans multiple tokens', () {
+ var scanner = Scanner('(foo && bar)');
var token = scanner.next();
expect(token.type, equals(TokenType.leftParen));
@@ -155,7 +155,7 @@
token = scanner.next();
expect(token.type, equals(TokenType.identifier));
- expect((token as IdentifierToken).name, equals("foo"));
+ expect((token as IdentifierToken).name, equals('foo'));
expect(token.span.start.offset, equals(1));
expect(token.span.end.offset, equals(4));
@@ -166,7 +166,7 @@
token = scanner.next();
expect(token.type, equals(TokenType.identifier));
- expect((token as IdentifierToken).name, equals("bar"));
+ expect((token as IdentifierToken).name, equals('bar'));
expect(token.span.start.offset, equals(8));
expect(token.span.end.offset, equals(11));
@@ -181,73 +181,73 @@
expect(token.span.end.offset, equals(12));
});
- group("ignores", () {
- test("a single-line comment", () {
- var scanner = Scanner("( // &&\n// ||\n)");
+ group('ignores', () {
+ test('a single-line comment', () {
+ var scanner = Scanner('( // &&\n// ||\n)');
expect(scanner.next().type, equals(TokenType.leftParen));
expect(scanner.next().type, equals(TokenType.rightParen));
expect(scanner.next().type, equals(TokenType.endOfFile));
});
- test("a single-line comment without a trailing newline", () {
- var scanner = Scanner("( // &&");
+ test('a single-line comment without a trailing newline', () {
+ var scanner = Scanner('( // &&');
expect(scanner.next().type, equals(TokenType.leftParen));
expect(scanner.next().type, equals(TokenType.endOfFile));
});
- test("a multi-line comment", () {
- var scanner = Scanner("( /* && * /\n|| */\n)");
+ test('a multi-line comment', () {
+ var scanner = Scanner('( /* && * /\n|| */\n)');
expect(scanner.next().type, equals(TokenType.leftParen));
expect(scanner.next().type, equals(TokenType.rightParen));
expect(scanner.next().type, equals(TokenType.endOfFile));
});
- test("a multi-line nested comment", () {
- var scanner = Scanner("(/* && /* ? /* || */ : */ ! */)");
+ test('a multi-line nested comment', () {
+ var scanner = Scanner('(/* && /* ? /* || */ : */ ! */)');
expect(scanner.next().type, equals(TokenType.leftParen));
expect(scanner.next().type, equals(TokenType.rightParen));
expect(scanner.next().type, equals(TokenType.endOfFile));
});
test("Dart's notion of whitespace", () {
- var scanner = Scanner("( \t \n)");
+ var scanner = Scanner('( \t \n)');
expect(scanner.next().type, equals(TokenType.leftParen));
expect(scanner.next().type, equals(TokenType.rightParen));
expect(scanner.next().type, equals(TokenType.endOfFile));
});
});
- group("disallows", () {
- test("a single |", () {
- expect(() => _scan("|"), throwsFormatException);
+ group('disallows', () {
+ test('a single |', () {
+ expect(() => _scan('|'), throwsFormatException);
});
test('"| |"', () {
- expect(() => _scan("| |"), throwsFormatException);
+ expect(() => _scan('| |'), throwsFormatException);
});
- test("a single &", () {
- expect(() => _scan("&"), throwsFormatException);
+ test('a single &', () {
+ expect(() => _scan('&'), throwsFormatException);
});
test('"& &"', () {
- expect(() => _scan("& &"), throwsFormatException);
+ expect(() => _scan('& &'), throwsFormatException);
});
- test("an unknown operator", () {
- expect(() => _scan("=="), throwsFormatException);
+ test('an unknown operator', () {
+ expect(() => _scan('=='), throwsFormatException);
});
- test("unicode", () {
- expect(() => _scan("öh"), throwsFormatException);
+ test('unicode', () {
+ expect(() => _scan('öh'), throwsFormatException);
});
- test("an unclosed multi-line comment", () {
- expect(() => _scan("/*"), throwsFormatException);
+ test('an unclosed multi-line comment', () {
+ expect(() => _scan('/*'), throwsFormatException);
});
- test("an unopened multi-line comment", () {
- expect(() => _scan("*/"), throwsFormatException);
+ test('an unopened multi-line comment', () {
+ expect(() => _scan('*/'), throwsFormatException);
});
});
}
@@ -256,7 +256,7 @@
/// and that that token's span is exactly [selector].
void _expectSimpleScan(String selector, TokenType type) {
// Complicate the selector to test that the span covers it correctly.
- var token = _scan(" $selector ");
+ var token = _scan(' $selector ');
expect(token.type, equals(type));
expect(token.span.text, equals(selector));
expect(token.span.start.offset, equals(3));
diff --git a/test/to_string_test.dart b/test/to_string_test.dart
index 11dad2a..ec1b4de 100644
--- a/test/to_string_test.dart
+++ b/test/to_string_test.dart
@@ -7,77 +7,77 @@
import 'package:boolean_selector/boolean_selector.dart';
void main() {
- group("toString() for", () {
- test("a variable is its name", () {
- _expectToString("foo");
- _expectToString("a-b");
+ group('toString() for', () {
+ test('a variable is its name', () {
+ _expectToString('foo');
+ _expectToString('a-b');
});
- group("not", () {
- test("doesn't parenthesize a variable", () => _expectToString("!a"));
- test("doesn't parenthesize a nested not", () => _expectToString("!!a"));
- test("parenthesizes an or", () => _expectToString("!(a || b)"));
- test("parenthesizes an and", () => _expectToString("!(a && b)"));
- test("parenthesizes a condition", () => _expectToString("!(a ? b : c)"));
+ group('not', () {
+ test("doesn't parenthesize a variable", () => _expectToString('!a'));
+ test("doesn't parenthesize a nested not", () => _expectToString('!!a'));
+ test('parenthesizes an or', () => _expectToString('!(a || b)'));
+ test('parenthesizes an and', () => _expectToString('!(a && b)'));
+ test('parenthesizes a condition', () => _expectToString('!(a ? b : c)'));
});
- group("or", () {
- test("doesn't parenthesize variables", () => _expectToString("a || b"));
- test("doesn't parenthesize nots", () => _expectToString("!a || !b"));
+ group('or', () {
+ test("doesn't parenthesize variables", () => _expectToString('a || b'));
+ test("doesn't parenthesize nots", () => _expectToString('!a || !b'));
test("doesn't parenthesize ors", () {
- _expectToString("a || b || c || d");
- _expectToString("((a || b) || c) || d", "a || b || c || d");
+ _expectToString('a || b || c || d');
+ _expectToString('((a || b) || c) || d', 'a || b || c || d');
});
- test("parenthesizes ands",
- () => _expectToString("a && b || c && d", "(a && b) || (c && d)"));
+ test('parenthesizes ands',
+ () => _expectToString('a && b || c && d', '(a && b) || (c && d)'));
- test("parenthesizes conditions",
- () => _expectToString("(a ? b : c) || (e ? f : g)"));
+ test('parenthesizes conditions',
+ () => _expectToString('(a ? b : c) || (e ? f : g)'));
});
- group("and", () {
- test("doesn't parenthesize variables", () => _expectToString("a && b"));
- test("doesn't parenthesize nots", () => _expectToString("!a && !b"));
+ group('and', () {
+ test("doesn't parenthesize variables", () => _expectToString('a && b'));
+ test("doesn't parenthesize nots", () => _expectToString('!a && !b'));
test(
- "parenthesizes ors",
+ 'parenthesizes ors',
() =>
- _expectToString("(a || b) && (c || d)", "(a || b) && (c || d)"));
+ _expectToString('(a || b) && (c || d)', '(a || b) && (c || d)'));
test("doesn't parenthesize ands", () {
- _expectToString("a && b && c && d");
- _expectToString("((a && b) && c) && d", "a && b && c && d");
+ _expectToString('a && b && c && d');
+ _expectToString('((a && b) && c) && d', 'a && b && c && d');
});
- test("parenthesizes conditions",
- () => _expectToString("(a ? b : c) && (e ? f : g)"));
+ test('parenthesizes conditions',
+ () => _expectToString('(a ? b : c) && (e ? f : g)'));
});
- group("conditional", () {
+ group('conditional', () {
test(
- "doesn't parenthesize variables", () => _expectToString("a ? b : c"));
+ "doesn't parenthesize variables", () => _expectToString('a ? b : c'));
- test("doesn't parenthesize nots", () => _expectToString("!a ? !b : !c"));
+ test("doesn't parenthesize nots", () => _expectToString('!a ? !b : !c'));
test("doesn't parenthesize ors",
- () => _expectToString("a || b ? c || d : e || f"));
+ () => _expectToString('a || b ? c || d : e || f'));
test("doesn't parenthesize ands",
- () => _expectToString("a && b ? c && d : e && f"));
+ () => _expectToString('a && b ? c && d : e && f'));
- test("parenthesizes non-trailing conditions", () {
- _expectToString("(a ? b : c) ? (e ? f : g) : h ? i : j");
- _expectToString("(a ? b : c) ? (e ? f : g) : (h ? i : j)",
- "(a ? b : c) ? (e ? f : g) : h ? i : j");
+ test('parenthesizes non-trailing conditions', () {
+ _expectToString('(a ? b : c) ? (e ? f : g) : h ? i : j');
+ _expectToString('(a ? b : c) ? (e ? f : g) : (h ? i : j)',
+ '(a ? b : c) ? (e ? f : g) : h ? i : j');
});
});
});
}
void _expectToString(String selector, [String result]) {
- if (result == null) result = selector;
+ result ??= selector;
expect(_toString(selector), equals(result),
reason: 'Expected toString of "$selector" to be "$result".');
}
diff --git a/test/validate_test.dart b/test/validate_test.dart
index d61fd36..f040069 100644
--- a/test/validate_test.dart
+++ b/test/validate_test.dart
@@ -6,11 +6,11 @@
import 'package:boolean_selector/boolean_selector.dart';
-var _selector = BooleanSelector.parse("foo && bar && baz");
+var _selector = BooleanSelector.parse('foo && bar && baz');
void main() {
- test("throws if any variables are undefined", () {
- expect(() => _selector.validate((variable) => variable == "bar"),
+ test('throws if any variables are undefined', () {
+ expect(() => _selector.validate((variable) => variable == 'bar'),
throwsFormatException);
});
diff --git a/test/variables_test.dart b/test/variables_test.dart
index 1cb4740..e354907 100644
--- a/test/variables_test.dart
+++ b/test/variables_test.dart
@@ -7,38 +7,38 @@
import 'package:boolean_selector/boolean_selector.dart';
void main() {
- test("a variable reports itself", () {
- expect(BooleanSelector.parse("foo").variables, equals(["foo"]));
+ test('a variable reports itself', () {
+ expect(BooleanSelector.parse('foo').variables, equals(['foo']));
});
- test("a negation reports its contents", () {
- expect(BooleanSelector.parse("!foo").variables, equals(["foo"]));
+ test('a negation reports its contents', () {
+ expect(BooleanSelector.parse('!foo').variables, equals(['foo']));
});
- test("a parenthesized expression reports its contents", () {
- expect(BooleanSelector.parse("(foo)").variables, equals(["foo"]));
+ test('a parenthesized expression reports its contents', () {
+ expect(BooleanSelector.parse('(foo)').variables, equals(['foo']));
});
- test("an or reports its contents", () {
+ test('an or reports its contents', () {
expect(
- BooleanSelector.parse("foo || bar").variables, equals(["foo", "bar"]));
+ BooleanSelector.parse('foo || bar').variables, equals(['foo', 'bar']));
});
- test("an and reports its contents", () {
+ test('an and reports its contents', () {
expect(
- BooleanSelector.parse("foo && bar").variables, equals(["foo", "bar"]));
+ BooleanSelector.parse('foo && bar').variables, equals(['foo', 'bar']));
});
- test("a conditional reports its contents", () {
- expect(BooleanSelector.parse("foo ? bar : baz").variables,
- equals(["foo", "bar", "baz"]));
+ test('a conditional reports its contents', () {
+ expect(BooleanSelector.parse('foo ? bar : baz').variables,
+ equals(['foo', 'bar', 'baz']));
});
- test("BooleanSelector.all reports no variables", () {
+ test('BooleanSelector.all reports no variables', () {
expect(BooleanSelector.all.variables, isEmpty);
});
- test("BooleanSelector.none reports no variables", () {
+ test('BooleanSelector.none reports no variables', () {
expect(BooleanSelector.none.variables, isEmpty);
});
}