// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// Looks for ".dart" files in "tests/" that appear to be orphaned. That means
/// they don't end in "_test.dart" so aren't run as tests by the test_runner,
/// but they also don't appear to be referenced by any other tests.
///
/// Usually this means that someone accidentally left off the "_test" and the
/// file is supposed to be a test but is silently getting ignored.
library;

import 'dart:io';

import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:test_runner/src/path.dart';

void main(List<String> arguments) {
  _initAnalysisContext();

  var suites = Directory('tests').listSync();
  suites.sort((a, b) => a.path.compareTo(b.path));

  for (var entry in suites) {
    // Skip the co19 tests since they don't use '_test.dart'.
    if (entry is Directory && !entry.path.contains('co19')) {
      _checkTestDirectory(entry);
    }
  }
}

late AnalysisContext _analysisContext;

void _checkTestDirectory(Directory directory) {
  print('-- ${directory.path} --');
  var paths = directory
      .listSync(recursive: true)
      .map((entry) => entry.path)
      .where((path) => path.endsWith('.dart'))
      .toList();
  paths.sort();

  // Collect the set of all files that are known to be referred to by others.
  print('Finding referenced files...');
  var importedPaths = <String>{};
  for (var path in paths) {
    _parseReferences(importedPaths, path);
  }

  // Find the ".dart" files that don't end in "_test.dart" but also aren't used
  // by another library. Those should probably be tests.
  var hasOrphan = false;
  for (var path in paths) {
    if (!path.endsWith('_test.dart') && !importedPaths.contains(path)) {
      print('Suspected orphan: $path');
      hasOrphan = true;
    }
  }

  if (!hasOrphan) print('No orphans :)');
}

void _initAnalysisContext() {
  var collection = AnalysisContextCollection(
    includedPaths: ['test'],
  );

  if (collection.contexts.length != 1) {
    throw StateError(
      'Expected to find exactly one context root, '
      'got ${collection.contexts.length}',
    );
  }

  _analysisContext = collection.contexts.single;
}

void _parseReferences(Set<String> importedPaths, String filePath) {
  var absolute = Path(filePath).absolute.toNativePath();
  var analysisSession = _analysisContext.currentSession;
  var parseResult = analysisSession.getParsedUnit(absolute);
  var unit = (parseResult as ParsedUnitResult).unit;

  void add(String importPath) {
    if (importPath.startsWith('dart:')) return;

    var resolved = Uri.file(filePath).resolve(importPath).path;
    importedPaths.add(resolved);
  }

  for (var directive in unit.directives) {
    if (directive is UriBasedDirective) {
      add(directive.uri.stringValue!);
    }
  }
}
