Convert paths to absolute and normalized in analyzer_cli arguments.

See https://github.com/dart-lang/linter/pull/2189#issuecomment-665984938

Change-Id: I6becb616dd8bcb0c9945ea5ad5ac6119bb93e330
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/156441
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2020-07-30 15:00:58 +00:00 committed by commit-bot@chromium.org
parent f925019c5a
commit fb0578159e
8 changed files with 129 additions and 85 deletions

View file

@ -55,16 +55,34 @@ void applyAnalysisOptionFlags(AnalysisOptionsImpl options, ArgResults args,
}
/// Use the command-line [args] to create a context builder.
ContextBuilderOptions createContextBuilderOptions(ArgResults args) {
ContextBuilderOptions createContextBuilderOptions(
ResourceProvider resourceProvider,
ArgResults args,
) {
String absoluteNormalizedPath(String path) {
if (path == null) {
return null;
}
var pathContext = resourceProvider.pathContext;
return pathContext.normalize(
pathContext.absolute(path),
);
}
ContextBuilderOptions builderOptions = ContextBuilderOptions();
builderOptions.argResults = args;
//
// File locations.
//
builderOptions.dartSdkSummaryPath = args[sdkSummaryPathOption];
builderOptions.defaultAnalysisOptionsFilePath =
args[analysisOptionsFileOption];
builderOptions.defaultPackageFilePath = args[packagesOption];
builderOptions.dartSdkSummaryPath = absoluteNormalizedPath(
args[sdkSummaryPathOption],
);
builderOptions.defaultAnalysisOptionsFilePath = absoluteNormalizedPath(
args[analysisOptionsFileOption],
);
builderOptions.defaultPackageFilePath = absoluteNormalizedPath(
args[packagesOption],
);
//
// Analysis options.
//

View file

@ -36,16 +36,28 @@ class ArgumentsTest with ResourceProviderMixin {
'--packages=$defaultPackageFilePath',
];
ArgResults result = parse(resourceProvider, parser, args);
ContextBuilderOptions options = createContextBuilderOptions(result);
ContextBuilderOptions options =
createContextBuilderOptions(resourceProvider, result);
expect(options, isNotNull);
expect(options.dartSdkSummaryPath, dartSdkSummaryPath);
expect(
options.defaultAnalysisOptionsFilePath,
endsWith(defaultAnalysisOptionsFilePath),
);
expect(
options.defaultPackageFilePath,
endsWith(defaultPackageFilePath),
);
expect(
options.dartSdkSummaryPath,
endsWith(dartSdkSummaryPath),
);
Map<String, String> declaredVariables = options.declaredVariables;
expect(declaredVariables, hasLength(2));
expect(declaredVariables['foo'], '1');
expect(declaredVariables['bar'], '2');
expect(
options.defaultAnalysisOptionsFilePath, defaultAnalysisOptionsFilePath);
expect(options.defaultPackageFilePath, defaultPackageFilePath);
AnalysisOptionsImpl defaultOptions = options.defaultOptions;
expect(defaultOptions, isNotNull);
expect(defaultOptions.strongMode, true);
@ -58,7 +70,8 @@ class ArgumentsTest with ResourceProviderMixin {
defineAnalysisArguments(parser);
List<String> args = [];
ArgResults result = parse(resourceProvider, parser, args);
ContextBuilderOptions options = createContextBuilderOptions(result);
ContextBuilderOptions options =
createContextBuilderOptions(resourceProvider, result);
expect(options, isNotNull);
expect(options.dartSdkSummaryPath, isNull);
expect(options.declaredVariables, isEmpty);
@ -130,7 +143,8 @@ class ArgumentsTest with ResourceProviderMixin {
'--implicit-casts',
];
ArgResults result = parse(resourceProvider, parser, args);
ContextBuilderOptions options = createContextBuilderOptions(result);
ContextBuilderOptions options =
createContextBuilderOptions(resourceProvider, result);
expect(options, isNotNull);
AnalysisOptionsImpl defaultOptions = options.defaultOptions;
expect(defaultOptions, isNotNull);
@ -144,7 +158,8 @@ class ArgumentsTest with ResourceProviderMixin {
'--no-implicit-casts',
];
ArgResults result = parse(resourceProvider, parser, args);
ContextBuilderOptions options = createContextBuilderOptions(result);
ContextBuilderOptions options =
createContextBuilderOptions(resourceProvider, result);
expect(options, isNotNull);
AnalysisOptionsImpl defaultOptions = options.defaultOptions;
expect(defaultOptions, isNotNull);

View file

@ -105,7 +105,7 @@ const Map<String, LibraryInfo> libraries = const {
defineAnalysisArguments(argParser);
ArgResults argResults = argParser.parse(['--$lintsFlag']);
var builder = ContextBuilder(resourceProvider, sdkManager, contentCache,
options: createContextBuilderOptions(argResults));
options: createContextBuilderOptions(resourceProvider, argResults));
AnalysisOptionsImpl expected = AnalysisOptionsImpl();
expected.lint = true;
@ -130,7 +130,7 @@ linter:
defineAnalysisArguments(argParser);
ArgResults argResults = argParser.parse(['--no-$lintsFlag']);
var builder = ContextBuilder(resourceProvider, sdkManager, contentCache,
options: createContextBuilderOptions(argResults));
options: createContextBuilderOptions(resourceProvider, argResults));
AnalysisOptionsImpl expected = AnalysisOptionsImpl();
expected.lint = false;
@ -155,7 +155,7 @@ linter:
defineAnalysisArguments(argParser);
ArgResults argResults = argParser.parse([]);
var builder = ContextBuilder(resourceProvider, sdkManager, contentCache,
options: createContextBuilderOptions(argResults));
options: createContextBuilderOptions(resourceProvider, argResults));
AnalysisOptionsImpl expected = AnalysisOptionsImpl();
expected.lint = true;
@ -180,7 +180,7 @@ linter:
defineAnalysisArguments(argParser);
ArgResults argResults = argParser.parse([]);
var builder = ContextBuilder(resourceProvider, sdkManager, contentCache,
options: createContextBuilderOptions(argResults));
options: createContextBuilderOptions(resourceProvider, argResults));
AnalysisOptionsImpl expected = AnalysisOptionsImpl();
expected.lint = false;
@ -599,7 +599,7 @@ analyzer:
ArgParser argParser = ArgParser();
defineAnalysisArguments(argParser);
ArgResults argResults = argParser.parse([]);
builderOptions = createContextBuilderOptions(argResults);
builderOptions = createContextBuilderOptions(resourceProvider, argResults);
builder = ContextBuilder(resourceProvider, sdkManager, contentCache,
options: builderOptions);
AnalysisOptionsImpl expected = AnalysisOptionsImpl();

