Replace the 49 hand-maintained named consts with one generated
label→codepoint map (phosphor_glyphs.g.dart, 1512 glyphs from the glyph
table via tool/gen_phosphor_glyphs.dart). Feature code now references
glyphs by their exact kebab-case name — PhosphorIcons.byName('folder') —
with no raw codepoints; this also lets a Lua extension name an icon
without crossing the FFI boundary with a codepoint.
byName is total: an unknown name degrades to the `placeholder` box so the
bug is visible (it's a real error), while phosphor_glyphs_test asserts
every byName('...') literal in lib/ resolves — recovering the typo check a
const gave. Migrated the 89 call sites. Adds EmptyIconPainter for an
intentional blank that still reserves the icon box; ClideFilterBox gains
showIcon to keep the slot aligned when blank.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
48 lines
2.1 KiB
Dart
48 lines
2.1 KiB
Dart
/// Guards the Phosphor label→codepoint indirection (T-314). The named consts
|
|
/// are gone; code resolves glyphs by string via [PhosphorIcons.byName]. A
|
|
/// string key loses the compiler's typo check, so this test recovers it: every
|
|
/// `byName('…')` string literal in `lib/` must exist in the generated map —
|
|
/// across all call sites, executed or not.
|
|
library;
|
|
|
|
import 'dart:io';
|
|
|
|
import 'package:clide/widgets/src/icons/phosphor_glyphs.g.dart';
|
|
import 'package:clide/widgets/widgets.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
void main() {
|
|
test('the generated glyph map covers the full Phosphor set', () {
|
|
expect(kPhosphorGlyphs.length, greaterThanOrEqualTo(1500));
|
|
expect(kPhosphorGlyphs.containsKey('folder'), isTrue);
|
|
// The fallback glyph must itself resolve, or byName would throw on a miss.
|
|
expect(kPhosphorGlyphs.containsKey(PhosphorIcons.fallbackName), isTrue);
|
|
});
|
|
|
|
test('every byName(\'…\') literal in lib/ resolves to a real glyph', () {
|
|
final call = RegExp(r"byName\(\s*'([a-z0-9-]+)'\s*\)");
|
|
final missing = <String, String>{}; // label -> first file it appears in
|
|
for (final entity in Directory('lib').listSync(recursive: true)) {
|
|
if (entity is! File || !entity.path.endsWith('.dart')) continue;
|
|
for (final m in call.allMatches(entity.readAsStringSync())) {
|
|
final label = m.group(1)!;
|
|
if (!kPhosphorGlyphs.containsKey(label)) {
|
|
missing.putIfAbsent(label, () => entity.path);
|
|
}
|
|
}
|
|
}
|
|
expect(missing, isEmpty, reason: 'unknown Phosphor glyph name(s) in byName(): $missing');
|
|
});
|
|
|
|
test('byName resolves a known name to its codepoint', () {
|
|
expect(PhosphorIcons.byName('folder').codePoint, kPhosphorGlyphs['folder']);
|
|
expect(PhosphorIcons.byName('caret-line-left').codePoint, kPhosphorGlyphs['caret-line-left']);
|
|
});
|
|
|
|
test('byName degrades an unknown name to the placeholder fallback (never throws)', () {
|
|
final fallback = kPhosphorGlyphs[PhosphorIcons.fallbackName];
|
|
expect(PhosphorIcons.byName('definitely-not-a-real-glyph').codePoint, fallback);
|
|
expect(PhosphorIcons.fallbackName, 'placeholder');
|
|
});
|
|
}
|