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

library analyzer_cli.test.driver;

import 'dart:async';
import 'dart:io';

import 'package:analyzer/error/error.dart';
import 'package:analyzer/source/analysis_options_provider.dart';
import 'package:analyzer/source/error_processor.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/services/lint.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/util/sdk.dart';
import 'package:analyzer_cli/src/ansi.dart' as ansi;
import 'package:analyzer_cli/src/driver.dart';
import 'package:analyzer_cli/src/options.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:yaml/src/yaml_node.dart';

import 'utils.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(BuildModeTest);
    defineReflectiveTests(ExitCodesTest);
    defineReflectiveTests(ExitCodesTest_PreviewDart2);
    // TODO(scheglov): Restore similar test coverage when the front-end API
    // allows it.  See https://github.com/dart-lang/sdk/issues/32258.
    // defineReflectiveTests(ExitCodesTest_UseCFE);
    defineReflectiveTests(LinterTest);
    defineReflectiveTests(LinterTest_PreviewDart2);
    defineReflectiveTests(LinterTest_UseCFE);
    defineReflectiveTests(NonDartFilesTest);
    defineReflectiveTests(OptionsTest);
    defineReflectiveTests(OptionsTest_PreviewDart2);
    // TODO(scheglov): Restore similar test coverage when the front-end API
    // allows it.  See https://github.com/dart-lang/sdk/issues/32258.
    // defineReflectiveTests(OptionsTest_UseCFE);
  }, name: 'Driver');
}

class BaseTest {
  static const emptyOptionsFile = 'data/empty_options.yaml';

  StringSink _savedOutSink, _savedErrorSink;
  int _savedExitCode;
  ExitHandler _savedExitHandler;

  Driver driver;

  bool get useCFE => false;

  bool get usePreviewDart2 => false;

  /// Normalize text with bullets.
  String bulletToDash(item) => '$item'.replaceAll('•', '-');

  /// Start a driver for the given [source], optionally providing additional
  /// [args] and an [options] file path. The value of [options] defaults to an
  /// empty options file to avoid unwanted configuration from an otherwise
  /// discovered options file.
  Future<Null> drive(
    String source, {
    String options: emptyOptionsFile,
    List<String> args: const <String>[],
  }) async {
    driver = new Driver(isTesting: true);
    var cmd = <String>[
      '--options',
      path.join(testDirectory, options),
      _adjustFileSpec(source)
    ]..addAll(args);
    if (usePreviewDart2) {
      cmd.insert(0, '--preview-dart-2');
    }
    if (useCFE) {
      cmd.insert(0, '--use-cfe');
    }
    await driver.start(cmd);
  }

  void setUp() {
    ansi.runningTests = true;
    _savedOutSink = outSink;
    _savedErrorSink = errorSink;
    _savedExitHandler = exitHandler;
    _savedExitCode = exitCode;
    exitHandler = (code) => exitCode = code;
    outSink = new StringBuffer();
    errorSink = new StringBuffer();
  }

  void tearDown() {
    outSink = _savedOutSink;
    errorSink = _savedErrorSink;
    exitCode = _savedExitCode;
    exitHandler = _savedExitHandler;
    ansi.runningTests = false;
  }

  /// Convert a file specification from a relative path to an absolute path.
  /// Handles the case where the file specification is of the form "$uri|$path".
  String _adjustFileSpec(String fileSpec) {
    int uriPrefixLength = fileSpec.indexOf('|') + 1;
    String uriPrefix = fileSpec.substring(0, uriPrefixLength);
    String relativePath = fileSpec.substring(uriPrefixLength);
    return '$uriPrefix${path.join(testDirectory, relativePath)}';
  }
}

