// Copyright (c) 2020, 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.

import 'dart:async';

import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/utilities/extensions/stream.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../../summary/macros_environment.dart';
import '../resolution/context_collection_resolution.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(AnalysisDriverCachingTest);
  });
}

@reflectiveTest
class AnalysisDriverCachingTest extends PubPackageResolutionTest {
  @override
  bool get retainDataForTesting => true;

  String get testFilePathPlatform => convertPath(testFilePath);

  List<Set<String>> get _linkedCycles {
    var driver = driverFor(testFilePath);
    return driver.testView!.libraryContext.linkedCycles;
  }

  @override
  void setUp() {
    super.setUp();

    writeTestPackageConfig(
      PackageConfigFileBuilder(),
      macrosEnvironment: MacrosEnvironment.instance,
    );
  }

  test_analysisOptions_strictCasts() async {
    useEmptyByteStore();

    // Configure `strict-casts: false`.
    writeTestPackageAnalysisOptionsFile(
      AnalysisOptionsFileConfig(
        strictCasts: false,
      ),
    );

    newFile(testFilePath, r'''
dynamic a = 0;
int b = a;
''');

    // `strict-cast: false`, so no errors.
    assertErrorsInList(await _computeTestFileErrors(), []);

    // Configure `strict-casts: true`.
    disposeAnalysisContextCollection();
    writeTestPackageAnalysisOptionsFile(
      AnalysisOptionsFileConfig(
        strictCasts: true,
      ),
    );

    // `strict-cast: true`, so has errors.
    assertErrorsInList(await _computeTestFileErrors(), [
      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 23, 1),
    ]);
  }

  test_change_factoryConstructor_addEqNothing() async {
    await resolveTestCode(r'''
class A {
  factory A();
}
''');

    var analysisDriver = driverFor(testFilePathPlatform);
    analysisDriver.changeFile(testFilePathPlatform);
    await analysisDriver.applyPendingFileChanges();

    await resolveTestCode(r'''
class A {
  factory A() =;
}
''');
  }

  test_change_factoryConstructor_moveStaticToken() async {
    await resolveTestCode(r'''
class A {
  factory A();
  static void foo<U>() {}
}
''');

    var analysisDriver = driverFor(testFilePathPlatform);
    analysisDriver.changeFile(testFilePathPlatform);
    await analysisDriver.applyPendingFileChanges();

    await resolveTestCode(r'''
class A {
  factory A() =
  static void foo<U>() {}
}
''');
  }

  test_change_field_outOfOrderStaticConst() async {
    await resolveTestCode(r'''
class A {
  static f = Object();
}
''');

    var analysisDriver = driverFor(testFilePathPlatform);
    analysisDriver.changeFile(testFilePathPlatform);
    await analysisDriver.applyPendingFileChanges();

    await resolveTestCode(r'''
class A {
  const
  static f = Object();
}
''');
  }

  test_change_field_staticFinal_hasConstConstructor_changeInitializer() async {
    useEmptyByteStore();

    newFile(testFilePath, r'''
class A {
  static const a = 0;
  static const b = 1;
  static final Set<int> f = {a};
  const A {}
}
''');

    await resolveTestFile();
    assertType(findElement.field('f').type, 'Set<int>');

    // The summary for the library was linked.
    _assertContainsLinkedCycle({testFilePath}, andClear: true);

    // Dispose the collection, with its driver.
    // The next analysis will recreate it.
    // We will reuse the byte store, so can reuse summaries.
    disposeAnalysisContextCollection();

    newFile(testFilePath, r'''
class A {
  static const a = 0;
  static const b = 1;
  static final Set<int> f = <int>{a, b, 2};
  const A {}
}
''');

    await resolveTestFile();
    assertType(findElement.field('f').type, 'Set<int>');

    // We changed the initializer of the final field. But it is static, so
    // even though the class hsa a constant constructor, we don't need its
    // initializer, so nothing should be linked.
    _assertNoLinkedCycles();
  }

  test_change_functionBody() async {
    useEmptyByteStore();

    newFile(testFilePath, r'''
void f() {
  print(0);
}
''');

    await resolveTestFile();
    expect(findNode.integerLiteral('0'), isNotNull);

    // The summary for the library was linked.
    _assertContainsLinkedCycle({testFilePath}, andClear: true);

    // Dispose the collection, with its driver.
    // The next analysis will recreate it.
    // We will reuse the byte store, so can reuse summaries.
    disposeAnalysisContextCollection();

    newFile(testFilePath, r'''
void f() {
  print(1);
}
''');

    await resolveTestFile();
    expect(findNode.integerLiteral('1'), isNotNull);

    // We changed only the function body, nothing should be linked.
    _assertNoLinkedCycles();
  }

  test_getLibraryByUri_invalidated_exportNamespace() async {
    useEmptyByteStore();

    var a = newFile('$testPackageLibPath/a.dart', 'const a1 = 0;');
    newFile('$testPackageLibPath/b.dart', r'''
import 'a.dart';
''');

    var driver = driverFor(testFilePath);

    // Link both libraries, keep them.
    await driver.getLibraryByUri('package:test/a.dart');
    await driver.getLibraryByUri('package:test/b.dart');

    // Discard both libraries.
    driver.changeFile(a.path);

    // Read `package:test/a.dart` from bytes.
    // Don't ask for `exportNamespace`, this used to keep it in the state
    // "should be asked from LinkedElementLibrary", which will ask it
    // from the `LibraryReader` current at the moment of `exportNamespace`
    // access, not necessary the same that created this instance.
    final aResult = await driver.getLibraryByUri('package:test/a.dart');
    final aElement = (aResult as LibraryElementResult).element;

    // The element is valid at this point.
    expect(driver.isValidLibraryElement(aElement), isTrue);

    // Discard both libraries.
    driver.changeFile(a.path);

    // Read `package:test/b.dart`, actually create `LibraryElement` for it.
    // We used to create only `LibraryReader` for `package:test/a.dart`.
    await driver.getLibraryByUri('package:test/b.dart');

    // The element is not valid anymore.
    expect(driver.isValidLibraryElement(aElement), isFalse);

    // But its `exportNamespace` can be accessed.
    expect(aElement.exportNamespace.definedNames, isNotEmpty);

    // TODO(scheglov) This is not quite right.
    // When we return `LibraryElement` that is not fully read, and read
    // anything lazily, we can be in a situation when there was a change,
    // and an imported library does not define a referenced element anymore.
    // But there is still a client that holds this `LibraryElement`, and
    // its summary information says "get element X from `package:Y"; and when
    // we attempt to get it, the might be no `X` in `Y`.
  }

  test_lint_dependOnReferencedPackage_update_pubspec_addDependency() async {
    useEmptyByteStore();

    var aaaPackageRootPath = '$packagesRootPath/aaa';
    newFile('$aaaPackageRootPath/lib/a.dart', '');

    writeTestPackageConfig(
      PackageConfigFileBuilder()
        ..add(name: 'aaa', rootPath: aaaPackageRootPath),
    );

    // Configure with the lint.
    writeTestPackageAnalysisOptionsFile(
      AnalysisOptionsFileConfig(lints: ['depend_on_referenced_packages']),
    );

    // Configure without dependencies, but with a (required) name.
    // So, the lint rule will be activated.
    writeTestPackagePubspecYamlFile(
      PubspecYamlFileConfig(
        name: 'my_test',
        dependencies: [],
      ),
    );

    newFile(testFilePath, r'''
// ignore:unused_import
import 'package:aaa/a.dart';
''');

    // We don't have a dependency on `package:aaa`, so there is a lint.
    _assertHasLintReported(
      await _computeTestFileErrors(),
      'depend_on_referenced_packages',
    );

    // The summary for the library was linked.
    _assertContainsLinkedCycle({testFilePath}, andClear: true);

    // We will recreate it with new pubspec.yaml content.
    // But we will reuse the byte store, so can reuse summaries.
    disposeAnalysisContextCollection();

    // Add dependency on `package:aaa`.
    writeTestPackagePubspecYamlFile(
      PubspecYamlFileConfig(
        name: 'my_test',
        dependencies: [
          PubspecYamlFileDependency(name: 'aaa'),
        ],
      ),
    );

    // With dependency on `package:aaa` added, no lint is reported.
    expect(await _computeTestFileErrors(), isEmpty);

    // Lints don't affect summaries, nothing should be linked.
    _assertNoLinkedCycles();
  }

  test_lints() async {
    useEmptyByteStore();

    // Configure without any lint, but without experiments as well.
    writeTestPackageAnalysisOptionsFile(
      AnalysisOptionsFileConfig(lints: []),
    );

    newFile(testFilePath, r'''
void f() {
  ![0].isEmpty;
}
''');

    // We don't have any lints configured, so no errors.
    await resolveTestFile();
    assertErrorsInResult([]);

    // The summary for the library was linked.
    _assertContainsLinkedCycle({testFilePath}, andClear: true);

    // We will recreate it with new analysis options.
    // But we will reuse the byte store, so can reuse summaries.
    disposeAnalysisContextCollection();

    // Configure to run a lint.
    writeTestPackageAnalysisOptionsFile(
      AnalysisOptionsFileConfig(
        lints: ['prefer_is_not_empty'],
      ),
    );

    // Check that the lint was run, and reported.
    await resolveTestFile();
    _assertHasLintReported(result.errors, 'prefer_is_not_empty');

    // Lints don't affect summaries, nothing should be linked.
    _assertNoLinkedCycles();
  }

  test_macro_libraryElement_changeMacroCode() async {
    final macroFile = _newFileWithFixedNameMacro('MacroA');

    var a = newFile('$testPackageLibPath/a.dart', r'''
import 'my_macro.dart';

@MyMacro()
class A {}
''');

    var b = newFile('$testPackageLibPath/b.dart', r'''
export 'a.dart';
''');

    final analysisContext = contextFor(macroFile.path);

    Future<LibraryElement> getLibrary(String uriStr) async {
      final result = await analysisContext.currentSession
          .getLibraryByUri(uriStr) as LibraryElementResult;
      return result.element;
    }

    // This macro generates `MacroA`, but not `MacroB`.
    {
      final libraryA = await getLibrary('package:test/a.dart');
      expect(libraryA.getType('MacroA'), isNotNull);
      expect(libraryA.getType('MacroB'), isNull);
      // This propagates transitively.
      final libraryB = await getLibrary('package:test/b.dart');
      expect(libraryB.exportNamespace.get('MacroA'), isNotNull);
      expect(libraryB.exportNamespace.get('MacroB'), isNull);
    }

    _assertContainsLinkedCycle({a.path});
    _assertContainsLinkedCycle({b.path}, andClear: true);

    // The macro will generate `MacroB`.
    _newFileWithFixedNameMacro('MacroB');

    // Notify about changes.
    analysisContext.changeFile(macroFile.path);
    await analysisContext.applyPendingFileChanges();

    // This macro generates `MacroB`, but not `MacroA`.
    {
      final libraryA = await getLibrary('package:test/a.dart');
      expect(libraryA.getType('MacroA'), isNull);
      expect(libraryA.getType('MacroB'), isNotNull);
      // This propagates transitively.
      final libraryB = await getLibrary('package:test/b.dart');
      expect(libraryB.exportNamespace.get('MacroA'), isNull);
      expect(libraryB.exportNamespace.get('MacroB'), isNotNull);
    }

    _assertContainsLinkedCycle({a.path});
    _assertContainsLinkedCycle({b.path}, andClear: true);
  }

  test_macro_reanalyze_errors_changeCodeUsedByMacro_importedLibrary() async {
    final a = newFile('$testPackageLibPath/a.dart', r'''
String getClassName() => 'MacroA';
''');

    newFile('$testPackageLibPath/my_macro.dart', r'''
import 'package:_fe_analyzer_shared/src/macros/api.dart';
import 'a.dart';

macro class MyMacro implements ClassTypesMacro {
  const MyMacro();

  buildTypesForClass(clazz, builder) {
    final className = getClassName();
    builder.declareType(
      '$className',
      DeclarationCode.fromString('class $className {}'),
    );
  }
}
''');

    var user = newFile('$testPackageLibPath/user.dart', r'''
import 'my_macro.dart';

@MyMacro()
class A {}

void f(MacroA a) {}
''');

    var analysisContext = contextFor(a.path);
    var analysisDriver = driverFor(a.path);

    var userErrors = analysisDriver.results
        .whereType<ErrorsResult>()
        .where((event) => event.path == user.path);

    // We get errors when the file is added.
    analysisDriver.addFile(user.path);
    assertErrorsInList((await userErrors.first).errors, []);

    // The macro will generate `MacroB`.
    newFile('$testPackageLibPath/a.dart', r'''
String getClassName() => 'MacroB';
''');

    // Notify about changes.
    analysisContext.changeFile(a.path);
    await analysisContext.applyPendingFileChanges();

    // The change to the macro cause re-analysis of the user file.
    assertErrorsInList((await userErrors.first).errors, [
      error(CompileTimeErrorCode.UNDEFINED_CLASS, 55, 6),
    ]);
  }

  test_macro_reanalyze_errors_changeCodeUsedByMacro_part() async {
    final a = newFile('$testPackageLibPath/a.dart', r'''
part of 'my_macro.dart';
String getClassName() => 'MacroA';
''');

    newFile('$testPackageLibPath/my_macro.dart', r'''
import 'package:_fe_analyzer_shared/src/macros/api.dart';
part 'a.dart';

macro class MyMacro implements ClassTypesMacro {
  const MyMacro();

  buildTypesForClass(clazz, builder) {
    final className = getClassName();
    builder.declareType(
      '$className',
      DeclarationCode.fromString('class $className {}'),
    );
  }
}
''');

    var user = newFile('$testPackageLibPath/user.dart', r'''
import 'my_macro.dart';

@MyMacro()
class A {}

void f(MacroA a) {}
''');

    var analysisContext = contextFor(a.path);
    var analysisDriver = driverFor(a.path);

    var userErrors = analysisDriver.results
        .whereType<ErrorsResult>()
        .where((event) => event.path == user.path);

    // We get errors when the file is added.
    analysisDriver.addFile(user.path);
    assertErrorsInList((await userErrors.first).errors, []);

    // The macro will generate `MacroB`.
    newFile('$testPackageLibPath/a.dart', r'''
part of 'my_macro.dart';
String getClassName() => 'MacroB';
''');

    // Notify about changes.
    analysisContext.changeFile(a.path);
    await analysisContext.applyPendingFileChanges();

    // The change to the macro cause re-analysis of the user file.
    assertErrorsInList((await userErrors.first).errors, [
      error(CompileTimeErrorCode.UNDEFINED_CLASS, 55, 6),
    ]);
  }

  test_macro_reanalyze_errors_changeMacroCode() async {
    var macroFile = _newFileWithFixedNameMacro('MacroA');

    var user = newFile('$testPackageLibPath/user.dart', r'''
import 'my_macro.dart';

@MyMacro()
class A {}

void f(MacroA a) {}
''');

    var analysisContext = contextFor(user.path);
    var analysisDriver = driverFor(user.path);

    var userErrors = analysisDriver.results
        .whereType<ErrorsResult>()
        .where((event) => event.path == user.path);

    // We get errors when the file is added.
    analysisDriver.addFile(user.path);
    assertErrorsInList((await userErrors.first).errors, []);

    // The macro will generate `MacroB`.
    _newFileWithFixedNameMacro('MacroB');

    // Notify about changes.
    analysisContext.changeFile(macroFile.path);
    await analysisContext.applyPendingFileChanges();

    // The change to the macro cause re-analysis of the user file.
    assertErrorsInList((await userErrors.first).errors, [
      error(CompileTimeErrorCode.UNDEFINED_CLASS, 55, 6),
    ]);
  }

  test_macro_resolvedUnit_changeCodeUsedByMacro() async {
    final a = newFile('$testPackageLibPath/a.dart', r'''
String getClassName() => 'MacroA';
''');

    newFile('$testPackageLibPath/my_macro.dart', r'''
import 'dart:async';
import 'package:_fe_analyzer_shared/src/macros/api.dart';
import 'a.dart';

macro class MyMacro implements ClassTypesMacro {
  const MyMacro();

  FutureOr<void> buildTypesForClass(clazz, builder) {
    final className = getClassName();
    builder.declareType(
      '$className',
      DeclarationCode.fromString('class $className {}'),
    );
  }
}
''');

    // The macro will generate `MacroA`, so no errors.
    await assertNoErrorsInCode('''
import 'my_macro.dart';

@MyMacro()
class A {}

void f(MacroA a) {}
''');

    // The macro will generate `MacroB`.
    newFile(a.path, r'''
String getClassName() => 'MacroB';
''');

    // Notify about changes.
    var analysisContext = contextFor(a.path);
    analysisContext.changeFile(a.path);
    await analysisContext.applyPendingFileChanges();

    // Resolve the test file, it still references `MacroA`, but the macro
    // generates `MacroB` now, so we have an error.
    await resolveTestFile();
    assertErrorsInResult([
      error(CompileTimeErrorCode.UNDEFINED_CLASS, 55, 6),
    ]);
  }

  void _assertContainsLinkedCycle(Set<String> expectedPosix,
      {bool andClear = false}) {
    var expected = expectedPosix.map(convertPath).toSet();
    expect(_linkedCycles, contains(unorderedEquals(expected)));
    if (andClear) {
      _linkedCycles.clear();
    }
  }

  void _assertHasLintReported(List<AnalysisError> errors, String name) {
    var matching = errors.where((element) {
      var errorCode = element.errorCode;
      return errorCode is LintCode && errorCode.name == name;
    }).toList();
    expect(matching, hasLength(1));
  }

  void _assertNoLinkedCycles() {
    expect(_linkedCycles, isEmpty);
  }

  /// Note that we intentionally use this method, we don't want to use
  /// [resolveFile] instead. Resolving a file will force to produce its
  /// resolved AST, and as a result to recompute the errors.
  ///
  /// But this method is used to check returning errors from the cache, or
  /// recomputing when the cache key is expected to be different.
  Future<List<AnalysisError>> _computeTestFileErrors() async {
    var testFilePathConverted = convertPath(testFilePath);
    var errorsResult = await contextFor(testFilePathConverted)
        .currentSession
        .getErrors(testFilePathConverted) as ErrorsResult;
    return errorsResult.errors;
  }

  File _newFileWithFixedNameMacro(String className) {
    return newFile('$testPackageLibPath/my_macro.dart', '''
import 'package:_fe_analyzer_shared/src/macros/api.dart';

macro class MyMacro implements ClassTypesMacro {
  const MyMacro();

  buildTypesForClass(clazz, builder) {
    builder.declareType(
      '$className',
      DeclarationCode.fromString('class $className {}'),
    );
  }
}
''');
  }
}

extension on AnalysisDriver {
  bool isValidLibraryElement(LibraryElement element) {
    return identical(element.session, currentSession);
  }
}
