// Copyright (c) 2016, 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/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/generated/engine.dart'
    show AnalysisContext, AnalysisOptionsImpl;
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/link.dart';
import 'package:analyzer/src/summary/prelink.dart';
import 'package:analyzer/src/summary/resynthesize.dart';
import 'package:analyzer/src/summary/summarize_ast.dart';
import 'package:analyzer/src/summary/summarize_elements.dart'
    show PackageBundleAssembler;
import 'package:analyzer/src/task/api/dart.dart' show PARSED_UNIT;
import 'package:analyzer/src/task/api/general.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../context/abstract_context.dart';
import 'element_text.dart';
import 'resynthesize_common.dart';
import 'summary_common.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(ResynthesizeAstStrongTest);
    defineReflectiveTests(ApplyCheckElementTextReplacements);
  });
}

@reflectiveTest
class ApplyCheckElementTextReplacements {
  test_applyReplacements() {
    applyCheckElementTextReplacements();
  }
}

/// Mixin for serializing ASTs during testing.
abstract class AstSerializeTestMixin
    implements _AstSerializeTestMixinInterface {
  final Set<Source> serializedSources = new Set<Source>();
  PackageBundleAssembler bundleAssembler = new PackageBundleAssembler();
  final Map<String, UnlinkedUnitBuilder> uriToUnit =
      <String, UnlinkedUnitBuilder>{};

  AnalysisContext get context;

  TestSummaryResynthesizer encodeLibrary(Source source) {
    _serializeLibrary(source);

    PackageBundle bundle =
        new PackageBundle.fromBuffer(bundleAssembler.assemble().toBuffer());

    Map<String, UnlinkedUnit> unlinkedSummaries = <String, UnlinkedUnit>{};
    for (int i = 0; i < bundle.unlinkedUnitUris.length; i++) {
      String uri = bundle.unlinkedUnitUris[i];
      unlinkedSummaries[uri] = bundle.unlinkedUnits[i];
    }

    LinkedLibrary getDependency(String absoluteUri) {
      Map<String, LinkedLibrary> sdkLibraries =
          SerializedMockSdk.instance.uriToLinkedLibrary;
      LinkedLibrary linkedLibrary = sdkLibraries[absoluteUri];
      if (linkedLibrary == null && !allowMissingFiles) {
        fail('Linker unexpectedly requested LinkedLibrary for "$absoluteUri".'
            '  Libraries available: ${sdkLibraries.keys}');
      }
      return linkedLibrary;
    }

    UnlinkedUnit getUnit(String absoluteUri) {
      UnlinkedUnit unit = uriToUnit[absoluteUri] ??
          SerializedMockSdk.instance.uriToUnlinkedUnit[absoluteUri];
      if (unit == null && !allowMissingFiles) {
        fail('Linker unexpectedly requested unit for "$absoluteUri".');
      }
      return unit;
    }

    Set<String> nonSdkLibraryUris = serializedSources
        .where((Source source) =>
            !source.isInSystemLibrary &&
            context.computeKindOf(source) == SourceKind.LIBRARY)
        .map((Source source) => source.uri.toString())
        .toSet();

    Map<String, LinkedLibrary> linkedSummaries = link(nonSdkLibraryUris,
        getDependency, getUnit, context.declaredVariables.get, true);

    return new TestSummaryResynthesizer(
        context,
        new Map<String, UnlinkedUnit>()
          ..addAll(SerializedMockSdk.instance.uriToUnlinkedUnit)
          ..addAll(unlinkedSummaries),
        new Map<String, LinkedLibrary>()
          ..addAll(SerializedMockSdk.instance.uriToLinkedLibrary)
          ..addAll(linkedSummaries),
        allowMissingFiles);
  }

  UnlinkedUnit _getUnlinkedUnit(Source source) {
    if (source == null) {
      return new UnlinkedUnitBuilder();
    }

    String uriStr = source.uri.toString();
    {
      UnlinkedUnit unlinkedUnitInSdk =
          SerializedMockSdk.instance.uriToUnlinkedUnit[uriStr];
      if (unlinkedUnitInSdk != null) {
        return unlinkedUnitInSdk;
      }
    }
    return uriToUnit.putIfAbsent(uriStr, () {
      int modificationTime = context.computeResult(source, MODIFICATION_TIME);
      if (modificationTime < 0) {
        // Source does not exist.
        if (!allowMissingFiles) {
          fail('Unexpectedly tried to get unlinked summary for $source');
        }
        return null;
      }
      CompilationUnit unit = context.computeResult(source, PARSED_UNIT);
      UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
      bundleAssembler.addUnlinkedUnit(source, unlinkedUnit);
      return unlinkedUnit;
    });
  }

  void _serializeLibrary(Source librarySource) {
    if (librarySource == null || librarySource.isInSystemLibrary) {
      return;
    }
    if (!serializedSources.add(librarySource)) {
      return;
    }

    UnlinkedUnit getPart(String absoluteUri) {
      Source source = context.sourceFactory.forUri(absoluteUri);
      return _getUnlinkedUnit(source);
    }

    UnlinkedPublicNamespace getImport(String relativeUri) {
      return getPart(relativeUri)?.publicNamespace;
    }

    UnlinkedUnit definingUnit = _getUnlinkedUnit(librarySource);
    if (definingUnit != null) {
      LinkedLibraryBuilder linkedLibrary = prelink(librarySource.uri.toString(),
          definingUnit, getPart, getImport, context.declaredVariables.get);
      linkedLibrary.dependencies.skip(1).forEach((LinkedDependency d) {
        Source source = context.sourceFactory.forUri(d.uri);
        _serializeLibrary(source);
      });
    }
  }
}