@reflectiveTest
class BuildModeTest extends BaseTest {
  test_buildLinked() async {
    await withTempDirAsync((tempDir) async {
      var outputPath = path.join(tempDir, 'test_file.dart.sum');
      await _doDrive(path.join('data', 'test_file.dart'), additionalArgs: [
        '--build-summary-only',
        '--build-summary-output=$outputPath'
      ]);
      var output = new File(outputPath);
      expect(output.existsSync(), isTrue);
      PackageBundle bundle =
          new PackageBundle.fromBuffer(await output.readAsBytes());
      var testFileUri = 'file:///test_file.dart';
      expect(bundle.unlinkedUnitUris, equals([testFileUri]));
      expect(bundle.linkedLibraryUris, equals([testFileUri]));
      expect(exitCode, 0);
    });
  }

  test_buildLinked_buildSummaryOutputSemantic() async {
    await withTempDirAsync((tempDir) async {
      var testDart = path.join(tempDir, 'test.dart');
      var testSumFull = path.join(tempDir, 'test.sum.full');
      var testSumSemantic = path.join(tempDir, 'test.sum.sem');

      new File(testDart).writeAsStringSync('var v = 42;');

      await _doDrive(testDart, additionalArgs: [
        '--build-summary-only',
        '--build-summary-output=$testSumFull',
        '--build-summary-output-semantic=$testSumSemantic',
      ]);
      expect(exitCode, 0);

      // The full summary is produced.
      {
        var file = new File(testSumFull);
        expect(file.existsSync(), isTrue);
        var bytes = file.readAsBytesSync();
        var bundle = new PackageBundle.fromBuffer(bytes);
        var v = bundle.unlinkedUnits[0].variables[0];
        expect(v.name, 'v');
        expect(v.nameOffset, 4);
      }

      // The semantic summary is produced.
      {
        var file = new File(testSumSemantic);
        expect(file.existsSync(), isTrue);
        var bytes = file.readAsBytesSync();
        var bundle = new PackageBundle.fromBuffer(bytes);
        var v = bundle.unlinkedUnits[0].variables[0];
        expect(v.name, 'v');
        expect(v.nameOffset, 0);
      }
    });
  }

  test_buildLinked_fromUnlinked() async {
    await withTempDirAsync((tempDir) async {
      var aDart = path.join(tempDir, 'a.dart');
      var bDart = path.join(tempDir, 'b.dart');

      var aUri = 'package:aaa/a.dart';
      var bUri = 'package:bbb/b.dart';

      var aUnlinked = path.join(tempDir, 'a.unlinked');
      var bUnlinked = path.join(tempDir, 'b.unlinked');
      var abLinked = path.join(tempDir, 'ab.linked');

      new File(aDart).writeAsStringSync('var a = 1;');
      new File(bDart).writeAsStringSync('''
import 'package:aaa/a.dart';
var b = a;
''');

      Future<Null> buildUnlinked(String uri, String path, String output) async {
        await _doDrive(path, uri: uri, additionalArgs: [
          '--build-summary-only',
          '--build-summary-only-unlinked',
          '--build-summary-output=$output'
        ]);
        expect(exitCode, 0);
        expect(new File(output).existsSync(), isTrue);
      }

      await buildUnlinked(aUri, aDart, aUnlinked);
      await buildUnlinked(bUri, bDart, bUnlinked);

      await new Driver(isTesting: true).start([
        '--dart-sdk',
        _findSdkDirForSummaries(),
        '--strong',
        '--build-mode',
        '--build-summary-unlinked-input=$aUnlinked,$bUnlinked',
        '--build-summary-output=$abLinked'
      ]);
      expect(exitCode, 0);
      var bytes = new File(abLinked).readAsBytesSync();
      var bundle = new PackageBundle.fromBuffer(bytes);

      // Only linked information.
      expect(bundle.unlinkedUnitUris, isEmpty);
      expect(bundle.linkedLibraryUris, unorderedEquals([aUri, bUri]));

      // Strong mode type inference was performed.
      expect(bundle.linkedLibraries[0].units[0].types, isNotEmpty);
      expect(bundle.linkedLibraries[1].units[0].types, isNotEmpty);
    });
  }

  test_buildSuppressExitCode_fail_whenFileNotFound() async {
    await _doDrive(path.join('data', 'non_existent_file.dart'),
        additionalArgs: ['--build-suppress-exit-code']);
    expect(exitCode, isNot(0));
  }

