OLD | NEW |
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 file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library analyze_helper; | 5 library analyze_helper; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:io'; | 8 import 'dart:io'; |
9 import 'package:compiler/compiler.dart' as api; | 9 import 'package:compiler/compiler.dart' as api; |
10 import 'package:compiler/src/apiimpl.dart'; | 10 import 'package:compiler/src/apiimpl.dart'; |
11 import 'package:compiler/src/commandline_options.dart'; | 11 import 'package:compiler/src/commandline_options.dart'; |
12 import 'package:compiler/src/diagnostics/messages.dart' show | 12 import 'package:compiler/src/diagnostics/messages.dart' |
13 Message, | 13 show Message, MessageKind; |
14 MessageKind; | |
15 import 'package:compiler/src/filenames.dart'; | 14 import 'package:compiler/src/filenames.dart'; |
16 import 'package:compiler/src/options.dart' show | 15 import 'package:compiler/src/options.dart' show CompilerOptions; |
17 CompilerOptions; | |
18 import 'package:compiler/src/source_file_provider.dart'; | 16 import 'package:compiler/src/source_file_provider.dart'; |
19 import 'package:compiler/src/util/uri_extras.dart'; | 17 import 'package:compiler/src/util/uri_extras.dart'; |
20 import 'diagnostic_helper.dart'; | 18 import 'diagnostic_helper.dart'; |
21 | 19 |
22 /// Option for hiding whitelisted messages. | 20 /// Option for hiding whitelisted messages. |
23 const String HIDE_WHITELISTED = '--hide-whitelisted'; | 21 const String HIDE_WHITELISTED = '--hide-whitelisted'; |
24 | 22 |
25 /** | 23 /** |
26 * Map of whitelisted warnings and errors. | 24 * Map of whitelisted warnings and errors. |
27 * | 25 * |
28 * Only add a whitelisting together with a bug report to dartbug.com and add | 26 * Only add a whitelisting together with a bug report to dartbug.com and add |
29 * the bug issue number as a comment on the whitelisting. | 27 * the bug issue number as a comment on the whitelisting. |
30 * | 28 * |
31 * Use an identifiable suffix of the file uri as key. Use a fixed substring of | 29 * Use an identifiable suffix of the file uri as key. Use a fixed substring of |
32 * the error/warning message in the list of whitelistings for each file. | 30 * the error/warning message in the list of whitelistings for each file. |
33 */ | 31 */ |
34 // TODO(johnniwinther): Support canonical URIs as keys and message kinds as | 32 // TODO(johnniwinther): Support canonical URIs as keys and message kinds as |
35 // values. | 33 // values. |
36 | 34 |
37 class CollectingDiagnosticHandler extends FormattingDiagnosticHandler { | 35 class CollectingDiagnosticHandler extends FormattingDiagnosticHandler { |
38 bool hasWarnings = false; | 36 bool hasWarnings = false; |
39 bool hasHint = false; | 37 bool hasHint = false; |
40 bool hasErrors = false; | 38 bool hasErrors = false; |
41 bool lastWasWhitelisted = false; | 39 bool lastWasWhitelisted = false; |
42 bool showWhitelisted = true; | 40 bool showWhitelisted = true; |
43 | 41 |
44 Map<String, Map<dynamic/*String|MessageKind*/, int>> whiteListMap | 42 Map<String, Map<dynamic /*String|MessageKind*/, int>> whiteListMap = |
45 = new Map<String, Map<dynamic/*String|MessageKind*/, int>>(); | 43 new Map<String, Map<dynamic /*String|MessageKind*/, int>>(); |
46 List<MessageKind> skipList; | 44 List<MessageKind> skipList; |
47 List<CollectedMessage> collectedMessages = <CollectedMessage>[]; | 45 List<CollectedMessage> collectedMessages = <CollectedMessage>[]; |
48 | 46 |
49 CollectingDiagnosticHandler( | 47 CollectingDiagnosticHandler( |
50 Map<String, List/*<String|MessageKind>*/> whiteList, | 48 Map<String, List/*<String|MessageKind>*/ > whiteList, |
51 this.skipList, | 49 this.skipList, |
52 SourceFileProvider provider) | 50 SourceFileProvider provider) |
53 : super(provider) { | 51 : super(provider) { |
54 whiteList.forEach((String file, List/*<String|MessageKind>*/ messageParts) { | 52 whiteList.forEach((String file, List/*<String|MessageKind>*/ messageParts) { |
55 var useMap = new Map<dynamic/*String|MessageKind*/, int>(); | 53 var useMap = new Map<dynamic /*String|MessageKind*/, int>(); |
56 for (var messagePart in messageParts) { | 54 for (var messagePart in messageParts) { |
57 useMap[messagePart] = 0; | 55 useMap[messagePart] = 0; |
58 } | 56 } |
59 whiteListMap[file] = useMap; | 57 whiteListMap[file] = useMap; |
60 }); | 58 }); |
61 } | 59 } |
62 | 60 |
63 bool checkResults() { | 61 bool checkResults() { |
64 bool validWhiteListUse = checkWhiteListUse(); | 62 bool validWhiteListUse = checkWhiteListUse(); |
65 reportWhiteListUse(); | 63 reportWhiteListUse(); |
66 reportCollectedMessages(); | 64 reportCollectedMessages(); |
67 return !hasWarnings && !hasHint && !hasErrors && validWhiteListUse; | 65 return !hasWarnings && !hasHint && !hasErrors && validWhiteListUse; |
68 } | 66 } |
69 | 67 |
70 bool checkWhiteListUse() { | 68 bool checkWhiteListUse() { |
71 bool allUsed = true; | 69 bool allUsed = true; |
72 for (String file in whiteListMap.keys) { | 70 for (String file in whiteListMap.keys) { |
73 for (var messagePart in whiteListMap[file].keys) { | 71 for (var messagePart in whiteListMap[file].keys) { |
74 if (whiteListMap[file][messagePart] == 0) { | 72 if (whiteListMap[file][messagePart] == 0) { |
75 print("Whitelisting '$messagePart' is unused in '$file'. " | 73 print("Whitelisting '$messagePart' is unused in '$file'. " |
76 "Remove the whitelisting from the whitelist map."); | 74 "Remove the whitelisting from the whitelist map."); |
77 allUsed = false; | 75 allUsed = false; |
78 } | 76 } |
79 } | 77 } |
80 } | 78 } |
81 return allUsed; | 79 return allUsed; |
82 } | 80 } |
83 | 81 |
84 void reportCollectedMessages() { | 82 void reportCollectedMessages() { |
85 if (collectedMessages.isNotEmpty) { | 83 if (collectedMessages.isNotEmpty) { |
86 print('----------------------------------------------------------------'); | 84 print('----------------------------------------------------------------'); |
87 print('Unexpected messages:'); | 85 print('Unexpected messages:'); |
88 print('----------------------------------------------------------------'); | 86 print('----------------------------------------------------------------'); |
89 for (CollectedMessage message in collectedMessages) { | 87 for (CollectedMessage message in collectedMessages) { |
90 super.report(message.message, message.uri, message.begin, | 88 super.report(message.message, message.uri, message.begin, message.end, |
91 message.end, message.text, message.kind); | 89 message.text, message.kind); |
92 } | 90 } |
93 print('----------------------------------------------------------------'); | 91 print('----------------------------------------------------------------'); |
94 } | 92 } |
95 } | 93 } |
96 | 94 |
97 void reportWhiteListUse() { | 95 void reportWhiteListUse() { |
98 for (String file in whiteListMap.keys) { | 96 for (String file in whiteListMap.keys) { |
99 for (var messagePart in whiteListMap[file].keys) { | 97 for (var messagePart in whiteListMap[file].keys) { |
100 int useCount = whiteListMap[file][messagePart]; | 98 int useCount = whiteListMap[file][messagePart]; |
101 print("Whitelisted message '$messagePart' suppressed $useCount " | 99 print("Whitelisted message '$messagePart' suppressed $useCount " |
102 "time(s) in '$file'."); | 100 "time(s) in '$file'."); |
103 } | 101 } |
104 } | 102 } |
105 } | 103 } |
106 | 104 |
107 bool checkWhiteList(Uri uri, Message message, String text) { | 105 bool checkWhiteList(Uri uri, Message message, String text) { |
108 if (uri == null) { | 106 if (uri == null) { |
109 return false; | 107 return false; |
110 } | 108 } |
111 if (skipList.contains(message.kind)) { | 109 if (skipList.contains(message.kind)) { |
112 return true; | 110 return true; |
(...skipping 14 matching lines...) Expand all Loading... |
127 return true; | 125 return true; |
128 } | 126 } |
129 } | 127 } |
130 } | 128 } |
131 } | 129 } |
132 return false; | 130 return false; |
133 } | 131 } |
134 | 132 |
135 @override | 133 @override |
136 void report(Message message, Uri uri, int begin, int end, String text, | 134 void report(Message message, Uri uri, int begin, int end, String text, |
137 api.Diagnostic kind) { | 135 api.Diagnostic kind) { |
138 if (kind == api.Diagnostic.WARNING) { | 136 if (kind == api.Diagnostic.WARNING) { |
139 if (checkWhiteList(uri, message, text)) { | 137 if (checkWhiteList(uri, message, text)) { |
140 // Suppress whitelisted warnings. | 138 // Suppress whitelisted warnings. |
141 lastWasWhitelisted = true; | 139 lastWasWhitelisted = true; |
142 if (showWhitelisted || verbose) { | 140 if (showWhitelisted || verbose) { |
143 super.report(message, uri, begin, end, text, kind); | 141 super.report(message, uri, begin, end, text, kind); |
144 } | 142 } |
145 return; | 143 return; |
146 } | 144 } |
147 hasWarnings = true; | 145 hasWarnings = true; |
(...skipping 18 matching lines...) Expand all Loading... |
166 } | 164 } |
167 return; | 165 return; |
168 } | 166 } |
169 hasErrors = true; | 167 hasErrors = true; |
170 } | 168 } |
171 if (kind == api.Diagnostic.INFO && lastWasWhitelisted) { | 169 if (kind == api.Diagnostic.INFO && lastWasWhitelisted) { |
172 return; | 170 return; |
173 } | 171 } |
174 lastWasWhitelisted = false; | 172 lastWasWhitelisted = false; |
175 if (kind != api.Diagnostic.VERBOSE_INFO) { | 173 if (kind != api.Diagnostic.VERBOSE_INFO) { |
176 collectedMessages.add(new CollectedMessage( | 174 collectedMessages |
177 message, uri, begin, end, text, kind)); | 175 .add(new CollectedMessage(message, uri, begin, end, text, kind)); |
178 } | 176 } |
179 super.report(message, uri, begin, end, text, kind); | 177 super.report(message, uri, begin, end, text, kind); |
180 } | 178 } |
181 } | 179 } |
182 | 180 |
183 typedef bool CheckResults(CompilerImpl compiler, | 181 typedef bool CheckResults( |
184 CollectingDiagnosticHandler handler); | 182 CompilerImpl compiler, CollectingDiagnosticHandler handler); |
185 | 183 |
186 enum AnalysisMode { | 184 enum AnalysisMode { |
187 /// Analyze all declarations in all libraries in one go. | 185 /// Analyze all declarations in all libraries in one go. |
188 ALL, | 186 ALL, |
| 187 |
189 /// Analyze all declarations in the main library. | 188 /// Analyze all declarations in the main library. |
190 MAIN, | 189 MAIN, |
| 190 |
191 /// Analyze all declarations in the given URIs one at a time. This mode can | 191 /// Analyze all declarations in the given URIs one at a time. This mode can |
192 /// handle URIs for parts (i.e. skips these). | 192 /// handle URIs for parts (i.e. skips these). |
193 URI, | 193 URI, |
| 194 |
194 /// Analyze all declarations reachable from the entry point. | 195 /// Analyze all declarations reachable from the entry point. |
195 TREE_SHAKING, | 196 TREE_SHAKING, |
196 } | 197 } |
197 | 198 |
198 /// Analyzes the file(s) in [uriList] using the provided [mode] and checks that | 199 /// Analyzes the file(s) in [uriList] using the provided [mode] and checks that |
199 /// no messages (errors, warnings or hints) are emitted. | 200 /// no messages (errors, warnings or hints) are emitted. |
200 /// | 201 /// |
201 /// Messages can be generally allowed using [skipList] or on a per-file basis | 202 /// Messages can be generally allowed using [skipList] or on a per-file basis |
202 /// using [whiteList]. | 203 /// using [whiteList]. |
203 Future analyze(List<Uri> uriList, | 204 Future analyze( |
204 Map<String, List/*<String|MessageKind>*/> whiteList, | 205 List<Uri> uriList, Map<String, List/*<String|MessageKind>*/ > whiteList, |
205 {AnalysisMode mode: AnalysisMode.ALL, | 206 {AnalysisMode mode: AnalysisMode.ALL, |
206 CheckResults checkResults, | 207 CheckResults checkResults, |
207 List<String> options: const <String>[], | 208 List<String> options: const <String>[], |
208 List<MessageKind> skipList: const <MessageKind>[]}) async { | 209 List<MessageKind> skipList: const <MessageKind>[]}) async { |
209 String testFileName = | 210 String testFileName = |
210 relativize(Uri.base, Platform.script, Platform.isWindows); | 211 relativize(Uri.base, Platform.script, Platform.isWindows); |
211 | 212 |
212 print(""" | 213 print(""" |
213 | 214 |
214 | 215 |
215 === | 216 === |
216 === NOTE: If this test fails, update [WHITE_LIST] in $testFileName | 217 === NOTE: If this test fails, update [WHITE_LIST] in $testFileName |
217 === | 218 === |
218 | 219 |
219 | 220 |
220 """); | 221 """); |
221 | 222 |
222 var libraryRoot = currentDirectory.resolve('sdk/'); | 223 var libraryRoot = currentDirectory.resolve('sdk/'); |
223 var packageConfig = currentDirectory.resolve('.packages'); | 224 var packageConfig = currentDirectory.resolve('.packages'); |
224 var provider = new CompilerSourceFileProvider(); | 225 var provider = new CompilerSourceFileProvider(); |
225 var handler = new CollectingDiagnosticHandler(whiteList, skipList, provider); | 226 var handler = new CollectingDiagnosticHandler(whiteList, skipList, provider); |
226 options = <String>[Flags.analyzeOnly, '--categories=Client,Server', | 227 options = <String>[ |
227 Flags.showPackageWarnings]..addAll(options); | 228 Flags.analyzeOnly, |
| 229 '--categories=Client,Server', |
| 230 Flags.showPackageWarnings |
| 231 ]..addAll(options); |
228 switch (mode) { | 232 switch (mode) { |
229 case AnalysisMode.URI: | 233 case AnalysisMode.URI: |
230 case AnalysisMode.MAIN: | 234 case AnalysisMode.MAIN: |
231 options.add(Flags.analyzeMain); | 235 options.add(Flags.analyzeMain); |
232 break; | 236 break; |
233 case AnalysisMode.ALL: | 237 case AnalysisMode.ALL: |
234 options.add(Flags.analyzeAll); | 238 options.add(Flags.analyzeAll); |
235 break; | 239 break; |
236 case AnalysisMode.TREE_SHAKING: | 240 case AnalysisMode.TREE_SHAKING: |
237 break; | 241 break; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 if (checkResults != null) { | 283 if (checkResults != null) { |
280 result = checkResults(compiler, handler); | 284 result = checkResults(compiler, handler); |
281 } else { | 285 } else { |
282 result = handler.checkResults(); | 286 result = handler.checkResults(); |
283 } | 287 } |
284 if (!result) { | 288 if (!result) { |
285 print(MESSAGE); | 289 print(MESSAGE); |
286 exit(1); | 290 exit(1); |
287 } | 291 } |
288 } | 292 } |
OLD | NEW |