1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 // Author: kenton@google.com (Kenton Varda)
9 // Based on original Protocol Buffers design by
10 // Sanjay Ghemawat, Jeff Dean, and others.
11
12 #include "google/protobuf/compiler/java/full/extension.h"
13
14 #include "google/protobuf/compiler/java/context.h"
15 #include "google/protobuf/compiler/java/doc_comment.h"
16 #include "google/protobuf/compiler/java/name_resolver.h"
17 #include "google/protobuf/io/printer.h"
18
19 // Must be last.
20 #include "google/protobuf/port_def.inc"
21
22 namespace google {
23 namespace protobuf {
24 namespace compiler {
25 namespace java {
26
ImmutableExtensionGenerator(const FieldDescriptor * descriptor,Context * context)27 ImmutableExtensionGenerator::ImmutableExtensionGenerator(
28 const FieldDescriptor* descriptor, Context* context)
29 : descriptor_(descriptor),
30 name_resolver_(context->GetNameResolver()),
31 context_(context) {
32 if (descriptor_->extension_scope() != nullptr) {
33 scope_ =
34 name_resolver_->GetImmutableClassName(descriptor_->extension_scope());
35 } else {
36 scope_ = name_resolver_->GetImmutableClassName(descriptor_->file());
37 }
38 }
39
~ImmutableExtensionGenerator()40 ImmutableExtensionGenerator::~ImmutableExtensionGenerator() {}
41
42 // Initializes the vars referenced in the generated code templates.
InitTemplateVars(const FieldDescriptor * descriptor,const std::string & scope,bool immutable,ClassNameResolver * name_resolver,absl::flat_hash_map<absl::string_view,std::string> * vars_pointer,Context * context)43 void ExtensionGenerator::InitTemplateVars(
44 const FieldDescriptor* descriptor, const std::string& scope, bool immutable,
45 ClassNameResolver* name_resolver,
46 absl::flat_hash_map<absl::string_view, std::string>* vars_pointer,
47 Context* context) {
48 absl::flat_hash_map<absl::string_view, std::string>& vars = *vars_pointer;
49 vars["scope"] = scope;
50 vars["name"] = UnderscoresToCamelCaseCheckReserved(descriptor);
51 vars["containing_type"] =
52 name_resolver->GetClassName(descriptor->containing_type(), immutable);
53 vars["number"] = absl::StrCat(descriptor->number());
54 vars["constant_name"] = FieldConstantName(descriptor);
55 vars["index"] = absl::StrCat(descriptor->index());
56 vars["default"] = descriptor->is_repeated()
57 ? ""
58 : DefaultValue(descriptor, immutable, name_resolver,
59 context->options());
60 vars["type_constant"] = std::string(FieldTypeName(GetType(descriptor)));
61 vars["packed"] = descriptor->is_packed() ? "true" : "false";
62 vars["enum_map"] = "null";
63 vars["prototype"] = "null";
64
65 JavaType java_type = GetJavaType(descriptor);
66 std::string singular_type;
67 switch (java_type) {
68 case JAVATYPE_MESSAGE:
69 singular_type =
70 name_resolver->GetClassName(descriptor->message_type(), immutable);
71 vars["prototype"] = absl::StrCat(singular_type, ".getDefaultInstance()");
72 break;
73 case JAVATYPE_ENUM:
74 singular_type =
75 name_resolver->GetClassName(descriptor->enum_type(), immutable);
76 vars["enum_map"] = absl::StrCat(singular_type, ".internalGetValueMap()");
77 break;
78 case JAVATYPE_STRING:
79 singular_type = "java.lang.String";
80 break;
81 case JAVATYPE_BYTES:
82 singular_type = immutable ? "com.google.protobuf.ByteString" : "byte[]";
83 break;
84 default:
85 singular_type = std::string(BoxedPrimitiveTypeName(java_type));
86 break;
87 }
88 vars["type"] = descriptor->is_repeated()
89 ? absl::StrCat("java.util.List<", singular_type, ">")
90 : singular_type;
91 vars["singular_type"] = singular_type;
92 }
93
Generate(io::Printer * printer)94 void ImmutableExtensionGenerator::Generate(io::Printer* printer) {
95 absl::flat_hash_map<absl::string_view, std::string> vars;
96 const bool kUseImmutableNames = true;
97 InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_,
98 &vars, context_);
99 printer->Print(vars, "public static final int $constant_name$ = $number$;\n");
100
101 WriteFieldDocComment(printer, descriptor_, context_->options());
102 if (descriptor_->extension_scope() == nullptr) {
103 // Non-nested
104 printer->Print(
105 vars,
106 "public static final\n"
107 " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
108 " $containing_type$,\n"
109 " $type$> $name$ = com.google.protobuf.GeneratedMessage\n"
110 " .newFileScopedGeneratedExtension(\n"
111 " $singular_type$.class,\n"
112 " $prototype$);\n");
113 } else {
114 // Nested
115 printer->Print(
116 vars,
117 "public static final\n"
118 " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
119 " $containing_type$,\n"
120 " $type$> $name$ = com.google.protobuf.GeneratedMessage\n"
121 " .newMessageScopedGeneratedExtension(\n"
122 " $scope$.getDefaultInstance(),\n"
123 " $index$,\n"
124 " $singular_type$.class,\n"
125 " $prototype$);\n");
126 }
127 printer->Annotate("name", descriptor_);
128 }
129
GenerateNonNestedInitializationCode(io::Printer * printer)130 int ImmutableExtensionGenerator::GenerateNonNestedInitializationCode(
131 io::Printer* printer) {
132 int bytecode_estimate = 0;
133 if (descriptor_->extension_scope() == nullptr) {
134 // Only applies to non-nested extensions.
135 printer->Print(
136 "$name$.internalInit(descriptor.getExtensions().get($index$));\n",
137 "name", UnderscoresToCamelCaseCheckReserved(descriptor_), "index",
138 absl::StrCat(descriptor_->index()));
139 bytecode_estimate += 21;
140 }
141 return bytecode_estimate;
142 }
143
GenerateRegistrationCode(io::Printer * printer)144 int ImmutableExtensionGenerator::GenerateRegistrationCode(
145 io::Printer* printer) {
146 printer->Print("registry.add($scope$.$name$);\n", "scope", scope_, "name",
147 UnderscoresToCamelCaseCheckReserved(descriptor_));
148 return 7;
149 }
150
151 } // namespace java
152 } // namespace compiler
153 } // namespace protobuf
154 } // namespace google
155
156 #include "google/protobuf/port_undef.inc"
157