| OLD | NEW |
| 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 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 }); | 274 }); |
| 275 for (var cls in _idl.classes.values) { | 275 for (var cls in _idl.classes.values) { |
| 276 List<String> builderParams = _generateBuilder(cls); | 276 List<String> builderParams = _generateBuilder(cls); |
| 277 out(); | 277 out(); |
| 278 _generateEncodeFunction(cls, builderParams); | 278 _generateEncodeFunction(cls, builderParams); |
| 279 out(); | 279 out(); |
| 280 _generateInterface(cls); | 280 _generateInterface(cls); |
| 281 out(); | 281 out(); |
| 282 _generateReader(cls); | 282 _generateReader(cls); |
| 283 out(); | 283 out(); |
| 284 _generateImpl(cls); |
| 285 out(); |
| 284 } | 286 } |
| 285 } | 287 } |
| 286 | 288 |
| 287 /** | 289 /** |
| 288 * Enclose [s] in quotes, escaping as necessary. | 290 * Enclose [s] in quotes, escaping as necessary. |
| 289 */ | 291 */ |
| 290 String quoted(String s) { | 292 String quoted(String s) { |
| 291 return JSON.encode(s); | 293 return JSON.encode(s); |
| 292 } | 294 } |
| 293 | 295 |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 out('$builderName builder = new $builderName();'); | 436 out('$builderName builder = new $builderName();'); |
| 435 for (idlModel.FieldDeclaration field in cls.fields) { | 437 for (idlModel.FieldDeclaration field in cls.fields) { |
| 436 String fieldName = field.name; | 438 String fieldName = field.name; |
| 437 out('builder.$fieldName = $fieldName;'); | 439 out('builder.$fieldName = $fieldName;'); |
| 438 } | 440 } |
| 439 out('return builder;'); | 441 out('return builder;'); |
| 440 }); | 442 }); |
| 441 out('}'); | 443 out('}'); |
| 442 } | 444 } |
| 443 | 445 |
| 444 void _generateInterface(idlModel.ClassDeclaration cls) { | 446 void _generateImpl(idlModel.ClassDeclaration cls) { |
| 445 String name = cls.name; | 447 String name = cls.name; |
| 446 outDoc(cls.documentation); | 448 String implName = '_${name}Impl'; |
| 447 out('abstract class $name extends base.SummaryClass {'); | 449 out('class $implName implements $name {'); |
| 448 indent(() { | |
| 449 if (cls.isTopLevel) { | |
| 450 out('factory $name.fromBuffer(List<int> buffer) {'); | |
| 451 indent(() { | |
| 452 out('fb.BufferPointer rootRef = new fb.BufferPointer.fromBytes(buffer)
;'); | |
| 453 out('return const _${name}Reader().read(rootRef);'); | |
| 454 }); | |
| 455 out('}'); | |
| 456 } | |
| 457 cls.fields.asMap().forEach((index, field) { | |
| 458 String fieldName = field.name; | |
| 459 idlModel.FieldType type = field.type; | |
| 460 out(); | |
| 461 outDoc(field.documentation); | |
| 462 out('${dartType(type)} get $fieldName;'); | |
| 463 }); | |
| 464 }); | |
| 465 out('}'); | |
| 466 } | |
| 467 | |
| 468 void _generateReader(idlModel.ClassDeclaration cls) { | |
| 469 String name = cls.name; | |
| 470 String readerName = '_${name}Reader'; | |
| 471 out('class $readerName extends fb.TableReader<$readerName> implements $name
{'); | |
| 472 indent(() { | 450 indent(() { |
| 473 out('final fb.BufferPointer _bp;'); | 451 out('final fb.BufferPointer _bp;'); |
| 474 out(); | 452 out(); |
| 475 out('const $readerName([this._bp]);'); | 453 out('$implName(this._bp);'); |
| 476 out(); | 454 out(); |
| 477 out('@override'); | 455 // Write cache fields. |
| 478 out('$readerName createReader(fb.BufferPointer bp) => new $readerName(bp);
'); | 456 for (idlModel.FieldDeclaration field in cls.fields) { |
| 457 String returnType = dartType(field.type); |
| 458 String fieldName = field.name; |
| 459 out('$returnType _$fieldName;'); |
| 460 } |
| 479 out(); | 461 out(); |
| 480 // Write toMap(). | 462 // Write toMap(). |
| 481 out('@override'); | 463 out('@override'); |
| 482 out('Map<String, Object> toMap() => {'); | 464 out('Map<String, Object> toMap() => {'); |
| 483 indent(() { | 465 indent(() { |
| 484 for (idlModel.FieldDeclaration field in cls.fields) { | 466 for (idlModel.FieldDeclaration field in cls.fields) { |
| 485 String fieldName = field.name; | 467 String fieldName = field.name; |
| 486 out('${quoted(fieldName)}: $fieldName,'); | 468 out('${quoted(fieldName)}: $fieldName,'); |
| 487 } | 469 } |
| 488 }); | 470 }); |
| 489 out('};'); | 471 out('};'); |
| 490 // Write getters. | 472 // Write getters. |
| 491 cls.fields.asMap().forEach((index, field) { | 473 cls.fields.asMap().forEach((index, field) { |
| 492 String fieldName = field.name; | 474 String fieldName = field.name; |
| 493 idlModel.FieldType type = field.type; | 475 idlModel.FieldType type = field.type; |
| 494 String typeName = type.typeName; | 476 String typeName = type.typeName; |
| 495 // Prepare "readLines" or "readCode" + "def" + "readSuffix" | 477 // Prepare "readExpr" or "readCode" + "def" |
| 496 List<String> readLines; | 478 String readExpr; |
| 497 String readCode; | 479 String readCode; |
| 498 String def = defaultValue(type); | 480 String def = defaultValue(type); |
| 499 if (type.isList) { | 481 if (type.isList) { |
| 500 if (typeName == 'int') { | 482 if (typeName == 'int') { |
| 501 String itemCode = 'const fb.Int32Reader()'; | 483 String itemCode = 'const fb.Int32Reader()'; |
| 502 readCode = 'const fb.ListReader<int>($itemCode)'; | 484 readCode = 'const fb.ListReader<int>($itemCode)'; |
| 503 } else if (typeName == 'String') { | 485 } else if (typeName == 'String') { |
| 504 String itemCode = 'const fb.StringReader()'; | 486 String itemCode = 'const fb.StringReader()'; |
| 505 readCode = 'const fb.ListReader<String>($itemCode)'; | 487 readCode = 'const fb.ListReader<String>($itemCode)'; |
| 506 } else { | 488 } else { |
| 507 String itemCode = '$typeName>(const _${typeName}Reader()'; | 489 String itemCode = '$typeName>(const _${typeName}Reader()'; |
| 508 readCode = 'const fb.ListReader<$itemCode)'; | 490 readCode = 'const fb.ListReader<$itemCode)'; |
| 509 } | 491 } |
| 510 } else if (typeName == 'bool') { | 492 } else if (typeName == 'bool') { |
| 511 readCode = 'const fb.BoolReader()'; | 493 readCode = 'const fb.BoolReader()'; |
| 512 } else if (typeName == 'int') { | 494 } else if (typeName == 'int') { |
| 513 readCode = 'const fb.Int32Reader()'; | 495 readCode = 'const fb.Int32Reader()'; |
| 514 } else if (typeName == 'String') { | 496 } else if (typeName == 'String') { |
| 515 readCode = 'const fb.StringReader()'; | 497 readCode = 'const fb.StringReader()'; |
| 516 } else if (_idl.enums.containsKey(typeName)) { | 498 } else if (_idl.enums.containsKey(typeName)) { |
| 517 readLines = <String>[ | 499 readExpr = |
| 518 'int index = const fb.Int32Reader().vTableGet(_bp, $index, 0);', | 500 '$typeName.values[const fb.Int32Reader().vTableGet(_bp, $index, 0)
]'; |
| 519 'return $typeName.values[index];' | |
| 520 ]; | |
| 521 } else if (_idl.classes.containsKey(typeName)) { | 501 } else if (_idl.classes.containsKey(typeName)) { |
| 522 readCode = 'const _${typeName}Reader()'; | 502 readCode = 'const _${typeName}Reader()'; |
| 523 } | 503 } |
| 524 assert(readCode != null || readLines != null); | 504 if (readExpr == null) { |
| 505 assert(readCode != null); |
| 506 readExpr = '$readCode.vTableGet(_bp, $index, $def)'; |
| 507 } |
| 525 // Write the getter implementation. | 508 // Write the getter implementation. |
| 526 out(); | 509 out(); |
| 527 out('@override'); | 510 out('@override'); |
| 528 String returnType = dartType(type); | 511 String returnType = dartType(type); |
| 529 if (readLines != null) { | 512 out('$returnType get $fieldName {'); |
| 530 out('$returnType get $fieldName {'); | 513 indent(() { |
| 531 indent(() { | 514 out('_$fieldName ??= $readExpr;'); |
| 532 readLines.forEach(out); | 515 out('return _$fieldName;'); |
| 533 }); | 516 }); |
| 534 out('}'); | 517 out('}'); |
| 535 } else { | |
| 536 String expr = '$readCode.vTableGet(_bp, $index, $def)'; | |
| 537 out('$returnType get $fieldName => $expr;'); | |
| 538 } | |
| 539 }); | 518 }); |
| 540 }); | 519 }); |
| 541 out('}'); | 520 out('}'); |
| 542 } | 521 } |
| 543 | 522 |
| 523 void _generateInterface(idlModel.ClassDeclaration cls) { |
| 524 String name = cls.name; |
| 525 outDoc(cls.documentation); |
| 526 out('abstract class $name extends base.SummaryClass {'); |
| 527 indent(() { |
| 528 if (cls.isTopLevel) { |
| 529 out('factory $name.fromBuffer(List<int> buffer) {'); |
| 530 indent(() { |
| 531 out('fb.BufferPointer rootRef = new fb.BufferPointer.fromBytes(buffer)
;'); |
| 532 out('return const _${name}Reader().read(rootRef);'); |
| 533 }); |
| 534 out('}'); |
| 535 } |
| 536 cls.fields.asMap().forEach((index, field) { |
| 537 String fieldName = field.name; |
| 538 idlModel.FieldType type = field.type; |
| 539 out(); |
| 540 outDoc(field.documentation); |
| 541 out('${dartType(type)} get $fieldName;'); |
| 542 }); |
| 543 }); |
| 544 out('}'); |
| 545 } |
| 546 |
| 547 void _generateReader(idlModel.ClassDeclaration cls) { |
| 548 String name = cls.name; |
| 549 String readerName = '_${name}Reader'; |
| 550 String implName = '_${name}Impl'; |
| 551 out('class $readerName extends fb.TableReader<$implName> {'); |
| 552 indent(() { |
| 553 out('const $readerName();'); |
| 554 out(); |
| 555 out('@override'); |
| 556 out('$implName createObject(fb.BufferPointer bp) => new $implName(bp);'); |
| 557 }); |
| 558 out('}'); |
| 559 } |
| 560 |
| 544 /** | 561 /** |
| 545 * Return the documentation text of the given [node], or `null` if the [node] | 562 * Return the documentation text of the given [node], or `null` if the [node] |
| 546 * does not have a comment. Each line is `\n` separated. | 563 * does not have a comment. Each line is `\n` separated. |
| 547 */ | 564 */ |
| 548 String _getNodeDoc(LineInfo lineInfo, AnnotatedNode node) { | 565 String _getNodeDoc(LineInfo lineInfo, AnnotatedNode node) { |
| 549 Comment comment = node.documentationComment; | 566 Comment comment = node.documentationComment; |
| 550 if (comment != null && | 567 if (comment != null && |
| 551 comment.isDocumentation && | 568 comment.isDocumentation && |
| 552 comment.tokens.length == 1 && | 569 comment.tokens.length == 1 && |
| 553 comment.tokens.first.type == TokenType.MULTI_LINE_COMMENT) { | 570 comment.tokens.first.type == TokenType.MULTI_LINE_COMMENT) { |
| 554 Token token = comment.tokens.first; | 571 Token token = comment.tokens.first; |
| 555 int column = lineInfo.getLocation(token.offset).columnNumber; | 572 int column = lineInfo.getLocation(token.offset).columnNumber; |
| 556 String indent = ' ' * (column - 1); | 573 String indent = ' ' * (column - 1); |
| 557 return token.lexeme.split('\n').map((String line) { | 574 return token.lexeme.split('\n').map((String line) { |
| 558 if (line.startsWith(indent)) { | 575 if (line.startsWith(indent)) { |
| 559 line = line.substring(indent.length); | 576 line = line.substring(indent.length); |
| 560 } | 577 } |
| 561 return line; | 578 return line; |
| 562 }).join('\n'); | 579 }).join('\n'); |
| 563 } | 580 } |
| 564 return null; | 581 return null; |
| 565 } | 582 } |
| 566 } | 583 } |
| OLD | NEW |