• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

albertms10 / music_notes / 20236957972

15 Dec 2025 03:05PM UTC coverage: 99.942% (-0.06%) from 100.0%
20236957972

Pull #675

github

web-flow
Merge bce981ac2 into eb5b7c119
Pull Request #675: refactor(notation_system): ♻️ split string match responsibilities from `NotationSystem`

19 of 19 new or added lines in 6 files covered. (100.0%)

1 existing line in 1 file now uncovered.

1712 of 1713 relevant lines covered (99.94%)

1.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.0
/lib/src/notation_system.dart
1
// ignore_for_file: one_member_abstracts - Code reusability
2

3
/// An abstract representation of a notation system for parsing
4
/// and formatting [I].
5
///
6
/// The [format] and [parse] methods should be designed to be [inverses](https://en.wikipedia.org/wiki/Inverse_function)
7
/// of each other:
8
/// the output of [format] should be a valid argument for [parse], and
9
/// `parse(format(value))` should return a value equal to the original value.
10
abstract class NotationSystem<I, O> implements Formatter<I, O>, Parser<O, I> {
11
  /// Creates a new formatter.
UNCOV
12
  const NotationSystem();
×
13

14
  /// Formats this [I].
15
  ///
16
  /// The output of this method should be accepted by [parse] to reconstruct
17
  /// the original value.
18
  @override
19
  O format(I value);
20

21
  /// Parses [source] as [I].
22
  ///
23
  /// The input [source] should typically be produced by [format], ensuring
24
  /// that `parse(format(value)) == value`.
25
  ///
26
  /// If the [source] string does not contain a valid [I], a [FormatException]
27
  /// should be thrown.
28
  @override
29
  I parse(O source);
30
}
31

32
/// An abstract representation of a notation system for parsing
33
/// and formatting [I] from and to a string.
34
abstract class StringNotationSystem<I>
35
    implements StringFormatter<I>, StringParser<I> {
36
  /// Creates a new formatter.
37
  const StringNotationSystem();
1✔
38

39
  @override
1✔
40
  RegExp? get regExp => null;
41

42
  @override
1✔
43
  bool matches(String source) =>
44
      regExp == null ||
1✔
45
      RegExp(
1✔
46
        '^${regExp?.pattern}\$',
3✔
47
        caseSensitive: regExp?.isCaseSensitive ?? true,
2✔
48
        unicode: regExp?.isUnicode ?? false,
2✔
49
      ).hasMatch(source);
1✔
50

51
  /// Parses [source] as [I].
52
  ///
53
  /// The input [source] should typically be produced by [format], ensuring
54
  /// that `parse(format(value)) == value`.
55
  ///
56
  /// If the [source] string does not contain a valid [I], a [FormatException]
57
  /// should be thrown.
58
  @override
1✔
59
  I parse(String source) => parseMatch(
1✔
60
    regExp?.firstMatch(source) ?? (throw FormatException('Invalid $I', source)),
4✔
61
  );
62

63
  @override
1✔
64
  I parseMatch(RegExpMatch match) => throw UnimplementedError(
1✔
65
    'parseMatch is not implemented for $runtimeType.',
2✔
66
  );
67
}
68

69
/// An abstract representation of a formatter for [I].
70
abstract interface class Formatter<I, O> {
71
  /// Formats this [I].
72
  O format(I value);
73
}
74

75
/// An abstract representation of a string formatter for [I].
76
abstract interface class StringFormatter<I> extends Formatter<I, String> {}
77

78
/// An abstract representation of a parser for [O].
79
abstract interface class Parser<S, O> {
80
  /// Parses [source] as [O].
81
  O parse(S source);
82
}
83

84
/// An abstract representation of a parser for [O].
85
abstract interface class StringParser<O> extends Parser<String, O> {
86
  /// The regular expression for matching [O].
87
  RegExp? get regExp;
88

89
  /// Whether [source] can be parsed with [parse].
90
  bool matches(String source);
91

92
  /// Parses [source] as [O].
93
  @override
94
  O parse(String source);
95

96
  /// Parses [match] from [regExp] as [O].
97
  O parseMatch(RegExpMatch match);
98
}
99

100
/// A [StringParser] chain.
101
extension StringParserChain<O> on List<StringParser<O>> {
102
  /// Parses [source] from this chain of [StringParser]s.
103
  O parse(String source) {
1✔
104
    for (final parser in this) {
2✔
105
      if (parser.matches(source)) return parser.parse(source);
2✔
106
    }
107
    throw FormatException('End of parser chain: invalid $O', source);
2✔
108
  }
109
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc