Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2014, 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 part of protoc; | |
| 6 | |
| 7 /// A function that parses options for the compiler from [request]. If an error | |
| 8 /// is detected during parsing, this function should report all errors in | |
| 9 /// `response.error` and return `null`. | |
| 10 typedef GenerationOptions GenerationOptionsParser( | |
| 11 CodeGeneratorRequest request, CodeGeneratorResponse response); | |
| 12 | |
| 13 /// Helper function implementing a generic [GenerationOptionsParser] that reads | |
| 14 /// `request.parameters` and treats each token as either a flag ("name") or a | |
| 15 /// key-value pair ("name=value"). For each option "name", it looks up whether a | |
| 16 /// [SingleOptionParser] exists in [parsers] and delegates the actual parsing of | |
| 17 /// the option to it. Finally, it no errors were reported, it will call | |
| 18 /// [optionsFactory] to create the resulting [GenerationOptions]. | |
| 19 GenerationOptions genericGenerationOptionsParser( | |
| 20 CodeGeneratorRequest request, CodeGeneratorResponse response, | |
| 21 Map<String, SingleOptionParser> parsers, | |
| 22 GenerationOptions optionsFactory(Map<String, SingleOptionParser> parsers)) { | |
| 23 var parameter = request.parameter != null ? request.parameter : ''; | |
| 24 var options = parameter.trim().split(','); | |
| 25 var map = <String, String>{}; | |
| 26 var errors = []; | |
| 27 | |
| 28 for (var option in options) { | |
| 29 option = option.trim(); | |
| 30 if (option.isEmpty) continue; | |
| 31 var reportError = (details) { | |
| 32 errors.add('Error found trying to parse the option: $option.\n$details'); | |
| 33 }; | |
| 34 | |
| 35 var nameValue = option.split('='); | |
| 36 if (nameValue.length != 1 && nameValue.length != 2) { | |
| 37 reportError('Options should be a single token, or a name=value pair'); | |
| 38 continue; | |
| 39 } | |
| 40 var name = nameValue[0].trim(); | |
| 41 var parser = parsers[name]; | |
| 42 if (parser == null) { | |
| 43 reportError('Unknown option ($name).'); | |
| 44 continue; | |
| 45 } | |
| 46 | |
| 47 var value = nameValue.length > 1 ? nameValue[1].trim() : null; | |
| 48 parser.parse(name, value, reportError); | |
| 49 } | |
| 50 | |
| 51 if (errors.length == 0) return optionsFactory(parsers); | |
| 52 | |
| 53 response.error = errors.join('\n'); | |
| 54 return null; | |
| 55 } | |
| 56 | |
| 57 /// Options expected by the protoc code generation compiler. | |
| 58 class GenerationOptions { | |
| 59 /// Maps a fully qualified field name, to the desired name we wish to | |
| 60 /// generate. For example `MyMessage.has_field` to `HasFld`. | |
| 61 final Map<String, String> fieldNameOverrides; | |
|
Chris Bracken
2014/05/16 19:58:45
+1 for the new name
| |
| 62 | |
| 63 GenerationOptions(this.fieldNameOverrides); | |
| 64 } | |
| 65 | |
| 66 /// A parser for a name-value pair option. Options parsed in | |
| 67 /// [genericGenerationOptionsParser] delegate to instances of this class to | |
| 68 /// parse the value of a specific option. | |
| 69 abstract class SingleOptionParser { | |
| 70 | |
| 71 /// Parse the [name]=[value] value pair and report any errors to [onError]. If | |
| 72 /// the option is a flag, [value] will be null. Note, [name] is commonly | |
| 73 /// unused. It is provided because [SingleOptionParser] can be registered for | |
| 74 /// multiple option names in [genericGenerationOptionsParser]. | |
| 75 void parse(String name, String value, onError(String details)); | |
| 76 } | |
| 77 | |
| 78 /// Default [GenerationOptionsParser] used by the compiler, which supports | |
| 79 /// the `field_name` option. This option overrides the default name given to | |
| 80 /// some fields that would otherwise collide with existing field names in Dart | |
| 81 /// core objects or in [GeneratedMessage] (see `README.md` for details). | |
| 82 GenerationOptions parseDefaultGenerationOptions( | |
| 83 CodeGeneratorRequest request, CodeGeneratorResponse response) { | |
| 84 var fieldNameOptionParser = new FieldNameOptionParser(); | |
| 85 return genericGenerationOptionsParser(request, response, | |
| 86 {'field_name': fieldNameOptionParser}, | |
| 87 (_) => new GenerationOptions(fieldNameOptionParser.mappings)); | |
| 88 } | |
| 89 | |
| 90 /// A [SingleOptionParser] to parse the `field_name` option. This option | |
| 91 /// overrides the default name given to some fields that would otherwise collide | |
| 92 /// with existing field names in Dart core objects or in [GeneratedMessage]. | |
| 93 class FieldNameOptionParser implements SingleOptionParser { | |
| 94 /// Maps a fully qualified field name, to the desired name we wish to | |
| 95 /// generate. For example `MyMessage.has_field` to `HasFld`. | |
| 96 final Map<String, String> mappings = {}; | |
| 97 | |
| 98 void parse(String name, String value, onError(String message)) { | |
| 99 if (value == null) { | |
| 100 onError('Invalid field_name option, expected a non-emtpy value.'); | |
| 101 return; | |
| 102 } | |
| 103 | |
| 104 List<String> fromTo = value.split('|'); | |
| 105 if (fromTo.length != 2) { | |
| 106 onError('Invalid field_name option, expected a single "|" separator.'); | |
| 107 return; | |
| 108 } | |
| 109 | |
| 110 var fromName = fromTo[0].trim(); | |
| 111 var toName = fromTo[1].trim(); | |
| 112 if (fromName.isEmpty || toName.isEmpty) { | |
| 113 onError('Invalid field_name option, ' | |
| 114 '"from" and "to" names should not be empty.'); | |
| 115 return; | |
| 116 } | |
| 117 | |
| 118 mappings['.$fromName'] = toName; | |
| 119 } | |
| 120 } | |
| OLD | NEW |