remove dead defensive throws in keytab tokenizer + parser
Four `throw` sites in `core/input/keytab/` were unreachable through
the public API:
- `keytab_token.dart` `_parseKeyboardNameDefine` and `_parseKeyDefine`
each tested `reader.readString() == 'keyboard'` / `'key'` after
the caller in the same file (`tokenize`) had already gated entry
on `_isKeyboardNameDefine` / `_isKeyDefine`. Both checks
redundantly re-derived a fact already established a function
call earlier; the `else { throw }` was dead code.
- `keytab_parse.dart` `_parseName` and `_parseKeyDefine` checked
the first token's type, but `addTokens` only delegates to those
functions after `peek().type` matches the expected kind. Same
pattern: the throw protects an invariant the caller already
enforces.
Surfaced while bringing `core/input/` to ~100% coverage. Per the
"near-perfect discipline" / "no carve-outs" rules, dead defensive
code is cleaned, not skipped — the surrounding callers in the same
file are tight enough that introducing a real callsite gap would
be a localised and obvious bug, not a silent failure rescued by
these guards.
The two `else`-throw sites in keytab_token.dart fold into a single
unconditional `reader.readString()` (consume the leading word) +
`yield` of the matching token type. The two type-check throws in
keytab_parse.dart fold into an unconditional `reader.take()` to
skip the already-validated token.
All public-API ParseError paths exercised by `core/input/`'s
unit tests still throw correctly — they're guarded by the second
check in each function (the action-token type check after
modeStatus loops, and the input-token check in _parseName).
After cleanup:
- keytab_token.dart: 80 / 80
- keytab_parse.dart: 63 / 63
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -55,9 +55,8 @@ class KeytabParser {
|
||||
}
|
||||
|
||||
void _parseName(TokensReader reader) {
|
||||
if (reader.take()!.type != KeytabTokenType.keyboard) {
|
||||
throw ParseError();
|
||||
}
|
||||
// Caller (`addTokens`) has already gated on the keyboard token type.
|
||||
reader.take();
|
||||
|
||||
final name = reader.take()!;
|
||||
if (name.type != KeytabTokenType.input) {
|
||||
@@ -68,9 +67,8 @@ class KeytabParser {
|
||||
}
|
||||
|
||||
void _parseKeyDefine(TokensReader reader) {
|
||||
if (reader.take()!.type != KeytabTokenType.keyDefine) {
|
||||
throw ParseError();
|
||||
}
|
||||
// Caller has already gated on the keyDefine token type.
|
||||
reader.take();
|
||||
|
||||
final keyName = reader.take()!;
|
||||
|
||||
|
||||
@@ -114,13 +114,11 @@ bool _isKeyDefine(String line) {
|
||||
}
|
||||
|
||||
Iterable<KeytabToken> _parseKeyboardNameDefine(String line) sync* {
|
||||
// Caller has already gated on `_isKeyboardNameDefine`, so the leading
|
||||
// word is guaranteed to be 'keyboard'. Just consume it.
|
||||
final reader = LineReader(line.trim());
|
||||
|
||||
if (reader.readString() == 'keyboard') {
|
||||
yield KeytabToken(KeytabTokenType.keyboard, 'keyboard');
|
||||
} else {
|
||||
throw TokenizeError();
|
||||
}
|
||||
reader.readString();
|
||||
yield KeytabToken(KeytabTokenType.keyboard, 'keyboard');
|
||||
|
||||
reader.skipWhitespace();
|
||||
|
||||
@@ -128,13 +126,10 @@ Iterable<KeytabToken> _parseKeyboardNameDefine(String line) sync* {
|
||||
}
|
||||
|
||||
Iterable<KeytabToken> _parseKeyDefine(String line) sync* {
|
||||
// Caller has already gated on `_isKeyDefine`.
|
||||
final reader = LineReader(line.trim());
|
||||
|
||||
if (reader.readString() == 'key') {
|
||||
yield KeytabToken(KeytabTokenType.keyDefine, 'key');
|
||||
} else {
|
||||
throw TokenizeError();
|
||||
}
|
||||
reader.readString();
|
||||
yield KeytabToken(KeytabTokenType.keyDefine, 'key');
|
||||
|
||||
reader.skipWhitespace();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user