migrateSource static method
Implementation
static MigrationResult migrateSource(
String source, {
required String className,
required String importUri,
}) {
final notes = <MigrationNote>[];
final changes = <String>[];
int lineOf(int index) =>
'\n'.allMatches(source.substring(0, index)).length + 1;
final imports = _import.allMatches(source).toList();
if (imports.isEmpty && !_anyDotenv.hasMatch(source)) {
return MigrationResult(source, changes, notes);
}
// Cases that need a human; the file is left untouched.
for (final m in imports) {
if (RegExp(r'\bas\s+\w+').hasMatch(m.group(1) ?? '')) {
notes.add(MigrationNote(lineOf(m.start),
'flutter_dotenv is imported with a prefix; update this file by hand.',
blocking: true));
}
}
for (final m in _mutation.allMatches(source)) {
notes.add(MigrationNote(lineOf(m.start),
'Code writes to dotenv.env; the generated values are constant. Update by hand.',
blocking: true));
}
if (notes.any((n) => n.blocking))
return MigrationResult(source, changes, notes);
var out = source;
// 1. `await dotenv.load(...);` statements are no longer needed.
out = _removeLoads(out, className, changes, notes, lineOf);
// 2. Compatible members become the generated class.
final memberCount = _member.allMatches(out).length;
if (memberCount > 0) {
out = out.replaceAllMapped(_member, (m) => '$className.${m.group(1)}');
changes.add(
'$memberCount dotenv usage${memberCount == 1 ? '' : 's'} → $className');
}
// 3. What's left can't be translated automatically.
for (final m in _anyDotenv.allMatches(out)) {
final member = m.group(1)!;
if (member == 'load') continue; // already reported by _removeLoads
final hint =
member == 'testLoad' ? ' (tests can read $className directly)' : '';
notes.add(MigrationNote(lineOf(source.indexOf(m.group(0)!)),
'dotenv.$member has no compiled equivalent; update by hand$hint.'));
}
for (final m in _dotEnvClass.allMatches(out)) {
notes.add(MigrationNote(lineOf(m.start < source.length ? m.start : 0),
'A DotEnv() instance is created here; switch it to $className by hand.'));
}
out = _removeUnusedClientEnvConstant(out, changes, notes, lineOf, source);
if (!changes.isNotEmpty) return MigrationResult(source, changes, notes);
// 4. Imports: add the generated file, drop flutter_dotenv when unused.
if (!out.contains(importUri)) {
out = _addImport(out, importUri);
changes.add("import '$importUri'");
}
final withoutImports = out.replaceAll(_import, '');
if (!RegExp(r'(?<![\w$])(dotenv|DotEnv)\b').hasMatch(withoutImports)) {
final before = out;
out = out.replaceAll(_import, '');
if (out != before) changes.add('removed the flutter_dotenv import');
}
return MigrationResult(out, changes, notes);
}