Skip to content

Commit 1dd71b4

Browse files
devoncarewCommit Queue
authored and
Commit Queue
committed
[dartdev] contribute a 'dart bug' command
Change-Id: Ib5557711df23d3a3e0485378c04ff6264194717f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/269750 Reviewed-by: Ben Konyi <[email protected]> Commit-Queue: Devon Carew <[email protected]>
1 parent e9de133 commit 1dd71b4

13 files changed

+686
-13
lines changed

pkg/dartdev/lib/dartdev.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import 'package:usage/usage.dart';
1717

1818
import 'src/analytics.dart';
1919
import 'src/commands/analyze.dart';
20+
import 'src/commands/bug.dart';
2021
import 'src/commands/compile.dart';
2122
import 'src/commands/compile_server_shutdown.dart';
2223
import 'src/commands/create.dart';
@@ -121,13 +122,12 @@ class DartdevRunner extends CommandRunner<int> {
121122
);
122123

123124
addCommand(AnalyzeCommand(verbose: verbose));
125+
addCommand(BugCommand(verbose: verbose));
124126
addCommand(CreateCommand(verbose: verbose));
125127
addCommand(DebugAdapterCommand(verbose: verbose));
126128
addCommand(CompileCommand(verbose: verbose));
127129
addCommand(DocCommand(verbose: verbose));
128-
addCommand(DevToolsCommand(
129-
verbose: verbose,
130-
));
130+
addCommand(DevToolsCommand(verbose: verbose));
131131
addCommand(FixCommand(verbose: verbose));
132132
addCommand(FormatCommand(verbose: verbose));
133133
addCommand(LanguageServerCommand(verbose: verbose));

pkg/dartdev/lib/src/commands/bug.dart

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:async';
6+
import 'dart:io';
7+
8+
import 'package:intl/intl.dart';
9+
import 'package:yaml/yaml.dart';
10+
11+
import '../core.dart';
12+
import '../processes.dart';
13+
import '../utils.dart';
14+
15+
// TODO(devoncarew): have a flag to elide paths (enabled by default)
16+
17+
final NumberFormat _nf = NumberFormat();
18+
19+
const bool _elideFilePaths = true;
20+
21+
/// Print output useful for diagnosing local issues.
22+
class BugCommand extends DartdevCommand {
23+
static const String cmdName = 'bug';
24+
25+
static const String cmdDescription =
26+
'Show diagnostic information about the installed tooling.';
27+
28+
BugCommand({bool verbose = false}) : super(cmdName, cmdDescription, verbose);
29+
30+
static const String _message =
31+
'If providing this information as part of reporting a bug, please review '
32+
'the information below carefully to ensure it only contains things '
33+
"you're comfortable posting publicly.";
34+
35+
@override
36+
FutureOr<int> run() async {
37+
print('');
38+
print(wrapText(_message, width: dartdevUsageLineLength));
39+
40+
print('');
41+
print('#### General info');
42+
print('');
43+
print('- Dart ${Platform.version}');
44+
print('- on ${Platform.operatingSystem} / '
45+
'${Platform.operatingSystemVersion}');
46+
print('- locale is ${Platform.localeName}');
47+
48+
// project information
49+
var projectInfo = getProjectInfo(project, onlySimpleDeps: _elideFilePaths);
50+
if (projectInfo != null) {
51+
print('');
52+
print('#### Project info');
53+
print('');
54+
print("- sdk constraint: '${projectInfo.sdkDependency ?? ''}'");
55+
print('- dependencies: ${projectInfo.dependencies.join(', ')}');
56+
print('- dev_dependencies: ${projectInfo.devDependencies.join(', ')}');
57+
if (projectInfo.elidedDependencies > 0) {
58+
print('- elided dependencies: ${projectInfo.elidedDependencies}');
59+
}
60+
}
61+
62+
// process information
63+
var processInfo =
64+
ProcessInfo.getProcessInfo(elideFilePaths: _elideFilePaths);
65+
if (processInfo != null) {
66+
print('');
67+
print('#### Process info');
68+
print('');
69+
70+
if (processInfo.isEmpty) {
71+
print('No Dart processes found.');
72+
} else {
73+
var table = MarkdownTable();
74+
table.startRow()
75+
..cell('Memory', right: true)
76+
..cell('CPU', right: true)
77+
..cell('Elapsed time', right: true)
78+
..cell('Command line');
79+
80+
for (var process in processInfo) {
81+
var row = table.startRow();
82+
row.cell('${_nf.format(process.memoryMb)} MB', right: true);
83+
row.cell('${process.cpuPercent.toStringAsFixed(1)}%', right: true);
84+
row.cell(process.elapsedTime, right: true);
85+
row.cell(_elideFilePaths
86+
? _noMoreThan(process.commandLine, MarkdownTable.defaultMaxWidth)
87+
: process.commandLine);
88+
}
89+
90+
print(table.finish().trimRight());
91+
}
92+
}
93+
94+
return 0;
95+
}
96+
}
97+
98+
ProjectInfo? getProjectInfo(Project project, {bool onlySimpleDeps = true}) {
99+
if (!project.hasPubspecFile) {
100+
return null;
101+
}
102+
103+
var pubspec = loadYaml(project.pubspecFile.readAsStringSync()) as Map;
104+
var elidedDependencies = 0;
105+
106+
List<String> getDeps(String dependencyType) {
107+
var deps = pubspec[dependencyType] as Map?;
108+
var results = <String>[];
109+
if (deps != null) {
110+
for (var pkgName in deps.keys) {
111+
var dep = deps[pkgName];
112+
113+
// Don't report path: or git: dependencies.
114+
if (onlySimpleDeps && dep is Map) {
115+
if (dep.length != 1) {
116+
elidedDependencies++;
117+
continue;
118+
}
119+
120+
final key = dep.keys.first;
121+
if (key != 'sdk') {
122+
elidedDependencies++;
123+
continue;
124+
}
125+
}
126+
127+
results.add(pkgName);
128+
}
129+
}
130+
return results..sort();
131+
}
132+
133+
return ProjectInfo(
134+
sdkDependency: (pubspec['environment'] as Map?)?['sdk'] as String?,
135+
dependencies: getDeps('dependencies'),
136+
devDependencies: getDeps('dev_dependencies'),
137+
elidedDependencies: elidedDependencies,
138+
);
139+
}
140+
141+
class ProjectInfo {
142+
final String? sdkDependency;
143+
final List<String> dependencies;
144+
final List<String> devDependencies;
145+
final int elidedDependencies;
146+
147+
ProjectInfo({
148+
required this.sdkDependency,
149+
required this.dependencies,
150+
required this.devDependencies,
151+
required this.elidedDependencies,
152+
});
153+
}
154+
155+
String _noMoreThan(String value, int length) {
156+
if (value.length <= length) return value;
157+
return '${value.substring(0, length - 1)}…';
158+
}