  test_buildSuppressExitCode_success_evenIfHasError() async {
    await _doDrive(path.join('data', 'file_with_error.dart'),
        additionalArgs: ['--build-suppress-exit-code']);
    expect(exitCode, 0);
  }

  test_buildUnlinked() async {
    await withTempDirAsync((tempDir) async {
      var outputPath = path.join(tempDir, 'test_file.dart.sum');
      await _doDrive(path.join('data', 'test_file.dart'), additionalArgs: [
        '--build-summary-only',
        '--build-summary-only-unlinked',
        '--build-summary-output=$outputPath'
      ]);
      var output = new File(outputPath);
      expect(output.existsSync(), isTrue);
      PackageBundle bundle =
          new PackageBundle.fromBuffer(await output.readAsBytes());
      var testFileUri = 'file:///test_file.dart';
      expect(bundle.unlinkedUnits.length, 1);
      expect(bundle.unlinkedUnitUris, equals([testFileUri]));
      expect(bundle.linkedLibraryUris, isEmpty);
      expect(exitCode, 0);
    });
  }

  test_consumeLinked() async {
    await withTempDirAsync((tempDir) async {
      var aDart = path.join(tempDir, 'a.dart');
      var bDart = path.join(tempDir, 'b.dart');
      var cDart = path.join(tempDir, 'c.dart');

      var aUri = 'package:aaa/a.dart';
      var bUri = 'package:bbb/b.dart';
      var cUri = 'package:ccc/c.dart';

      var aSum = path.join(tempDir, 'a.sum');
      var bSum = path.join(tempDir, 'b.sum');
      var cSum = path.join(tempDir, 'c.sum');

      new File(aDart).writeAsStringSync('class A {}');
      new File(bDart).writeAsStringSync('''
export 'package:aaa/a.dart';
class B {}
''');
      new File(cDart).writeAsStringSync('''
import 'package:bbb/b.dart';
var a = new A();
var b = new B();
''');

      // Analyze package:aaa/a.dart and compute summary.
      {
        await _doDrive(aDart,
            uri: aUri, additionalArgs: ['--build-summary-output=$aSum']);
        expect(exitCode, 0);
        var bytes = new File(aSum).readAsBytesSync();
        var bundle = new PackageBundle.fromBuffer(bytes);
        expect(bundle.unlinkedUnitUris, equals([aUri]));
        expect(bundle.linkedLibraryUris, equals([aUri]));
      }

      // Analyze package:bbb/b.dart and compute summary.
      {
        await _doDrive(bDart, uri: bUri, additionalArgs: [
          '--build-summary-input=$aSum',
          '--build-summary-output=$bSum'
        ]);
        expect(exitCode, 0);
        var bytes = new File(bSum).readAsBytesSync();
        var bundle = new PackageBundle.fromBuffer(bytes);
        expect(bundle.unlinkedUnitUris, equals([bUri]));
        expect(bundle.linkedLibraryUris, equals([bUri]));
      }

      // Analyze package:ccc/c.dart and compute summary.
      {
        await _doDrive(cDart, uri: cUri, additionalArgs: [
          '--build-summary-input=$aSum,$bSum',
          '--build-summary-output=$cSum'
        ]);
        expect(exitCode, 0);
        var bytes = new File(cSum).readAsBytesSync();
        var bundle = new PackageBundle.fromBuffer(bytes);
        expect(bundle.unlinkedUnitUris, equals([cUri]));
        expect(bundle.linkedLibraryUris, equals([cUri]));
      }
    });
  }

