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

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

Issue 1743713002: Generate a ".fbs" file representing the summary format. (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 | « pkg/analyzer/tool/summary/check_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 20 matching lines...) Expand all
31 import 'package:analyzer/src/dart/scanner/scanner.dart'; 31 import 'package:analyzer/src/dart/scanner/scanner.dart';
32 import 'package:analyzer/src/generated/parser.dart'; 32 import 'package:analyzer/src/generated/parser.dart';
33 import 'package:analyzer/src/generated/source.dart'; 33 import 'package:analyzer/src/generated/source.dart';
34 import 'package:path/path.dart'; 34 import 'package:path/path.dart';
35 35
36 import 'idl_model.dart' as idlModel; 36 import 'idl_model.dart' as idlModel;
37 37
38 main() { 38 main() {
39 String script = Platform.script.toFilePath(windows: Platform.isWindows); 39 String script = Platform.script.toFilePath(windows: Platform.isWindows);
40 String pkgPath = normalize(join(dirname(script), '..', '..')); 40 String pkgPath = normalize(join(dirname(script), '..', '..'));
41 GeneratedContent.generateAll(pkgPath, <GeneratedContent>[target]); 41 GeneratedContent.generateAll(pkgPath, allTargets);
42 } 42 }
43 43
44 final GeneratedFile target = 44 final List<GeneratedContent> allTargets = <GeneratedContent>[
45 formatTarget,
46 schemaTarget
47 ];
48
49 final GeneratedFile formatTarget =
45 new GeneratedFile('lib/src/summary/format.dart', (String pkgPath) { 50 new GeneratedFile('lib/src/summary/format.dart', (String pkgPath) {
46 // Parse the input "IDL" file and pass it to the [_CodeGenerator]. 51 _CodeGenerator codeGenerator = new _CodeGenerator(pkgPath);
47 PhysicalResourceProvider provider = new PhysicalResourceProvider( 52 codeGenerator.generateFormatCode();
48 PhysicalResourceProvider.NORMALIZE_EOL_ALWAYS);
49 String idlPath = join(pkgPath, 'lib', 'src', 'summary', 'idl.dart');
50 File idlFile = provider.getFile(idlPath);
51 Source idlSource = provider.getFile(idlPath).createSource();
52 String idlText = idlFile.readAsStringSync();
53 BooleanErrorListener errorListener = new BooleanErrorListener();
54 CharacterReader idlReader = new CharSequenceReader(idlText);
55 Scanner scanner = new Scanner(idlSource, idlReader, errorListener);
56 Token tokenStream = scanner.tokenize();
57 LineInfo lineInfo = new LineInfo(scanner.lineStarts);
58 Parser parser = new Parser(idlSource, new BooleanErrorListener());
59 CompilationUnit idlParsed = parser.parseCompilationUnit(tokenStream);
60 _CodeGenerator codeGenerator = new _CodeGenerator();
61 codeGenerator.processCompilationUnit(lineInfo, idlParsed);
62 return codeGenerator._outBuffer.toString(); 53 return codeGenerator._outBuffer.toString();
63 }); 54 });
64 55
56 final GeneratedFile schemaTarget =
57 new GeneratedFile('lib/src/summary/format.fbs', (String pkgPath) {
58 _CodeGenerator codeGenerator = new _CodeGenerator(pkgPath);
59 codeGenerator.generateFlatBufferSchema();
60 return codeGenerator._outBuffer.toString();
61 });
62
65 typedef String _StringToString(String s); 63 typedef String _StringToString(String s);
66 64
67 class _CodeGenerator { 65 class _CodeGenerator {
68 /** 66 /**
69 * Buffer in which generated code is accumulated. 67 * Buffer in which generated code is accumulated.
70 */ 68 */
71 final StringBuffer _outBuffer = new StringBuffer(); 69 final StringBuffer _outBuffer = new StringBuffer();
72 70
73 /** 71 /**
74 * Current indentation level. 72 * Current indentation level.
75 */ 73 */
76 String _indentation = ''; 74 String _indentation = '';
77 75
78 /** 76 /**
79 * Semantic model of the "IDL" input file. 77 * Semantic model of the "IDL" input file.
80 */ 78 */
81 idlModel.Idl _idl; 79 idlModel.Idl _idl;
82 80
81 _CodeGenerator(String pkgPath) {
82 // Parse the input "IDL" file.
83 PhysicalResourceProvider provider = new PhysicalResourceProvider(
84 PhysicalResourceProvider.NORMALIZE_EOL_ALWAYS);
85 String idlPath = join(pkgPath, 'lib', 'src', 'summary', 'idl.dart');
86 File idlFile = provider.getFile(idlPath);
87 Source idlSource = provider.getFile(idlPath).createSource();
88 String idlText = idlFile.readAsStringSync();
89 BooleanErrorListener errorListener = new BooleanErrorListener();
90 CharacterReader idlReader = new CharSequenceReader(idlText);
91 Scanner scanner = new Scanner(idlSource, idlReader, errorListener);
92 Token tokenStream = scanner.tokenize();
93 LineInfo lineInfo = new LineInfo(scanner.lineStarts);
94 Parser parser = new Parser(idlSource, new BooleanErrorListener());
95 CompilationUnit idlParsed = parser.parseCompilationUnit(tokenStream);
96 // Extract a description of the IDL and make sure it is valid.
97 extractIdl(lineInfo, idlParsed);
98 checkIdl();
99 }
100
83 /** 101 /**
84 * Perform basic sanity checking of the IDL (over and above that done by 102 * Perform basic sanity checking of the IDL (over and above that done by
85 * [extractIdl]). 103 * [extractIdl]).
86 */ 104 */
87 void checkIdl() { 105 void checkIdl() {
88 _idl.classes.forEach((String name, idlModel.ClassDeclaration cls) { 106 _idl.classes.forEach((String name, idlModel.ClassDeclaration cls) {
89 if (cls.fileIdentifier != null) { 107 if (cls.fileIdentifier != null) {
90 if (cls.fileIdentifier.length != 4) { 108 if (cls.fileIdentifier.length != 4) {
91 throw new Exception('$name: file identifier must be 4 characters'); 109 throw new Exception('$name: file identifier must be 4 characters');
92 } 110 }
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 } else if (decl is TopLevelVariableDeclaration) { 325 } else if (decl is TopLevelVariableDeclaration) {
308 // Ignore top level variable declarations; they are present just to make 326 // Ignore top level variable declarations; they are present just to make
309 // the IDL analyze without warnings. 327 // the IDL analyze without warnings.
310 } else { 328 } else {
311 throw new Exception('Unexpected declaration `$decl`'); 329 throw new Exception('Unexpected declaration `$decl`');
312 } 330 }
313 } 331 }
314 } 332 }
315 333
316 /** 334 /**
335 * Generate a string representing the FlatBuffer schema type which should be
336 * used to represent [type].
337 */
338 String fbsType(idlModel.FieldType type) {
339 String typeStr;
340 switch (type.typeName) {
341 case 'bool':
342 typeStr = 'bool';
343 break;
344 case 'double':
345 typeStr = 'double';
346 break;
347 case 'int':
348 typeStr = 'uint';
349 break;
350 case 'String':
351 typeStr = 'string';
352 break;
353 default:
354 typeStr = type.typeName;
355 break;
356 }
357 if (type.isList) {
358 return '[$typeStr]';
359 } else {
360 return typeStr;
361 }
362 }
363
364 /**
365 * Entry point to the code generator when generating the "format.fbs" file.
366 */
367 void generateFlatBufferSchema() {
368 outputHeader();
369 for (idlModel.EnumDeclaration enm in _idl.enums.values) {
370 out();
371 outDoc(enm.documentation);
372 out('enum ${enm.name} : byte {');
373 indent(() {
374 for (int i = 0; i < enm.values.length; i++) {
375 idlModel.EnumValueDeclaration value = enm.values[i];
376 if (i != 0) {
377 out();
378 }
379 String suffix = i < enm.values.length - 1 ? ',' : '';
380 outDoc(value.documentation);
381 out('${value.name}$suffix');
382 }
383 });
384 out('}');
385 }
386 for (idlModel.ClassDeclaration cls in _idl.classes.values) {
387 out();
388 outDoc(cls.documentation);
389 out('table ${cls.name} {');
390 indent(() {
391 for (int i = 0; i < cls.fields.length; i++) {
392 idlModel.FieldDeclaration field = cls.fields[i];
393 if (i != 0) {
394 out();
395 }
396 outDoc(field.documentation);
397 out('${field.name}:${fbsType(field.type)} (id: ${field.id});');
398 }
399 });
400 out('}');
401 }
402 out();
403 // Standard flatbuffers only support one root type. We support multiple
404 // root types. For now work around this by forcing PackageBundle to be the
405 // root type. TODO(paulberry): come up with a better solution.
406 idlModel.ClassDeclaration rootType = _idl.classes['PackageBundle'];
407 out('root_type ${rootType.name};');
408 if (rootType.fileIdentifier != null) {
409 out();
410 out('file_identifier ${quoted(rootType.fileIdentifier)};');
411 }
412 }
413
414 /**
415 * Entry point to the code generator when generating the "format.dart" file.
416 */
417 void generateFormatCode() {
418 outputHeader();
419 out('library analyzer.src.summary.format;');
420 out();
421 out("import 'flat_buffers.dart' as fb;");
422 out("import 'idl.dart' as idl;");
423 out("import 'dart:convert' as convert;");
424 out();
425 for (idlModel.EnumDeclaration enm in _idl.enums.values) {
426 _generateEnumReader(enm);
427 out();
428 }
429 for (idlModel.ClassDeclaration cls in _idl.classes.values) {
430 _generateBuilder(cls);
431 out();
432 if (cls.isTopLevel) {
433 _generateReadFunction(cls);
434 out();
435 }
436 _generateReader(cls);
437 out();
438 _generateImpl(cls);
439 out();
440 _generateMixin(cls);
441 out();
442 }
443 }
444
445 /**
317 * Add the prefix `idl.` to a type name, unless that type name is the name of 446 * Add the prefix `idl.` to a type name, unless that type name is the name of
318 * a built-in type. 447 * a built-in type.
319 */ 448 */
320 String idlPrefix(String s) { 449 String idlPrefix(String s) {
321 switch (s) { 450 switch (s) {
322 case 'bool': 451 case 'bool':
323 case 'double': 452 case 'double':
324 case 'int': 453 case 'int':
325 case 'String': 454 case 'String':
326 return s; 455 return s;
(...skipping 26 matching lines...) Expand all
353 _outBuffer.writeln('$_indentation$s'); 482 _outBuffer.writeln('$_indentation$s');
354 } 483 }
355 } 484 }
356 485
357 void outDoc(String documentation) { 486 void outDoc(String documentation) {
358 if (documentation != null) { 487 if (documentation != null) {
359 documentation.split('\n').forEach(out); 488 documentation.split('\n').forEach(out);
360 } 489 }
361 } 490 }
362 491
363 /** 492 void outputHeader() {
364 * Entry point to the code generator. Interpret the AST in [idlParsed],
365 * generate code, and output it to [_outBuffer].
366 */
367 void processCompilationUnit(LineInfo lineInfo, CompilationUnit idlParsed) {
368 extractIdl(lineInfo, idlParsed);
369 checkIdl();
370 out('// Copyright (c) 2015, the Dart project authors. Please see the AUTHOR S file'); 493 out('// Copyright (c) 2015, the Dart project authors. Please see the AUTHOR S file');
371 out('// for details. All rights reserved. Use of this source code is governe d by a'); 494 out('// for details. All rights reserved. Use of this source code is governe d by a');
372 out('// BSD-style license that can be found in the LICENSE file.'); 495 out('// BSD-style license that can be found in the LICENSE file.');
373 out('//'); 496 out('//');
374 out('// This file has been automatically generated. Please do not edit it m anually.'); 497 out('// This file has been automatically generated. Please do not edit it m anually.');
375 out('// To regenerate the file, use the script "pkg/analyzer/tool/generate_f iles".'); 498 out('// To regenerate the file, use the script "pkg/analyzer/tool/generate_f iles".');
376 out(); 499 out();
377 out('library analyzer.src.summary.format;');
378 out();
379 out("import 'flat_buffers.dart' as fb;");
380 out("import 'idl.dart' as idl;");
381 out("import 'dart:convert' as convert;");
382 out();
383 for (idlModel.EnumDeclaration enm in _idl.enums.values) {
384 _generateEnumReader(enm);
385 out();
386 }
387 for (idlModel.ClassDeclaration cls in _idl.classes.values) {
388 _generateBuilder(cls);
389 out();
390 if (cls.isTopLevel) {
391 _generateReadFunction(cls);
392 out();
393 }
394 _generateReader(cls);
395 out();
396 _generateImpl(cls);
397 out();
398 _generateMixin(cls);
399 out();
400 }
401 } 500 }
402 501
403 /** 502 /**
404 * Enclose [s] in quotes, escaping as necessary. 503 * Enclose [s] in quotes, escaping as necessary.
405 */ 504 */
406 String quoted(String s) { 505 String quoted(String s) {
407 return JSON.encode(s); 506 return JSON.encode(s);
408 } 507 }
409 508
410 void _generateBuilder(idlModel.ClassDeclaration cls) { 509 void _generateBuilder(idlModel.ClassDeclaration cls) {
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
769 return token.lexeme.split('\n').map((String line) { 868 return token.lexeme.split('\n').map((String line) {
770 if (line.startsWith(indent)) { 869 if (line.startsWith(indent)) {
771 line = line.substring(indent.length); 870 line = line.substring(indent.length);
772 } 871 }
773 return line; 872 return line;
774 }).join('\n'); 873 }).join('\n');
775 } 874 }
776 return null; 875 return null;
777 } 876 }
778 } 877 }
OLDNEW
« no previous file with comments | « pkg/analyzer/tool/summary/check_test.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698