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 |