  test_dartSdkSummaryPath_strong() async {
    await withTempDirAsync((tempDir) async {
      String sdkPath = _findSdkDirForSummaries();
      String strongSummaryPath =
          path.join(sdkPath, 'lib', '_internal', 'strong.sum');

      var testDart = path.join(tempDir, 'test.dart');
      var testSum = path.join(tempDir, 'test.sum');
      new File(testDart).writeAsStringSync('var v = 42;');

      await _doDrive(testDart,
          additionalArgs: [
            '--strong',
            '--build-summary-only',
            '--build-summary-output=$testSum'
          ],
          dartSdkSummaryPath: strongSummaryPath);
      var output = new File(testSum);
      expect(output.existsSync(), isTrue);
      expect(exitCode, 0);
    });
  }

  test_error_linkedAsUnlinked() async {
    await withTempDirAsync((tempDir) async {
      var aDart = path.join(tempDir, 'a.dart');
      var bDart = path.join(tempDir, 'b.dart');

      var aUri = 'package:aaa/a.dart';
      var bUri = 'package:bbb/b.dart';

      var aSum = path.join(tempDir, 'a.sum');
      var bSum = path.join(tempDir, 'b.sum');

      new File(aDart).writeAsStringSync('class A {}');

      // Build linked a.sum
      await _doDrive(aDart, uri: aUri, additionalArgs: [
        '--build-summary-only',
        '--build-summary-output=$aSum'
      ]);
      expect(new File(aSum).existsSync(), isTrue);

      // Try to consume linked a.sum as unlinked.
      try {
        await _doDrive(bDart, uri: bUri, additionalArgs: [
          '--build-summary-unlinked-input=$aSum',
          '--build-summary-output=$bSum'
        ]);
        fail('ArgumentError expected.');
      } on ArgumentError catch (e) {
        expect(
            e.message,
            contains(
                'Got a linked summary for --build-summary-input-unlinked'));
      }
    });
  }

  test_error_notUriPipePath() async {
    await withTempDirAsync((tempDir) async {
      var testDart = path.join(tempDir, 'test.dart');
      new File(testDart).writeAsStringSync('var v = 42;');

      // We pass just path, not "uri|path", this is a fatal error.
      await drive(testDart, args: ['--build-mode', '--format=machine']);
      expect(exitCode, ErrorSeverity.ERROR.ordinal);
    });
  }

  test_error_unlinkedAsLinked() async {
    await withTempDirAsync((tempDir) async {
      var aDart = path.join(tempDir, 'a.dart');
      var bDart = path.join(tempDir, 'b.dart');

      var aUri = 'package:aaa/a.dart';
      var bUri = 'package:bbb/b.dart';

      var aSum = path.join(tempDir, 'a.sum');
      var bSum = path.join(tempDir, 'b.sum');

      new File(aDart).writeAsStringSync('class A {}');

      // Build unlinked a.sum
      await _doDrive(aDart, uri: aUri, additionalArgs: [
        '--build-summary-only',
        '--build-summary-only-unlinked',
        '--build-summary-output=$aSum'
      ]);
      expect(new File(aSum).existsSync(), isTrue);

      // Try to consume unlinked a.sum as linked.
      try {
        await _doDrive(bDart, uri: bUri, additionalArgs: [
          '--build-summary-input=$aSum',
          '--build-summary-output=$bSum'
        ]);
        fail('ArgumentError expected.');
      } on ArgumentError catch (e) {
        expect(e.message,
            contains('Got an unlinked summary for --build-summary-input'));
      }
    });
  }

  test_fail_whenHasError() async {
    await _doDrive(path.join('data', 'file_with_error.dart'));
    expect(exitCode, isNot(0));
  }

  test_noStatistics() async {
    await _doDrive(path.join('data', 'test_file.dart'));
    // Should not print statistics summary.
    expect(outSink.toString(), isEmpty);
    expect(errorSink.toString(), isEmpty);
    expect(exitCode, 0);
  }

