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

Side by Side Diff: pkg/analyzer/tool/summary/generate.dart

Issue 1576663002: Use FlatBuffers for summaries. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Remove IsSet flags and restore toMap() generation. Created 4 years, 11 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/analyzer/test/src/summary/summary_test.dart ('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) 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 /** 5 /**
6 * This file contains code to generate serialization/deserialization logic for 6 * This file contains code to generate serialization/deserialization logic for
7 * summaries based on an "IDL" description of the summary format (written in 7 * summaries based on an "IDL" description of the summary format (written in
8 * stylized Dart). 8 * stylized Dart).
9 * 9 *
10 * For each class in the "IDL" input, two corresponding classes are generated: 10 * For each class in the "IDL" input, two corresponding classes are generated:
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 checkIdl(); 253 checkIdl();
254 out('// Copyright (c) 2015, the Dart project authors. Please see the AUTHOR S file'); 254 out('// Copyright (c) 2015, the Dart project authors. Please see the AUTHOR S file');
255 out('// for details. All rights reserved. Use of this source code is governe d by a'); 255 out('// for details. All rights reserved. Use of this source code is governe d by a');
256 out('// BSD-style license that can be found in the LICENSE file.'); 256 out('// BSD-style license that can be found in the LICENSE file.');
257 out('//'); 257 out('//');
258 out('// This file has been automatically generated. Please do not edit it m anually.'); 258 out('// This file has been automatically generated. Please do not edit it m anually.');
259 out('// To regenerate the file, use the script "pkg/analyzer/tool/generate_f iles".'); 259 out('// To regenerate the file, use the script "pkg/analyzer/tool/generate_f iles".');
260 out(); 260 out();
261 out('library analyzer.src.summary.format;'); 261 out('library analyzer.src.summary.format;');
262 out(); 262 out();
263 out("import 'dart:convert';");
264 out("import 'base.dart' as base;"); 263 out("import 'base.dart' as base;");
264 out("import 'flat_buffers.dart' as fb;");
265 out(); 265 out();
266 _idl.enums.forEach((String name, idlModel.EnumDeclaration enm) { 266 _idl.enums.forEach((String name, idlModel.EnumDeclaration enm) {
267 outDoc(enm.documentation); 267 outDoc(enm.documentation);
268 out('enum $name {'); 268 out('enum $name {');
269 indent(() { 269 indent(() {
270 for (String value in enm.values) { 270 for (String value in enm.values) {
271 out('$value,'); 271 out('$value,');
272 } 272 }
273 }); 273 });
274 out('}'); 274 out('}');
275 out(); 275 out();
276 }); 276 });
277 _idl.classes.forEach((String name, idlModel.ClassDeclaration cls) { 277 for (var cls in _idl.classes.values) {
278 outDoc(cls.documentation); 278 List<String> builderParams = _generateBuilder(cls);
279 out('class $name extends base.SummaryClass {'); 279 out();
280 indent(() { 280 _generateEncodeFunction(cls, builderParams);
281 for (idlModel.FieldDeclaration field in cls.fields) { 281 out();
282 String fieldName = field.name; 282 _generateInterface(cls);
283 idlModel.FieldType type = field.type; 283 out();
284 out('${dartType(type)} _$fieldName;'); 284 _generateReader(cls);
285 } 285 out();
286 out(); 286 }
287 out('$name.fromJson(Map json)');
288 indent(() {
289 List<String> initializers = <String>[];
290 for (idlModel.FieldDeclaration field in cls.fields) {
291 String fieldName = field.name;
292 idlModel.FieldType type = field.type;
293 String convert = 'json[${quoted(fieldName)}]';
294 if (type.isList) {
295 if (type.typeName == 'int' || type.typeName == 'String') {
296 // No conversion necessary.
297 } else {
298 convert =
299 '$convert?.map((x) => new ${type.typeName}.fromJson(x))?.toL ist()';
300 }
301 } else if (_idl.classes.containsKey(type.typeName)) {
302 convert =
303 '$convert == null ? null : new ${type.typeName}.fromJson($conv ert)';
304 } else if (_idl.enums.containsKey(type.typeName)) {
305 convert =
306 '$convert == null ? null : ${type.typeName}.values[$convert]';
307 }
308 initializers.add('_$fieldName = $convert');
309 }
310 for (int i = 0; i < initializers.length; i++) {
311 String prefix = i == 0 ? ': ' : ' ';
312 String suffix = i == initializers.length - 1 ? ';' : ',';
313 out('$prefix${initializers[i]}$suffix');
314 }
315 });
316 out();
317 out('@override');
318 out('Map<String, Object> toMap() => {');
319 indent(() {
320 for (idlModel.FieldDeclaration field in cls.fields) {
321 String fieldName = field.name;
322 out('${quoted(fieldName)}: $fieldName,');
323 }
324 });
325 out('};');
326 out();
327 if (cls.isTopLevel) {
328 out('$name.fromBuffer(List<int> buffer) : this.fromJson(JSON.decode(UT F8.decode(buffer)));');
329 out();
330 }
331 cls.fields.asMap().forEach((index, field) {
332 String fieldName = field.name;
333 idlModel.FieldType type = field.type;
334 if (index != 0) {
335 out();
336 }
337 String def = defaultValue(type);
338 String defaultSuffix = def == null ? '' : ' ?? $def';
339 outDoc(field.documentation);
340 out('${dartType(type)} get $fieldName => _$fieldName$defaultSuffix;');
341 });
342 });
343 out('}');
344 out();
345 List<String> builderParams = <String>[];
346 out('class ${name}Builder {');
347 indent(() {
348 out('final Map _json = {};');
349 out();
350 out('bool _finished = false;');
351 out();
352 out('${name}Builder(base.BuilderContext context);');
353 for (idlModel.FieldDeclaration field in cls.fields) {
354 String fieldName = field.name;
355 idlModel.FieldType type = field.type;
356 out();
357 outDoc(field.documentation);
358 String conversion = '_value';
359 String condition = '';
360 if (type.isList) {
361 if (_idl.classes.containsKey(type.typeName)) {
362 conversion = '$conversion.map((b) => b.finish()).toList()';
363 } else {
364 conversion = '$conversion.toList()';
365 }
366 condition = ' || _value.isEmpty';
367 } else if (_idl.enums.containsKey(type.typeName)) {
368 conversion = '$conversion.index';
369 condition = ' || _value == ${defaultValue(type)}';
370 } else if (_idl.classes.containsKey(type.typeName)) {
371 conversion = '$conversion.finish()';
372 }
373 builderParams.add('${encodedType(type)} $fieldName');
374 out('void set $fieldName(${encodedType(type)} _value) {');
375 indent(() {
376 out('assert(!_finished);');
377 out('assert(!_json.containsKey(${quoted(fieldName)}));');
378 if (condition.isEmpty) {
379 out('if (_value != null) {');
380 } else {
381 out('if (!(_value == null$condition)) {');
382 }
383 indent(() {
384 out('_json[${quoted(fieldName)}] = $conversion;');
385 });
386 out('}');
387 });
388 out('}');
389 }
390 if (cls.isTopLevel) {
391 out();
392 out('List<int> toBuffer() => UTF8.encode(JSON.encode(finish()));');
393 }
394 out();
395 out('Map finish() {');
396 indent(() {
397 out('assert(!_finished);');
398 out('_finished = true;');
399 out('return _json;');
400 });
401 out('}');
402 });
403 out('}');
404 out();
405 out('${name}Builder encode$name(base.BuilderContext builderContext, {${bui lderParams.join(', ')}}) {');
406 indent(() {
407 out('${name}Builder builder = new ${name}Builder(builderContext);');
408 for (idlModel.FieldDeclaration field in cls.fields) {
409 String fieldName = field.name;
410 out('builder.$fieldName = $fieldName;');
411 }
412 out('return builder;');
413 });
414 out('}');
415 out();
416 });
417 } 287 }
418 288
419 /** 289 /**
420 * Enclose [s] in quotes, escaping as necessary. 290 * Enclose [s] in quotes, escaping as necessary.
421 */ 291 */
422 String quoted(String s) { 292 String quoted(String s) {
423 return JSON.encode(s); 293 return JSON.encode(s);
424 } 294 }
425 295
296 List<String> _generateBuilder(idlModel.ClassDeclaration cls) {
297 String builderName = cls.name + 'Builder';
298 List<String> builderParams = <String>[];
299 out('class $builderName {');
300 indent(() {
301 out('bool _finished = false;');
302 // Generate fields.
303 out();
304 for (idlModel.FieldDeclaration field in cls.fields) {
305 String fieldName = field.name;
306 idlModel.FieldType type = field.type;
307 String typeStr = encodedType(type);
308 out('$typeStr _$fieldName;');
309 }
310 // Generate constructor.
311 out();
312 out('$builderName(base.BuilderContext context);');
313 // Generate setters.
314 for (idlModel.FieldDeclaration field in cls.fields) {
315 String fieldName = field.name;
316 String typeStr = encodedType(field.type);
317 out();
318 outDoc(field.documentation);
319 builderParams.add('$typeStr $fieldName');
320 out('void set $fieldName($typeStr _value) {');
321 indent(() {
322 String stateFieldName = '_' + fieldName;
323 out('assert(!_finished);');
324 out('$stateFieldName = _value;');
325 });
326 out('}');
327 }
328 // Generate finish.
329 if (cls.isTopLevel) {
330 out();
331 out('List<int> toBuffer() {');
332 indent(() {
333 out('fb.Builder fbBuilder = new fb.Builder();');
334 out('return fbBuilder.finish(finish(fbBuilder));');
335 });
336 out('}');
337 }
338 out();
339 out('fb.Offset finish(fb.Builder fbBuilder) {');
340 indent(() {
341 out('assert(!_finished);');
342 out('_finished = true;');
343 // Write objects and remember Offset(s).
344 cls.fields.asMap().forEach((index, idlModel.FieldDeclaration field) {
345 idlModel.FieldType fieldType = field.type;
346 String offsetName = 'offset_' + field.name;
347 if (fieldType.isList ||
348 fieldType.typeName == 'String' ||
349 _idl.classes.containsKey(fieldType.typeName)) {
350 out('fb.Offset $offsetName;');
351 }
352 });
353 cls.fields.asMap().forEach((index, idlModel.FieldDeclaration field) {
354 idlModel.FieldType fieldType = field.type;
355 String valueName = '_' + field.name;
356 String offsetName = 'offset_' + field.name;
357 String condition;
358 String writeCode;
359 if (fieldType.isList) {
360 condition = ' || $valueName.isEmpty';
361 if (_idl.classes.containsKey(fieldType.typeName)) {
362 String itemCode = 'b.finish(fbBuilder)';
363 String listCode = '$valueName.map((b) => $itemCode).toList()';
364 writeCode = '$offsetName = fbBuilder.writeList($listCode);';
365 } else if (fieldType.typeName == 'int') {
366 writeCode = '$offsetName = fbBuilder.writeListInt32($valueName);';
367 } else {
368 assert(fieldType.typeName == 'String');
369 String itemCode = 'fbBuilder.writeString(b)';
370 String listCode = '$valueName.map((b) => $itemCode).toList()';
371 writeCode = '$offsetName = fbBuilder.writeList($listCode);';
372 }
373 } else if (fieldType.typeName == 'String') {
374 writeCode = '$offsetName = fbBuilder.writeString($valueName);';
375 } else if (_idl.classes.containsKey(fieldType.typeName)) {
376 writeCode = '$offsetName = $valueName.finish(fbBuilder);';
377 }
378 if (writeCode != null) {
379 if (condition == null) {
380 out('if ($valueName != null) {');
381 } else {
382 out('if (!($valueName == null$condition)) {');
383 }
384 indent(() {
385 out(writeCode);
386 });
387 out('}');
388 }
389 });
390 // Write the table.
391 out('fbBuilder.startTable();');
392 cls.fields.asMap().forEach((index, idlModel.FieldDeclaration field) {
393 idlModel.FieldType fieldType = field.type;
394 String valueName = '_' + field.name;
395 String condition = '$valueName != null';
396 String writeCode;
397 if (fieldType.isList ||
398 fieldType.typeName == 'String' ||
399 _idl.classes.containsKey(fieldType.typeName)) {
400 String offsetName = 'offset_' + field.name;
401 condition = '$offsetName != null';
402 writeCode = 'fbBuilder.addOffset($index, $offsetName);';
403 } else if (fieldType.typeName == 'bool') {
404 // TODO(scheglov) implement booleans merging?
405 condition = '$valueName == true';
406 writeCode = 'fbBuilder.addInt8($index, 1);';
407 } else if (fieldType.typeName == 'int') {
408 condition += ' && $valueName != ${defaultValue(fieldType)}';
409 writeCode = 'fbBuilder.addInt32($index, $valueName);';
410 } else if (_idl.enums.containsKey(fieldType.typeName)) {
411 condition += ' && $valueName != ${defaultValue(fieldType)}';
412 writeCode = 'fbBuilder.addInt32($index, $valueName.index);';
413 }
414 if (writeCode == null) {
415 throw new UnimplementedError('Writing type ${fieldType.typeName}');
416 }
417 out('if ($condition) {');
418 indent(() {
419 out(writeCode);
420 });
421 out('}');
422 });
423 out('return fbBuilder.endTable();');
424 });
425 out('}');
426 });
427 out('}');
428 return builderParams;
429 }
430
431 void _generateEncodeFunction(
432 idlModel.ClassDeclaration cls, List<String> builderParams) {
433 String className = cls.name;
434 String builderName = className + 'Builder';
435 out('$builderName encode$className(base.BuilderContext builderContext, {${bu ilderParams.join(', ')}}) {');
436 indent(() {
437 out('$builderName builder = new $builderName(builderContext);');
438 for (idlModel.FieldDeclaration field in cls.fields) {
439 String fieldName = field.name;
440 out('builder.$fieldName = $fieldName;');
441 }
442 out('return builder;');
443 });
444 out('}');
445 }
446
447 void _generateInterface(idlModel.ClassDeclaration cls) {
448 String name = cls.name;
449 outDoc(cls.documentation);
450 out('abstract class $name extends base.SummaryClass {');
451 indent(() {
452 if (cls.isTopLevel) {
453 out('factory $name.fromBuffer(List<int> buffer) {');
454 indent(() {
455 out('fb.BufferPointer rootRef = new fb.BufferPointer.fromBytes(buffer) ;');
456 out('return const _${name}Reader().read(rootRef);');
457 });
458 out('}');
459 }
460 cls.fields.asMap().forEach((index, field) {
461 String fieldName = field.name;
462 idlModel.FieldType type = field.type;
463 out();
464 outDoc(field.documentation);
465 out('${dartType(type)} get $fieldName;');
466 });
467 });
468 out('}');
469 }
470
471 void _generateReader(idlModel.ClassDeclaration cls) {
472 String name = cls.name;
473 String readerName = '_${name}Reader';
474 out('class $readerName extends fb.TableReader<$readerName> implements $name {');
475 indent(() {
476 out('final fb.BufferPointer _bp;');
477 out();
478 out('const $readerName([this._bp]);');
479 out();
480 out('@override');
481 out('$readerName createReader(fb.BufferPointer bp) => new $readerName(bp); ');
482 out();
483 // Write toMap().
484 out('@override');
485 out('Map<String, Object> toMap() => {');
486 indent(() {
487 for (idlModel.FieldDeclaration field in cls.fields) {
488 String fieldName = field.name;
489 out('${quoted(fieldName)}: $fieldName,');
490 }
491 });
492 out('};');
493 // Write getters.
494 cls.fields.asMap().forEach((index, field) {
495 String fieldName = field.name;
496 idlModel.FieldType type = field.type;
497 String typeName = type.typeName;
498 // Prepare "readLines" or "readCode" + "def" + "readSuffix"
499 List<String> readLines;
500 String readCode;
501 String def = defaultValue(type);
502 String readSuffix = '';
503 if (type.isList) {
504 if (typeName == 'int') {
505 String itemCode = 'const fb.Int32Reader()';
506 readCode = 'const fb.ListReader<int>($itemCode)';
507 } else if (typeName == 'String') {
508 String itemCode = 'const fb.StringReader()';
509 readCode = 'const fb.ListReader<String>($itemCode)';
510 } else {
511 String itemCode = '$typeName>(const _${typeName}Reader()';
512 readCode = 'const fb.ListReader<$itemCode)';
513 }
514 } else if (typeName == 'bool') {
515 // TODO(scheglov) implement booleans merging?
516 def = '0';
517 readCode = 'const fb.Int8Reader()';
518 readSuffix = ' == 1';
519 } else if (typeName == 'int') {
520 readCode = 'const fb.Int32Reader()';
521 } else if (typeName == 'String') {
522 readCode = 'const fb.StringReader()';
523 } else if (_idl.enums.containsKey(typeName)) {
524 readLines = <String>[
525 'int index = const fb.Int32Reader().vTableGet(_bp, $index, 0);',
526 'return $typeName.values[index];'
527 ];
528 } else if (_idl.classes.containsKey(typeName)) {
529 readCode = 'const _${typeName}Reader()';
530 }
531 assert(readCode != null || readLines != null);
532 // Write the getter implementation.
533 out();
534 out('@override');
535 String returnType = dartType(type);
536 if (readLines != null) {
537 out('$returnType get $fieldName {');
538 indent(() {
539 readLines.forEach(out);
540 });
541 out('}');
542 } else {
543 String expr = '$readCode.vTableGet(_bp, $index, $def)$readSuffix';
544 out('$returnType get $fieldName => $expr;');
545 }
546 });
547 });
548 out('}');
549 }
550
426 /** 551 /**
427 * Return the documentation text of the given [node], or `null` if the [node] 552 * Return the documentation text of the given [node], or `null` if the [node]
428 * does not have a comment. Each line is `\n` separated. 553 * does not have a comment. Each line is `\n` separated.
429 */ 554 */
430 String _getNodeDoc(LineInfo lineInfo, AnnotatedNode node) { 555 String _getNodeDoc(LineInfo lineInfo, AnnotatedNode node) {
431 Comment comment = node.documentationComment; 556 Comment comment = node.documentationComment;
432 if (comment != null && 557 if (comment != null &&
433 comment.isDocumentation && 558 comment.isDocumentation &&
434 comment.tokens.length == 1 && 559 comment.tokens.length == 1 &&
435 comment.tokens.first.type == TokenType.MULTI_LINE_COMMENT) { 560 comment.tokens.first.type == TokenType.MULTI_LINE_COMMENT) {
436 Token token = comment.tokens.first; 561 Token token = comment.tokens.first;
437 int column = lineInfo.getLocation(token.offset).columnNumber; 562 int column = lineInfo.getLocation(token.offset).columnNumber;
438 String indent = ' ' * (column - 1); 563 String indent = ' ' * (column - 1);
439 return token.lexeme.split('\n').map((String line) { 564 return token.lexeme.split('\n').map((String line) {
440 if (line.startsWith(indent)) { 565 if (line.startsWith(indent)) {
441 line = line.substring(indent.length); 566 line = line.substring(indent.length);
442 } 567 }
443 return line; 568 return line;
444 }).join('\n'); 569 }).join('\n');
445 } 570 }
446 return null; 571 return null;
447 } 572 }
448 } 573 }
OLDNEW
« no previous file with comments | « pkg/analyzer/test/src/summary/summary_test.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698