97 lines
2.9 KiB
Dart
97 lines
2.9 KiB
Dart
import 'dart:io';
|
|
|
|
/// Prunes unused step files under test/features/step.
|
|
///
|
|
/// Heuristic: A step file is considered used if any test under test/features
|
|
/// imports it like: `import './step/<file>.dart';` (as generated by bdd_widget_test).
|
|
/// Otherwise it's unused and can be deleted.
|
|
///
|
|
/// Usage:
|
|
/// dart run tool/prune_unused_steps.dart # dry-run (prints list)
|
|
/// dart run tool/prune_unused_steps.dart --delete # delete unused files
|
|
/// dart run tool/prune_unused_steps.dart --verbose # show details
|
|
void main(List<String> args) {
|
|
final delete = args.contains('--delete');
|
|
final verbose = args.contains('--verbose');
|
|
|
|
final stepDir = Directory('test/features/step');
|
|
final testsDir = Directory('test/features');
|
|
|
|
if (!stepDir.existsSync()) {
|
|
stderr.writeln('Step folder not found at ${stepDir.path}');
|
|
exitCode = 2;
|
|
return;
|
|
}
|
|
if (!testsDir.existsSync()) {
|
|
stderr.writeln('Tests folder not found at ${testsDir.path}');
|
|
exitCode = 2;
|
|
return;
|
|
}
|
|
|
|
// Collect all step files (exclude private helpers like _world.dart)
|
|
final stepFiles = stepDir
|
|
.listSync(recursive: false)
|
|
.whereType<File>()
|
|
.where((f) => f.path.endsWith('.dart'))
|
|
.where((f) => !basename(f.path).startsWith('_'))
|
|
.toList();
|
|
|
|
// Collect all step imports from generated tests
|
|
// Matches imports like: import './step/<file>.dart';
|
|
final importRegex = RegExp(r'''import ['"]\./step/([^'\"]+)['"];\s*''');
|
|
final imported = <String>{};
|
|
|
|
for (final entity in testsDir.listSync(recursive: true)) {
|
|
if (entity is! File) continue;
|
|
if (!entity.path.endsWith('_test.dart')) continue;
|
|
final content = entity.readAsStringSync();
|
|
for (final m in importRegex.allMatches(content)) {
|
|
imported.add(m.group(1)!);
|
|
}
|
|
}
|
|
|
|
final unused = <File>[];
|
|
for (final f in stepFiles) {
|
|
final name = basename(f.path);
|
|
final isUsed = imported.contains(name);
|
|
if (verbose) {
|
|
stdout.writeln('- ${isUsed ? 'USED ' : 'UNUSED '} $name');
|
|
}
|
|
if (!isUsed) unused.add(f);
|
|
}
|
|
|
|
if (unused.isEmpty) {
|
|
stdout.writeln('No unused step files found.');
|
|
return;
|
|
}
|
|
|
|
stdout.writeln('Unused step files (${unused.length}):');
|
|
for (final f in unused) {
|
|
stdout.writeln(' ${relative(f.path)}');
|
|
}
|
|
|
|
if (!delete) {
|
|
stdout.writeln('\nDry-run. Re-run with --delete to remove these files.');
|
|
return;
|
|
}
|
|
|
|
// Delete unused files
|
|
var deleted = 0;
|
|
for (final f in unused) {
|
|
try {
|
|
f.deleteSync();
|
|
deleted++;
|
|
} catch (e) {
|
|
stderr.writeln('Failed to delete ${f.path}: $e');
|
|
}
|
|
}
|
|
stdout.writeln('Deleted $deleted unused step files.');
|
|
}
|
|
|
|
String basename(String path) => path.split(RegExp(r'[\\/]')).last;
|
|
String relative(String path) {
|
|
final cwd = Directory.current.path.replaceAll('\\\\', '/');
|
|
final norm = path.replaceAll('\\\\', '/');
|
|
return norm.startsWith('$cwd/') ? norm.substring(cwd.length + 1) : norm;
|
|
}
|