  test_onlyErrors_partFirst() async {
    await withTempDirAsync((tempDir) async {
      var aDart = path.join(tempDir, 'a.dart');
      var bDart = path.join(tempDir, 'b.dart');

      var aUri = 'package:aaa/a.dart';
      var bUri = 'package:aaa/b.dart';

      new File(aDart).writeAsStringSync(r'''
library lib;
part 'b.dart';
class A {}
''');
      new File(bDart).writeAsStringSync('''
part of lib;
class B {}
var a = new A();
var b = new B();
''');

      // Analyze b.dart (part) and then a.dart (its library).
      // No errors should be reported - the part should know its library.
      await _doDrive(bDart, uri: bUri, additionalArgs: ['$aUri|$aDart']);
      expect(errorSink, isEmpty);
    });
  }

  Future<Null> _doDrive(String path,
      {String uri,
      List<String> additionalArgs: const [],
      String dartSdkSummaryPath}) async {
    var optionsFileName = AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE;

    List<String> args = <String>[];
    if (dartSdkSummaryPath != null) {
      args.add('--dart-sdk-summary');
      args.add(dartSdkSummaryPath);
    } else {
      String sdkPath = _findSdkDirForSummaries();
      args.add('--dart-sdk');
      args.add(sdkPath);
    }
    args.add('--build-mode');
    args.add('--format=machine');
    args.addAll(additionalArgs);

    uri ??= 'file:///test_file.dart';
    String source = '$uri|$path';

    await drive(source,
        args: args, options: 'data/options_tests_project/$optionsFileName');
  }

  /// Try to find a appropriate directory to pass to "--dart-sdk" that will
  /// allow summaries to be found.
  String _findSdkDirForSummaries() {
    Set<String> triedDirectories = new Set<String>();
    bool isSuitable(String sdkDir) {
      triedDirectories.add(sdkDir);
      return new File(path.join(sdkDir, 'lib', '_internal', 'spec.sum'))
          .existsSync();
    }

    // Usually the sdk directory is the parent of the parent of the "dart"
    // executable.
    Directory executableParent = new File(Platform.executable).parent;
    Directory executableGrandparent = executableParent.parent;
    if (isSuitable(executableGrandparent.path)) {
      return executableGrandparent.path;
    }
    // During build bot execution, the sdk directory is simply the parent of the
    // "dart" executable.
    if (isSuitable(executableParent.path)) {
      return executableParent.path;
    }
    // If neither of those are suitable, assume we are running locally within the
    // SDK project (e.g. within an IDE).  Find the build output directory and
    // search all built configurations.
    Directory sdkRootDir =
        new File(Platform.script.toFilePath()).parent.parent.parent.parent;
    for (String outDirName in ['out', 'xcodebuild']) {
      Directory outDir = new Directory(path.join(sdkRootDir.path, outDirName));
      if (outDir.existsSync()) {
        for (FileSystemEntity subdir in outDir.listSync()) {
          if (subdir is Directory) {
            String candidateSdkDir = path.join(subdir.path, 'dart-sdk');
            if (isSuitable(candidateSdkDir)) {
              return candidateSdkDir;
            }
          }
        }
      }
    }
    throw new Exception('Could not find an SDK directory containing summaries.'
        '  Tried: ${triedDirectories.toList()}');
  }
}

@reflectiveTest
class ExitCodesTest extends BaseTest {
  test_bazelWorkspace_relativePath() async {
    // Copy to temp dir so that existing analysis options
    // in the test directory hierarchy do not interfere
    await withTempDirAsync((String tempDirPath) async {
      String dartSdkPath = path.absolute(getSdkPath());
      await recursiveCopy(
          new Directory(path.join(testDirectory, 'data', 'bazel')),
          tempDirPath);
      Directory origWorkingDir = Directory.current;
      try {
        Directory.current = path.join(tempDirPath, 'proj');
        Driver driver = new Driver(isTesting: true);
        try {
          await driver.start([
            path.join('lib', 'file.dart'),
            '--dart-sdk',
            dartSdkPath,
          ]);
        } catch (e) {
          print('=== debug info ===');
          print('dartSdkPath: $dartSdkPath');
          print('stderr:\n${errorSink.toString()}');
          rethrow;
        }
        expect(errorSink.toString(), isEmpty);
        expect(outSink.toString(), contains('No issues found'));
        expect(exitCode, 0);
      } finally {
        Directory.current = origWorkingDir;
      }
    });
  }

