updateFileContexts method

Future<bool> updateFileContexts(
  1. Set<String> filePaths
)

Inform the analyzer that the provided filePaths have been updated.

Refreshes the Dart analysis context for the changed files and returns true if any of them are (or were) endpoint files, meaning code generation should run. The actual full analysis is deferred to the next analyze call.

Implementation

Future<bool> updateFileContexts(Set<String> filePaths) async {
  // Only consider files within the tracked directory.
  final relevantPaths = filePaths
      .where((f) => p.isWithin(absoluteIncludedPaths, p.absolute(f)))
      .toSet();

  final erroredFilesBefore = _erroredFiles;
  final keysBefore = _fileCache.keys.toSet();

  await analyze(
    collector: CodeGenerationCollector(),
    changedFiles: relevantPaths,
  );

  final erroredFilesAfter = _erroredFiles;
  final keysAfter = _fileCache.keys.toSet();

  // Regenerate when the set of endpoint files changed, or when any file's
  // error state flipped (an error appearing or clearing changes the parsed
  // definitions). A persistently broken file, by contrast, must not turn
  // every unrelated change - such as watcher echoes of freshly generated
  // files - into another generation, or generation loops forever while an
  // error exists anywhere in the project.
  if (keysBefore.length != keysAfter.length ||
      keysAfter.difference(keysBefore).isNotEmpty ||
      erroredFilesBefore.length != erroredFilesAfter.length ||
      erroredFilesAfter.difference(erroredFilesBefore).isNotEmpty) {
    return true;
  }

  // Editing methods on an existing endpoint does not add/remove cache keys,
  // but generated protocol must still be refreshed (otherwise stale
  // generated Dart can break analysis/compile before the next generate).
  for (final path in relevantPaths) {
    if (!path.endsWith('.dart') || path.endsWith('_test.dart')) continue;
    if (_fileCache.containsKey(path)) return true;
    if (_isEndpointFile(File(path))) return true;
  }

  return false;
}