mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
dabdade731
Change-Id: I2a386c1f9412ebcfaeb509715da616ff078591fd Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/206673 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
574 lines
17 KiB
Dart
574 lines
17 KiB
Dart
// 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.
|
|
|
|
import 'dart:io';
|
|
|
|
import 'package:analyzer/dart/analysis/features.dart';
|
|
import 'package:analyzer/file_system/physical_file_system.dart';
|
|
import 'package:analyzer/src/dart/analysis/experiments.dart';
|
|
import 'package:analyzer/src/dart/analysis/experiments_impl.dart'
|
|
show overrideKnownFeatures;
|
|
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
|
|
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
|
|
import 'package:analyzer_cli/src/driver.dart';
|
|
import 'package:analyzer_cli/src/options.dart';
|
|
import 'package:args/args.dart';
|
|
import 'package:pub_semver/pub_semver.dart';
|
|
import 'package:test/test.dart';
|
|
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
|
|
|
void main() {
|
|
group('CommandLineOptions', () {
|
|
group('parse', () {
|
|
var outStringBuffer = StringBuffer();
|
|
var errorStringBuffer = StringBuffer();
|
|
|
|
StringSink savedOutSink, savedErrorSink;
|
|
int savedExitCode;
|
|
ExitHandler savedExitHandler;
|
|
|
|
CommandLineOptions parse(List<String> args,
|
|
{void Function(String msg) printAndFail = printAndFail}) {
|
|
var resourceProvider = PhysicalResourceProvider.INSTANCE;
|
|
return CommandLineOptions.parse(resourceProvider, args,
|
|
printAndFail: printAndFail);
|
|
}
|
|
|
|
setUp(() {
|
|
savedOutSink = outSink;
|
|
savedErrorSink = errorSink;
|
|
savedExitHandler = exitHandler;
|
|
savedExitCode = exitCode;
|
|
exitHandler = (int code) {};
|
|
outSink = outStringBuffer;
|
|
errorSink = errorStringBuffer;
|
|
});
|
|
|
|
tearDown(() {
|
|
outSink = savedOutSink;
|
|
errorSink = savedErrorSink;
|
|
exitCode = savedExitCode;
|
|
exitHandler = savedExitHandler;
|
|
});
|
|
|
|
test('defaults', () {
|
|
var options = parse(['--dart-sdk', '.', 'foo.dart']);
|
|
expect(options, isNotNull);
|
|
expect(options.dartSdkPath, isNotNull);
|
|
expect(options.disableCacheFlushing, isFalse);
|
|
expect(options.disableHints, isFalse);
|
|
expect(options.enabledExperiments, isEmpty);
|
|
expect(options.lints, isNull);
|
|
expect(options.displayVersion, isFalse);
|
|
expect(options.infosAreFatal, isFalse);
|
|
expect(options.ignoreUnrecognizedFlags, isFalse);
|
|
expect(options.implicitCasts, isNull);
|
|
expect(options.log, isFalse);
|
|
expect(options.jsonFormat, isFalse);
|
|
expect(options.machineFormat, isFalse);
|
|
expect(options.noImplicitDynamic, isNull);
|
|
expect(options.batchMode, isFalse);
|
|
expect(options.showPackageWarnings, isFalse);
|
|
expect(options.showSdkWarnings, isFalse);
|
|
expect(options.sourceFiles, equals(['foo.dart']));
|
|
expect(options.warningsAreFatal, isFalse);
|
|
expect(options.lintsAreFatal, isFalse);
|
|
expect(options.trainSnapshot, isFalse);
|
|
});
|
|
|
|
test('batch', () {
|
|
var options = parse(['--dart-sdk', '.', '--batch']);
|
|
expect(options.batchMode, isTrue);
|
|
});
|
|
|
|
test('defined variables', () {
|
|
var options = parse(['--dart-sdk', '.', '-Dfoo=bar', 'foo.dart']);
|
|
expect(options.declaredVariables['foo'], equals('bar'));
|
|
expect(options.declaredVariables['bar'], isNull);
|
|
});
|
|
|
|
test('disable cache flushing', () {
|
|
var options =
|
|
parse(['--dart-sdk', '.', '--disable-cache-flushing', 'foo.dart']);
|
|
expect(options.disableCacheFlushing, isTrue);
|
|
});
|
|
|
|
group('enable experiment', () {
|
|
var knownFeatures = {
|
|
'a': ExperimentalFeature(
|
|
index: 0,
|
|
enableString: 'a',
|
|
isEnabledByDefault: false,
|
|
isExpired: false,
|
|
documentation: 'a',
|
|
experimentalReleaseVersion: null,
|
|
releaseVersion: null,
|
|
),
|
|
'b': ExperimentalFeature(
|
|
index: 1,
|
|
enableString: 'b',
|
|
isEnabledByDefault: false,
|
|
isExpired: false,
|
|
documentation: 'b',
|
|
experimentalReleaseVersion: null,
|
|
releaseVersion: null,
|
|
),
|
|
'c': ExperimentalFeature(
|
|
index: 2,
|
|
enableString: 'c',
|
|
isEnabledByDefault: false,
|
|
isExpired: false,
|
|
documentation: 'c',
|
|
experimentalReleaseVersion: null,
|
|
releaseVersion: null,
|
|
),
|
|
};
|
|
|
|
test('no values', () {
|
|
var options =
|
|
overrideKnownFeatures(knownFeatures, () => parse(['foo.dart']));
|
|
expect(options.enabledExperiments, isEmpty);
|
|
});
|
|
|
|
test('single value', () {
|
|
var options = overrideKnownFeatures(knownFeatures,
|
|
() => parse(['--enable-experiment', 'a', 'foo.dart']));
|
|
expect(options.enabledExperiments, ['a']);
|
|
});
|
|
|
|
group('multiple values', () {
|
|
test('single flag', () {
|
|
var options = overrideKnownFeatures(knownFeatures,
|
|
() => parse(['--enable-experiment', 'a,b', 'foo.dart']));
|
|
expect(options.enabledExperiments, ['a', 'b']);
|
|
});
|
|
|
|
test('mixed single and multiple flags', () {
|
|
var options = overrideKnownFeatures(
|
|
knownFeatures,
|
|
() => parse([
|
|
'--enable-experiment',
|
|
'a,b',
|
|
'--enable-experiment',
|
|
'c',
|
|
'foo.dart'
|
|
]));
|
|
expect(options.enabledExperiments, ['a', 'b', 'c']);
|
|
});
|
|
|
|
test('multiple flags', () {
|
|
var options = overrideKnownFeatures(
|
|
knownFeatures,
|
|
() => parse([
|
|
'--enable-experiment',
|
|
'a',
|
|
'--enable-experiment',
|
|
'b',
|
|
'foo.dart'
|
|
]));
|
|
expect(options.enabledExperiments, ['a', 'b']);
|
|
});
|
|
});
|
|
});
|
|
|
|
test('hintsAreFatal', () {
|
|
var options = parse(['--dart-sdk', '.', '--fatal-hints', 'foo.dart']);
|
|
expect(options.infosAreFatal, isTrue);
|
|
});
|
|
|
|
test('infosAreFatal', () {
|
|
var options = parse(['--dart-sdk', '.', '--fatal-infos', 'foo.dart']);
|
|
expect(options.infosAreFatal, isTrue);
|
|
});
|
|
|
|
test('log', () {
|
|
var options = parse(['--dart-sdk', '.', '--log', 'foo.dart']);
|
|
expect(options.log, isTrue);
|
|
});
|
|
|
|
group('format', () {
|
|
test('json', () {
|
|
var options = parse(['--dart-sdk', '.', '--format=json', 'foo.dart']);
|
|
expect(options.jsonFormat, isTrue);
|
|
expect(options.machineFormat, isFalse);
|
|
});
|
|
|
|
test('machine', () {
|
|
var options =
|
|
parse(['--dart-sdk', '.', '--format=machine', 'foo.dart']);
|
|
expect(options.jsonFormat, isFalse);
|
|
expect(options.machineFormat, isTrue);
|
|
});
|
|
});
|
|
|
|
test('no-hints', () {
|
|
var options = parse(['--dart-sdk', '.', '--no-hints', 'foo.dart']);
|
|
expect(options.disableHints, isTrue);
|
|
});
|
|
|
|
test('options', () {
|
|
var options =
|
|
parse(['--dart-sdk', '.', '--options', 'options.yaml', 'foo.dart']);
|
|
expect(options.defaultAnalysisOptionsPath, endsWith('options.yaml'));
|
|
});
|
|
|
|
test('lints', () {
|
|
var options = parse(['--dart-sdk', '.', '--lints', 'foo.dart']);
|
|
expect(options.lints, isTrue);
|
|
});
|
|
|
|
test('package warnings', () {
|
|
var options =
|
|
parse(['--dart-sdk', '.', '--package-warnings', 'foo.dart']);
|
|
expect(options.showPackageWarnings, isTrue);
|
|
});
|
|
|
|
test('sdk warnings', () {
|
|
var options = parse(['--dart-sdk', '.', '--sdk-warnings', 'foo.dart']);
|
|
expect(options.showSdkWarnings, isTrue);
|
|
});
|
|
|
|
test('sourceFiles', () {
|
|
var options = parse(
|
|
['--dart-sdk', '.', '--log', 'foo.dart', 'foo2.dart', 'foo3.dart']);
|
|
expect(options.sourceFiles,
|
|
equals(['foo.dart', 'foo2.dart', 'foo3.dart']));
|
|
});
|
|
|
|
test('warningsAreFatal', () {
|
|
var options =
|
|
parse(['--dart-sdk', '.', '--fatal-warnings', 'foo.dart']);
|
|
expect(options.warningsAreFatal, isTrue);
|
|
});
|
|
|
|
test('ignore unrecognized flags', () {
|
|
var options = parse([
|
|
'--ignore-unrecognized-flags',
|
|
'--bar',
|
|
'--baz',
|
|
'--dart-sdk',
|
|
'.',
|
|
'foo.dart'
|
|
]);
|
|
expect(options, isNotNull);
|
|
expect(options.sourceFiles, equals(['foo.dart']));
|
|
});
|
|
|
|
test('hintsAreFatal', () {
|
|
var options = parse(['--dart-sdk', '.', '--fatal-lints', 'foo.dart']);
|
|
expect(options.lintsAreFatal, isTrue);
|
|
});
|
|
|
|
test('bad SDK dir', () {
|
|
String failureMessage;
|
|
parse(['--dart-sdk', '&&&&&', 'foo.dart'],
|
|
printAndFail: (msg) => failureMessage = msg);
|
|
expect(failureMessage, equals('Invalid Dart SDK path: &&&&&'));
|
|
});
|
|
|
|
test('--train-snapshot', () {
|
|
var options = parse(['--train-snapshot', 'foo.dart']);
|
|
expect(options.trainSnapshot, isTrue);
|
|
});
|
|
});
|
|
});
|
|
defineReflectiveTests(ArgumentsTest);
|
|
}
|
|
|
|
@reflectiveTest
|
|
class ArgumentsTest with ResourceProviderMixin {
|
|
CommandLineOptions commandLineOptions;
|
|
String failureMessage;
|
|
|
|
void test_declaredVariables() {
|
|
_parse(['-Da=0', '-Db=', 'a.dart']);
|
|
|
|
var definedVariables = commandLineOptions.declaredVariables;
|
|
|
|
expect(definedVariables['a'], '0');
|
|
expect(definedVariables['b'], '');
|
|
expect(definedVariables['c'], isNull);
|
|
}
|
|
|
|
void test_defaultAnalysisOptionsFilePath() {
|
|
var expected = 'my_options.yaml';
|
|
_parse(['--options=$expected', 'a.dart']);
|
|
|
|
expect(
|
|
commandLineOptions.defaultAnalysisOptionsPath,
|
|
endsWith(expected),
|
|
);
|
|
}
|
|
|
|
void test_defaultPackageFilePath() {
|
|
var expected = 'my_package_config.json';
|
|
_parse(['--packages=$expected', 'a.dart']);
|
|
|
|
expect(
|
|
commandLineOptions.defaultPackagesPath,
|
|
endsWith(expected),
|
|
);
|
|
}
|
|
|
|
void test_defaults() {
|
|
_parse(['a.dart']);
|
|
expect(commandLineOptions.declaredVariables, isEmpty);
|
|
expect(commandLineOptions.defaultAnalysisOptionsPath, isNull);
|
|
expect(commandLineOptions.defaultPackagesPath, isNull);
|
|
}
|
|
|
|
void test_filterUnknownArguments() {
|
|
var args = ['--a', '--b', '--c=0', '--d=1', '-Da=b', '-e=2', '-f', 'bar'];
|
|
var parser = ArgParser();
|
|
parser.addFlag('a');
|
|
parser.addOption('c');
|
|
parser.addOption('ee', abbr: 'e');
|
|
parser.addFlag('ff', abbr: 'f');
|
|
var result = CommandLineOptions.filterUnknownArguments(args, parser);
|
|
expect(
|
|
result,
|
|
orderedEquals(['--a', '--c=0', '-Da=b', '-e=2', '-f', 'bar']),
|
|
);
|
|
}
|
|
|
|
void test_updateAnalysisOptions_defaultLanguageVersion() {
|
|
_applyAnalysisOptions(
|
|
['a.dart'],
|
|
(analysisOptions) {},
|
|
(analysisOptions) {
|
|
expect(
|
|
analysisOptions.nonPackageLanguageVersion,
|
|
ExperimentStatus.currentVersion,
|
|
);
|
|
var featureSet = analysisOptions.nonPackageFeatureSet;
|
|
expect(featureSet.isEnabled(Feature.non_nullable), isTrue);
|
|
},
|
|
);
|
|
|
|
_applyAnalysisOptions(
|
|
['--default-language-version=2.7', 'a.dart'],
|
|
(analysisOptions) {},
|
|
(analysisOptions) {
|
|
expect(
|
|
analysisOptions.nonPackageLanguageVersion,
|
|
Version.parse('2.7.0'),
|
|
);
|
|
var featureSet = analysisOptions.nonPackageFeatureSet;
|
|
expect(featureSet.isEnabled(Feature.non_nullable), isFalse);
|
|
},
|
|
);
|
|
}
|
|
|
|
void test_updateAnalysisOptions_enableExperiment() {
|
|
var feature_a = ExperimentalFeature(
|
|
index: 0,
|
|
enableString: 'a',
|
|
isEnabledByDefault: false,
|
|
isExpired: false,
|
|
documentation: 'a',
|
|
experimentalReleaseVersion: null,
|
|
releaseVersion: null,
|
|
);
|
|
|
|
var feature_b = ExperimentalFeature(
|
|
index: 1,
|
|
enableString: 'a',
|
|
isEnabledByDefault: false,
|
|
isExpired: false,
|
|
documentation: 'a',
|
|
experimentalReleaseVersion: null,
|
|
releaseVersion: null,
|
|
);
|
|
|
|
FeatureSet featuresWithExperiments(List<String> experiments) {
|
|
return FeatureSet.fromEnableFlags2(
|
|
sdkLanguageVersion: ExperimentStatus.currentVersion,
|
|
flags: experiments,
|
|
);
|
|
}
|
|
|
|
overrideKnownFeatures({'a': feature_a, 'b': feature_b}, () {
|
|
// Replace.
|
|
_applyAnalysisOptions(
|
|
['--enable-experiment=b', 'a.dart'],
|
|
(analysisOptions) {
|
|
analysisOptions.contextFeatures = featuresWithExperiments(['a']);
|
|
},
|
|
(analysisOptions) {
|
|
var featureSet = analysisOptions.contextFeatures;
|
|
expect(featureSet.isEnabled(feature_a), isFalse);
|
|
expect(featureSet.isEnabled(feature_b), isTrue);
|
|
},
|
|
);
|
|
|
|
// Don't change if not provided.
|
|
_applyAnalysisOptions(
|
|
['a.dart'],
|
|
(analysisOptions) {
|
|
analysisOptions.contextFeatures = featuresWithExperiments(['a']);
|
|
},
|
|
(analysisOptions) {
|
|
var featureSet = analysisOptions.contextFeatures;
|
|
expect(featureSet.isEnabled(feature_a), isTrue);
|
|
expect(featureSet.isEnabled(feature_b), isFalse);
|
|
},
|
|
);
|
|
});
|
|
}
|
|
|
|
void test_updateAnalysisOptions_implicitCasts() {
|
|
// Turn on.
|
|
_applyAnalysisOptions(
|
|
['--implicit-casts', 'a.dart'],
|
|
(analysisOptions) {
|
|
analysisOptions.implicitCasts = false;
|
|
},
|
|
(analysisOptions) {
|
|
expect(analysisOptions.implicitCasts, isTrue);
|
|
},
|
|
);
|
|
|
|
// Turn off.
|
|
_applyAnalysisOptions(
|
|
['--no-implicit-casts', 'a.dart'],
|
|
(analysisOptions) {
|
|
analysisOptions.implicitCasts = true;
|
|
},
|
|
(analysisOptions) {
|
|
expect(analysisOptions.implicitCasts, isFalse);
|
|
},
|
|
);
|
|
|
|
// Don't change if not provided, false.
|
|
_applyAnalysisOptions(
|
|
['a.dart'],
|
|
(analysisOptions) {
|
|
analysisOptions.implicitCasts = false;
|
|
},
|
|
(analysisOptions) {
|
|
expect(analysisOptions.implicitCasts, isFalse);
|
|
},
|
|
);
|
|
|
|
// Don't change if not provided, true.
|
|
_applyAnalysisOptions(
|
|
['a.dart'],
|
|
(analysisOptions) {
|
|
analysisOptions.implicitCasts = true;
|
|
},
|
|
(analysisOptions) {
|
|
expect(analysisOptions.implicitCasts, isTrue);
|
|
},
|
|
);
|
|
}
|
|
|
|
void test_updateAnalysisOptions_lints() {
|
|
// Turn lints on.
|
|
_applyAnalysisOptions(
|
|
['--lints', 'a.dart'],
|
|
(analysisOptions) {
|
|
analysisOptions.lint = false;
|
|
},
|
|
(analysisOptions) {
|
|
expect(analysisOptions.lint, isTrue);
|
|
},
|
|
);
|
|
|
|
// Turn lints off.
|
|
_applyAnalysisOptions(
|
|
['--no-lints', 'a.dart'],
|
|
(analysisOptions) {
|
|
analysisOptions.lint = true;
|
|
},
|
|
(analysisOptions) {
|
|
expect(analysisOptions.lint, isFalse);
|
|
},
|
|
);
|
|
|
|
// Don't change if not provided, false.
|
|
_applyAnalysisOptions(
|
|
['a.dart'],
|
|
(analysisOptions) {
|
|
analysisOptions.lint = false;
|
|
},
|
|
(analysisOptions) {
|
|
expect(analysisOptions.lint, isFalse);
|
|
},
|
|
);
|
|
|
|
// Don't change if not provided, true.
|
|
_applyAnalysisOptions(
|
|
['a.dart'],
|
|
(analysisOptions) {
|
|
analysisOptions.lint = true;
|
|
},
|
|
(analysisOptions) {
|
|
expect(analysisOptions.lint, isTrue);
|
|
},
|
|
);
|
|
}
|
|
|
|
void test_updateAnalysisOptions_noImplicitDynamic() {
|
|
_applyAnalysisOptions(
|
|
['--no-implicit-dynamic', 'a.dart'],
|
|
(analysisOptions) {
|
|
analysisOptions.implicitDynamic = true;
|
|
},
|
|
(analysisOptions) {
|
|
expect(analysisOptions.implicitDynamic, isFalse);
|
|
},
|
|
);
|
|
|
|
// Don't change if not provided, false.
|
|
_applyAnalysisOptions(
|
|
['a.dart'],
|
|
(analysisOptions) {
|
|
analysisOptions.implicitDynamic = false;
|
|
},
|
|
(analysisOptions) {
|
|
expect(analysisOptions.implicitDynamic, isFalse);
|
|
},
|
|
);
|
|
|
|
// Don't change if not provided, true.
|
|
_applyAnalysisOptions(
|
|
['a.dart'],
|
|
(analysisOptions) {
|
|
analysisOptions.implicitDynamic = true;
|
|
},
|
|
(analysisOptions) {
|
|
expect(analysisOptions.implicitDynamic, isTrue);
|
|
},
|
|
);
|
|
}
|
|
|
|
void _applyAnalysisOptions(
|
|
List<String> args,
|
|
void Function(AnalysisOptionsImpl) configureInitial,
|
|
void Function(AnalysisOptionsImpl) checkApplied,
|
|
) {
|
|
_parse(args);
|
|
expect(commandLineOptions, isNotNull);
|
|
|
|
var analysisOptions = AnalysisOptionsImpl();
|
|
configureInitial(analysisOptions);
|
|
|
|
commandLineOptions.updateAnalysisOptions(analysisOptions);
|
|
checkApplied(analysisOptions);
|
|
}
|
|
|
|
void _parse(List<String> args, {bool ignoreUnrecognized = true}) {
|
|
var resourceProvider = PhysicalResourceProvider.INSTANCE;
|
|
commandLineOptions = CommandLineOptions.parse(
|
|
resourceProvider,
|
|
[
|
|
if (ignoreUnrecognized) '--ignore-unrecognized-flags',
|
|
...args,
|
|
],
|
|
printAndFail: (msg) {
|
|
failureMessage = msg;
|
|
},
|
|
);
|
|
}
|
|
}
|