findAnalysisOptions method

AnalysisOptions? findAnalysisOptions(
  1. File? file
)

Implementation

AnalysisOptions? findAnalysisOptions(File? file) {
  if (file == null) {
    return null;
  }
  final now = _now();
  final searched = <String>[];
  for (var dir = file.parent; ; dir = dir.parent) {
    final knownEmptyAt = _withoutOptions[dir.path];
    if (knownEmptyAt != null &&
        now.difference(knownEmptyAt) < _negativeCacheTtl) {
      break;
    }
    searched.add(dir.path);
    try {
      final optionsFile = dir.getFile('analysis_options.yaml');
      if (optionsFile.exists) {
        final stamp = optionsFile.modificationStamp;
        final cached = _analysisOptions[optionsFile.path];
        if (cached != null && cached.$1 == stamp) {
          return cached.$2;
        }
        _logger.finer('parsing ${optionsFile.path}');
        final options = AnalysisOptions.loadFromYaml(
          dir.path,
          optionsFile.readAsStringSync(),
        );
        _analysisOptions[optionsFile.path] = (stamp, options);
        // Reading it worked, so a later break is news again rather than a
        // repeat of a complaint already made.
        _warnedAbout.remove(dir.path);
        return options;
      }
      // No file here. A complaint about one that has since been deleted is
      // stale too, and keeping it would silence the next breakage of a
      // recreated one. Deliberately not `continue`: the loop's exit test is
      // at the bottom, and skipping it spins forever at the filesystem root.
      _warnedAbout.remove(dir.path);
    } catch (e, stackTrace) {
      // Failing here silently disables every exclude_glob, so say so -- but
      // only once per file, since this runs for every reported literal.
      if (_warnedAbout.add(dir.path)) {
        _logger.warning(
          'Unable to read analysis options near ${dir.path}',
          e,
          stackTrace,
        );
      }
      // Return rather than break: caching this as "no options above here"
      // would turn a malformed or briefly unreadable file into a permanent
      // one, surviving the fix that repairs it.
      return null;
    }
    // Checked after reading, so an options file at the root is still found.
    if (dir.isRoot) {
      break;
    }
  }
  for (final path in searched) {
    _withoutOptions[path] = now;
  }
  return null;
}