pkg/dartdev/lib/src/commands/language_server.dart

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import 'dart:io' as io;
66

7-
import 'package:analysis_server/src/server/driver.dart' as server_driver;
7+
import 'package:analysis_server/src/server/driver.dart' as server;
88
import 'package:args/args.dart';
99

1010
import '../core.dart';
@@ -31,7 +31,7 @@ For more information about the server's capabilities and configuration, see:
3131

3232
@override
3333
ArgParser createArgParser() {
34-
return server_driver.Driver.createArgParser(
34+
return server.Driver.createArgParser(
3535
usageLineLength: dartdevUsageLineLength,
3636
includeHelpFlag: false,
3737
defaultToLsp: true,
@@ -40,19 +40,21 @@ For more information about the server's capabilities and configuration, see:
4040

4141
@override
4242
Future<int> run() async {
43+
const protocol = server.Driver.SERVER_PROTOCOL;
44+
const lsp = server.Driver.PROTOCOL_LSP;
45+
4346
var args = argResults!.arguments;
44-
if (!args.any((arg) => arg.startsWith('--protocol'))) {
45-
args = [...args, '--protocol=lsp'];
47+
if (!args.any((arg) => arg.startsWith('--$protocol'))) {
48+
args = [...args, '--$protocol=$lsp'];
4649
}
4750

4851
if (!Sdk.checkArtifactExists(sdk.analysisServerSnapshot)) return 255;
4952

5053
VmInteropHandler.run(
51-
sdk.analysisServerSnapshot,
52-
[
53-
...args,
54-
],
55-
packageConfigOverride: null);
54+
sdk.analysisServerSnapshot,
55+
args,
56+
packageConfigOverride: null,
57+
);
5658

5759
// The server will continue to run past the return from this method.
5860
//

pkg/dartdev/lib/src/core.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ class Project {
151151
bool get hasPubspecFile =>
152152
FileSystemEntity.isFileSync(path.join(dir.path, 'pubspec.yaml'));
153153

154+
File get pubspecFile => File(path.join(dir.path, 'pubspec.yaml'));
155+
154156
bool get hasPackageConfigFile => packageConfig != null;
155157

156158
PackageConfig? get packageConfig {

0 commit comments

Comments
 (0)