  test_enableAssertInitializer() async {
    await drive('data/file_with_assert_initializers.dart',
        args: ['--enable-assert-initializers']);
    expect(exitCode, 0);
  }

  test_fatalErrors() async {
    await drive('data/file_with_error.dart');
    expect(exitCode, 3);
  }

  test_fatalHints() async {
    await drive('data/file_with_hint.dart', args: ['--fatal-hints']);
    expect(exitCode, 1);
  }

  test_fatalWarnings() async {
    await drive('data/file_with_warning.dart', args: ['--fatal-warnings']);
    expect(exitCode, 2);
  }

  test_missingDartFile() async {
    await drive('data/NO_DART_FILE_HERE.dart');
    expect(exitCode, 3);
  }

  test_missingOptionsFile() async {
    await drive('data/test_file.dart', options: 'data/NO_OPTIONS_HERE');
    expect(exitCode, 3);
  }

  test_notFatalHints() async {
    await drive('data/file_with_hint.dart');
    expect(exitCode, 0);
  }

  test_notFatalWarnings() async {
    await drive('data/file_with_warning.dart');
    expect(exitCode, 0);
  }

  test_partFile() async {
    Driver driver = new Driver(isTesting: true);
    await driver.start([
      path.join(testDirectory, 'data/library_and_parts/lib.dart'),
      path.join(testDirectory, 'data/library_and_parts/part1.dart')
    ]);
    expect(exitCode, 0);
  }

  test_partFile_dangling() async {
    await drive('data/library_and_parts/part2.dart');
    expect(exitCode, 3);
  }

  test_partFile_extra() async {
    Driver driver = new Driver(isTesting: true);
    await driver.start([
      path.join(testDirectory, 'data/library_and_parts/lib.dart'),
      path.join(testDirectory, 'data/library_and_parts/part1.dart'),
      path.join(testDirectory, 'data/library_and_parts/part2.dart')
    ]);
    expect(exitCode, 3);
  }
}

@reflectiveTest
class ExitCodesTest_PreviewDart2 extends ExitCodesTest {
  @override
  bool get usePreviewDart2 => true;

  @override
  @failingTest
  test_fatalErrors() {
    // TODO(devoncarew): This test times out when used with @failingTest.
    return new Future.error('failing test');
  }
}

@reflectiveTest
class ExitCodesTest_UseCFE extends ExitCodesTest {
  @override
  bool get useCFE => true;

  @override
  @failingTest
  test_fatalErrors() {
    // TODO(devoncarew): This test times out when used with @failingTest.
    return new Future.error('failing test');
  }

  @override
  @failingTest
  test_fatalWarnings() => super.test_fatalWarnings();

  @override
  @failingTest
  test_notFatalWarnings() => super.test_notFatalWarnings();
}

@reflectiveTest
class LinterTest extends BaseTest {
  String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE;

  test_containsLintRuleEntry() async {
    Map<String, YamlNode> options;
    options = _parseOptions('''
linter:
  rules:
    - foo
        ''');
    expect(containsLintRuleEntry(options), true);
    options = _parseOptions('''
        ''');
    expect(containsLintRuleEntry(options), false);
    options = _parseOptions('''
linter:
  rules:
    # - foo
        ''');
    expect(containsLintRuleEntry(options), true);
    options = _parseOptions('''
linter:
 # rules:
    # - foo
        ''');
    expect(containsLintRuleEntry(options), false);
  }

  test_defaultLints_generatedLints() async {
    await _runLinter_defaultLints();
    expect(bulletToDash(outSink),
        contains('lint - Name types using UpperCamelCase'));
  }

  test_defaultLints_getsDefaultLints() async {
    await _runLinter_defaultLints();

    /// Lints should be enabled.
    expect(driver.context.analysisOptions.lint, isTrue);

    /// Default list should include camel_case_types.
    var lintNames = getLints(driver.context).map((r) => r.name);
    expect(lintNames, contains('camel_case_types'));
  }

