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

Side by Side Diff: lib/info.dart

Issue 1411523003: add a JsonInfoCodec class (Closed) Base URL: git@github.com:dart-lang/dart2js_info.git@master
Patch Set: make accept dynamic Created 5 years, 2 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
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 /// Data produced by dart2js when run with the `--dump-info` flag. 5 /// Data produced by dart2js when run with the `--dump-info` flag.
6 library dart2js_info.info; 6 library dart2js_info.info;
7 7
8 import 'dart:convert';
9
8 import 'src/measurements.dart'; 10 import 'src/measurements.dart';
9 export 'src/measurements.dart'; 11 export 'src/measurements.dart';
10 12
13 part 'json_info_codec.dart';
14
11 /// Common interface to many pieces of information generated by the dart2js 15 /// Common interface to many pieces of information generated by the dart2js
12 /// compiler that are directly associated with an element (compilation unit, 16 /// compiler that are directly associated with an element (compilation unit,
13 /// library, class, function, or field). 17 /// library, class, function, or field).
14 abstract class Info { 18 abstract class Info {
15 /// An identifier for the kind of information. 19 /// An identifier for the kind of information.
16 InfoKind get kind; 20 InfoKind get kind;
17 21
18 /// Name of the element associated with this info. 22 /// Name of the element associated with this info.
19 String name; 23 String name;
20 24
21 /// An id to uniquely identify this info among infos of the same [kind]. 25 /// An id to uniquely identify this info among infos of the same [kind].
22 int get id; 26 int get id;
23 27
24 /// A globally unique id combining [kind] and [id] together. 28 /// A globally unique id combining [kind] and [id] together.
25 String get serializedId; 29 String get serializedId;
26 30
27 /// Id used by the compiler when instrumenting code for code coverage. 31 /// Id used by the compiler when instrumenting code for code coverage.
28 // TODO(sigmund): It would be nice if we could use the same id for 32 // TODO(sigmund): It would be nice if we could use the same id for
29 // serialization and for coverage. Could we unify them? 33 // serialization and for coverage. Could we unify them?
30 String coverageId; 34 String coverageId;
31 35
32 /// Bytes used in the generated code for the corresponding element. 36 /// Bytes used in the generated code for the corresponding element.
33 int size; 37 int size;
34 38
35 /// Info of the enclosing element. 39 /// Info of the enclosing element.
36 Info parent; 40 Info parent;
37 41
38 /// Serializes the information into a JSON format. 42 dynamic accept(InfoVisitor visitor);
39 // TODO(sigmund): refactor and put toJson outside the class, so we can have 2
40 // different serializer/deserializers at once.
41 Map toJson();
42
43 void accept(InfoVisitor visitor);
44 } 43 }
45 44
46 /// Common information used for most kind of elements. 45 /// Common information used for most kind of elements.
47 // TODO(sigmund): add more: 46 // TODO(sigmund): add more:
48 // - inputSize: bytes used in the Dart source program 47 // - inputSize: bytes used in the Dart source program
49 abstract class BasicInfo implements Info { 48 abstract class BasicInfo implements Info {
50 final InfoKind kind; 49 final InfoKind kind;
51 final int id; 50 final int id;
52 String coverageId; 51 String coverageId;
53 int size; 52 int size;
54 Info parent; 53 Info parent;
55 54
56 String get serializedId => '${_kindToString(kind)}/$id'; 55 String get serializedId => '${_kindToString(kind)}/$id';
57 56
58 String name; 57 String name;
59 58
60 /// If using deferred libraries, where the element associated with this info 59 /// If using deferred libraries, where the element associated with this info
61 /// is generated. 60 /// is generated.
62 OutputUnitInfo outputUnit; 61 OutputUnitInfo outputUnit;
63 62
64 BasicInfo(this.kind, this.id, this.name, this.outputUnit, this.size, 63 BasicInfo(this.kind, this.id, this.name, this.outputUnit, this.size,
65 this.coverageId); 64 this.coverageId);
66 65
67 BasicInfo._fromId(String serializedId) 66 BasicInfo._fromId(String serializedId)
68 : kind = _kindFromSerializedId(serializedId), 67 : kind = _kindFromSerializedId(serializedId),
69 id = _idFromSerializedId(serializedId); 68 id = _idFromSerializedId(serializedId);
70 69
71 Map toJson() {
72 var res = {
73 'id': serializedId,
74 'kind': _kindToString(kind),
75 'name': name,
76 'size': size,
77 };
78 // TODO(sigmund): Omit this also when outputUnit.id == 0 (most code is in
79 // the main output unit by default).
80 if (outputUnit != null) res['outputUnit'] = outputUnit.serializedId;
81 if (coverageId != null) res['coverageId'] = coverageId;
82 if (parent != null) res['parent'] = parent.serializedId;
83 return res;
84 }
85
86 String toString() => '$serializedId $name [$size]'; 70 String toString() => '$serializedId $name [$size]';
87 } 71 }
88 72
89 /// Info associated with elements containing executable code (like fields and 73 /// Info associated with elements containing executable code (like fields and
90 /// methods) 74 /// methods)
91 abstract class CodeInfo implements Info { 75 abstract class CodeInfo implements Info {
92 /// How does this function or field depend on others. 76 /// How does this function or field depend on others.
93 final List<DependencyInfo> uses = <DependencyInfo>[]; 77 final List<DependencyInfo> uses = <DependencyInfo>[];
94 } 78 }
95 79
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 127
144 /// Minor version indicating non-breaking changes in the format. A change in 128 /// Minor version indicating non-breaking changes in the format. A change in
145 /// this version number means that the json parsing in this library from a 129 /// this version number means that the json parsing in this library from a
146 /// previous will continue to work after the change. This is typically 130 /// previous will continue to work after the change. This is typically
147 /// increased when adding new entries to the file format. 131 /// increased when adding new entries to the file format.
148 // Note: the dump-info.viewer app was written using a json parser version 3.2. 132 // Note: the dump-info.viewer app was written using a json parser version 3.2.
149 final int minorVersion = 6; 133 final int minorVersion = 6;
150 134
151 AllInfo(); 135 AllInfo();
152 136
153 // TODO(het): Remove this when we have an external InfoCodec, see 137 dynamic accept(InfoVisitor visitor) => visitor.visitAll(this);
154 // https://github.com/dart-lang/dart2js_info/issues/4
155 factory AllInfo.fromJson(Map json) => new _ParseHelper().parseAll(json);
156
157 Map _listAsJsonMap(List<Info> list) {
158 var map = <String, Map>{};
159 for (var info in list) {
160 map['${info.id}'] = info.toJson();
161 }
162 return map;
163 }
164
165 Map _extractHoldingInfo() {
166 var map = <String, List>{};
167 void helper(CodeInfo info) {
168 if (info.uses.isEmpty) return;
169 map[info.serializedId] = info.uses.map((u) => u.toJson()).toList();
170 }
171 functions.forEach(helper);
172 fields.forEach(helper);
173 return map;
174 }
175
176 Map _extractDependencies() {
177 var map = <String, List>{};
178 dependencies.forEach((k, v) {
179 map[k.serializedId] = v.map((i) => i.serializedId).toList();
180 });
181 return map;
182 }
183
184 Map toJson() => {
185 'elements': {
186 'library': _listAsJsonMap(libraries),
187 'class': _listAsJsonMap(classes),
188 'function': _listAsJsonMap(functions),
189 'typedef': _listAsJsonMap(typedefs),
190 'field': _listAsJsonMap(fields),
191 'constant': _listAsJsonMap(constants),
192 },
193 'holding': _extractHoldingInfo(),
194 'dependencies': _extractDependencies(),
195 'outputUnits': outputUnits.map((u) => u.toJson()).toList(),
196 'dump_version': version,
197 'deferredFiles': deferredFiles,
198 'dump_minor_version': '$minorVersion',
199 // TODO(sigmund): change viewer to accept an int?
200 'program': program.toJson(),
201 };
202
203 void accept(InfoVisitor visitor) => visitor.visitAll(this);
204 } 138 }
205 139
206 class ProgramInfo { 140 class ProgramInfo {
207 FunctionInfo entrypoint; 141 FunctionInfo entrypoint;
208 int size; 142 int size;
209 String dart2jsVersion; 143 String dart2jsVersion;
210 DateTime compilationMoment; 144 DateTime compilationMoment;
211 Duration compilationDuration; 145 Duration compilationDuration;
212 // TODO(sigmund): use Duration. 146 // TODO(sigmund): use Duration.
213 int toJsonDuration; 147 int toJsonDuration;
214 int dumpInfoDuration; 148 int dumpInfoDuration;
215 bool noSuchMethodEnabled; 149 bool noSuchMethodEnabled;
216 bool minified; 150 bool minified;
217 151
218 ProgramInfo( 152 ProgramInfo(
219 {this.entrypoint, 153 {this.entrypoint,
220 this.size, 154 this.size,
221 this.dart2jsVersion, 155 this.dart2jsVersion,
222 this.compilationMoment, 156 this.compilationMoment,
223 this.compilationDuration, 157 this.compilationDuration,
224 this.toJsonDuration, 158 this.toJsonDuration,
225 this.dumpInfoDuration, 159 this.dumpInfoDuration,
226 this.noSuchMethodEnabled, 160 this.noSuchMethodEnabled,
227 this.minified}); 161 this.minified});
228 162
229 Map toJson() => { 163 dynamic accept(InfoVisitor visitor) => visitor.visitProgram(this);
230 'entrypoint': entrypoint.serializedId,
231 'size': size,
232 'dart2jsVersion': dart2jsVersion,
233 'compilationMoment': '$compilationMoment',
234 'compilationDuration': '${compilationDuration}',
235 'toJsonDuration': toJsonDuration,
236 'dumpInfoDuration': '$dumpInfoDuration',
237 'noSuchMethodEnabled': noSuchMethodEnabled,
238 'minified': minified,
239 };
240
241 void accept(InfoVisitor visitor) => visitor.visitProgram(this);
242 }
243
244 // TODO(sigmund): add unit tests.
245 class _ParseHelper {
246 Map<String, Info> registry = {};
247
248 AllInfo parseAll(Map json) {
249 var result = new AllInfo();
250 var elements = json['elements'];
251 result.libraries.addAll(elements['library'].values.map(parseLibrary));
252 result.classes.addAll(elements['class'].values.map(parseClass));
253 result.functions.addAll(elements['function'].values.map(parseFunction));
254 result.fields.addAll(elements['field'].values.map(parseField));
255 result.typedefs.addAll(elements['typedef'].values.map(parseTypedef));
256
257 // TODO(sigmund): remove null check on next breaking version
258 var constants = elements['constant'];
259 if (constants != null) {
260 result.constants.addAll(constants.values.map(parseConstant));
261 }
262
263 var idMap = {};
264 for (var f in result.functions) {
265 idMap[f.serializedId] = f;
266 }
267 for (var f in result.fields) {
268 idMap[f.serializedId] = f;
269 }
270
271 json['holding'].forEach((k, deps) {
272 var src = idMap[k];
273 assert(src != null);
274 for (var dep in deps) {
275 var target = idMap[dep['id']];
276 assert(target != null);
277 src.uses.add(new DependencyInfo(target, dep['mask']));
278 }
279 });
280
281 json['dependencies']?.forEach((k, deps) {
282 result.dependencies[idMap[k]] = deps.map((d) => idMap[d]).toList();
283 });
284
285 result.program = parseProgram(json['program']);
286 // todo: version, etc
287 return result;
288 }
289
290 LibraryInfo parseLibrary(Map json) {
291 LibraryInfo result = parseId(json['id']);
292 result
293 ..name = json['name']
294 ..uri = Uri.parse(json['canonicalUri'])
295 ..outputUnit = parseId(json['outputUnit'])
296 ..size = json['size'];
297 for (var child in json['children'].map(parseId)) {
298 if (child is FunctionInfo) {
299 result.topLevelFunctions.add(child);
300 } else if (child is FieldInfo) {
301 result.topLevelVariables.add(child);
302 } else if (child is ClassInfo) {
303 result.classes.add(child);
304 } else {
305 assert(child is TypedefInfo);
306 result.typedefs.add(child);
307 }
308 }
309 return result;
310 }
311
312 ClassInfo parseClass(Map json) {
313 ClassInfo result = parseId(json['id']);
314 result
315 ..name = json['name']
316 ..parent = parseId(json['parent'])
317 ..outputUnit = parseId(json['outputUnit'])
318 ..size = json['size']
319 ..isAbstract = json['modifiers']['abstract'] == true;
320 assert(result is ClassInfo);
321 for (var child in json['children'].map(parseId)) {
322 if (child is FunctionInfo) {
323 result.functions.add(child);
324 } else {
325 assert(child is FieldInfo);
326 result.fields.add(child);
327 }
328 }
329 return result;
330 }
331
332 FieldInfo parseField(Map json) {
333 FieldInfo result = parseId(json['id']);
334 return result
335 ..name = json['name']
336 ..parent = parseId(json['parent'])
337 ..coverageId = json['coverageId']
338 ..outputUnit = parseId(json['outputUnit'])
339 ..size = json['size']
340 ..type = json['type']
341 ..inferredType = json['inferredType']
342 ..code = json['code']
343 ..isConst = json['const'] ?? false
344 ..initializer = parseId(json['initializer'])
345 ..closures = json['children'].map(parseId).toList();
346 }
347
348 ConstantInfo parseConstant(Map json) {
349 ConstantInfo result = parseId(json['id']);
350 return result
351 ..code = json['code']
352 ..size = json['size'];
353 }
354
355 TypedefInfo parseTypedef(Map json) {
356 TypedefInfo result = parseId(json['id']);
357 return result
358 ..name = json['name']
359 ..parent = parseId(json['parent'])
360 ..type = json['type']
361 ..size = 0;
362 }
363
364 ProgramInfo parseProgram(Map json) => new ProgramInfo()
365 ..size = json['size']
366 ..entrypoint = parseId(json['entrypoint']);
367
368 FunctionInfo parseFunction(Map json) {
369 FunctionInfo result = parseId(json['id']);
370 return result
371 ..name = json['name']
372 ..parent = parseId(json['parent'])
373 ..coverageId = json['coverageId']
374 ..outputUnit = parseId(json['outputUnit'])
375 ..size = json['size']
376 ..type = json['type']
377 ..returnType = json['returnType']
378 ..inferredReturnType = json['inferredReturnType']
379 ..parameters = json['parameters'].map(parseParameter).toList()
380 ..code = json['code']
381 ..sideEffects = json['sideEffects']
382 ..modifiers = parseModifiers(json['modifiers'])
383 ..closures = json['children'].map(parseId).toList()
384 ..measurements = parseMeasurements(json['measurements']);
385 }
386
387 ParameterInfo parseParameter(Map json) =>
388 new ParameterInfo(json['name'], json['type'], json['declaredType']);
389
390 Measurements parseMeasurements(Map json) {
391 if (json == null) return null;
392 var uri = json['sourceFile'];
393 var res = new Measurements(uri == null ? null : Uri.parse(uri));
394 for (var key in json.keys) {
395 var value = json[key];
396 if (value == null) continue;
397 if (key == 'entries') {
398 value.forEach((metricName, entries) {
399 var metric = Metric.fromJson(metricName);
400 for (var i = 0; i < entries.length; i += 2) {
401 res.record(metric, entries[i], entries[i + 1]);
402 }
403 });
404 } else {
405 res.counters[Metric.fromJson(key)] = value;
406 }
407 }
408 return res;
409 }
410
411 FunctionModifiers parseModifiers(Map<String, bool> json) {
412 return new FunctionModifiers(
413 isStatic: json['static'] == true,
414 isConst: json['const'] == true,
415 isFactory: json['factory'] == true,
416 isExternal: json['external'] == true);
417 }
418
419 Info parseId(String serializedId) => registry.putIfAbsent(serializedId, () {
420 if (serializedId == null) {
421 return null;
422 } else if (serializedId.startsWith('function/')) {
423 return new FunctionInfo._(serializedId);
424 } else if (serializedId.startsWith('library/')) {
425 return new LibraryInfo._(serializedId);
426 } else if (serializedId.startsWith('class/')) {
427 return new ClassInfo._(serializedId);
428 } else if (serializedId.startsWith('field/')) {
429 return new FieldInfo._(serializedId);
430 } else if (serializedId.startsWith('constant/')) {
431 return new ConstantInfo._(serializedId);
432 } else if (serializedId.startsWith('typedef/')) {
433 return new TypedefInfo._(serializedId);
434 } else if (serializedId.startsWith('outputUnit/')) {
435 return new OutputUnitInfo._(serializedId);
436 }
437 assert(false);
438 });
439 } 164 }
440 165
441 /// Info associated with a library element. 166 /// Info associated with a library element.
442 class LibraryInfo extends BasicInfo { 167 class LibraryInfo extends BasicInfo {
443 /// Canonical uri that identifies the library. 168 /// Canonical uri that identifies the library.
444 Uri uri; 169 Uri uri;
445 170
446 /// Top level functions defined within the library. 171 /// Top level functions defined within the library.
447 final List<FunctionInfo> topLevelFunctions = <FunctionInfo>[]; 172 final List<FunctionInfo> topLevelFunctions = <FunctionInfo>[];
448 173
(...skipping 14 matching lines...) Expand all
463 188
464 /// Whether there is any information recorded for this library. 189 /// Whether there is any information recorded for this library.
465 bool get isEmpty => 190 bool get isEmpty =>
466 topLevelFunctions.isEmpty && topLevelVariables.isEmpty && classes.isEmpty; 191 topLevelFunctions.isEmpty && topLevelVariables.isEmpty && classes.isEmpty;
467 192
468 LibraryInfo(String name, this.uri, OutputUnitInfo outputUnit, int size) 193 LibraryInfo(String name, this.uri, OutputUnitInfo outputUnit, int size)
469 : super(InfoKind.library, _id++, name, outputUnit, size, null); 194 : super(InfoKind.library, _id++, name, outputUnit, size, null);
470 195
471 LibraryInfo._(String serializedId) : super._fromId(serializedId); 196 LibraryInfo._(String serializedId) : super._fromId(serializedId);
472 197
473 Map toJson() => super.toJson() 198 dynamic accept(InfoVisitor visitor) => visitor.visitLibrary(this);
474 ..addAll({
475 'children': []
476 ..addAll(topLevelFunctions.map((f) => f.serializedId))
477 ..addAll(topLevelVariables.map((v) => v.serializedId))
478 ..addAll(classes.map((c) => c.serializedId))
479 ..addAll(typedefs.map((t) => t.serializedId)),
480 'canonicalUri': '$uri',
481 });
482
483 void accept(InfoVisitor visitor) => visitor.visitLibrary(this);
484 } 199 }
485 200
486 /// Information about an output unit. Normally there is just one for the entire 201 /// Information about an output unit. Normally there is just one for the entire
487 /// program unless the application uses deferred imports, in which case there 202 /// program unless the application uses deferred imports, in which case there
488 /// would be an additional output unit per deferred chunk. 203 /// would be an additional output unit per deferred chunk.
489 class OutputUnitInfo extends BasicInfo { 204 class OutputUnitInfo extends BasicInfo {
490 static int _ids = 0; 205 static int _ids = 0;
491 OutputUnitInfo(String name, int size) 206 OutputUnitInfo(String name, int size)
492 : super(InfoKind.outputUnit, _ids++, name, null, size, null); 207 : super(InfoKind.outputUnit, _ids++, name, null, size, null);
493 208
494 OutputUnitInfo._(String serializedId) : super._fromId(serializedId); 209 OutputUnitInfo._(String serializedId) : super._fromId(serializedId);
495 210
496 void accept(InfoVisitor visitor) => visitor.visitOutput(this); 211 dynamic accept(InfoVisitor visitor) => visitor.visitOutput(this);
497 } 212 }
498 213
499 /// Information about a class element. 214 /// Information about a class element.
500 class ClassInfo extends BasicInfo { 215 class ClassInfo extends BasicInfo {
501 /// Whether the class is abstract. 216 /// Whether the class is abstract.
502 bool isAbstract; 217 bool isAbstract;
503 218
504 // TODO(sigmund): split static vs instance vs closures 219 // TODO(sigmund): split static vs instance vs closures
505 /// Functions (static or instance) defined in the class. 220 /// Functions (static or instance) defined in the class.
506 final List<FunctionInfo> functions = <FunctionInfo>[]; 221 final List<FunctionInfo> functions = <FunctionInfo>[];
507 222
508 /// Fields defined in the class. 223 /// Fields defined in the class.
509 // TODO(sigmund): currently appears to only be populated with instance fields, 224 // TODO(sigmund): currently appears to only be populated with instance fields,
510 // but this should be fixed. 225 // but this should be fixed.
511 final List<FieldInfo> fields = <FieldInfo>[]; 226 final List<FieldInfo> fields = <FieldInfo>[];
512 static int _ids = 0; 227 static int _ids = 0;
513 228
514 ClassInfo( 229 ClassInfo(
515 {String name, this.isAbstract, OutputUnitInfo outputUnit, int size: 0}) 230 {String name, this.isAbstract, OutputUnitInfo outputUnit, int size: 0})
516 : super(InfoKind.clazz, _ids++, name, outputUnit, size, null); 231 : super(InfoKind.clazz, _ids++, name, outputUnit, size, null);
517 232
518 ClassInfo._(String serializedId) : super._fromId(serializedId); 233 ClassInfo._(String serializedId) : super._fromId(serializedId);
519 234
520 Map toJson() => super.toJson() 235 dynamic accept(InfoVisitor visitor) => visitor.visitClass(this);
521 ..addAll({
522 // TODO(sigmund): change format, include only when abstract is true.
523 'modifiers': {'abstract': isAbstract},
524 'children': []
525 ..addAll(fields.map((f) => f.serializedId))
526 ..addAll(functions.map((m) => m.serializedId))
527 });
528
529 void accept(InfoVisitor visitor) => visitor.visitClass(this);
530 } 236 }
531 237
532 /// Information about a constant value. 238 /// Information about a constant value.
533 // TODO(sigmund): add dependency data for ConstantInfo 239 // TODO(sigmund): add dependency data for ConstantInfo
534 class ConstantInfo extends BasicInfo { 240 class ConstantInfo extends BasicInfo {
535 /// The actual generated code for the constant. 241 /// The actual generated code for the constant.
536 String code; 242 String code;
537 243
538 static int _ids = 0; 244 static int _ids = 0;
539 // TODO(sigmund): Add coverage support to constants? 245 // TODO(sigmund): Add coverage support to constants?
540 ConstantInfo({int size: 0, this.code, OutputUnitInfo outputUnit}) 246 ConstantInfo({int size: 0, this.code, OutputUnitInfo outputUnit})
541 : super(InfoKind.constant, _ids++, null, outputUnit, size, null); 247 : super(InfoKind.constant, _ids++, null, outputUnit, size, null);
542 248
543 ConstantInfo._(String serializedId) : super._fromId(serializedId); 249 ConstantInfo._(String serializedId) : super._fromId(serializedId);
544 250
545 Map toJson() => super.toJson()..addAll({'code': code}); 251 dynamic accept(InfoVisitor visitor) => visitor.visitConstant(this);
546
547 void accept(InfoVisitor visitor) => visitor.visitConstant(this);
548 } 252 }
549 253
550 /// Information about a field element. 254 /// Information about a field element.
551 class FieldInfo extends BasicInfo with CodeInfo { 255 class FieldInfo extends BasicInfo with CodeInfo {
552 /// The type of the field. 256 /// The type of the field.
553 String type; 257 String type;
554 258
555 /// The type inferred by dart2js's whole program analysis 259 /// The type inferred by dart2js's whole program analysis
556 String inferredType; 260 String inferredType;
557 261
(...skipping 17 matching lines...) Expand all
575 this.type, 279 this.type,
576 this.inferredType, 280 this.inferredType,
577 this.closures, 281 this.closures,
578 this.code, 282 this.code,
579 OutputUnitInfo outputUnit, 283 OutputUnitInfo outputUnit,
580 this.isConst}) 284 this.isConst})
581 : super(InfoKind.field, _ids++, name, outputUnit, size, coverageId); 285 : super(InfoKind.field, _ids++, name, outputUnit, size, coverageId);
582 286
583 FieldInfo._(String serializedId) : super._fromId(serializedId); 287 FieldInfo._(String serializedId) : super._fromId(serializedId);
584 288
585 Map toJson() { 289 dynamic accept(InfoVisitor visitor) => visitor.visitField(this);
586 var result = super.toJson()
587 ..addAll({
588 'children': closures.map((i) => i.serializedId).toList(),
589 'inferredType': inferredType,
590 'code': code,
591 'type': type,
592 });
593 if (isConst) {
594 result['const'] = true;
595 if (initializer != null) result['initializer'] = initializer.serializedId;
596 }
597 return result;
598 }
599
600 void accept(InfoVisitor visitor) => visitor.visitField(this);
601 } 290 }
602 291
603 /// Information about a typedef declaration. 292 /// Information about a typedef declaration.
604 class TypedefInfo extends BasicInfo { 293 class TypedefInfo extends BasicInfo {
605 /// The declared type. 294 /// The declared type.
606 String type; 295 String type;
607 296
608 static int _ids = 0; 297 static int _ids = 0;
609 TypedefInfo(String name, this.type, OutputUnitInfo outputUnit) 298 TypedefInfo(String name, this.type, OutputUnitInfo outputUnit)
610 : super(InfoKind.typedef, _ids++, name, outputUnit, 0, null); 299 : super(InfoKind.typedef, _ids++, name, outputUnit, 0, null);
611 300
612 TypedefInfo._(String serializedId) : super._fromId(serializedId); 301 TypedefInfo._(String serializedId) : super._fromId(serializedId);
613 302
614 Map toJson() => super.toJson()..['type'] = '$type'; 303 dynamic accept(InfoVisitor visitor) => visitor.visitTypedef(this);
615
616 void accept(InfoVisitor visitor) => visitor.visitTypedef(this);
617 } 304 }
618 305
619 /// Information about a function or method. 306 /// Information about a function or method.
620 class FunctionInfo extends BasicInfo with CodeInfo { 307 class FunctionInfo extends BasicInfo with CodeInfo {
621 static const int TOP_LEVEL_FUNCTION_KIND = 0; 308 static const int TOP_LEVEL_FUNCTION_KIND = 0;
622 static const int CLOSURE_FUNCTION_KIND = 1; 309 static const int CLOSURE_FUNCTION_KIND = 1;
623 static const int METHOD_FUNCTION_KIND = 2; 310 static const int METHOD_FUNCTION_KIND = 2;
624 static const int CONSTRUCTOR_FUNCTION_KIND = 3; 311 static const int CONSTRUCTOR_FUNCTION_KIND = 3;
625 static int _ids = 0; 312 static int _ids = 0;
626 313
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
671 this.inferredReturnType, 358 this.inferredReturnType,
672 this.parameters, 359 this.parameters,
673 this.sideEffects, 360 this.sideEffects,
674 this.inlinedCount, 361 this.inlinedCount,
675 this.code, 362 this.code,
676 this.measurements}) 363 this.measurements})
677 : super(InfoKind.function, _ids++, name, outputUnit, size, coverageId); 364 : super(InfoKind.function, _ids++, name, outputUnit, size, coverageId);
678 365
679 FunctionInfo._(String serializedId) : super._fromId(serializedId); 366 FunctionInfo._(String serializedId) : super._fromId(serializedId);
680 367
681 Map toJson() => super.toJson() 368 dynamic accept(InfoVisitor visitor) => visitor.visitFunction(this);
682 ..addAll({
683 'children': closures.map((i) => i.serializedId).toList(),
684 'modifiers': modifiers.toJson(),
685 'returnType': returnType,
686 'inferredReturnType': inferredReturnType,
687 'parameters': parameters.map((p) => p.toJson()).toList(),
688 'sideEffects': sideEffects,
689 'inlinedCount': inlinedCount,
690 'code': code,
691 'type': type,
692 'measurements': measurements?.toJson(),
693 // Note: version 3.2 of dump-info serializes `uses` in a section called
694 // `holding` at the top-level.
695 });
696
697 void accept(InfoVisitor visitor) => visitor.visitFunction(this);
698 } 369 }
699 370
700 /// Information about how a dependency is used. 371 /// Information about how a dependency is used.
701 class DependencyInfo { 372 class DependencyInfo {
702 /// The dependency, either a FunctionInfo or FieldInfo. 373 /// The dependency, either a FunctionInfo or FieldInfo.
703 final Info target; 374 final Info target;
704 375
705 /// Either a selector mask indicating how this is used, or 'inlined'. 376 /// Either a selector mask indicating how this is used, or 'inlined'.
706 // TODO(sigmund): split mask into an enum or something more precise to really 377 // TODO(sigmund): split mask into an enum or something more precise to really
707 // describe the dependencies in detail. 378 // describe the dependencies in detail.
708 final String mask; 379 final String mask;
709 380
710 DependencyInfo(this.target, this.mask); 381 DependencyInfo(this.target, this.mask);
711
712 Map toJson() => {'id': target.serializedId, 'mask': mask};
713 } 382 }
714 383
715 /// Name and type information about a function parameter. 384 /// Name and type information about a function parameter.
716 class ParameterInfo { 385 class ParameterInfo {
717 final String name; 386 final String name;
718 final String type; 387 final String type;
719 final String declaredType; 388 final String declaredType;
720 389
721 ParameterInfo(this.name, this.type, this.declaredType); 390 ParameterInfo(this.name, this.type, this.declaredType);
722
723 Map toJson() => {'name': name, 'type': type, 'declaredType': declaredType};
724 } 391 }
725 392
726 /// Modifiers that may apply to methods. 393 /// Modifiers that may apply to methods.
727 class FunctionModifiers { 394 class FunctionModifiers {
728 final bool isStatic; 395 final bool isStatic;
729 final bool isConst; 396 final bool isConst;
730 final bool isFactory; 397 final bool isFactory;
731 final bool isExternal; 398 final bool isExternal;
732 399
733 FunctionModifiers( 400 FunctionModifiers(
734 {this.isStatic: false, 401 {this.isStatic: false,
735 this.isConst: false, 402 this.isConst: false,
736 this.isFactory: false, 403 this.isFactory: false,
737 this.isExternal: false}); 404 this.isExternal: false});
738
739 // TODO(sigmund): exclude false values (requires bumping the format version):
740 // Map toJson() {
741 // var res = <String, bool>{};
742 // if (isStatic) res['static'] = true;
743 // if (isConst) res['const'] = true;
744 // if (isFactory) res['factory'] = true;
745 // if (isExternal) res['external'] = true;
746 // return res;
747 // }
748 Map toJson() => {
749 'static': isStatic,
750 'const': isConst,
751 'factory': isFactory,
752 'external': isExternal,
753 };
754 } 405 }
755 406
756 /// Possible values of the `kind` field in the serialied infos. 407 /// Possible values of the `kind` field in the serialied infos.
757 enum InfoKind { 408 enum InfoKind {
758 library, 409 library,
759 clazz, 410 clazz,
760 function, 411 function,
761 field, 412 field,
762 constant, 413 constant,
763 outputUnit, 414 outputUnit,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
806 case 'outputUnit': 457 case 'outputUnit':
807 return InfoKind.outputUnit; 458 return InfoKind.outputUnit;
808 case 'typedef': 459 case 'typedef':
809 return InfoKind.typedef; 460 return InfoKind.typedef;
810 default: 461 default:
811 return null; 462 return null;
812 } 463 }
813 } 464 }
814 465
815 /// A simple visitor for information produced by the dart2js compiler. 466 /// A simple visitor for information produced by the dart2js compiler.
816 class InfoVisitor { 467 abstract class InfoVisitor<T> {
817 visitAll(AllInfo info) {} 468 T visitAll(AllInfo info);
818 visitProgram(ProgramInfo info) {} 469 T visitProgram(ProgramInfo info);
819 visitLibrary(LibraryInfo info) {} 470 T visitLibrary(LibraryInfo info);
820 visitClass(ClassInfo info) {} 471 T visitClass(ClassInfo info);
821 visitField(FieldInfo info) {} 472 T visitField(FieldInfo info);
822 visitConstant(ConstantInfo info) {} 473 T visitConstant(ConstantInfo info);
823 visitFunction(FunctionInfo info) {} 474 T visitFunction(FunctionInfo info);
824 visitTypedef(TypedefInfo info) {} 475 T visitTypedef(TypedefInfo info);
825 visitOutput(OutputUnitInfo info) {} 476 T visitOutput(OutputUnitInfo info);
826 } 477 }
827 478
828 /// A visitor that recursively walks each portion of the program. Because the 479 /// A visitor that recursively walks each portion of the program. Because the
829 /// info representation is redundant, this visitor only walks the structure of 480 /// info representation is redundant, this visitor only walks the structure of
830 /// the program and skips some redundant links. For example, even though 481 /// the program and skips some redundant links. For example, even though
831 /// visitAll contains references to functions, this visitor only recurses to 482 /// visitAll contains references to functions, this visitor only recurses to
832 /// visit libraries, then from each library we visit functions and classes, and 483 /// visit libraries, then from each library we visit functions and classes, and
833 /// so on. 484 /// so on.
834 class RecursiveInfoVisitor extends InfoVisitor { 485 class RecursiveInfoVisitor extends InfoVisitor<Null> {
Siggi Cherem (dart-lang) 2015/10/15 23:36:08 should we add <T> to the recursive visitor as well
Harry Terkelsen 2015/10/15 23:59:55 The default implementation won't work for any T be
835 visitAll(AllInfo info) { 486 visitAll(AllInfo info) {
836 // Note: we don't visit functions, fields, classes, and typedefs because 487 // Note: we don't visit functions, fields, classes, and typedefs because
837 // they are reachable from the library info. 488 // they are reachable from the library info.
838 info.libraries.forEach(visitLibrary); 489 info.libraries.forEach(visitLibrary);
839 info.constants.forEach(visitConstant); 490 info.constants.forEach(visitConstant);
840 } 491 }
841 492
493 visitProgram(ProgramInfo info) {}
494
842 visitLibrary(LibraryInfo info) { 495 visitLibrary(LibraryInfo info) {
843 info.topLevelFunctions.forEach(visitFunction); 496 info.topLevelFunctions.forEach(visitFunction);
844 info.topLevelVariables.forEach(visitField); 497 info.topLevelVariables.forEach(visitField);
845 info.classes.forEach(visitClass); 498 info.classes.forEach(visitClass);
846 info.typedefs.forEach(visitTypedef); 499 info.typedefs.forEach(visitTypedef);
847 } 500 }
848 501
849 visitClass(ClassInfo info) { 502 visitClass(ClassInfo info) {
850 info.functions.forEach(visitFunction); 503 info.functions.forEach(visitFunction);
851 info.fields.forEach(visitField); 504 info.fields.forEach(visitField);
852 } 505 }
853 506
854 visitField(FieldInfo info) { 507 visitField(FieldInfo info) {
855 info.closures.forEach(visitFunction); 508 info.closures.forEach(visitFunction);
856 } 509 }
857 510
511 visitConstant(ConstantInfo info) {}
512
858 visitFunction(FunctionInfo info) { 513 visitFunction(FunctionInfo info) {
859 info.closures.forEach(visitFunction); 514 info.closures.forEach(visitFunction);
860 } 515 }
516
517 visitTypedef(TypedefInfo info) {}
518 visitOutput(OutputUnitInfo info) {}
861 } 519 }
OLDNEW
« no previous file with comments | « bin/verify_deps.dart ('k') | lib/json_info_codec.dart » ('j') | lib/json_info_codec.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698