Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: pkg/testing/lib/src/analyze.dart

Issue 2904483002: Improve analysis coverage. (Closed)
Patch Set: Ignore another file. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/front_end/test/fasta/testing.json ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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.md file. 3 // BSD-style license that can be found in the LICENSE.md file.
4 4
5 library testing.analyze; 5 library testing.analyze;
6 6
7 import 'dart:async' show Stream, Future; 7 import 'dart:async' show Stream, Future;
8 8
9 import 'dart:convert' show LineSplitter, UTF8; 9 import 'dart:convert' show LineSplitter, UTF8;
10 10
11 import 'dart:io' show File, Process; 11 import 'dart:io'
12 show Directory, File, FileSystemEntity, Platform, Process, ProcessResult;
12 13
13 import '../testing.dart' show startDart; 14 import '../testing.dart' show startDart;
14 15
15 import 'log.dart' show isVerbose; 16 import 'log.dart' show isVerbose, splitLines;
16 17
17 import 'suite.dart' show Suite; 18 import 'suite.dart' show Suite;
18 19
19 class Analyze extends Suite { 20 class Analyze extends Suite {
20 final Uri analysisOptions; 21 final Uri analysisOptions;
21 22
22 final List<Uri> uris; 23 final List<Uri> uris;
23 24
24 final List<RegExp> exclude; 25 final List<RegExp> exclude;
25 26
26 Analyze(this.analysisOptions, this.uris, this.exclude) 27 final List<String> gitGrepPathspecs;
28
29 final List<String> gitGrepPatterns;
30
31 Analyze(this.analysisOptions, this.uris, this.exclude, this.gitGrepPathspecs,
32 this.gitGrepPatterns)
27 : super("analyze", "analyze", null); 33 : super("analyze", "analyze", null);
28 34
29 Future<Null> run(Uri packages, List<Uri> extraUris) { 35 Future<Null> run(Uri packages, List<Uri> extraUris) {
30 List<Uri> allUris = new List<Uri>.from(uris); 36 List<Uri> allUris = new List<Uri>.from(uris);
31 if (extraUris != null) { 37 if (extraUris != null) {
32 allUris.addAll(extraUris); 38 allUris.addAll(extraUris);
33 } 39 }
34 return analyzeUris(analysisOptions, packages, allUris, exclude); 40 return analyzeUris(analysisOptions, packages, allUris, exclude,
41 gitGrepPathspecs, gitGrepPatterns);
35 } 42 }
36 43
37 static Future<Analyze> fromJsonMap( 44 static Future<Analyze> fromJsonMap(
38 Uri base, Map json, List<Suite> suites) async { 45 Uri base, Map json, List<Suite> suites) async {
39 String optionsPath = json["options"]; 46 String optionsPath = json["options"];
40 Uri optionsUri = optionsPath == null ? null : base.resolve(optionsPath); 47 Uri optionsUri = optionsPath == null ? null : base.resolve(optionsPath);
41 48
42 List<Uri> uris = new List<Uri>.from( 49 List<Uri> uris = new List<Uri>.from(
43 json["uris"].map((String relative) => base.resolve(relative))); 50 json["uris"].map((String relative) => base.resolve(relative)));
44 51
45 List<RegExp> exclude = 52 List<RegExp> exclude =
46 new List<RegExp>.from(json["exclude"].map((String p) => new RegExp(p))); 53 new List<RegExp>.from(json["exclude"].map((String p) => new RegExp(p)));
47 54
48 return new Analyze(optionsUri, uris, exclude); 55 Map gitGrep = json["git grep"];
56 List<String> gitGrepPathspecs;
57 List<String> gitGrepPatterns;
58 if (gitGrep != null) {
59 gitGrepPathspecs = gitGrep["pathspecs"] ?? const <String>["."];
60 gitGrepPatterns = gitGrep["patterns"];
61 }
62
63 return new Analyze(
64 optionsUri, uris, exclude, gitGrepPathspecs, gitGrepPatterns);
49 } 65 }
50 66
51 String toString() => "Analyze($uris, $exclude)"; 67 String toString() => "Analyze($uris, $exclude)";
52 } 68 }
53 69
54 class AnalyzerDiagnostic { 70 class AnalyzerDiagnostic {
55 final String kind; 71 final String kind;
56 72
57 final String detailedKind; 73 final String detailedKind;
58 74
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 "${kind == 'INFO' ? 'warning: hint' : kind.toLowerCase()}:\n" 135 "${kind == 'INFO' ? 'warning: hint' : kind.toLowerCase()}:\n"
120 "[$code] $message"; 136 "[$code] $message";
121 } 137 }
122 } 138 }
123 139
124 Stream<AnalyzerDiagnostic> parseAnalyzerOutput( 140 Stream<AnalyzerDiagnostic> parseAnalyzerOutput(
125 Stream<List<int>> stream) async* { 141 Stream<List<int>> stream) async* {
126 Stream<String> lines = 142 Stream<String> lines =
127 stream.transform(UTF8.decoder).transform(new LineSplitter()); 143 stream.transform(UTF8.decoder).transform(new LineSplitter());
128 await for (String line in lines) { 144 await for (String line in lines) {
145 if (line.startsWith(">>> ")) continue;
129 yield new AnalyzerDiagnostic.fromLine(line); 146 yield new AnalyzerDiagnostic.fromLine(line);
130 } 147 }
131 } 148 }
132 149
133 /// Run dartanalyzer on all tests in [uris]. 150 /// Run dartanalyzer on all tests in [uris].
134 Future<Null> analyzeUris(Uri analysisOptions, Uri packages, List<Uri> uris, 151 Future<Null> analyzeUris(
135 List<RegExp> exclude) async { 152 Uri analysisOptions,
153 Uri packages,
154 List<Uri> uris,
155 List<RegExp> exclude,
156 List<String> gitGrepPathspecs,
157 List<String> gitGrepPatterns) async {
136 if (uris.isEmpty) return; 158 if (uris.isEmpty) return;
159 String topLevel;
160 try {
161 topLevel = Uri
162 .directory(await git("rev-parse", <String>["--show-toplevel"]))
163 .toFilePath();
164 } catch (e) {
165 topLevel = Uri.base.toFilePath(windows: false);
166 }
167
168 String toFilePath(Uri uri) {
169 String path = uri.toFilePath(windows: false);
170 return path.startsWith(topLevel) ? path.substring(topLevel.length) : path;
171 }
172
173 Set<String> filesToAnalyze = new Set<String>();
174
175 for (Uri uri in uris) {
176 if (await new Directory.fromUri(uri).exists()) {
177 await for (FileSystemEntity entity in new Directory.fromUri(uri)
178 .list(recursive: true, followLinks: false)) {
179 if (entity is File && entity.path.endsWith(".dart")) {
180 filesToAnalyze.add(toFilePath(entity.uri));
181 }
182 }
183 } else if (await new File.fromUri(uri).exists()) {
184 filesToAnalyze.add(toFilePath(uri));
185 } else {
186 throw "File not found: ${uri}";
187 }
188 }
189
190 if (gitGrepPatterns != null) {
191 List<String> arguments = <String>["-l"];
192 arguments.addAll(
193 gitGrepPatterns.expand((String pattern) => <String>["-e", pattern]));
194 arguments.add("--");
195 arguments.addAll(gitGrepPathspecs);
196 filesToAnalyze.addAll(splitLines(await git("grep", arguments))
197 .map((String line) => line.trimRight()));
198 }
199
137 const String analyzerPath = "pkg/analyzer_cli/bin/analyzer.dart"; 200 const String analyzerPath = "pkg/analyzer_cli/bin/analyzer.dart";
138 Uri analyzer = Uri.base.resolve(analyzerPath); 201 Uri analyzer = Uri.base.resolve(analyzerPath);
139 if (!await new File.fromUri(analyzer).exists()) { 202 if (!await new File.fromUri(analyzer).exists()) {
140 throw "Couldn't find '$analyzerPath' in '${Uri.base.toFilePath()}'"; 203 throw "Couldn't find '$analyzerPath' in '${toFilePath(Uri.base)}'";
141 } 204 }
142 List<String> arguments = <String>[ 205 List<String> arguments = <String>[
143 "--packages=${packages.toFilePath()}", 206 "--packages=${toFilePath(packages)}",
144 "--package-warnings",
145 "--format=machine", 207 "--format=machine",
146 "--dart-sdk=${Uri.base.resolve('sdk/').toFilePath()}", 208 "--dart-sdk=${Uri.base.resolve('sdk/').toFilePath()}",
147 ]; 209 ];
148 if (analysisOptions != null) { 210 if (analysisOptions != null) {
149 arguments.add("--options=${analysisOptions.toFilePath()}"); 211 arguments.add("--options=${toFilePath(analysisOptions)}");
150 } 212 }
151 arguments.addAll(uris.map((Uri uri) => uri.toFilePath())); 213
214 filesToAnalyze = filesToAnalyze
215 .where((String path) => !exclude.any((RegExp r) => path.contains(r)))
216 .toSet();
217 arguments.addAll(filesToAnalyze);
152 if (isVerbose) { 218 if (isVerbose) {
153 print("Running:\n ${analyzer.toFilePath()} ${arguments.join(' ')}"); 219 print("Running:\n ${toFilePath(analyzer)} ${arguments.join(' ')}");
154 } else { 220 } else {
155 print("Running dartanalyzer."); 221 print("Running dartanalyzer.");
156 } 222 }
157 Stopwatch sw = new Stopwatch()..start(); 223 Stopwatch sw = new Stopwatch()..start();
158 Process process = await startDart(analyzer, arguments); 224 Process process = await startDart(analyzer, const <String>["--batch"]);
225 process.stdin.writeln(arguments.join(" "));
159 process.stdin.close(); 226 process.stdin.close();
160 Future stdoutFuture = parseAnalyzerOutput(process.stdout).toList(); 227
161 Future stderrFuture = parseAnalyzerOutput(process.stderr).toList();
162 await process.exitCode;
163 List<AnalyzerDiagnostic> diagnostics = <AnalyzerDiagnostic>[];
164 diagnostics.addAll(await stdoutFuture);
165 diagnostics.addAll(await stderrFuture);
166 bool hasOutput = false; 228 bool hasOutput = false;
167 Set<String> seen = new Set<String>(); 229 Set<String> seen = new Set<String>();
168 for (AnalyzerDiagnostic diagnostic in diagnostics) { 230
169 String path = diagnostic.uri?.path; 231 processAnalyzerOutput(Stream<AnalyzerDiagnostic> diagnostics) async {
170 if (path != null && exclude.any((RegExp r) => path.contains(r))) { 232 await for (AnalyzerDiagnostic diagnostic in diagnostics) {
171 continue; 233 if (diagnostic.uri != null) {
172 } 234 String path = toFilePath(diagnostic.uri);
173 String message = "$diagnostic"; 235 if (diagnostic.code.startsWith("STRONG_MODE") &&
174 if (seen.add(message)) { 236 (path.startsWith("pkg/compiler/") ||
175 hasOutput = true; 237 path.startsWith("tests/compiler/dart2js/"))) {
176 print(message); 238 // Hack to work around dart2js not being strong-mode clean.
239 continue;
240 }
241 if (!filesToAnalyze.contains(path)) continue;
242 }
243 String message = "$diagnostic";
244 if (seen.add(message)) {
245 hasOutput = true;
246 print(message);
247 }
177 } 248 }
178 } 249 }
250
251 Future stderrFuture =
252 processAnalyzerOutput(parseAnalyzerOutput(process.stderr));
253 Future stdoutFuture =
254 processAnalyzerOutput(parseAnalyzerOutput(process.stdout));
255 await process.exitCode;
256 await stdoutFuture;
257 await stderrFuture;
258 sw.stop();
259 print("Running analyzer took: ${sw.elapsed}.");
179 if (hasOutput) { 260 if (hasOutput) {
180 throw "Non-empty output from analyzer."; 261 throw "Non-empty output from analyzer.";
181 } 262 }
182 sw.stop();
183 print("Running analyzer took: ${sw.elapsed}.");
184 } 263 }
264
265 Future<String> git(String command, Iterable<String> arguments,
266 {String workingDirectory}) async {
267 ProcessResult result = await Process.run(
268 Platform.isWindows ? "git.bat" : "git",
269 <String>[command]..addAll(arguments),
270 workingDirectory: workingDirectory);
271 if (result.exitCode != 0) {
272 throw "Non-zero exit code from git $command (${result.exitCode})\n"
273 "${result.stdout}\n${result.stderr}";
274 }
275 return result.stdout;
276 }
OLDNEW
« no previous file with comments | « pkg/front_end/test/fasta/testing.json ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698