addImportAndChangesInFile method
Implementation
Future<void> addImportAndChangesInFile({
required String filePath,
required List<String> importStatements,
required List<String> methodCalls,
}) async {
final file = File(filePath);
final lines = await file.readAsLines();
// Scan the WHOLE file for the last import line. The previous version
// `break`-ed at the first non-import line, so a leading comment, blank
// line or `library`/`part` directive left lastImportIndex = -1 and the
// entire block (imports AND method calls) was silently skipped.
int lastImportIndex = -1;
for (int i = 0; i < lines.length; i++) {
if (lines[i].startsWith("$kImport ")) {
lastImportIndex = i;
}
}
// Skip imports the file already has. The comparison runs against a
// whitespace-collapsed view of the file for the same reason as `addImport`:
// `dart format` may have wrapped or re-indented an existing import, and a
// plain line match would then miss it and insert a duplicate. Without this,
// the DI files gained one extra `injection_container.dart` import per
// generated feature.
final existing = StringBuffer(collapseWhitespace(lines.join(' ')));
final List<String> newImports = [];
for (final importStatement in importStatements) {
final normalized = collapseWhitespace(importStatement);
if (existing.toString().contains(normalized)) {
continue;
}
newImports.add(importStatement);
existing.write(' $normalized');
}
if (newImports.isNotEmpty) {
// Insert after the last import, or at the top when there are none.
lines.insertAll(lastImportIndex + 1, newImports);
}
int completionIndex = -1;
for (int i = 0; i < lines.length; i++) {
if (lines[i].trim() == '}') {
completionIndex = i;
}
}
if (completionIndex != -1) {
if (methodCalls.isNotEmpty) {
lines.insertAll(completionIndex, methodCalls);
}
await file.writeAsString(lines.join('\n'));
}
}