Migrate pkg/status_file to primary constructors and new constructor syntax.
Unlike my previous couple of CLs, I went ahead here and also migrated most of the classes to use primary constructors since so many of them were small and well suited for it. In the process, I found and fixed one bug in the assist to convert to a primary constructor: https://dart-review.googlesource.com/c/sdk/+/506760 So I guess this CL has already paid its way. :) Change-Id: I9b7d08e27f4ddce3f19127aaf4f14fe627b75dab Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/506743 Reviewed-by: Paul Berry <paulberry@google.com> Commit-Queue: Bob Nystrom <rnystrom@google.com> Commit-Queue: Paul Berry <paulberry@google.com> Auto-Submit: Bob Nystrom <rnystrom@google.com>
This commit is contained in:
committed by
dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent
afcfbbeba8
commit
9f11b2fd45
@@ -8,3 +8,7 @@ analyzer:
|
||||
errors:
|
||||
# Allow having TODOs in the code
|
||||
todo: ignore
|
||||
linter:
|
||||
rules:
|
||||
- unnecessary_const_in_enum_constructor
|
||||
- unnecessary_type_name_in_constructor
|
||||
|
||||
@@ -74,19 +74,19 @@ class StatusFile {
|
||||
|
||||
/// Constructor for creating a new [StatusFile]. Will not create the default
|
||||
/// section that status files have.
|
||||
StatusFile(this.path);
|
||||
new(this.path);
|
||||
|
||||
/// Reads and parses the status file at [path].
|
||||
///
|
||||
/// Throws a [SyntaxError] if the file could not be parsed.
|
||||
StatusFile.read(this.path) {
|
||||
new read(this.path) {
|
||||
_parse(File(path).readAsLinesSync());
|
||||
}
|
||||
|
||||
/// Parses lines of strings coming from a status file at [path].
|
||||
///
|
||||
/// Throws a [SyntaxError] if the file could not be parsed.
|
||||
StatusFile.parse(this.path, List<String> lines) {
|
||||
new parse(this.path, List<String> lines) {
|
||||
_parse(lines.map((line) => line.trim()).toList());
|
||||
}
|
||||
|
||||
@@ -305,27 +305,26 @@ class StatusFile {
|
||||
///
|
||||
/// Contains the condition from the header that begins the section, then all of
|
||||
/// the entries within the section.
|
||||
class StatusSection {
|
||||
class StatusSection(
|
||||
/// The expression that determines when this section is applied.
|
||||
///
|
||||
/// Will be [Expression.always] for paths that appear before any section
|
||||
/// header in the file. In that case, the section always applies.
|
||||
final Expression condition;
|
||||
final Expression condition,
|
||||
|
||||
/// The one-based line number where the section appears in the file.
|
||||
final int lineNumber;
|
||||
final int lineNumber,
|
||||
|
||||
final List<Entry> sectionHeaderComments,
|
||||
) {
|
||||
/// Collection of all comment and status line entries.
|
||||
final List<Entry> entries = [];
|
||||
final List<Entry> sectionHeaderComments;
|
||||
|
||||
/// Returns true if this section should apply in the given [environment].
|
||||
bool isEnabled(Environment environment) => condition.evaluate(environment);
|
||||
|
||||
bool isEmpty() => !entries.any((entry) => entry is StatusEntry);
|
||||
|
||||
StatusSection(this.condition, this.lineNumber, this.sectionHeaderComments);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
var buffer = StringBuffer();
|
||||
@@ -338,11 +337,7 @@ class StatusSection {
|
||||
}
|
||||
}
|
||||
|
||||
class Comment {
|
||||
final String _comment;
|
||||
|
||||
Comment(this._comment);
|
||||
|
||||
class Comment(final String _comment) {
|
||||
/// Returns the issue number embedded in [comment] or `null` if there is none.
|
||||
int? issueNumber(String comment) {
|
||||
var match = _issuePattern.firstMatch(comment);
|
||||
@@ -351,32 +346,20 @@ class Comment {
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _comment;
|
||||
}
|
||||
String toString() => _comment;
|
||||
}
|
||||
|
||||
abstract class Entry {
|
||||
abstract class Entry(
|
||||
/// The one-based line number where the entry appears in the file.
|
||||
final int lineNumber;
|
||||
|
||||
Entry(this.lineNumber);
|
||||
}
|
||||
|
||||
class EmptyEntry extends Entry {
|
||||
EmptyEntry(super.lineNumber);
|
||||
final int lineNumber,
|
||||
);
|
||||
|
||||
class EmptyEntry(super.lineNumber) extends Entry {
|
||||
@override
|
||||
String toString() {
|
||||
return "";
|
||||
}
|
||||
String toString() => '';
|
||||
}
|
||||
|
||||
class CommentEntry extends Entry {
|
||||
final Comment comment;
|
||||
|
||||
CommentEntry(super.lineNumber, this.comment);
|
||||
|
||||
class CommentEntry(super.lineNumber, final Comment comment) extends Entry {
|
||||
@override
|
||||
String toString() {
|
||||
return comment.toString();
|
||||
@@ -384,13 +367,12 @@ class CommentEntry extends Entry {
|
||||
}
|
||||
|
||||
/// Describes the test status of the file or files at a given path.
|
||||
class StatusEntry extends Entry {
|
||||
final String path;
|
||||
final List<Expectation> expectations;
|
||||
final Comment? comment;
|
||||
|
||||
StatusEntry(this.path, super.lineNumber, this.expectations, this.comment);
|
||||
|
||||
class StatusEntry(
|
||||
final String path,
|
||||
super.lineNumber,
|
||||
final List<Expectation> expectations,
|
||||
final Comment? comment,
|
||||
) extends Entry {
|
||||
@override
|
||||
String toString() {
|
||||
return comment == null
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
/// The possible outcomes from running a test.
|
||||
class Expectation {
|
||||
class Expectation._(
|
||||
final String _name, {
|
||||
final Expectation? _group,
|
||||
bool isMeta = false,
|
||||
}) {
|
||||
/// The test completed normally and did what it intended to do.
|
||||
static final Expectation pass = Expectation._('Pass');
|
||||
|
||||
@@ -234,14 +238,8 @@ class Expectation {
|
||||
return expectation;
|
||||
}
|
||||
|
||||
final String _name;
|
||||
final Expectation? _group;
|
||||
|
||||
/// Whether this expectation is a test outcome. If not, it's a "meta marker".
|
||||
final bool isOutcome;
|
||||
|
||||
Expectation._(this._name, {this._group, bool isMeta = false})
|
||||
: isOutcome = !isMeta;
|
||||
final bool isOutcome = !isMeta;
|
||||
|
||||
bool canBeOutcomeOf(Expectation expectation) {
|
||||
Expectation? outcome = this;
|
||||
|
||||
@@ -143,12 +143,10 @@ List<Expression>? _satisfiableMinTerms(Expression expression) {
|
||||
/// [variables] are assigned a value bases on the [configuration]. This
|
||||
/// environment can then be used to evaluate the corresponding expression from
|
||||
/// which the [variables] was found.
|
||||
class TruthTableEnvironment extends Environment {
|
||||
final List<Expression> variables;
|
||||
class TruthTableEnvironment(final List<Expression> variables)
|
||||
extends Environment {
|
||||
int configuration = -1;
|
||||
|
||||
TruthTableEnvironment(this.variables);
|
||||
|
||||
void setConfiguration(int configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import 'dart:math' as math;
|
||||
import '../environment.dart';
|
||||
|
||||
/// A parsed Boolean expression AST.
|
||||
abstract class Expression implements Comparable<Expression> {
|
||||
abstract class const Expression() implements Comparable<Expression> {
|
||||
/// An expression that always evaluates to true.
|
||||
///
|
||||
/// Used for the section at the top of a status file with no expression.
|
||||
@@ -31,8 +31,6 @@ abstract class Expression implements Comparable<Expression> {
|
||||
static Expression parse(String expression) =>
|
||||
_ExpressionParser(expression).parse();
|
||||
|
||||
const Expression();
|
||||
|
||||
/// Validates that this expression does not contain any invalid uses of
|
||||
/// variables.
|
||||
///
|
||||
@@ -97,11 +95,7 @@ class _Token {
|
||||
}
|
||||
|
||||
/// A reference to a variable.
|
||||
class Variable {
|
||||
final String name;
|
||||
|
||||
Variable(this.name);
|
||||
|
||||
class Variable(final String name) {
|
||||
String lookup(Environment environment) {
|
||||
var value = environment.lookUp(name);
|
||||
if (value == null) {
|
||||
@@ -125,9 +119,7 @@ class Variable {
|
||||
///
|
||||
/// Used for the implicit section at the top of a status file that always
|
||||
/// matches.
|
||||
class _AlwaysExpression extends Expression {
|
||||
const _AlwaysExpression();
|
||||
|
||||
class const _AlwaysExpression() extends Expression {
|
||||
@override
|
||||
int _compareToMyType(covariant _AlwaysExpression other) => 0;
|
||||
|
||||
@@ -149,13 +141,11 @@ class _AlwaysExpression extends Expression {
|
||||
/// $variable == someValue
|
||||
/// ```
|
||||
/// Negate the result if [negate] is true.
|
||||
class ComparisonExpression extends Expression {
|
||||
final Variable left;
|
||||
final String right;
|
||||
final bool negate;
|
||||
|
||||
ComparisonExpression(this.left, this.right, this.negate);
|
||||
|
||||
class ComparisonExpression(
|
||||
final Variable left,
|
||||
final String right,
|
||||
final bool negate,
|
||||
) extends Expression {
|
||||
@override
|
||||
void validate(Environment environment, List<String> errors) {
|
||||
environment.validate(left.name, right, errors);
|
||||
@@ -217,12 +207,8 @@ class ComparisonExpression extends Expression {
|
||||
/// ```
|
||||
/// $variable != true
|
||||
/// ```
|
||||
class VariableExpression extends Expression {
|
||||
final Variable variable;
|
||||
final bool negate;
|
||||
|
||||
VariableExpression(this.variable, {this.negate = false});
|
||||
|
||||
class VariableExpression(final Variable variable, {final bool negate = false})
|
||||
extends Expression {
|
||||
@override
|
||||
void validate(Environment environment, List<String> errors) {
|
||||
// It must be a Boolean, so it should allow either Boolean value.
|
||||
@@ -254,16 +240,13 @@ class VariableExpression extends Expression {
|
||||
}
|
||||
|
||||
/// A logical `||` or `&&` expression.
|
||||
class LogicExpression extends Expression {
|
||||
class LogicExpression(
|
||||
/// The operator, `||` or `&&`.
|
||||
final String op;
|
||||
|
||||
final List<Expression> operands;
|
||||
|
||||
LogicExpression(this.op, this.operands);
|
||||
|
||||
LogicExpression.and(this.operands) : op = _Token.and;
|
||||
LogicExpression.or(this.operands) : op = _Token.or;
|
||||
final String op,
|
||||
final List<Expression> operands,
|
||||
) extends Expression {
|
||||
new and(List<Expression> operands) : this(_Token.and, operands);
|
||||
new or(List<Expression> operands) : this(_Token.or, operands);
|
||||
|
||||
bool get isAnd => op == _Token.and;
|
||||
bool get isOr => op == _Token.or;
|
||||
@@ -350,10 +333,8 @@ class LogicExpression extends Expression {
|
||||
}
|
||||
|
||||
/// Parser for Boolean expressions in a .status file for Dart.
|
||||
class _ExpressionParser {
|
||||
final _Scanner _scanner;
|
||||
|
||||
_ExpressionParser(String expression) : _scanner = _Scanner(expression);
|
||||
class _ExpressionParser(String expression) {
|
||||
final _Scanner _scanner = _Scanner(expression);
|
||||
|
||||
Expression parse() {
|
||||
var expression = _parseOr();
|
||||
@@ -442,7 +423,7 @@ class _ExpressionParser {
|
||||
}
|
||||
|
||||
/// An iterator that allows peeking at the current token.
|
||||
class _Scanner {
|
||||
class _Scanner(String expression) {
|
||||
/// Tokens are "(", ")", "$", "&&", "||", "!", ==", "!=", and (maximal) \w+.
|
||||
static final _testPattern = RegExp(r"^(?:[()$\w\s]|&&|\|\||==|!=?)+$");
|
||||
static final _tokenPattern = RegExp(r"[()$]|&&|\|\||==|!=?|\w+");
|
||||
@@ -454,11 +435,11 @@ class _Scanner {
|
||||
static final _identifierPattern = RegExp(r"^\w");
|
||||
|
||||
/// The token strings being iterated.
|
||||
final Iterator<String> tokenIterator;
|
||||
final Iterator<String> tokenIterator = tokenize(expression).iterator;
|
||||
|
||||
String? current;
|
||||
|
||||
_Scanner(String expression) : tokenIterator = tokenize(expression).iterator {
|
||||
this {
|
||||
advance();
|
||||
}
|
||||
|
||||
|
||||
@@ -49,12 +49,12 @@ class StatusFile {
|
||||
|
||||
int _lineCount = 0;
|
||||
|
||||
StatusFile(this.path);
|
||||
new(this.path);
|
||||
|
||||
/// Parses the status file at [path].
|
||||
///
|
||||
/// Throws a [SyntaxError] if the file could not be parsed.
|
||||
StatusFile.read(this.path) {
|
||||
new read(this.path) {
|
||||
var lines = File(path).readAsLinesSync();
|
||||
_comments.length = lines.length + 1;
|
||||
|
||||
@@ -266,7 +266,7 @@ class StatusSection {
|
||||
/// Returns true if this section should apply in the given [environment].
|
||||
bool isEnabled(Environment environment) => condition.evaluate(environment);
|
||||
|
||||
StatusSection(this.condition, this.lineNumber);
|
||||
new(this.condition, this.lineNumber);
|
||||
}
|
||||
|
||||
/// Describes the test status of the file or files at a given path.
|
||||
@@ -279,7 +279,7 @@ class StatusEntry {
|
||||
final List<Expectation> expectations;
|
||||
final int? issue;
|
||||
|
||||
StatusEntry(this.path, this.lineNumber, this.expectations, this.issue);
|
||||
new(this.path, this.lineNumber, this.expectations, this.issue);
|
||||
}
|
||||
|
||||
/// Error thrown when a parse or validation error occurs in a [StatusFile].
|
||||
@@ -290,7 +290,7 @@ class SyntaxError implements Exception {
|
||||
final String message;
|
||||
final List<String>? errors;
|
||||
|
||||
SyntaxError(this.file, this.lineNumber, this.line, this.message, this.errors);
|
||||
new(this.file, this.lineNumber, this.line, this.message, this.errors);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
|
||||
@@ -7,15 +7,9 @@ import 'dart:math' as math;
|
||||
import 'package:status_file/canonical_status_file.dart';
|
||||
import 'package:status_file/status_file_entries_file_checker.dart';
|
||||
|
||||
class LintingError {
|
||||
final int lineNumber;
|
||||
final String message;
|
||||
LintingError(this.lineNumber, this.message);
|
||||
|
||||
class LintingError(final int lineNumber, final String message) {
|
||||
@override
|
||||
String toString() {
|
||||
return "Error at line $lineNumber: $message";
|
||||
}
|
||||
String toString() => "Error at line $lineNumber: $message";
|
||||
}
|
||||
|
||||
/// Main function to check a status file for linting errors.
|
||||
@@ -268,8 +262,4 @@ ListNotEqualWitness<T>? _findNotEqualWitness<T>(List<T> first, List<T> second) {
|
||||
return null;
|
||||
}
|
||||
|
||||
class ListNotEqualWitness<T> {
|
||||
final T? first;
|
||||
final T? second;
|
||||
ListNotEqualWitness(this.first, this.second);
|
||||
}
|
||||
class ListNotEqualWitness<T>(final T? first, final T? second);
|
||||
|
||||
@@ -3,7 +3,7 @@ name: status_file
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: '^3.12.0-0'
|
||||
sdk: '^3.13.0-0'
|
||||
|
||||
resolution: workspace
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import "package:status_file/src/expression.dart";
|
||||
class TestEnvironment implements Environment {
|
||||
final Map<String, String> _values;
|
||||
|
||||
TestEnvironment(this._values);
|
||||
new(this._values);
|
||||
|
||||
@override
|
||||
void validate(String name, String value, List<String> errors) {
|
||||
|
||||
Reference in New Issue
Block a user