@reflectiveTest
class ResynthesizeAstStrongTest extends _ResynthesizeAstTest {
  @failingTest // See dartbug.com/32290
  test_const_constructor_inferred_args() =>
      super.test_const_constructor_inferred_args();

  @failingTest // See dartbug.com/33441
  test_const_list_inferredType() => super.test_const_list_inferredType();

  @failingTest // See dartbug.com/33441
  test_const_map_inferredType() => super.test_const_map_inferredType();

  @override
  @failingTest
  test_syntheticFunctionType_genericClosure() async {
    await super.test_syntheticFunctionType_genericClosure();
  }

  @override
  @failingTest
  test_syntheticFunctionType_inGenericClass() async {
    await super.test_syntheticFunctionType_inGenericClass();
  }

  @override
  @failingTest
  test_syntheticFunctionType_noArguments() async {
    await super.test_syntheticFunctionType_noArguments();
  }

  @override
  @failingTest
  test_syntheticFunctionType_withArguments() async {
    await super.test_syntheticFunctionType_withArguments();
  }
}

/**
 * Abstract mixin for serializing ASTs and resynthesizing elements from it.
 */
abstract class _AstResynthesizeTestMixin
    implements _AstSerializeTestMixinInterface {
  AnalysisContext get context;

  TestSummaryResynthesizer encodeLibrary(Source source);

  LibraryElementImpl _encodeDecodeLibraryElement(Source source) {
    SummaryResynthesizer resynthesizer = encodeLibrary(source);
    return resynthesizer.getLibraryElement(source.uri.toString());
  }
}

/**
 * Interface that [_AstSerializeTestMixin] requires of classes it's mixed
 * into.  We can't place the getter below into [_AstSerializeTestMixin]
 * directly, because then it would be overriding a field at the site where the
 * mixin is instantiated.
 */
abstract class _AstSerializeTestMixinInterface {
  /**
   * A test should return `true` to indicate that a missing file at the time of
   * summary resynthesis shouldn't trigger an error.
   */
  bool get allowMissingFiles;
}