  test_lintsInOptions_generatedLints() async {
    await _runLinter_lintsInOptions();
    expect(bulletToDash(outSink),
        contains('lint - Name types using UpperCamelCase'));
  }

  test_lintsInOptions_getAnalysisOptions() async {
    await _runLinter_lintsInOptions();

    /// Lints should be enabled.
    expect(driver.context.analysisOptions.lint, isTrue);

    /// The analysis options file only specifies 'camel_case_types'.
    var lintNames = getLints(driver.context).map((r) => r.name);
    expect(lintNames, orderedEquals(['camel_case_types']));
  }

  test_noLints_lintsDisabled() async {
    await _runLinter_noLintsFlag();
    expect(driver.context.analysisOptions.lint, isFalse);
  }

  test_noLints_noGeneratedWarnings() async {
    await _runLinter_noLintsFlag();
    expect(outSink.toString(), contains('No issues found'));
  }

  test_noLints_noRegisteredLints() async {
    await _runLinter_noLintsFlag();
    expect(getLints(driver.context), isEmpty);
  }

  Map<String, YamlNode> _parseOptions(String src) =>
      new AnalysisOptionsProvider().getOptionsFromString(src);

  Future<Null> _runLinter_defaultLints() async {
    await drive('data/linter_project/test_file.dart',
        options: 'data/linter_project/$optionsFileName', args: ['--lints']);
  }

  Future<Null> _runLinter_lintsInOptions() async {
    await drive('data/linter_project/test_file.dart',
        options: 'data/linter_project/$optionsFileName', args: ['--lints']);
  }

  Future<Null> _runLinter_noLintsFlag() async {
    await drive('data/no_lints_project/test_file.dart',
        options: 'data/no_lints_project/$optionsFileName');
  }
}

@reflectiveTest
class LinterTest_PreviewDart2 extends LinterTest {
  @override
  bool get usePreviewDart2 => true;
}

@reflectiveTest
class LinterTest_UseCFE extends LinterTest {
  @override
  bool get useCFE => true;
}

@reflectiveTest
class NonDartFilesTest extends BaseTest {
  test_analysisOptionsYaml() async {
    await withTempDirAsync((tempDir) async {
      String filePath =
          path.join(tempDir, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE);
      new File(filePath).writeAsStringSync('''
analyzer:
  string-mode: true
''');
      await drive(filePath);
      expect(
          bulletToDash(outSink),
          contains(
              "warning - The option 'string-mode' isn't supported by 'analyzer'"));
      expect(exitCode, 0);
    });
  }

  test_pubspecYaml() async {
    await withTempDirAsync((tempDir) async {
      String filePath = path.join(tempDir, AnalysisEngine.PUBSPEC_YAML_FILE);
      new File(filePath).writeAsStringSync('''
name: foo
flutter:
  assets:
    doesNotExist.gif
''');
      await drive(filePath);
      expect(
          bulletToDash(outSink),
          contains(
              "warning - The value of the 'asset' field is expected to be a list of relative file paths"));
      expect(exitCode, 0);
    });
  }
}

@reflectiveTest
class OptionsTest extends BaseTest {
  String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE;

  List<ErrorProcessor> get processors =>
      driver.context.analysisOptions.errorProcessors;

  ErrorProcessor processorFor(AnalysisError error) =>
      processors.firstWhere((p) => p.appliesTo(error));

  test_basic_filters() async {
    await _driveBasic();
    expect(processors, hasLength(3));

    // unused_local_variable: ignore
    var unused_local_variable = new AnalysisError(
        new TestSource(), 0, 1, HintCode.UNUSED_LOCAL_VARIABLE, [
      ['x']
    ]);
    expect(processorFor(unused_local_variable).severity, isNull);

    // missing_return: error
    var missing_return =
        new AnalysisError(new TestSource(), 0, 1, HintCode.MISSING_RETURN, [
      ['x']
    ]);
    expect(processorFor(missing_return).severity, ErrorSeverity.ERROR);
    expect(bulletToDash(outSink),
        contains("error - This function declares a return type of 'int'"));
    expect(outSink.toString(), contains("1 error and 1 warning found."));
  }

