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

Side by Side Diff: packages/analyzer/tool/summary/inspect.dart

Issue 2990843002: Removed fixed dependencies (Closed)
Patch Set: Created 3 years, 4 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
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 import 'dart:convert';
6 import 'dart:io';
7 import 'dart:mirrors';
8
9 import 'package:analyzer/src/generated/utilities_dart.dart';
10 import 'package:analyzer/src/summary/base.dart';
11 import 'package:analyzer/src/summary/format.dart';
12 import 'package:analyzer/src/summary/idl.dart';
13 import 'package:args/args.dart';
14
15 main(List<String> args) {
16 ArgParser argParser = new ArgParser()..addFlag('raw');
17 ArgResults argResults = argParser.parse(args);
18 if (argResults.rest.length != 1) {
19 print(argParser.usage);
20 exitCode = 1;
21 return;
22 }
23 String path = argResults.rest[0];
24 List<int> bytes = new File(path).readAsBytesSync();
25 PackageBundle bundle = new PackageBundle.fromBuffer(bytes);
26 SummaryInspector inspector = new SummaryInspector(argResults['raw']);
27 print(inspector.dumpPackageBundle(bundle).join('\n'));
28 }
29
30 const int MAX_LINE_LENGTH = 80;
31
32 /**
33 * Cache used to speed up [isEnum].
34 */
35 Map<Type, bool> _isEnumCache = <Type, bool>{};
36
37 /**
38 * Determine if the given [obj] has an enumerated type.
39 */
40 bool isEnum(Object obj) {
41 return _isEnumCache.putIfAbsent(
42 obj.runtimeType, () => reflect(obj).type.isEnum);
43 }
44
45 /**
46 * Decoded reprensentation of a part of a summary that occupies multiple lines
47 * of output.
48 */
49 class BrokenEntity implements DecodedEntity {
50 final String opener;
51 final Map<String, DecodedEntity> parts;
52 final String closer;
53
54 BrokenEntity(this.opener, this.parts, this.closer);
55
56 @override
57 List<String> getLines() {
58 List<String> result = <String>[opener];
59 bool first = true;
60 for (String key in parts.keys) {
61 if (first) {
62 first = false;
63 } else {
64 result[result.length - 1] += ',';
65 }
66 List<String> subResult = parts[key].getLines();
67 subResult[0] = '$key: ${subResult[0]}';
68 result.addAll(subResult.map((String s) => ' $s'));
69 }
70 result.add(closer);
71 return result;
72 }
73 }
74
75 /**
76 * Decoded representation of a part of a summary.
77 */
78 abstract class DecodedEntity {
79 /**
80 * Create a representation of a part of the summary that consists of a group
81 * of entities (represented by [parts]) contained between [opener] and
82 * [closer].
83 *
84 * If [forceKeys] is `true`, the keys in [parts] will always be shown. If
85 * [forceKeys] is `false`, they keys will only be shown if the output is
86 * broken into multiple lines.
87 */
88 factory DecodedEntity.group(String opener, Map<String, DecodedEntity> parts,
89 String closer, bool forceKeys) {
90 // Attempt to format the entity in a single line; if not bail out and
91 // construct a _BrokenEntity.
92 DecodedEntity bailout() => new BrokenEntity(opener, parts, closer);
93 String short = opener;
94 bool first = true;
95 for (String key in parts.keys) {
96 if (first) {
97 first = false;
98 } else {
99 short += ', ';
100 }
101 DecodedEntity value = parts[key];
102 if (forceKeys) {
103 short += '$key: ';
104 }
105 if (value is UnbrokenEntity) {
106 short += value._s;
107 } else {
108 return bailout();
109 }
110 if (short.length > MAX_LINE_LENGTH) {
111 return bailout();
112 }
113 }
114 return new DecodedEntity.short(short + closer);
115 }
116
117 /**
118 * Create a representation of a part of the summary that is represented by a
119 * single unbroken string.
120 */
121 factory DecodedEntity.short(String s) = UnbrokenEntity;
122
123 /**
124 * Format this entity into a sequence of strings (one per output line).
125 */
126 List<String> getLines();
127 }
128
129 /**
130 * Wrapper around a [LinkedLibrary] and its constituent [UnlinkedUnit]s.
131 */
132 class LibraryWrapper {
133 final LinkedLibrary _linked;
134 final List<UnlinkedUnit> _unlinked;
135
136 LibraryWrapper(this._linked, this._unlinked);
137 }
138
139 /**
140 * Wrapper around a [LinkedReference] and its corresponding [UnlinkedReference].
141 */
142 class ReferenceWrapper {
143 final LinkedReference _linked;
144 final UnlinkedReference _unlinked;
145
146 ReferenceWrapper(this._linked, this._unlinked);
147
148 String get name {
149 if (_linked != null && _linked.name.isNotEmpty) {
150 return _linked.name;
151 } else if (_unlinked != null && _unlinked.name.isNotEmpty) {
152 return _unlinked.name;
153 } else {
154 return '???';
155 }
156 }
157 }
158
159 /**
160 * Instances of [SummaryInspector] are capable of traversing a summary and
161 * converting it to semi-human-readable output.
162 */
163 class SummaryInspector {
164 /**
165 * The dependencies of the library currently being visited.
166 */
167 List<LinkedDependency> _dependencies;
168
169 /**
170 * The references of the unit currently being visited.
171 */
172 List<ReferenceWrapper> _references;
173
174 /**
175 * Indicates whether summary inspection should operate in "raw" mode. In this
176 * mode, the structure of the summary file is not altered for easier
177 * readability; everything is output in exactly the form in which it appears
178 * in the file.
179 */
180 final bool raw;
181
182 SummaryInspector(this.raw);
183
184 /**
185 * Decode the object [obj], which was reached by examining [key] inside
186 * another object.
187 */
188 DecodedEntity decode(Object obj, String key) {
189 if (!raw && obj is PackageBundle) {
190 return decodePackageBundle(obj);
191 }
192 if (obj is LibraryWrapper) {
193 return decodeLibrary(obj);
194 }
195 if (obj is UnitWrapper) {
196 return decodeUnit(obj);
197 }
198 if (obj is ReferenceWrapper) {
199 return decodeReference(obj);
200 }
201 if (obj is DecodedEntity) {
202 return obj;
203 }
204 if (obj is SummaryClass) {
205 Map<String, Object> map = obj.toMap();
206 return decodeMap(map);
207 } else if (obj is List) {
208 Map<String, DecodedEntity> parts = <String, DecodedEntity>{};
209 for (int i = 0; i < obj.length; i++) {
210 parts[i.toString()] = decode(obj[i], key);
211 }
212 return new DecodedEntity.group('[', parts, ']', false);
213 } else if (obj is String) {
214 return new DecodedEntity.short(JSON.encode(obj));
215 } else if (isEnum(obj)) {
216 return new DecodedEntity.short(obj.toString().split('.')[1]);
217 } else if (obj is int &&
218 key == 'dependency' &&
219 _dependencies != null &&
220 obj < _dependencies.length) {
221 return new DecodedEntity.short('$obj (${_dependencies[obj].uri})');
222 } else if (obj is int &&
223 key == 'reference' &&
224 _references != null &&
225 obj < _references.length) {
226 return new DecodedEntity.short('$obj (${_references[obj].name})');
227 } else {
228 return new DecodedEntity.short(obj.toString());
229 }
230 }
231
232 /**
233 * Decode the given [LibraryWrapper].
234 */
235 DecodedEntity decodeLibrary(LibraryWrapper obj) {
236 try {
237 LinkedLibrary linked = obj._linked;
238 List<UnlinkedUnit> unlinked = obj._unlinked;
239 _dependencies = linked.dependencies;
240 Map<String, Object> result = linked.toMap();
241 result.remove('units');
242 result['defining compilation unit'] =
243 new UnitWrapper(linked.units[0], unlinked[0]);
244 for (int i = 1; i < linked.units.length; i++) {
245 String partUri = unlinked[0].publicNamespace.parts[i - 1];
246 result['part ${JSON.encode(partUri)}'] =
247 new UnitWrapper(linked.units[i], unlinked[i]);
248 }
249 return decodeMap(result);
250 } finally {
251 _dependencies = null;
252 }
253 }
254
255 /**
256 * Decode the given [map].
257 */
258 DecodedEntity decodeMap(Map<String, Object> map) {
259 Map<String, DecodedEntity> parts = <String, DecodedEntity>{};
260 map = reorderMap(map);
261 map.forEach((String key, Object value) {
262 if (value is String && value.isEmpty) {
263 return;
264 }
265 if (isEnum(value) && (value as dynamic).index == 0) {
266 return;
267 }
268 if (value is int && value == 0) {
269 return;
270 }
271 if (value is bool && value == false) {
272 return;
273 }
274 if (value == null) {
275 return;
276 }
277 if (value is List) {
278 if (value.isEmpty) {
279 return;
280 }
281 DecodedEntity entity = decode(value, key);
282 if (entity is BrokenEntity) {
283 for (int i = 0; i < value.length; i++) {
284 parts['$key[$i]'] = decode(value[i], key);
285 }
286 return;
287 } else {
288 parts[key] = entity;
289 }
290 }
291 parts[key] = decode(value, key);
292 });
293 return new DecodedEntity.group('{', parts, '}', true);
294 }
295
296 /**
297 * Decode the given [PackageBundle].
298 */
299 DecodedEntity decodePackageBundle(PackageBundle bundle) {
300 Map<String, UnlinkedUnit> units = <String, UnlinkedUnit>{};
301 Set<String> seenUnits = new Set<String>();
302 for (int i = 0; i < bundle.unlinkedUnits.length; i++) {
303 units[bundle.unlinkedUnitUris[i]] = bundle.unlinkedUnits[i];
304 }
305 Map<String, Object> restOfMap = bundle.toMap();
306 Map<String, Object> result = <String, Object>{};
307 result['version'] = new DecodedEntity.short(
308 '${bundle.majorVersion}.${bundle.minorVersion}');
309 restOfMap.remove('majorVersion');
310 restOfMap.remove('minorVersion');
311 result['linkedLibraryUris'] = restOfMap['linkedLibraryUris'];
312 result['unlinkedUnitUris'] = restOfMap['unlinkedUnitUris'];
313 for (int i = 0; i < bundle.linkedLibraries.length; i++) {
314 String libraryUriString = bundle.linkedLibraryUris[i];
315 Uri libraryUri = Uri.parse(libraryUriString);
316 UnlinkedUnit unlinkedDefiningUnit = units[libraryUriString];
317 seenUnits.add(libraryUriString);
318 List<UnlinkedUnit> libraryUnits = <UnlinkedUnit>[unlinkedDefiningUnit];
319 LinkedLibrary linkedLibrary = bundle.linkedLibraries[i];
320 for (int j = 1; j < linkedLibrary.units.length; j++) {
321 String partUriString = resolveRelativeUri(libraryUri,
322 Uri.parse(unlinkedDefiningUnit.publicNamespace.parts[j - 1]))
323 .toString();
324 libraryUnits.add(units[partUriString]);
325 seenUnits.add(partUriString);
326 }
327 result['library ${JSON.encode(libraryUriString)}'] =
328 new LibraryWrapper(linkedLibrary, libraryUnits);
329 }
330 for (String uriString in units.keys) {
331 if (seenUnits.contains(uriString)) {
332 continue;
333 }
334 result['orphan unit ${JSON.encode(uriString)}'] =
335 new UnitWrapper(null, units[uriString]);
336 }
337 restOfMap.remove('linkedLibraries');
338 restOfMap.remove('linkedLibraryUris');
339 restOfMap.remove('unlinkedUnits');
340 restOfMap.remove('unlinkedUnitUris');
341 result.addAll(restOfMap);
342 return decodeMap(result);
343 }
344
345 /**
346 * Decode the given [ReferenceWrapper].
347 */
348 DecodedEntity decodeReference(ReferenceWrapper obj) {
349 Map<String, Object> result = obj._unlinked != null
350 ? obj._unlinked.toMap()
351 : <String, Object>{'linkedOnly': true};
352 if (obj._linked != null) {
353 mergeMaps(result, obj._linked.toMap());
354 }
355 return decodeMap(result);
356 }
357
358 /**
359 * Decode the given [UnitWrapper].
360 */
361 DecodedEntity decodeUnit(UnitWrapper obj) {
362 try {
363 LinkedUnit linked = obj._linked;
364 UnlinkedUnit unlinked = obj._unlinked ?? new UnlinkedUnitBuilder();
365 Map<String, Object> unlinkedMap = unlinked.toMap();
366 Map<String, Object> linkedMap =
367 linked != null ? linked.toMap() : <String, Object>{};
368 Map<String, Object> result = <String, Object>{};
369 List<ReferenceWrapper> references = <ReferenceWrapper>[];
370 int numReferences = linked != null
371 ? linked.references.length
372 : unlinked.references.length;
373 for (int i = 0; i < numReferences; i++) {
374 references.add(new ReferenceWrapper(
375 linked != null ? linked.references[i] : null,
376 i < unlinked.references.length ? unlinked.references[i] : null));
377 }
378 result['references'] = references;
379 _references = references;
380 unlinkedMap.remove('references');
381 linkedMap.remove('references');
382 linkedMap.forEach((String key, Object value) {
383 result['linked $key'] = value;
384 });
385 unlinkedMap.forEach((String key, Object value) {
386 result[key] = value;
387 });
388 return decodeMap(result);
389 } finally {
390 _references = null;
391 }
392 }
393
394 /**
395 * Decode the given [PackageBundle] and dump it to a list of strings.
396 */
397 List<String> dumpPackageBundle(PackageBundle bundle) {
398 DecodedEntity decoded = decode(bundle, 'PackageBundle');
399 return decoded.getLines();
400 }
401
402 /**
403 * Merge the contents of [other] into [result], discarding empty entries.
404 */
405 void mergeMaps(Map<String, Object> result, Map<String, Object> other) {
406 other.forEach((String key, Object value) {
407 if (value is String && value.isEmpty) {
408 return;
409 }
410 if (result.containsKey(key)) {
411 Object oldValue = result[key];
412 if (oldValue is String && oldValue.isEmpty) {
413 result[key] = value;
414 } else {
415 throw new Exception(
416 'Duplicate values for $key: $oldValue and $value');
417 }
418 } else {
419 result[key] = value;
420 }
421 });
422 }
423
424 /**
425 * Reorder [map] for more intuitive display.
426 */
427 Map<String, Object> reorderMap(Map<String, Object> map) {
428 Map<String, Object> result = <String, Object>{};
429 if (map.containsKey('name')) {
430 result['name'] = map['name'];
431 }
432 result.addAll(map);
433 return result;
434 }
435 }
436
437 /**
438 * Decoded reprensentation of a part of a summary that occupies a single line of
439 * output.
440 */
441 class UnbrokenEntity implements DecodedEntity {
442 final String _s;
443
444 UnbrokenEntity(this._s);
445
446 @override
447 List<String> getLines() => <String>[_s];
448 }
449
450 /**
451 * Wrapper around a [LinkedUnit] and its corresponding [UnlinkedUnit].
452 */
453 class UnitWrapper {
454 final LinkedUnit _linked;
455 final UnlinkedUnit _unlinked;
456
457 UnitWrapper(this._linked, this._unlinked);
458 }
OLDNEW
« no previous file with comments | « packages/analyzer/tool/summary/idl_model.dart ('k') | packages/analyzer/tool/summary/stats.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698