abstract class _ResynthesizeAstTest extends ResynthesizeTest
    with _AstResynthesizeTestMixin, AstSerializeTestMixin {
  bool get shouldCompareLibraryElements;

  @override
  Future<LibraryElementImpl> checkLibrary(String text,
      {bool allowErrors: false, bool dumpSummaries: false}) async {
    Source source = addTestSource(text);
    LibraryElementImpl resynthesized = _encodeDecodeLibraryElement(source);
    LibraryElementImpl original = context.computeLibraryElement(source);
    if (!allowErrors) {
      List<AnalysisError> errors = context.computeErrors(source);
      if (errors.where((e) => e.message.startsWith('unused')).isNotEmpty) {
        fail('Analysis errors: $errors');
      }
    }
    if (shouldCompareLibraryElements) {
      checkLibraryElements(original, resynthesized);
    }
    return resynthesized;
  }

  @override
  DartSdk createDartSdk() => AbstractContextTest.SHARED_MOCK_SDK;

  @override
  AnalysisOptionsImpl createOptions() {
    if (isStrongMode) {
      return super.createOptions()..previewDart2 = true;
    } else {
      return super.createOptions()..previewDart2 = false;
    }
  }

  test_getElement_constructor_named() async {
    String text = 'class C { C.named(); }';
    Source source = addLibrarySource('/test.dart', text);
    ConstructorElement original = context
        .computeLibraryElement(source)
        .getType('C')
        .getNamedConstructor('named');
    expect(original, isNotNull);
    ConstructorElement resynthesized = _validateGetElement(text, original);
    compareConstructorElements(resynthesized, original, 'C.constructor named');
  }

  test_getElement_constructor_unnamed() async {
    String text = 'class C { C(); }';
    Source source = addLibrarySource('/test.dart', text);
    ConstructorElement original =
        context.computeLibraryElement(source).getType('C').unnamedConstructor;
    expect(original, isNotNull);
    ConstructorElement resynthesized = _validateGetElement(text, original);
    compareConstructorElements(resynthesized, original, 'C.constructor');
  }

  test_getElement_field() async {
    String text = 'class C { var f; }';
    Source source = addLibrarySource('/test.dart', text);
    FieldElement original =
        context.computeLibraryElement(source).getType('C').getField('f');
    expect(original, isNotNull);
    FieldElement resynthesized = _validateGetElement(text, original);
    compareFieldElements(resynthesized, original, 'C.field f');
  }

  test_getElement_getter() async {
    String text = 'class C { get f => null; }';
    Source source = addLibrarySource('/test.dart', text);
    PropertyAccessorElement original =
        context.computeLibraryElement(source).getType('C').getGetter('f');
    expect(original, isNotNull);
    PropertyAccessorElement resynthesized = _validateGetElement(text, original);
    comparePropertyAccessorElements(resynthesized, original, 'C.getter f');
  }

  test_getElement_method() async {
    String text = 'class C { f() {} }';
    Source source = addLibrarySource('/test.dart', text);
    MethodElement original =
        context.computeLibraryElement(source).getType('C').getMethod('f');
    expect(original, isNotNull);
    MethodElement resynthesized = _validateGetElement(text, original);
    compareMethodElements(resynthesized, original, 'C.method f');
  }

  test_getElement_operator() async {
    String text = 'class C { operator+(x) => null; }';
    Source source = addLibrarySource('/test.dart', text);
    MethodElement original =
        context.computeLibraryElement(source).getType('C').getMethod('+');
    expect(original, isNotNull);
    MethodElement resynthesized = _validateGetElement(text, original);
    compareMethodElements(resynthesized, original, 'C.operator+');
  }

  test_getElement_setter() async {
    String text = 'class C { void set f(value) {} }';
    Source source = addLibrarySource('/test.dart', text);
    PropertyAccessorElement original =
        context.computeLibraryElement(source).getType('C').getSetter('f');
    expect(original, isNotNull);
    PropertyAccessorElement resynthesized = _validateGetElement(text, original);
    comparePropertyAccessorElements(resynthesized, original, 'C.setter f');
  }

  test_getElement_unit() async {
    String text = 'class C { f() {} }';
    Source source = addLibrarySource('/test.dart', text);
    CompilationUnitElement original =
        context.computeLibraryElement(source).definingCompilationUnit;
    expect(original, isNotNull);
    CompilationUnitElement resynthesized = _validateGetElement(text, original);
    compareCompilationUnitElements(resynthesized, original);
  }

  /**
   * Encode the library containing [original] into a summary and then use
   * [TestSummaryResynthesizer.getElement] to retrieve just the original
   * element from the resynthesized summary.
   */
  Element _validateGetElement(String text, Element original) {
    SummaryResynthesizer resynthesizer = encodeLibrary(original.library.source);
    ElementLocationImpl location = original.location;
    Element result = resynthesizer.getElement(location);
    checkMinimalResynthesisWork(resynthesizer, original.library);
    // Check that no other summaries needed to be resynthesized to resynthesize
    // the library element.
    expect(resynthesizer.resynthesisCount, 3);
    expect(result.location, location);
    return result;
  }
}
