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

Side by Side Diff: lib/json_info_codec.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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 /// Converters and codecs for converting between JSON and [Info] classes.
6 part of dart2js_info.info;
7
8 // TODO(sigmund): add unit tests.
9 class JsonToInfoConverter extends Converter<Map, AllInfo> {
10 Map<String, Info> registry;
11
12 AllInfo convert(Map json) {
13 registry = <String, Info>{};
14
15 var result = new AllInfo();
16 var elements = json['elements'];
17 result.libraries.addAll(elements['library'].values.map(parseLibrary));
18 result.classes.addAll(elements['class'].values.map(parseClass));
19 result.functions.addAll(elements['function'].values.map(parseFunction));
20 result.fields.addAll(elements['field'].values.map(parseField));
21 result.typedefs.addAll(elements['typedef'].values.map(parseTypedef));
22
23 // TODO(sigmund): remove null check on next breaking version
24 var constants = elements['constant'];
25 if (constants != null) {
26 result.constants.addAll(constants.values.map(parseConstant));
27 }
28
29 var idMap = {};
30 for (var f in result.functions) {
31 idMap[f.serializedId] = f;
32 }
33 for (var f in result.fields) {
34 idMap[f.serializedId] = f;
35 }
36
37 json['holding'].forEach((k, deps) {
38 var src = idMap[k];
39 assert(src != null);
40 for (var dep in deps) {
41 var target = idMap[dep['id']];
42 assert(target != null);
43 src.uses.add(new DependencyInfo(target, dep['mask']));
44 }
45 });
46
47 json['dependencies']?.forEach((k, deps) {
48 result.dependencies[idMap[k]] = deps.map((d) => idMap[d]).toList();
49 });
50
51 result.program = parseProgram(json['program']);
52 // todo: version, etc
53 return result;
54 }
55
56 LibraryInfo parseLibrary(Map json) {
57 LibraryInfo result = parseId(json['id']);
58 result
59 ..name = json['name']
60 ..uri = Uri.parse(json['canonicalUri'])
61 ..outputUnit = parseId(json['outputUnit'])
62 ..size = json['size'];
63 for (var child in json['children'].map(parseId)) {
64 if (child is FunctionInfo) {
65 result.topLevelFunctions.add(child);
66 } else if (child is FieldInfo) {
67 result.topLevelVariables.add(child);
68 } else if (child is ClassInfo) {
69 result.classes.add(child);
70 } else {
71 assert(child is TypedefInfo);
72 result.typedefs.add(child);
73 }
74 }
75 return result;
76 }
77
78 ClassInfo parseClass(Map json) {
79 ClassInfo result = parseId(json['id']);
80 result
81 ..name = json['name']
82 ..parent = parseId(json['parent'])
83 ..outputUnit = parseId(json['outputUnit'])
84 ..size = json['size']
85 ..isAbstract = json['modifiers']['abstract'] == true;
86 assert(result is ClassInfo);
87 for (var child in json['children'].map(parseId)) {
88 if (child is FunctionInfo) {
89 result.functions.add(child);
90 } else {
91 assert(child is FieldInfo);
92 result.fields.add(child);
93 }
94 }
95 return result;
96 }
97
98 FieldInfo parseField(Map json) {
99 FieldInfo result = parseId(json['id']);
100 return result
101 ..name = json['name']
102 ..parent = parseId(json['parent'])
103 ..coverageId = json['coverageId']
104 ..outputUnit = parseId(json['outputUnit'])
105 ..size = json['size']
106 ..type = json['type']
107 ..inferredType = json['inferredType']
108 ..code = json['code']
109 ..isConst = json['const'] ?? false
110 ..initializer = parseId(json['initializer'])
111 ..closures = json['children'].map(parseId).toList();
112 }
113
114 ConstantInfo parseConstant(Map json) {
115 ConstantInfo result = parseId(json['id']);
116 return result
117 ..code = json['code']
118 ..size = json['size'];
119 }
120
121 TypedefInfo parseTypedef(Map json) {
122 TypedefInfo result = parseId(json['id']);
123 return result
124 ..name = json['name']
125 ..parent = parseId(json['parent'])
126 ..type = json['type']
127 ..size = 0;
128 }
129
130 ProgramInfo parseProgram(Map json) => new ProgramInfo()
131 ..size = json['size']
132 ..entrypoint = parseId(json['entrypoint']);
133
134 FunctionInfo parseFunction(Map json) {
135 FunctionInfo result = parseId(json['id']);
136 return result
137 ..name = json['name']
138 ..parent = parseId(json['parent'])
139 ..coverageId = json['coverageId']
140 ..outputUnit = parseId(json['outputUnit'])
141 ..size = json['size']
142 ..type = json['type']
143 ..returnType = json['returnType']
144 ..inferredReturnType = json['inferredReturnType']
145 ..parameters = json['parameters'].map(parseParameter).toList()
146 ..code = json['code']
147 ..sideEffects = json['sideEffects']
148 ..modifiers = parseModifiers(json['modifiers'])
149 ..closures = json['children'].map(parseId).toList()
150 ..measurements = parseMeasurements(json['measurements']);
151 }
152
153 ParameterInfo parseParameter(Map json) =>
154 new ParameterInfo(json['name'], json['type'], json['declaredType']);
155
156 Measurements parseMeasurements(Map json) {
157 if (json == null) return null;
158 var uri = json['sourceFile'];
159 var res = new Measurements(uri == null ? null : Uri.parse(uri));
160 for (var key in json.keys) {
161 var value = json[key];
162 if (value == null) continue;
163 if (key == 'entries') {
164 value.forEach((metricName, entries) {
165 var metric = new Metric.fromName(metricName);
166 for (var i = 0; i < entries.length; i += 2) {
167 res.record(metric, entries[i], entries[i + 1]);
168 }
169 });
170 } else {
171 res.counters[new Metric.fromName(key)] = value;
172 }
173 }
174 return res;
175 }
176
177 FunctionModifiers parseModifiers(Map<String, bool> json) {
178 return new FunctionModifiers(
179 isStatic: json['static'] == true,
180 isConst: json['const'] == true,
181 isFactory: json['factory'] == true,
182 isExternal: json['external'] == true);
183 }
184
185 Info parseId(String serializedId) => registry.putIfAbsent(serializedId, () {
186 if (serializedId == null) {
187 return null;
188 } else if (serializedId.startsWith('function/')) {
189 return new FunctionInfo._(serializedId);
190 } else if (serializedId.startsWith('library/')) {
191 return new LibraryInfo._(serializedId);
192 } else if (serializedId.startsWith('class/')) {
193 return new ClassInfo._(serializedId);
194 } else if (serializedId.startsWith('field/')) {
195 return new FieldInfo._(serializedId);
196 } else if (serializedId.startsWith('constant/')) {
197 return new ConstantInfo._(serializedId);
198 } else if (serializedId.startsWith('typedef/')) {
199 return new TypedefInfo._(serializedId);
200 } else if (serializedId.startsWith('outputUnit/')) {
201 return new OutputUnitInfo._(serializedId);
202 }
203 assert(false);
204 });
205 }
206
207 class InfoToJsonConverter extends Converter<AllInfo, Map>
208 implements InfoVisitor<Map> {
209 Map convert(AllInfo info) => info.accept(this);
210
211 Map _visitList(List<Info> infos) {
212 var map = <String, Map>{};
213 for (var info in infos) {
214 map['${info.id}'] = info.accept(this);
215 }
216 return map;
217 }
218
219 Map _visitAllInfoElements(AllInfo info) {
220 var jsonLibraries = _visitList(info.libraries);
221 var jsonClasses = _visitList(info.classes);
222 var jsonFunctions = _visitList(info.functions);
223 var jsonTypedefs = _visitList(info.typedefs);
224 var jsonFields = _visitList(info.fields);
225 var jsonConstants = _visitList(info.constants);
226 return {
227 'library': jsonLibraries,
228 'class': jsonClasses,
229 'function': jsonFunctions,
230 'typedef': jsonTypedefs,
231 'field': jsonFields,
232 'constant': jsonConstants
233 };
234 }
235
236 Map _visitDependencyInfo(DependencyInfo info) =>
237 {'id': info.target.serializedId, 'mask': info.mask};
238
239 Map _visitAllInfoHolding(AllInfo allInfo) {
240 var map = <String, List>{};
241 void helper(CodeInfo info) {
242 if (info.uses.isEmpty) return;
243 map[info.serializedId] =
244 info.uses.map((u) => _visitDependencyInfo(u)).toList();
245 }
246 allInfo.functions.forEach(helper);
247 allInfo.fields.forEach(helper);
248 return map;
249 }
250
251 Map _visitAllInfoDependencies(AllInfo allInfo) {
252 var map = <String, List>{};
253 allInfo.dependencies.forEach((k, v) {
254 map[k.serializedId] = v.map((i) => i.serializedId).toList();
255 });
256 return map;
257 }
258
259 Map visitAll(AllInfo info) {
260 var elements = _visitAllInfoElements(info);
261 var jsonHolding = _visitAllInfoHolding(info);
262 var jsonDependencies = _visitAllInfoDependencies(info);
263 return {
264 'elements': elements,
265 'holding': jsonHolding,
266 'dependencies': jsonDependencies,
267 'outputUnits': info.outputUnits.map((u) => u.accept(this)).toList(),
268 'dump_version': info.version,
269 'deferredFiles': info.deferredFiles,
270 'dump_minor_version': '${info.minorVersion}',
271 'program': info.program.accept(this)
272 };
273 }
274
275 Map visitProgram(ProgramInfo info) {
276 return {
277 'entrypoint': info.entrypoint.serializedId,
278 'size': info.size,
279 'dart2jsVersion': info.dart2jsVersion,
280 'compilationMoment': '${info.compilationMoment}',
281 'compilationDuration': '${info.compilationDuration}',
282 'toJsonDuration': info.toJsonDuration,
283 'dumpInfoDuration': '${info.dumpInfoDuration}',
284 'noSuchMethodEnabled': info.noSuchMethodEnabled,
285 'minified': info.minified,
286 };
287 }
288
289 Map _visitBasicInfo(BasicInfo info) {
290 var res = {
291 'id': info.serializedId,
292 'kind': _kindToString(info.kind),
293 'name': info.name,
294 'size': info.size,
295 };
296 // TODO(sigmund): Omit this also when outputUnit.id == 0 (most code is in
297 // the main output unit by default).
298 if (info.outputUnit != null) res['outputUnit'] =
299 info.outputUnit.serializedId;
300 if (info.coverageId != null) res['coverageId'] = info.coverageId;
301 if (info.parent != null) res['parent'] = info.parent.serializedId;
302 return res;
303 }
304
305 Map visitLibrary(LibraryInfo info) {
306 return _visitBasicInfo(info)
307 ..addAll({
308 'children': []
309 ..addAll(info.topLevelFunctions.map((f) => f.serializedId))
310 ..addAll(info.topLevelVariables.map((v) => v.serializedId))
311 ..addAll(info.classes.map((c) => c.serializedId))
312 ..addAll(info.typedefs.map((t) => t.serializedId)),
313 'canonicalUri': '${info.uri}',
314 });
315 }
316
317 Map visitClass(ClassInfo info) {
318 return _visitBasicInfo(info)
319 ..addAll({
320 // TODO(sigmund): change format, include only when abstract is true.
321 'modifiers': {'abstract': info.isAbstract},
322 'children': []
323 ..addAll(info.fields.map((f) => f.serializedId))
324 ..addAll(info.functions.map((m) => m.serializedId))
325 });
326 }
327
328 Map visitField(FieldInfo info) {
329 var result = _visitBasicInfo(info)
330 ..addAll({
331 'children': info.closures.map((i) => i.serializedId).toList(),
332 'inferredType': info.inferredType,
333 'code': info.code,
334 'type': info.type,
335 });
336 if (info.isConst) {
337 result['const'] = true;
338 if (info.initializer != null) result['initializer'] =
339 info.initializer.serializedId;
340 }
341 return result;
342 }
343
344 Map visitConstant(ConstantInfo info) =>
345 _visitBasicInfo(info)..addAll({'code': info.code});
346
347 // TODO(sigmund): exclude false values (requires bumping the format version):
348 // var res = <String, bool>{};
349 // if (isStatic) res['static'] = true;
350 // if (isConst) res['const'] = true;
351 // if (isFactory) res['factory'] = true;
352 // if (isExternal) res['external'] = true;
353 // return res;
354 Map _visitFunctionModifiers(FunctionModifiers mods) => {
355 'static': mods.isStatic,
356 'const': mods.isConst,
357 'factory': mods.isFactory,
358 'external': mods.isExternal,
359 };
360
361 Map _visitParameterInfo(ParameterInfo info) =>
362 {'name': info.name, 'type': info.type, 'declaredType': info.declaredType};
363
364 String _visitMetric(Metric metric) => metric.name;
365
366 Map _visitMeasurements(Measurements measurements) {
367 if (measurements == null) return null;
368 var jsonEntries = <String, List<Map>>{};
369 measurements.entries.forEach((metric, values) {
370 jsonEntries[_visitMetric(metric)] =
371 values.expand((e) => [e.begin, e.end]).toList();
372 });
373 var json = {'entries': jsonEntries};
374 // TODO(sigmund): encode uri as an offset of the URIs available in the parts
375 // of the library info.
376 if (measurements.uri != null) json['sourceFile'] = '${measurements.uri}';
377 if (measurements.counters[Metric.functions] != null) {
378 json[_visitMetric(Metric.functions)] =
379 measurements.counters[Metric.functions];
380 }
381 if (measurements.counters[Metric.reachableFunctions] != null) {
382 json[_visitMetric(Metric.reachableFunctions)] =
383 measurements.counters[Metric.reachableFunctions];
384 }
385 return json;
386 }
387
388 Map visitFunction(FunctionInfo info) {
389 return _visitBasicInfo(info)
390 ..addAll({
391 'children': info.closures.map((i) => i.serializedId).toList(),
392 'modifiers': _visitFunctionModifiers(info.modifiers),
393 'returnType': info.returnType,
394 'inferredReturnType': info.inferredReturnType,
395 'parameters':
396 info.parameters.map((p) => _visitParameterInfo(p)).toList(),
397 'sideEffects': info.sideEffects,
398 'inlinedCount': info.inlinedCount,
399 'code': info.code,
400 'type': info.type,
401 'measurements': _visitMeasurements(info.measurements),
402 // Note: version 3.2 of dump-info serializes `uses` in a section called
403 // `holding` at the top-level.
404 });
405 }
406
407 visitTypedef(TypedefInfo info) => _visitBasicInfo(info)..['type'] = info.type;
408
409 visitOutput(OutputUnitInfo info) => _visitBasicInfo(info);
410 }
411
412 class JsonInfoCodec extends Codec<AllInfo, Map> {
Siggi Cherem (dart-lang) 2015/10/15 23:36:08 What are your thoughts on these alternative naming
Harry Terkelsen 2015/10/15 23:59:55 I see what you mean, "info" is not a very meaningf
413 final Converter<AllInfo, Map> encoder = new InfoToJsonConverter();
414 final Converter<Map, AllInfo> decoder = new JsonToInfoConverter();
415 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698