updateImportStatements method

  1. @visibleForTesting
Future<void> updateImportStatements(
  1. ResolvedReferences import, {
  2. Config? config,
})

Implementation

@visibleForTesting
Future<void> updateImportStatements(
  ResolvedReferences import, {
  Config? config,
}) async {
  final _config = config ?? Config();
  final ResolvedReferences(:path, :imports, :hasImports) = import;

  if (path == null) return;
  if (!hasImports) return;

  final lines = fs.file(path).readAsLinesSync();

  int? importStart;
  int? importEnd;
  int? commentStart;

  final skippable = ['as', 'hide', 'show', 'export', RegExp(r'^\w+[,;]$')];

  for (final (index, line) in lines.indexed) {
    final trimmed = line.trim();
    if (trimmed.isEmpty) continue;
    if (trimmed.startsWith('//')) {
      commentStart ??= index;
      continue;
    }

    if (skippable.any(trimmed.startsWith)) {
      continue;
    }

    if (trimmed.startsWith('import ')) {
      if (index > 0 && lines[index - 1].startsWith('// dart format off')) {
        importStart ??= index - 1;
      }

      importStart ??= index;
      commentStart = null;
      continue;
    }

    importEnd = commentStart ?? index;
    break;
  }

  if (importStart == null) {
    if (importEnd != null) {
      importStart = importEnd;
    } else {
      log('No import start found for ${fs.path.relative(path)}');
      return;
    }
  }

  if (importEnd == null) {
    log('No import end found for ${fs.path.relative(path)}');
    return;
  }

  final contentStart = lines.take(importStart).join('\n');
  final contentEnd = switch (lines.sublist(importEnd)) {
    ['// dart format on', ...final lines] => lines.join('\n'),
    final lines => lines.join('\n'),
  };

  final (:dart, :relative, :package) = imports(
    trailComments: !_config.format,
  );

  final importStatements = [
    if (dart.isNotEmpty) ...dart.map((e) => '$e').followedBy(['']),
    if (package.isNotEmpty) ...package.map((e) => '$e').followedBy(['']),
    if (relative.isNotEmpty) ...relative.map((e) => '$e').followedBy(['']),
  ];

  if (_config case Config(format: false) when importStatements.isNotEmpty) {
    importStatements.insert(0, '// dart format off');
    // leave the last line empty
    importStatements.insert(importStatements.length - 1, '// dart format on');
  }

  var content = [
    if (contentStart.trim() case final String start when start.isNotEmpty)
      start,
    ...importStatements,
    contentEnd.trim(),
    '',
  ].join('\n');

  fs.file(path).writeAsStringSync(content.trimLeft());
}