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

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

Issue 1753883002: Add the ability to deprecate Flatbuffer fields. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 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 | « no previous file | pkg/analyzer/tool/summary/idl_model.dart » ('j') | 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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 final GeneratedFile schemaTarget = 56 final GeneratedFile schemaTarget =
57 new GeneratedFile('lib/src/summary/format.fbs', (String pkgPath) { 57 new GeneratedFile('lib/src/summary/format.fbs', (String pkgPath) {
58 _CodeGenerator codeGenerator = new _CodeGenerator(pkgPath); 58 _CodeGenerator codeGenerator = new _CodeGenerator(pkgPath);
59 codeGenerator.generateFlatBufferSchema(); 59 codeGenerator.generateFlatBufferSchema();
60 return codeGenerator._outBuffer.toString(); 60 return codeGenerator._outBuffer.toString();
61 }); 61 });
62 62
63 typedef String _StringToString(String s); 63 typedef String _StringToString(String s);
64 64
65 class _CodeGenerator { 65 class _CodeGenerator {
66 static const String _throwDeprecated =
67 "throw new UnimplementedError('attempt to access deprecated field')";
68
66 /** 69 /**
67 * Buffer in which generated code is accumulated. 70 * Buffer in which generated code is accumulated.
68 */ 71 */
69 final StringBuffer _outBuffer = new StringBuffer(); 72 final StringBuffer _outBuffer = new StringBuffer();
70 73
71 /** 74 /**
72 * Current indentation level. 75 * Current indentation level.
73 */ 76 */
74 String _indentation = ''; 77 String _indentation = '';
75 78
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 if (type.name.name == 'List' && 273 if (type.name.name == 'List' &&
271 type.typeArguments != null && 274 type.typeArguments != null &&
272 type.typeArguments.arguments.length == 1) { 275 type.typeArguments.arguments.length == 1) {
273 isList = true; 276 isList = true;
274 type = type.typeArguments.arguments[0]; 277 type = type.typeArguments.arguments[0];
275 } 278 }
276 if (type.typeArguments != null) { 279 if (type.typeArguments != null) {
277 throw new Exception('Cannot handle type arguments in `$type`'); 280 throw new Exception('Cannot handle type arguments in `$type`');
278 } 281 }
279 int id; 282 int id;
283 bool isDeprecated = false;
280 for (Annotation annotation in classMember.metadata) { 284 for (Annotation annotation in classMember.metadata) {
281 if (annotation.name.name == 'Id') { 285 if (annotation.name.name == 'Id') {
282 if (id != null) { 286 if (id != null) {
283 throw new Exception( 287 throw new Exception(
284 'Duplicate @id annotation ($classMember)'); 288 'Duplicate @id annotation ($classMember)');
285 } 289 }
286 if (annotation.arguments.arguments.length != 1) { 290 if (annotation.arguments.arguments.length != 1) {
287 throw new Exception( 291 throw new Exception(
288 '@Id must be passed exactly one argument ($desc)'); 292 '@Id must be passed exactly one argument ($desc)');
289 } 293 }
290 Expression expression = annotation.arguments.arguments[0]; 294 Expression expression = annotation.arguments.arguments[0];
291 if (expression is IntegerLiteral) { 295 if (expression is IntegerLiteral) {
292 id = expression.value; 296 id = expression.value;
293 } else { 297 } else {
294 throw new Exception( 298 throw new Exception(
295 '@Id parameter must be an integer literal ($desc)'); 299 '@Id parameter must be an integer literal ($desc)');
296 } 300 }
301 } else if (annotation.name.name == 'deprecated') {
302 if (annotation.arguments != null) {
303 throw new Exception('@deprecated does not take args ($desc)');
304 }
305 isDeprecated = true;
297 } 306 }
298 } 307 }
299 if (id == null) { 308 if (id == null) {
300 throw new Exception('Missing @id annotation ($desc)'); 309 throw new Exception('Missing @id annotation ($desc)');
301 } 310 }
302 String doc = _getNodeDoc(lineInfo, classMember); 311 String doc = _getNodeDoc(lineInfo, classMember);
303 idlModel.FieldType fieldType = 312 idlModel.FieldType fieldType =
304 new idlModel.FieldType(type.name.name, isList); 313 new idlModel.FieldType(type.name.name, isList);
305 cls.fields.add(new idlModel.FieldDeclaration( 314 cls.allFields.add(new idlModel.FieldDeclaration(
306 doc, classMember.name.name, fieldType, id)); 315 doc, classMember.name.name, fieldType, id, isDeprecated));
307 } else if (classMember is ConstructorDeclaration && 316 } else if (classMember is ConstructorDeclaration &&
308 classMember.name.name == 'fromBuffer') { 317 classMember.name.name == 'fromBuffer') {
309 // Ignore `fromBuffer` declarations; they simply forward to the 318 // Ignore `fromBuffer` declarations; they simply forward to the
310 // read functions generated by [_generateReadFunction]. 319 // read functions generated by [_generateReadFunction].
311 } else { 320 } else {
312 throw new Exception('Unexpected class member `$classMember`'); 321 throw new Exception('Unexpected class member `$classMember`');
313 } 322 }
314 } 323 }
315 } else if (decl is EnumDeclaration) { 324 } else if (decl is EnumDeclaration) {
316 String doc = _getNodeDoc(lineInfo, decl); 325 String doc = _getNodeDoc(lineInfo, decl);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 out('${value.name}$suffix'); 390 out('${value.name}$suffix');
382 } 391 }
383 }); 392 });
384 out('}'); 393 out('}');
385 } 394 }
386 for (idlModel.ClassDeclaration cls in _idl.classes.values) { 395 for (idlModel.ClassDeclaration cls in _idl.classes.values) {
387 out(); 396 out();
388 outDoc(cls.documentation); 397 outDoc(cls.documentation);
389 out('table ${cls.name} {'); 398 out('table ${cls.name} {');
390 indent(() { 399 indent(() {
391 for (int i = 0; i < cls.fields.length; i++) { 400 for (int i = 0; i < cls.allFields.length; i++) {
392 idlModel.FieldDeclaration field = cls.fields[i]; 401 idlModel.FieldDeclaration field = cls.allFields[i];
393 if (i != 0) { 402 if (i != 0) {
394 out(); 403 out();
395 } 404 }
396 outDoc(field.documentation); 405 outDoc(field.documentation);
397 out('${field.name}:${fbsType(field.type)} (id: ${field.id});'); 406 List<String> attributes = <String>['id: ${field.id}'];
407 if (field.isDeprecated) {
408 attributes.add('deprecated');
409 }
410 String attrText = attributes.join(', ');
411 out('${field.name}:${fbsType(field.type)} ($attrText);');
398 } 412 }
399 }); 413 });
400 out('}'); 414 out('}');
401 } 415 }
402 out(); 416 out();
403 // Standard flatbuffers only support one root type. We support multiple 417 // Standard flatbuffers only support one root type. We support multiple
404 // root types. For now work around this by forcing PackageBundle to be the 418 // root types. For now work around this by forcing PackageBundle to be the
405 // root type. TODO(paulberry): come up with a better solution. 419 // root type. TODO(paulberry): come up with a better solution.
406 idlModel.ClassDeclaration rootType = _idl.classes['PackageBundle']; 420 idlModel.ClassDeclaration rootType = _idl.classes['PackageBundle'];
407 out('root_type ${rootType.name};'); 421 out('root_type ${rootType.name};');
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 out('bool _finished = false;'); 531 out('bool _finished = false;');
518 // Generate fields. 532 // Generate fields.
519 out(); 533 out();
520 for (idlModel.FieldDeclaration field in cls.fields) { 534 for (idlModel.FieldDeclaration field in cls.fields) {
521 String fieldName = field.name; 535 String fieldName = field.name;
522 idlModel.FieldType type = field.type; 536 idlModel.FieldType type = field.type;
523 String typeStr = encodedType(type); 537 String typeStr = encodedType(type);
524 out('$typeStr _$fieldName;'); 538 out('$typeStr _$fieldName;');
525 } 539 }
526 // Generate getters and setters. 540 // Generate getters and setters.
527 for (idlModel.FieldDeclaration field in cls.fields) { 541 for (idlModel.FieldDeclaration field in cls.allFields) {
528 String fieldName = field.name; 542 String fieldName = field.name;
529 idlModel.FieldType fieldType = field.type; 543 idlModel.FieldType fieldType = field.type;
530 String typeStr = encodedType(fieldType); 544 String typeStr = encodedType(fieldType);
531 String def = defaultValue(fieldType, true); 545 String def = defaultValue(fieldType, true);
532 String defSuffix = def == null ? '' : ' ??= $def'; 546 String defSuffix = def == null ? '' : ' ??= $def';
533 out(); 547 out();
534 out('@override'); 548 out('@override');
535 out('$typeStr get $fieldName => _$fieldName$defSuffix;'); 549 if (field.isDeprecated) {
536 out(); 550 out('$typeStr get $fieldName => $_throwDeprecated;');
537 outDoc(field.documentation); 551 } else {
538 constructorParams.add('$typeStr $fieldName'); 552 out('$typeStr get $fieldName => _$fieldName$defSuffix;');
539 out('void set $fieldName($typeStr _value) {'); 553 out();
540 indent(() { 554 outDoc(field.documentation);
541 String stateFieldName = '_' + fieldName; 555 constructorParams.add('$typeStr $fieldName');
542 out('assert(!_finished);'); 556 out('void set $fieldName($typeStr _value) {');
543 // Validate that int(s) are non-negative. 557 indent(() {
544 if (fieldType.typeName == 'int') { 558 String stateFieldName = '_' + fieldName;
545 if (!fieldType.isList) { 559 out('assert(!_finished);');
546 out('assert(_value == null || _value >= 0);'); 560 // Validate that int(s) are non-negative.
547 } else { 561 if (fieldType.typeName == 'int') {
548 out('assert(_value == null || _value.every((e) => e >= 0));'); 562 if (!fieldType.isList) {
563 out('assert(_value == null || _value >= 0);');
564 } else {
565 out('assert(_value == null || _value.every((e) => e >= 0));');
566 }
549 } 567 }
550 } 568 // Set the value.
551 // Set the value. 569 out('$stateFieldName = _value;');
552 out('$stateFieldName = _value;'); 570 });
553 }); 571 out('}');
554 out('}'); 572 }
555 } 573 }
556 // Generate constructor. 574 // Generate constructor.
557 out(); 575 out();
558 out('$builderName({${constructorParams.join(', ')}})'); 576 out('$builderName({${constructorParams.join(', ')}})');
559 for (int i = 0; i < cls.fields.length; i++) { 577 List<idlModel.FieldDeclaration> fields = cls.fields.toList();
560 idlModel.FieldDeclaration field = cls.fields[i]; 578 for (int i = 0; i < fields.length; i++) {
579 idlModel.FieldDeclaration field = fields[i];
561 String prefix = i == 0 ? ' : ' : ' '; 580 String prefix = i == 0 ? ' : ' : ' ';
562 String suffix = i == cls.fields.length - 1 ? ';' : ','; 581 String suffix = i == fields.length - 1 ? ';' : ',';
563 out('${prefix}_${field.name} = ${field.name}$suffix'); 582 out('${prefix}_${field.name} = ${field.name}$suffix');
564 } 583 }
565 // Generate finish. 584 // Generate finish.
566 if (cls.isTopLevel) { 585 if (cls.isTopLevel) {
567 out(); 586 out();
568 out('List<int> toBuffer() {'); 587 out('List<int> toBuffer() {');
569 indent(() { 588 indent(() {
570 out('fb.Builder fbBuilder = new fb.Builder();'); 589 out('fb.Builder fbBuilder = new fb.Builder();');
571 String fileId = cls.fileIdentifier == null 590 String fileId = cls.fileIdentifier == null
572 ? '' 591 ? ''
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
707 out(); 726 out();
708 out('$implName(this._bp);'); 727 out('$implName(this._bp);');
709 out(); 728 out();
710 // Write cache fields. 729 // Write cache fields.
711 for (idlModel.FieldDeclaration field in cls.fields) { 730 for (idlModel.FieldDeclaration field in cls.fields) {
712 String returnType = dartType(field.type); 731 String returnType = dartType(field.type);
713 String fieldName = field.name; 732 String fieldName = field.name;
714 out('$returnType _$fieldName;'); 733 out('$returnType _$fieldName;');
715 } 734 }
716 // Write getters. 735 // Write getters.
717 for (idlModel.FieldDeclaration field in cls.fields) { 736 for (idlModel.FieldDeclaration field in cls.allFields) {
718 int index = field.id; 737 int index = field.id;
719 String fieldName = field.name; 738 String fieldName = field.name;
720 idlModel.FieldType type = field.type; 739 idlModel.FieldType type = field.type;
721 String typeName = type.typeName; 740 String typeName = type.typeName;
722 // Prepare "readCode" + "def" 741 // Prepare "readCode" + "def"
723 String readCode; 742 String readCode;
724 String def = defaultValue(type, false); 743 String def = defaultValue(type, false);
725 if (type.isList) { 744 if (type.isList) {
726 if (typeName == 'int') { 745 if (typeName == 'int') {
727 readCode = 'const fb.Uint32ListReader()'; 746 readCode = 'const fb.Uint32ListReader()';
(...skipping 19 matching lines...) Expand all
747 } else if (_idl.enums.containsKey(typeName)) { 766 } else if (_idl.enums.containsKey(typeName)) {
748 readCode = 'const _${typeName}Reader()'; 767 readCode = 'const _${typeName}Reader()';
749 } else if (_idl.classes.containsKey(typeName)) { 768 } else if (_idl.classes.containsKey(typeName)) {
750 readCode = 'const _${typeName}Reader()'; 769 readCode = 'const _${typeName}Reader()';
751 } 770 }
752 assert(readCode != null); 771 assert(readCode != null);
753 // Write the getter implementation. 772 // Write the getter implementation.
754 out(); 773 out();
755 out('@override'); 774 out('@override');
756 String returnType = dartType(type); 775 String returnType = dartType(type);
757 out('$returnType get $fieldName {'); 776 if (field.isDeprecated) {
758 indent(() { 777 out('$returnType get $fieldName => $_throwDeprecated;');
759 String readExpr = '$readCode.vTableGet(_bp, $index, $def)'; 778 } else {
760 out('_$fieldName ??= $readExpr;'); 779 out('$returnType get $fieldName {');
761 out('return _$fieldName;'); 780 indent(() {
762 }); 781 String readExpr = '$readCode.vTableGet(_bp, $index, $def)';
763 out('}'); 782 out('_$fieldName ??= $readExpr;');
783 out('return _$fieldName;');
784 });
785 out('}');
786 }
764 } 787 }
765 }); 788 });
766 out('}'); 789 out('}');
767 } 790 }
768 791
769 void _generateMixin(idlModel.ClassDeclaration cls) { 792 void _generateMixin(idlModel.ClassDeclaration cls) {
770 String name = cls.name; 793 String name = cls.name;
771 String mixinName = '_${name}Mixin'; 794 String mixinName = '_${name}Mixin';
772 out('abstract class $mixinName implements ${idlPrefix(name)} {'); 795 out('abstract class $mixinName implements ${idlPrefix(name)} {');
773 indent(() { 796 indent(() {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
868 return token.lexeme.split('\n').map((String line) { 891 return token.lexeme.split('\n').map((String line) {
869 if (line.startsWith(indent)) { 892 if (line.startsWith(indent)) {
870 line = line.substring(indent.length); 893 line = line.substring(indent.length);
871 } 894 }
872 return line; 895 return line;
873 }).join('\n'); 896 }).join('\n');
874 } 897 }
875 return null; 898 return null;
876 } 899 }
877 } 900 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/tool/summary/idl_model.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698