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 = [
    'library',
    '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('//')) {
      if (trimmed != '// dart format on') {
        commentStart ??= index;
      }

      continue;
    }

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

    if (trimmed.startsWith('import ')) {
      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 = lines.sublist(importEnd).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');
  }

  String? startContent = null;

  if (contentStart.trim() case final String start when start.isNotEmpty) {
    final lines = start.split('\n');
    for (final (index, line) in lines.reversed.indexed) {
      if (line.trim().isEmpty) {
        continue;
      }

      if (line.trim() == '// dart format off') {
        continue;
      }

      startContent = lines.sublist(0, index).join('\n');
      break;
    }
  }

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

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