[pkg/dartdev] support analyzing multiple directories

Bug: https://github.com/dart-lang/sdk/issues/45352
Change-Id: I9ffdf1d56ea52fd17ff8e9ce936ee82f108d7b61
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/202065
Commit-Queue: Devon Carew <devoncarew@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Devon Carew 2021-06-02 20:11:24 +00:00 committed by commit-bot@chromium.org
parent f14f0798ee
commit 154b217822
6 changed files with 67 additions and 41 deletions

View file

@ -67,6 +67,9 @@ https://github.com/dart-lang/sdk/issues/46100
'recommended' set of lints from `package:lints`. See https://dart.dev/go/core-lints
for more information about these lints.
* The `dart analyze` command has been extended to support specifying multiple
files or directories to analyze; see also https://github.com/dart-lang/sdk/issues/45352.
#### Linter
Updated the Linter to `1.5.0`, which includes:

View file

@ -20,12 +20,12 @@ import 'utils.dart';
class AnalysisServer {
AnalysisServer(
this.sdkPath,
this.analysisRoot, {
this.analysisRoots, {
@required this.commandName,
});
final Directory sdkPath;
final FileSystemEntity analysisRoot;
final List<FileSystemEntity> analysisRoots;
final String commandName;
Process _process;
@ -107,10 +107,10 @@ class AnalysisServer {
//
// The call to absolute.resolveSymbolicLinksSync() canonicalizes the path to
// be passed to the analysis server.
var analysisRootPath = trimEnd(
analysisRoot.absolute.resolveSymbolicLinksSync(),
path.context.separator,
);
List<String> analysisRootPaths = analysisRoots.map((root) {
return trimEnd(
root.absolute.resolveSymbolicLinksSync(), path.context.separator);
}).toList();
onAnalyzing.listen((bool isAnalyzing) {
if (isAnalyzing && _analysisFinished.isCompleted) {
@ -124,7 +124,7 @@ class AnalysisServer {
// ignore: unawaited_futures
_sendCommand('analysis.setAnalysisRoots', params: <String, dynamic>{
'included': [analysisRootPath],
'included': analysisRootPaths,
'excluded': <String>[]
});
}

View file

@ -69,26 +69,19 @@ class AnalyzeCommand extends DartdevCommand {
@override
FutureOr<int> run() async {
if (argResults.rest.length > 1) {
usageException('Only one directory or file is expected.');
}
// find target from argResults.rest
io.FileSystemEntity target;
io.Directory relativeToDir;
// Find targets from the 'rest' params.
final List<io.FileSystemEntity> targets = [];
if (argResults.rest.isEmpty) {
target = io.Directory.current;
relativeToDir = target;
targets.add(io.Directory.current);
} else {
var targetPath = argResults.rest.single;
if (io.Directory(targetPath).existsSync()) {
target = io.Directory(targetPath);
relativeToDir = target;
} else if (io.File(targetPath).existsSync()) {
target = io.File(targetPath);
relativeToDir = target.parent;
} else {
usageException("Directory or file doesn't exist: $targetPath");
for (String targetPath in argResults.rest) {
if (io.Directory(targetPath).existsSync()) {
targets.add(io.Directory(targetPath));
} else if (io.File(targetPath).existsSync()) {
targets.add(io.File(targetPath));
} else {
usageException("Directory or file doesn't exist: $targetPath");
}
}
}
@ -97,13 +90,15 @@ class AnalyzeCommand extends DartdevCommand {
final machineFormat = argResults['format'] == 'machine';
final jsonFormat = argResults['format'] == 'json';
var progress = machineFormat
? null
: log.progress('Analyzing ${path.basename(target.path)}');
final targetsNames =
targets.map((entity) => path.basename(entity.path)).join(', ');
var progress =
machineFormat ? null : log.progress('Analyzing $targetsNames');
final AnalysisServer server = AnalysisServer(
io.Directory(sdk.sdkPath),
target,
targets,
commandName: 'analyze',
);
@ -145,8 +140,14 @@ class AnalyzeCommand extends DartdevCommand {
} else if (jsonFormat) {
emitJsonFormat(log, errors);
} else {
emitDefaultFormat(log, errors,
relativeToDir: relativeToDir, verbose: verbose);
var relativeTo = targets.length == 1 ? targets.single : null;
emitDefaultFormat(
log,
errors,
relativeToDir: relativeTo is io.File ? relativeTo.parent : relativeTo,
verbose: verbose,
);
}
bool hasErrors = false;

View file

@ -91,7 +91,7 @@ To use the tool, run either ['dart fix --dry-run'] for a preview of the proposed
var server = AnalysisServer(
io.Directory(sdk.sdkPath),
dir,
[dir],
commandName: 'fix',
);

View file

@ -24,14 +24,14 @@ void main() {
tearDown(() => p?.dispose());
test('can start', () async {
AnalysisServer server = AnalysisServer(io.Directory(sdk.sdkPath), p.dir,
AnalysisServer server = AnalysisServer(io.Directory(sdk.sdkPath), [p.dir],
commandName: 'testing');
await server.start();
await server.shutdown();
});
test('can send message', () async {
AnalysisServer server = AnalysisServer(io.Directory(sdk.sdkPath), p.dir,
AnalysisServer server = AnalysisServer(io.Directory(sdk.sdkPath), [p.dir],
commandName: 'testing');
await server.start();

View file

@ -85,14 +85,36 @@ void defineAnalyze() {
expect(result.stdout, contains(_analyzeVerboseUsageText));
});
test('multiple directories', () {
p = project();
var result = p.runSync(['analyze', '/no/such/dir1/', '/no/such/dir2/']);
group('multiple items', () {
TestProject secondProject;
expect(result.exitCode, 64);
expect(result.stdout, isEmpty);
expect(result.stderr, contains('Only one directory or file is expected.'));
expect(result.stderr, contains(_analyzeUsageText));
tearDown(() => secondProject?.dispose());
test('folder and file', () {
p = project(mainSrc: "int get foo => 'str';\n");
secondProject = project(mainSrc: "int get foo => 'str';\n");
var result = p.runSync(['analyze', p.dirPath, secondProject.mainPath]);
expect(result.exitCode, 3);
expect(result.stderr, isEmpty);
expect(result.stdout, contains('A value of type '));
expect(result.stdout, contains('lib/main.dart:1:16 '));
expect(result.stdout, contains('return_of_invalid_type'));
expect(result.stdout, contains('2 issues found.'));
});
test('two folders', () {
p = project(mainSrc: "int get foo => 'str';\n");
secondProject = project(mainSrc: "int get foo => 'str';\n");
var result = p.runSync(['analyze', p.dirPath, secondProject.dirPath]);
expect(result.exitCode, 3);
expect(result.stderr, isEmpty);
expect(result.stdout, contains('A value of type '));
expect(result.stdout, contains('main.dart:1:16 '));
expect(result.stdout, contains('return_of_invalid_type'));
expect(result.stdout, contains('2 issues found.'));
});
});
test('no such directory', () {