View file

@ -112,8 +112,8 @@ class AnalyzerWorkerLoop extends AsyncWorkerLoop {
}
// Prepare options.
var options =
CommandLineOptions.parse(arguments, printAndFail: (String msg) {
var options = CommandLineOptions.parse(resourceProvider, arguments,
printAndFail: (String msg) {
throw ArgumentError(msg);
});

View file

@ -126,7 +126,7 @@ class Driver with HasContextMixin implements CommandLineStarter {
linter.registerLintRules();
// Parse commandline options.
var options = CommandLineOptions.parse(args);
var options = CommandLineOptions.parse(resourceProvider, args);
// Do analysis.
if (options.buildMode) {
@ -140,7 +140,7 @@ class Driver with HasContextMixin implements CommandLineStarter {
batchRunner.runAsBatch(args, (List<String> args) async {
// TODO(brianwilkerson) Determine whether this await is necessary.
await null;
var options = CommandLineOptions.parse(args);
var options = CommandLineOptions.parse(resourceProvider, args);
return await _analyzeAll(options);
});
} else {

View file

@ -2,8 +2,9 @@
// 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 'dart:io' as io;
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/command_line/arguments.dart';
import 'package:analyzer/src/context/builder.dart';
@ -18,7 +19,7 @@ const _binaryName = 'dartanalyzer';
/// Shared exit handler.
///
/// *Visible for testing.*
ExitHandler exitHandler = exit;
ExitHandler exitHandler = io.exit;
T cast<T>(dynamic value) => value as T;
@ -151,8 +152,10 @@ class CommandLineOptions {
final String summaryDepsOutput;
/// Initialize options from the given parsed [args].
CommandLineOptions._fromArgs(ArgResults args)
: buildAnalysisOutput = cast(args['build-analysis-output']),
CommandLineOptions._fromArgs(
ResourceProvider resourceProvider,
ArgResults args,
) : buildAnalysisOutput = cast(args['build-analysis-output']),
buildMode = cast(args['build-mode']),
buildModePersistentWorker = cast(args['persistent_worker']),
buildSummaryInputs =
@ -162,7 +165,10 @@ class CommandLineOptions {
buildSummaryOutputSemantic =
cast(args['build-summary-output-semantic']),
buildSuppressExitCode = cast(args['build-suppress-exit-code']),
contextBuilderOptions = createContextBuilderOptions(args),
contextBuilderOptions = createContextBuilderOptions(
resourceProvider,
args,
),
dartSdkPath = cast(args['dart-sdk']),
dartSdkSummaryPath = cast(args['dart-sdk-summary']),
defaultLanguageVersion = cast(args['default-language-version']),
@ -214,9 +220,10 @@ class CommandLineOptions {
/// Parse [args] into [CommandLineOptions] describing the specified
/// analyzer options. In case of a format error, calls [printAndFail], which
/// by default prints an error message to stderr and exits.
static CommandLineOptions parse(List<String> args,
static CommandLineOptions parse(
ResourceProvider resourceProvider, List<String> args,
{void Function(String msg) printAndFail = printAndFail}) {
var options = _parse(args);
var options = _parse(resourceProvider, args);
/// Only happens in testing.
if (options == null) {
@ -236,7 +243,7 @@ class CommandLineOptions {
return null; // Only reachable in testing.
}
// Check that SDK is existing directory.
if (!(Directory(sdkPath)).existsSync()) {
if (!(io.Directory(sdkPath)).existsSync()) {
printAndFail('Invalid Dart SDK path: $sdkPath');
return null; // Only reachable in testing.
}
@ -271,8 +278,9 @@ class CommandLineOptions {
static String _getVersion() {
try {
// This is relative to bin/snapshot, so ../..
var versionPath = Platform.script.resolve('../../version').toFilePath();
var versionFile = File(versionPath);
var versionPath =
io.Platform.script.resolve('../../version').toFilePath();
var versionFile = io.File(versionPath);
return versionFile.readAsStringSync().trim();
} catch (_) {
// This happens when the script is not running in the context of an SDK.
@ -280,7 +288,10 @@ class CommandLineOptions {
}
}
static CommandLineOptions _parse(List<String> args) {
static CommandLineOptions _parse(
ResourceProvider resourceProvider,
List<String> args,
) {
args = preprocessArgs(PhysicalResourceProvider.INSTANCE, args);
var verbose = args.contains('-v') || args.contains('--verbose');
@ -504,7 +515,7 @@ class CommandLineOptions {
'option. Got: $args');
return null; // Only reachable in testing.
}
return CommandLineOptions._fromArgs(results);
return CommandLineOptions._fromArgs(resourceProvider, results);
}
// Help requests.
@ -565,7 +576,7 @@ class CommandLineOptions {
}
}
return CommandLineOptions._fromArgs(results);
return CommandLineOptions._fromArgs(resourceProvider, results);
} on FormatException catch (e) {
errorSink.writeln(e.message);
_showUsage(parser);

View file

@ -4,6 +4,7 @@
import 'dart:io';
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;
@ -22,6 +23,13 @@ void main() {
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;
@ -40,7 +48,7 @@ void main() {
});
test('defaults', () {
var options = CommandLineOptions.parse(['--dart-sdk', '.', 'foo.dart']);
var options = parse(['--dart-sdk', '.', 'foo.dart']);
expect(options, isNotNull);
expect(options.buildMode, isFalse);
expect(options.buildAnalysisOutput, isNull);
@ -70,20 +78,19 @@ void main() {
});
test('batch', () {
var options = CommandLineOptions.parse(['--dart-sdk', '.', '--batch']);
var options = parse(['--dart-sdk', '.', '--batch']);
expect(options.batchMode, isTrue);
});
test('defined variables', () {
var options = CommandLineOptions.parse(
['--dart-sdk', '.', '-Dfoo=bar', 'foo.dart']);
var options = parse(['--dart-sdk', '.', '-Dfoo=bar', 'foo.dart']);
expect(options.definedVariables['foo'], equals('bar'));
expect(options.definedVariables['bar'], isNull);
});
test('disable cache flushing', () {
var options = CommandLineOptions.parse(
['--dart-sdk', '.', '--disable-cache-flushing', 'foo.dart']);
var options =
parse(['--dart-sdk', '.', '--disable-cache-flushing', 'foo.dart']);
expect(options.disableCacheFlushing, isTrue);
});
@ -116,32 +123,28 @@ void main() {
};
test('no values', () {
var options = overrideKnownFeatures(
knownFeatures, () => CommandLineOptions.parse(['foo.dart']));
var options =
overrideKnownFeatures(knownFeatures, () => parse(['foo.dart']));
expect(options.enabledExperiments, isEmpty);
});
test('single value', () {
var options = overrideKnownFeatures(
knownFeatures,
() => CommandLineOptions.parse(
['--enable-experiment', 'a', 'foo.dart']));
var options = overrideKnownFeatures(knownFeatures,
() => parse(['--enable-experiment', 'a', 'foo.dart']));
expect(options.enabledExperiments, ['a']);
});
group('multiple values', () {
test('single flag', () {
var options = overrideKnownFeatures(
knownFeatures,
() => CommandLineOptions.parse(
['--enable-experiment', 'a,b', 'foo.dart']));
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,
() => CommandLineOptions.parse([
() => parse([
'--enable-experiment',
'a,b',
'--enable-experiment',
@ -154,7 +157,7 @@ void main() {
test('multiple flags', () {
var options = overrideKnownFeatures(
knownFeatures,
() => CommandLineOptions.parse([
() => parse([
'--enable-experiment',
'a',
'--enable-experiment',
@ -167,74 +170,68 @@ void main() {
});
test('hintsAreFatal', () {
var options = CommandLineOptions.parse(
['--dart-sdk', '.', '--fatal-hints', 'foo.dart']);
var options = parse(['--dart-sdk', '.', '--fatal-hints', 'foo.dart']);
expect(options.infosAreFatal, isTrue);
});
test('infosAreFatal', () {
var options = CommandLineOptions.parse(
['--dart-sdk', '.', '--fatal-infos', 'foo.dart']);
var options = parse(['--dart-sdk', '.', '--fatal-infos', 'foo.dart']);
expect(options.infosAreFatal, isTrue);
});
test('log', () {
var options =
CommandLineOptions.parse(['--dart-sdk', '.', '--log', 'foo.dart']);
var options = parse(['--dart-sdk', '.', '--log', 'foo.dart']);
expect(options.log, isTrue);
});
test('machine format', () {
var options = CommandLineOptions.parse(
['--dart-sdk', '.', '--format=machine', 'foo.dart']);
var options =
parse(['--dart-sdk', '.', '--format=machine', 'foo.dart']);
expect(options.machineFormat, isTrue);
});
test('no-hints', () {
var options = CommandLineOptions.parse(
['--dart-sdk', '.', '--no-hints', 'foo.dart']);
var options = parse(['--dart-sdk', '.', '--no-hints', 'foo.dart']);
expect(options.disableHints, isTrue);
});
test('options', () {
var options = CommandLineOptions.parse(
['--dart-sdk', '.', '--options', 'options.yaml', 'foo.dart']);
expect(options.analysisOptionsFile, equals('options.yaml'));
var options =
parse(['--dart-sdk', '.', '--options', 'options.yaml', 'foo.dart']);
expect(options.analysisOptionsFile, endsWith('options.yaml'));
});
test('lints', () {
var options = CommandLineOptions.parse(
['--dart-sdk', '.', '--lints', 'foo.dart']);
var options = parse(['--dart-sdk', '.', '--lints', 'foo.dart']);
expect(options.lints, isTrue);
});
test('package warnings', () {
var options = CommandLineOptions.parse(
['--dart-sdk', '.', '--package-warnings', 'foo.dart']);
var options =
parse(['--dart-sdk', '.', '--package-warnings', 'foo.dart']);
expect(options.showPackageWarnings, isTrue);
});
test('sdk warnings', () {
var options = CommandLineOptions.parse(
['--dart-sdk', '.', '--sdk-warnings', 'foo.dart']);
var options = parse(['--dart-sdk', '.', '--sdk-warnings', 'foo.dart']);
expect(options.showSdkWarnings, isTrue);
});
test('sourceFiles', () {
var options = CommandLineOptions.parse(
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 = CommandLineOptions.parse(
['--dart-sdk', '.', '--fatal-warnings', 'foo.dart']);
var options =
parse(['--dart-sdk', '.', '--fatal-warnings', 'foo.dart']);
expect(options.warningsAreFatal, isTrue);
});
test('ignore unrecognized flags', () {
var options = CommandLineOptions.parse([
var options = parse([
'--ignore-unrecognized-flags',
'--bar',
'--baz',
@ -247,27 +244,24 @@ void main() {
});
test('hintsAreFatal', () {
var options = CommandLineOptions.parse(
['--dart-sdk', '.', '--fatal-lints', 'foo.dart']);
var options = parse(['--dart-sdk', '.', '--fatal-lints', 'foo.dart']);
expect(options.lintsAreFatal, isTrue);
});
test('bad SDK dir', () {
String failureMessage;
CommandLineOptions.parse(['--dart-sdk', '&&&&&', 'foo.dart'],
parse(['--dart-sdk', '&&&&&', 'foo.dart'],
printAndFail: (msg) => failureMessage = msg);
expect(failureMessage, equals('Invalid Dart SDK path: &&&&&'));
});
test('--use-fasta-parser', () {
var options =
CommandLineOptions.parse(['--use-fasta-parser', 'foo.dart']);
var options = parse(['--use-fasta-parser', 'foo.dart']);
expect(options.useFastaParser, isTrue);
});
test('--train-snapshot', () {
var options =
CommandLineOptions.parse(['--train-snapshot', 'foo.dart']);
var options = parse(['--train-snapshot', 'foo.dart']);
expect(options.trainSnapshot, isTrue);
});
});
@ -421,7 +415,9 @@ class CommandLineOptions_BuildMode_Test extends AbstractStatusTest {
}
void _parse(List<String> args) {
options = CommandLineOptions.parse(args, printAndFail: (msg) {
var resourceProvider = PhysicalResourceProvider.INSTANCE;
options =
CommandLineOptions.parse(resourceProvider, args, printAndFail: (msg) {
failureMessage = msg;
});
}

View file

@ -4,6 +4,7 @@
import 'dart:convert' show json;
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer_cli/src/error_formatter.dart' show AnalysisStats;
import 'package:analyzer_cli/src/options.dart';
import 'package:analyzer_cli/src/perf_report.dart';
@ -11,7 +12,10 @@ import 'package:test/test.dart';
void main() {
test('makePerfReport', () {
var options = CommandLineOptions.parse(['somefile.dart']);
var options = CommandLineOptions.parse(
PhysicalResourceProvider.INSTANCE,
['somefile.dart'],
);
var encoded = makePerfReport(1000, 1234, options, 0, AnalysisStats());
var jsonData = json.decode(encoded);