<commit_before>// 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:yaml/src/yaml_node.dart';

import 'utils.dart';

main() {
  StringSink savedOutSink, savedErrorSink;
  int savedExitCode;
  ExitHandler savedExitHandler;

  /// Base setup.
  _setUp() {
    ansi.runningTests = true;
    savedOutSink = outSink;
    savedErrorSink = errorSink;
    savedExitHandler = exitHandler;
    savedExitCode = exitCode;
    exitHandler = (code) => exitCode = code;
    outSink = new StringBuffer();
    errorSink = new StringBuffer();
  }

  /// Base teardown.
  _tearDown() {
    outSink = savedOutSink;
    errorSink = savedErrorSink;
    exitCode = savedExitCode;
    exitHandler = savedExitHandler;
    ansi.runningTests = false;
  }

  setUp(() => _setUp());

  tearDown(() => _tearDown());

  group('Driver', () {
    group('options', () {
      test('todos', () async {
        await drive('data/file_with_todo.dart');
        expect(outSink.toString().contains('[info]'), isFalse);
      });
    });

    group('exit codes', () {
      test('fatal hints', () async {
        await drive('data/file_with_hint.dart', args: ['--fatal-hints']);
        expect(exitCode, 3);
      });

      test('not fatal hints', () async {
        await drive('data/file_with_hint.dart');
        expect(exitCode, 0);
      });

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

      test('not fatal warnings', () async {
        await drive('data/file_with_warning.dart');
        expect(exitCode, 0);
      });

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

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

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

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

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

      test('non-dangling part file', () async {
        Driver driver = new Driver();
        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('extra part file', () async {
        Driver driver = new Driver();
        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);
      });

      test('bazel workspace relative path', () 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();
            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;
          }
        });
      });
    });

    group('linter', () {
      void createTests(String designator, String optionsFileName) {
        group('lints in options - $designator', () {
          // Shared lint command.
          Future<Null> runLinter() async {
            return await drive('data/linter_project/test_file.dart',
                options: 'data/linter_project/$optionsFileName',
                args: ['--lints']);
          }

          test('gets analysis options', () async {
            await runLinter();

            /// 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('generates lints', () async {
            await runLinter();
            expect(_bulletToDash(outSink),
                contains('lint - Name types using UpperCamelCase'));
          });
        });

        group('default lints - $designator', () {
          // Shared lint command.
          Future<Null> runLinter() async {
            return await drive('data/linter_project/test_file.dart',
                options: 'data/linter_project/$optionsFileName',
                args: ['--lints']);
          }

          test('gets default lints', () async {
            await runLinter();

            /// 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('generates lints', () async {
            await runLinter();
            expect(_bulletToDash(outSink),
                contains('lint - Name types using UpperCamelCase'));
          });
        });

        group('no `--lints` flag (none in options) - $designator', () {
          // Shared lint command.
          Future<Null> runLinter() async {
            return await drive('data/no_lints_project/test_file.dart',
                options: 'data/no_lints_project/$optionsFileName');
          }

          test('lints disabled', () async {
            await runLinter();
            expect(driver.context.analysisOptions.lint, isFalse);
          });

          test('no registered lints', () async {
            await runLinter();
            expect(getLints(driver.context), isEmpty);
          });

          test('no generated warnings', () async {
            await runLinter();
            expect(outSink.toString(), contains('No issues found'));
          });
        });
      }

      createTests('old', AnalysisEngine.ANALYSIS_OPTIONS_FILE);
      createTests('new', AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE);
    });

    test('containsLintRuleEntry', () {
      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);
    });

    group('options processing', () {
      void createTests(String designator, String optionsFileName) {
        group('basic config - $designator', () {
          // Shared driver command.
          Future<Null> doDrive() async {
            await drive('data/options_tests_project/test_file.dart',
                options: 'data/options_tests_project/$optionsFileName');
          }

          test('filters', () async {
            await doDrive();
            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('language', () async {
            await doDrive();
            expect(driver.context.analysisOptions.enableSuperMixins, isTrue);
          });

          test('strongMode', () async {
            await doDrive();
            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);
          });
        });

        group('with flags - $designator', () {
          // Shared driver command.
          Future<Null> doDrive() async {
            await drive('data/options_tests_project/test_file.dart',
                args: ['--fatal-warnings'],
                options: 'data/options_tests_project/$optionsFileName');
          }

          test('override fatal warning', () async {
            await doDrive();
            // 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."));
          });
        });
      }

      createTests('old', AnalysisEngine.ANALYSIS_OPTIONS_FILE);
      createTests('new', AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE);

      test('include directive', () 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'),
        );
        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('test strong SDK', () 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);
      });
    });

    void createTests(String designator, String optionsFileName) {
      group('build-mode - $designator', () {<commit_msg>fix driver test<commit_after>// 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:yaml/src/yaml_node.dart';

import 'utils.dart';

main() {
  StringSink savedOutSink, savedErrorSink;
  int savedExitCode;
  ExitHandler savedExitHandler;

  /// Base setup.
  _setUp() {
    ansi.runningTests = true;
    savedOutSink = outSink;
    savedErrorSink = errorSink;
    savedExitHandler = exitHandler;
    savedExitCode = exitCode;
    exitHandler = (code) => exitCode = code;
    outSink = new StringBuffer();
    errorSink = new StringBuffer();
  }

  /// Base teardown.
  _tearDown() {
    outSink = savedOutSink;
    errorSink = savedErrorSink;
    exitCode = savedExitCode;
    exitHandler = savedExitHandler;
    ansi.runningTests = false;
  }

  setUp(() => _setUp());

  tearDown(() => _tearDown());

  group('Driver', () {
    group('options', () {
      test('todos', () async {
        await drive('data/file_with_todo.dart');
        expect(outSink.toString().contains('[info]'), isFalse);
      });
    });

    group('exit codes', () {
      test('fatal hints', () async {
        await drive('data/file_with_hint.dart', args: ['--fatal-hints']);
        expect(exitCode, 3);
      });

      test('not fatal hints', () async {
        await drive('data/file_with_hint.dart');
        expect(exitCode, 0);
      });

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

      test('not fatal warnings', () async {
        await drive('data/file_with_warning.dart');
        expect(exitCode, 0);
      });

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

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

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

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

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

      test('non-dangling part file', () async {
        Driver driver = new Driver();
        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('extra part file', () async {
        Driver driver = new Driver();
        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);
      });

      test('bazel workspace relative path', () 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();
            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;
          }
        });
      });
    });

    group('linter', () {
      void createTests(String designator, String optionsFileName) {
        group('lints in options - $designator', () {
          // Shared lint command.
          Future<Null> runLinter() async {
            return await drive('data/linter_project/test_file.dart',
                options: 'data/linter_project/$optionsFileName',
                args: ['--lints']);
          }

          test('gets analysis options', () async {
            await runLinter();

            /// 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('generates lints', () async {
            await runLinter();
            expect(_bulletToDash(outSink),
                contains('lint - Name types using UpperCamelCase'));
          });
        });

        group('default lints - $designator', () {
          // Shared lint command.
          Future<Null> runLinter() async {
            return await drive('data/linter_project/test_file.dart',
                options: 'data/linter_project/$optionsFileName',
                args: ['--lints']);
          }

          test('gets default lints', () async {
            await runLinter();

            /// 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('generates lints', () async {
            await runLinter();
            expect(_bulletToDash(outSink),
                contains('lint - Name types using UpperCamelCase'));
          });
        });

        group('no `--lints` flag (none in options) - $designator', () {
          // Shared lint command.
          Future<Null> runLinter() async {
            return await drive('data/no_lints_project/test_file.dart',
                options: 'data/no_lints_project/$optionsFileName');
          }

          test('lints disabled', () async {
            await runLinter();
            expect(driver.context.analysisOptions.lint, isFalse);
          });

          test('no registered lints', () async {
            await runLinter();
            expect(getLints(driver.context), isEmpty);
          });

          test('no generated warnings', () async {
            await runLinter();
            expect(outSink.toString(), contains('No issues found'));
          });
        });
      }

      createTests('old', AnalysisEngine.ANALYSIS_OPTIONS_FILE);
      createTests('new', AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE);
    });

    test('containsLintRuleEntry', () {
      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);
    });

    group('options processing', () {
      void createTests(String designator, String optionsFileName) {
        group('basic config - $designator', () {
          // Shared driver command.
          Future<Null> doDrive() async {
            await drive('data/options_tests_project/test_file.dart',
                options: 'data/options_tests_project/$optionsFileName');
          }

          test('filters', () async {
            await doDrive();
            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('language', () async {
            await doDrive();
            expect(driver.context.analysisOptions.enableSuperMixins, isTrue);
          });

          test('strongMode', () async {
            await doDrive();
            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);
          });
        });

        group('with flags - $designator', () {
          // Shared driver command.
          Future<Null> doDrive() async {
            await drive('data/options_tests_project/test_file.dart',
                args: ['--fatal-warnings'],
                options: 'data/options_tests_project/$optionsFileName');
          }

          test('override fatal warning', () async {
            await doDrive();
            // 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."));
          });
        });
      }

      createTests('old', AnalysisEngine.ANALYSIS_OPTIONS_FILE);
      createTests('new', AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE);

      test('include directive', () 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('test strong SDK', () 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);
      });
    });

    void createTests(String designator, String optionsFileName) {
      group('build-mode - $designator', () {
{'fraction_non_alphanumeric': 0.13356901321856748, 'fraction_numerical': 0.0029203811865969875, 'mean_word_length': 2.1656732757572073, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 25, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '352588', 'n_tokens_mistral': 7379, 'n_tokens_neox': 7172, 'n_words': 1456}