  test_basic_language() async {
    await _driveBasic();
    expect(driver.context.analysisOptions.enableSuperMixins, isTrue);
  }

  test_basic_strongMode() async {
    await _driveBasic();
    expect(driver.context.analysisOptions.strongMode, isTrue);
    // https://github.com/dart-lang/sdk/issues/26129
    AnalysisContext sdkContext = driver.context.sourceFactory.dartSdk.context;
    expect(sdkContext.analysisOptions.strongMode, isTrue);
  }

  test_includeDirective() async {
    String testDir = path.join(
        testDirectory, 'data', 'options_include_directive_tests_project');
    await drive(
      path.join(testDir, 'lib', 'test_file.dart'),
      args: [
        '--fatal-warnings',
        '--packages',
        path.join(testDir, '_packages'),
      ],
      options: path.join(testDir, 'analysis_options.yaml'),
    );
    expect(exitCode, 3);
    expect(outSink.toString(),
        contains('but doesn\'t end with a return statement'));
    expect(outSink.toString(), contains('isn\'t defined'));
    expect(outSink.toString(), contains('Avoid empty else statements'));
  }

  test_previewDart2() async {
    await drive('data/options_tests_project/test_file.dart',
        args: ['--preview-dart-2']);
    expect(driver.context.analysisOptions.useFastaParser, isFalse);
  }

  test_strongSdk() async {
    String testDir = path.join(testDirectory, 'data', 'strong_sdk');
    await drive(path.join(testDir, 'main.dart'), args: ['--strong']);
    expect(driver.context.analysisOptions.strongMode, isTrue);
    expect(outSink.toString(), contains('No issues found'));
    expect(exitCode, 0);
  }

  test_todo() async {
    await drive('data/file_with_todo.dart');
    expect(outSink.toString().contains('[info]'), isFalse);
  }

  @failingTest
  test_useCFE() async {
    await drive('data/options_tests_project/test_file.dart',
        args: ['--use-cfe']);
    expect(driver.context.analysisOptions.useFastaParser, isTrue);
  }

  test_withFlags_overrideFatalWarning() async {
    await drive('data/options_tests_project/test_file.dart',
        args: ['--fatal-warnings'],
        options: 'data/options_tests_project/$optionsFileName');

    // missing_return: error
    var undefined_function = new AnalysisError(
        new TestSource(), 0, 1, StaticTypeWarningCode.UNDEFINED_FUNCTION, [
      ['x']
    ]);
    expect(processorFor(undefined_function).severity, ErrorSeverity.WARNING);
    // Should not be made fatal by `--fatal-warnings`.
    expect(bulletToDash(outSink),
        contains("warning - The function 'baz' isn't defined"));
    expect(outSink.toString(), contains("1 error and 1 warning found."));
  }

  Future<Null> _driveBasic() async {
    await drive('data/options_tests_project/test_file.dart',
        options: 'data/options_tests_project/$optionsFileName');
  }
}

@reflectiveTest
class OptionsTest_PreviewDart2 extends OptionsTest {
  @override
  bool get usePreviewDart2 => true;
}

@reflectiveTest
class OptionsTest_UseCFE extends OptionsTest {
  @override
  bool get useCFE => true;

  @override
  @failingTest
  test_basic_filters() => super.test_basic_filters();

  @override
  @failingTest
  test_basic_language() => super.test_basic_language();

  @override
  @failingTest
  test_basic_strongMode() => super.test_basic_strongMode();

  @override
  @failingTest
  test_includeDirective() => super.test_includeDirective();

  @override
  @failingTest
  test_previewDart2() => super.test_previewDart2();

  @override
  @failingTest
  test_withFlags_overrideFatalWarning() =>
      super.test_withFlags_overrideFatalWarning();
}

class TestSource implements Source {
  TestSource();

  @override
  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
