1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // Author: [email protected] (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34
35 #include <google/protobuf/compiler/java/field.h>
36
37 #include <memory>
38
39 #include <google/protobuf/stubs/logging.h>
40 #include <google/protobuf/stubs/common.h>
41 #include <google/protobuf/io/printer.h>
42 #include <google/protobuf/stubs/strutil.h>
43 #include <google/protobuf/stubs/substitute.h>
44 #include <google/protobuf/compiler/java/context.h>
45 #include <google/protobuf/compiler/java/enum_field.h>
46 #include <google/protobuf/compiler/java/enum_field_lite.h>
47 #include <google/protobuf/compiler/java/helpers.h>
48 #include <google/protobuf/compiler/java/map_field.h>
49 #include <google/protobuf/compiler/java/map_field_lite.h>
50 #include <google/protobuf/compiler/java/message_field.h>
51 #include <google/protobuf/compiler/java/message_field_lite.h>
52 #include <google/protobuf/compiler/java/primitive_field.h>
53 #include <google/protobuf/compiler/java/primitive_field_lite.h>
54 #include <google/protobuf/compiler/java/string_field.h>
55 #include <google/protobuf/compiler/java/string_field_lite.h>
56
57
58 namespace google {
59 namespace protobuf {
60 namespace compiler {
61 namespace java {
62
63 namespace {
64
MakeImmutableGenerator(const FieldDescriptor * field,int messageBitIndex,int builderBitIndex,Context * context)65 ImmutableFieldGenerator* MakeImmutableGenerator(const FieldDescriptor* field,
66 int messageBitIndex,
67 int builderBitIndex,
68 Context* context) {
69 if (field->is_repeated()) {
70 switch (GetJavaType(field)) {
71 case JAVATYPE_MESSAGE:
72 if (IsMapEntry(field->message_type())) {
73 return new ImmutableMapFieldGenerator(field, messageBitIndex,
74 builderBitIndex, context);
75 } else {
76 return new RepeatedImmutableMessageFieldGenerator(
77 field, messageBitIndex, builderBitIndex, context);
78 }
79 case JAVATYPE_ENUM:
80 return new RepeatedImmutableEnumFieldGenerator(
81 field, messageBitIndex, builderBitIndex, context);
82 case JAVATYPE_STRING:
83 return new RepeatedImmutableStringFieldGenerator(
84 field, messageBitIndex, builderBitIndex, context);
85 default:
86 return new RepeatedImmutablePrimitiveFieldGenerator(
87 field, messageBitIndex, builderBitIndex, context);
88 }
89 } else {
90 if (IsRealOneof(field)) {
91 switch (GetJavaType(field)) {
92 case JAVATYPE_MESSAGE:
93 return new ImmutableMessageOneofFieldGenerator(
94 field, messageBitIndex, builderBitIndex, context);
95 case JAVATYPE_ENUM:
96 return new ImmutableEnumOneofFieldGenerator(field, messageBitIndex,
97 builderBitIndex, context);
98 case JAVATYPE_STRING:
99 return new ImmutableStringOneofFieldGenerator(
100 field, messageBitIndex, builderBitIndex, context);
101 default:
102 return new ImmutablePrimitiveOneofFieldGenerator(
103 field, messageBitIndex, builderBitIndex, context);
104 }
105 } else {
106 switch (GetJavaType(field)) {
107 case JAVATYPE_MESSAGE:
108 return new ImmutableMessageFieldGenerator(field, messageBitIndex,
109 builderBitIndex, context);
110 case JAVATYPE_ENUM:
111 return new ImmutableEnumFieldGenerator(field, messageBitIndex,
112 builderBitIndex, context);
113 case JAVATYPE_STRING:
114 return new ImmutableStringFieldGenerator(field, messageBitIndex,
115 builderBitIndex, context);
116 default:
117 return new ImmutablePrimitiveFieldGenerator(field, messageBitIndex,
118 builderBitIndex, context);
119 }
120 }
121 }
122 }
123
MakeImmutableLiteGenerator(const FieldDescriptor * field,int messageBitIndex,Context * context)124 ImmutableFieldLiteGenerator* MakeImmutableLiteGenerator(
125 const FieldDescriptor* field, int messageBitIndex, Context* context) {
126 if (field->is_repeated()) {
127 switch (GetJavaType(field)) {
128 case JAVATYPE_MESSAGE:
129 if (IsMapEntry(field->message_type())) {
130 return new ImmutableMapFieldLiteGenerator(field, messageBitIndex,
131 context);
132 } else {
133 return new RepeatedImmutableMessageFieldLiteGenerator(
134 field, messageBitIndex, context);
135 }
136 case JAVATYPE_ENUM:
137 return new RepeatedImmutableEnumFieldLiteGenerator(
138 field, messageBitIndex, context);
139 case JAVATYPE_STRING:
140 return new RepeatedImmutableStringFieldLiteGenerator(
141 field, messageBitIndex, context);
142 default:
143 return new RepeatedImmutablePrimitiveFieldLiteGenerator(
144 field, messageBitIndex, context);
145 }
146 } else {
147 if (IsRealOneof(field)) {
148 switch (GetJavaType(field)) {
149 case JAVATYPE_MESSAGE:
150 return new ImmutableMessageOneofFieldLiteGenerator(
151 field, messageBitIndex, context);
152 case JAVATYPE_ENUM:
153 return new ImmutableEnumOneofFieldLiteGenerator(
154 field, messageBitIndex, context);
155 case JAVATYPE_STRING:
156 return new ImmutableStringOneofFieldLiteGenerator(
157 field, messageBitIndex, context);
158 default:
159 return new ImmutablePrimitiveOneofFieldLiteGenerator(
160 field, messageBitIndex, context);
161 }
162 } else {
163 switch (GetJavaType(field)) {
164 case JAVATYPE_MESSAGE:
165 return new ImmutableMessageFieldLiteGenerator(field, messageBitIndex,
166 context);
167 case JAVATYPE_ENUM:
168 return new ImmutableEnumFieldLiteGenerator(field, messageBitIndex,
169 context);
170 case JAVATYPE_STRING:
171 return new ImmutableStringFieldLiteGenerator(field, messageBitIndex,
172 context);
173 default:
174 return new ImmutablePrimitiveFieldLiteGenerator(
175 field, messageBitIndex, context);
176 }
177 }
178 }
179 }
180
181
ReportUnexpectedPackedFieldsCall(io::Printer * printer)182 static inline void ReportUnexpectedPackedFieldsCall(io::Printer* printer) {
183 // Reaching here indicates a bug. Cases are:
184 // - This FieldGenerator should support packing,
185 // but this method should be overridden.
186 // - This FieldGenerator doesn't support packing, and this method
187 // should never have been called.
188 GOOGLE_LOG(FATAL) << "GenerateBuilderParsingCodeFromPacked() "
189 << "called on field generator that does not support packing.";
190 }
191
192 } // namespace
193
~ImmutableFieldGenerator()194 ImmutableFieldGenerator::~ImmutableFieldGenerator() {}
195
GenerateBuilderParsingCodeFromPacked(io::Printer * printer) const196 void ImmutableFieldGenerator::GenerateBuilderParsingCodeFromPacked(
197 io::Printer* printer) const {
198 ReportUnexpectedPackedFieldsCall(printer);
199 }
200
~ImmutableFieldLiteGenerator()201 ImmutableFieldLiteGenerator::~ImmutableFieldLiteGenerator() {}
202
203 // ===================================================================
204
205 template <>
FieldGeneratorMap(const Descriptor * descriptor,Context * context)206 FieldGeneratorMap<ImmutableFieldGenerator>::FieldGeneratorMap(
207 const Descriptor* descriptor, Context* context)
208 : descriptor_(descriptor), field_generators_(descriptor->field_count()) {
209 // Construct all the FieldGenerators and assign them bit indices for their
210 // bit fields.
211 int messageBitIndex = 0;
212 int builderBitIndex = 0;
213 for (int i = 0; i < descriptor->field_count(); i++) {
214 ImmutableFieldGenerator* generator = MakeImmutableGenerator(
215 descriptor->field(i), messageBitIndex, builderBitIndex, context);
216 field_generators_[i].reset(generator);
217 messageBitIndex += generator->GetNumBitsForMessage();
218 builderBitIndex += generator->GetNumBitsForBuilder();
219 }
220 }
221
222 template <>
~FieldGeneratorMap()223 FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap() {}
224
225 template <>
FieldGeneratorMap(const Descriptor * descriptor,Context * context)226 FieldGeneratorMap<ImmutableFieldLiteGenerator>::FieldGeneratorMap(
227 const Descriptor* descriptor, Context* context)
228 : descriptor_(descriptor), field_generators_(descriptor->field_count()) {
229 // Construct all the FieldGenerators and assign them bit indices for their
230 // bit fields.
231 int messageBitIndex = 0;
232 for (int i = 0; i < descriptor->field_count(); i++) {
233 ImmutableFieldLiteGenerator* generator = MakeImmutableLiteGenerator(
234 descriptor->field(i), messageBitIndex, context);
235 field_generators_[i].reset(generator);
236 messageBitIndex += generator->GetNumBitsForMessage();
237 }
238 }
239
240 template <>
~FieldGeneratorMap()241 FieldGeneratorMap<ImmutableFieldLiteGenerator>::~FieldGeneratorMap() {}
242
243
SetCommonFieldVariables(const FieldDescriptor * descriptor,const FieldGeneratorInfo * info,std::map<std::string,std::string> * variables)244 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
245 const FieldGeneratorInfo* info,
246 std::map<std::string, std::string>* variables) {
247 (*variables)["field_name"] = descriptor->name();
248 (*variables)["name"] = info->name;
249 (*variables)["classname"] = descriptor->containing_type()->name();
250 (*variables)["capitalized_name"] = info->capitalized_name;
251 (*variables)["disambiguated_reason"] = info->disambiguated_reason;
252 (*variables)["constant_name"] = FieldConstantName(descriptor);
253 (*variables)["number"] = StrCat(descriptor->number());
254 (*variables)["kt_dsl_builder"] = "_builder";
255 // These variables are placeholders to pick out the beginning and ends of
256 // identifiers for annotations (when doing so with existing variables would
257 // be ambiguous or impossible). They should never be set to anything but the
258 // empty string.
259 (*variables)["{"] = "";
260 (*variables)["}"] = "";
261 (*variables)["kt_name"] =
262 IsForbiddenKotlin(info->name) ? info->name + "_" : info->name;
263 (*variables)["kt_capitalized_name"] = IsForbiddenKotlin(info->name)
264 ? info->capitalized_name + "_"
265 : info->capitalized_name;
266 if (!descriptor->is_repeated()) {
267 (*variables)["annotation_field_type"] = FieldTypeName(descriptor->type());
268 } else if (GetJavaType(descriptor) == JAVATYPE_MESSAGE &&
269 IsMapEntry(descriptor->message_type())) {
270 (*variables)["annotation_field_type"] =
271 std::string(FieldTypeName(descriptor->type())) + "MAP";
272 } else {
273 (*variables)["annotation_field_type"] =
274 std::string(FieldTypeName(descriptor->type())) + "_LIST";
275 if (descriptor->is_packed()) {
276 (*variables)["annotation_field_type"] =
277 (*variables)["annotation_field_type"] + "_PACKED";
278 }
279 }
280 }
281
SetCommonOneofVariables(const FieldDescriptor * descriptor,const OneofGeneratorInfo * info,std::map<std::string,std::string> * variables)282 void SetCommonOneofVariables(const FieldDescriptor* descriptor,
283 const OneofGeneratorInfo* info,
284 std::map<std::string, std::string>* variables) {
285 (*variables)["oneof_name"] = info->name;
286 (*variables)["oneof_capitalized_name"] = info->capitalized_name;
287 (*variables)["oneof_index"] =
288 StrCat(descriptor->containing_oneof()->index());
289 (*variables)["oneof_stored_type"] = GetOneofStoredType(descriptor);
290 (*variables)["set_oneof_case_message"] =
291 info->name + "Case_ = " + StrCat(descriptor->number());
292 (*variables)["clear_oneof_case_message"] = info->name + "Case_ = 0";
293 (*variables)["has_oneof_case_message"] =
294 info->name + "Case_ == " + StrCat(descriptor->number());
295 }
296
PrintExtraFieldInfo(const std::map<std::string,std::string> & variables,io::Printer * printer)297 void PrintExtraFieldInfo(const std::map<std::string, std::string>& variables,
298 io::Printer* printer) {
299 const std::map<std::string, std::string>::const_iterator it =
300 variables.find("disambiguated_reason");
301 if (it != variables.end() && !it->second.empty()) {
302 printer->Print(
303 variables,
304 "// An alternative name is used for field \"$field_name$\" because:\n"
305 "// $disambiguated_reason$\n");
306 }
307 }
308
309 } // namespace java
310 } // namespace compiler
311 } // namespace protobuf
312 } // namespace google
313