Skip to content

Commit b0980bd

Browse files
Merge pull request googleapis#1 from michaelbausor/generator-initial-commit
Generator initial commit
2 parents a34d362 + 3fcc071 commit b0980bd

15 files changed

+972
-0
lines changed

.gitignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Common build output directory names
2+
.build/
3+
_build/
4+
build-output/
5+
6+
# Common bazel output directories
7+
bazel-*
8+
9+
# Common editor files
10+
*~
11+
*.swp
12+
13+
# Ignore IDEA / IntelliJ files
14+
.idea/
15+
cmake-build-*/
16+

BUILD.bazel

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright 2019 Google Inc. All rights reserved
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
package(default_visibility = ["//visibility:public"])
16+
17+
licenses(["notice"]) # Apache 2.0
18+
19+
exports_files([
20+
"LICENSE",
21+
])
22+

WORKSPACE

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright 2019 Google Inc. All rights reserved
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
workspace(name = "com_google_gapic_generator_cpp")
16+
17+
load(
18+
"//:repositories.bzl",
19+
"com_google_gapic_generator_cpp_repositories",
20+
)
21+
22+
com_google_gapic_generator_cpp_repositories()
23+
24+
bind(
25+
name = "zlib",
26+
actual = "@net_zlib//:zlib",
27+
)
28+

generator/BUILD.bazel

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Copyright 2019 Google Inc. All rights reserved
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
package(default_visibility = ["//visibility:public"])
16+
17+
licenses(["notice"]) # Apache 2.0
18+
19+
cc_library(
20+
name = "cpp_gapic_generator",
21+
srcs = [
22+
"gapic_generator.cc",
23+
"internal/gapic_utils.h",
24+
],
25+
hdrs = [
26+
"gapic_generator.h",
27+
],
28+
deps = [
29+
"@absl//absl/base",
30+
"@absl//absl/strings",
31+
"@com_google_protobuf//:protoc_lib",
32+
"@api_common_protos//google/api:client_cc_proto",
33+
],
34+
)
35+
36+
cc_binary(
37+
name = "cpp_gapic_generator_plugin",
38+
srcs = ["plugin.cc"],
39+
deps = [
40+
":cpp_gapic_generator",
41+
],
42+
)
43+
44+
cc_test(
45+
name = "gapic_generator_unittest",
46+
srcs = ["gapic_generator_unittest.cc"],
47+
deps = [
48+
"//generator:cpp_gapic_generator",
49+
"@gtest//:gtest_main",
50+
],
51+
data = glob(
52+
["testdata/**"],
53+
) + [
54+
"@api_common_protos//google/api:client_proto",
55+
],
56+
)
57+
58+
generator_unit_tests = [
59+
"internal/gapic_utils_unittest.cc"
60+
]
61+
62+
[cc_test(
63+
name = "generator_" + test.replace("/", "_").replace(".cc", ""),
64+
srcs = [test],
65+
deps = [
66+
"@absl//absl/base",
67+
"@absl//absl/strings",
68+
"//generator:cpp_gapic_generator",
69+
"@gtest//:gtest_main",
70+
],
71+
) for test in generator_unit_tests]

generator/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# API Client Generator for C++
2+
3+
A generator for protocol buffer described APIs for and in C++.
4+
5+
This is a generator for API client libraries for APIs specified by protocol buffers, such as those inside Google.
6+
It takes a protocol buffer (with particular annotations) and uses it to generate a client library.
7+

generator/gapic_generator.cc

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
// Copyright 2019 Google Inc. All rights reserved
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include <string>
16+
#include <map>
17+
#include <vector>
18+
19+
#include "absl/strings/str_cat.h"
20+
#include "absl/strings/string_view.h"
21+
#include "absl/strings/str_replace.h"
22+
#include "generator/gapic_generator.h"
23+
#include "internal/gapic_utils.h"
24+
25+
#include "google/api/client.pb.h"
26+
27+
namespace pb = google::protobuf;
28+
29+
namespace google {
30+
namespace api {
31+
namespace codegen {
32+
33+
using Vars = std::map<std::string, std::string>;
34+
35+
void SetServiceVars(
36+
pb::ServiceDescriptor const* service,
37+
std::map<std::string, std::string>& vars) {
38+
vars["class_name"] = service->name();
39+
vars["proto_file_name"] = service->file()->name();
40+
vars["header_include_guard_const"] = absl::StrCat(service->name(), "_H_");
41+
vars["class_comment_block"] = "// TODO: pull in comments";
42+
vars["grpc_stub_fqn"] = internal::ProtoNameToCppName(service->full_name());
43+
vars["service_endpoint"] = service->options().GetExtension(google::api::default_host);
44+
}
45+
46+
void SetMethodVars(
47+
pb::MethodDescriptor const* method,
48+
std::map<std::string, std::string>& vars) {
49+
vars["method_name"] = method->name();
50+
vars["request_object"] = internal::ProtoNameToCppName(method->input_type()->full_name());
51+
vars["response_object"] = internal::ProtoNameToCppName(method->output_type()->full_name());
52+
}
53+
54+
std::vector<std::string> BuildHeaderIncludes(
55+
pb::ServiceDescriptor const* /* service */) {
56+
return std::vector<std::string>();
57+
}
58+
59+
std::vector<std::string> BuildCCIncludes(
60+
pb::ServiceDescriptor const* /* service */) {
61+
return std::vector<std::string>();
62+
}
63+
64+
std::vector<std::string> BuildNamespaces(
65+
pb::ServiceDescriptor const* /* service */) {
66+
return std::vector<std::string>();
67+
}
68+
69+
void PrintMethods(
70+
pb::ServiceDescriptor const* service,
71+
std::map<std::string, std::string> vars,
72+
pb::io::Printer* p,
73+
char const* tmplt) {
74+
for (int i = 0; i < service->method_count(); i++) {
75+
const pb::MethodDescriptor* method = service->method(i);
76+
SetMethodVars(method, vars);
77+
p->Print(vars, tmplt);
78+
}
79+
}
80+
81+
bool GenerateClientHeaderFile(
82+
pb::ServiceDescriptor const* service,
83+
std::map<std::string, std::string> const& vars,
84+
pb::io::Printer* p,
85+
std::string * /* error */) {
86+
auto includes = BuildHeaderIncludes(service);
87+
auto namespaces = BuildNamespaces(service);
88+
89+
p->Print(vars,
90+
"// Generated by the GAPIC C++ plugin.\n"
91+
"// If you make any local changes, they will be lost.\n"
92+
"// source: $proto_file_name$\n"
93+
"#ifndef $header_include_guard_const$\n"
94+
"#define $header_include_guard_const$");
95+
96+
for (auto include : includes) {
97+
p->Print("\n#include $include$", "include", include);
98+
}
99+
for (auto nspace : namespaces) {
100+
p->Print("\nnamespace $namespace$ {", "namespace", nspace);
101+
}
102+
103+
p->Print(vars, "\n"
104+
"$class_comment_block$\n"
105+
"class $class_name$ {");
106+
107+
PrintMethods(service, vars, p, "");
108+
109+
p->Print(vars, "\n}; // $class_name$");
110+
111+
for (auto nspace : namespaces) {
112+
p->Print("\n} // namespace $namespace$", "namespace", nspace);
113+
}
114+
115+
p->Print(vars, "\n"
116+
"#endif // $header_include_guard_const$\n");
117+
118+
return true;
119+
}
120+
121+
bool GenerateClientCCFile(
122+
pb::ServiceDescriptor const* service,
123+
std::map<std::string, std::string> const& vars,
124+
pb::io::Printer* p,
125+
std::string * /* error */) {
126+
auto includes = BuildCCIncludes(service);
127+
auto namespaces = BuildNamespaces(service);
128+
129+
p->Print(vars,
130+
"// Generated by the GAPIC C++ plugin.\n"
131+
"// If you make any local changes, they will be lost.\n"
132+
"// source: $proto_file_name$");
133+
134+
for (auto include : includes) {
135+
p->Print("\n#include $include$", "include", include);
136+
}
137+
for (auto nspace : namespaces) {
138+
p->Print("\nnamespace $namespace$ {", "namespace", nspace);
139+
}
140+
141+
p->Print(vars, "\n"
142+
"// TODO: add content");
143+
144+
for (auto nspace : namespaces) {
145+
p->Print("\n} // namespace $namespace$", "namespace", nspace);
146+
}
147+
148+
p->Print("\n");
149+
150+
return true;
151+
}
152+
153+
bool GapicGenerator::Generate(pb::FileDescriptor const* file,
154+
std::string const& /* parameter */,
155+
pb::compiler::GeneratorContext* generator_context,
156+
std::string* error) const {
157+
if (file->options().cc_generic_services()) {
158+
*error =
159+
"cpp gapic proto compiler plugin does not work with generic "
160+
"services. To generate cpp grpc APIs, please set \""
161+
"cc_generic_service = false\".";
162+
return false;
163+
}
164+
165+
for (int i = 0; i < file->service_count(); i++) {
166+
pb::ServiceDescriptor const* service = file->service(i);
167+
168+
// TODO(michaelbausor): initialize Vars with cross-file-descriptor
169+
// configuration, e.g. metadata annotation.
170+
std::map<std::string, std::string> vars;
171+
SetServiceVars(service, vars);
172+
173+
std::string service_file_path = internal::ServiceNameToFilePath(
174+
service->full_name());
175+
176+
std::string header_file_path = absl::StrCat(service_file_path, ".gapic.h");
177+
std::unique_ptr<pb::io::ZeroCopyOutputStream> header_output(
178+
generator_context->Open(header_file_path));
179+
pb::io::Printer header_printer(header_output.get(), '$', NULL);
180+
if (!GenerateClientHeaderFile(service, vars, &header_printer, error)) {
181+
return false;
182+
}
183+
184+
std::string cc_file_path = absl::StrCat(service_file_path, ".gapic.cc");
185+
std::unique_ptr<pb::io::ZeroCopyOutputStream> cc_output(
186+
generator_context->Open(cc_file_path));
187+
pb::io::Printer cc_printer(cc_output.get(), '$', NULL);
188+
if (!GenerateClientCCFile(service, vars, &cc_printer, error)) {
189+
return false;
190+
}
191+
}
192+
return true;
193+
}
194+
195+
} // namespace codegen
196+
} // namespace api
197+
} // namespace google

generator/gapic_generator.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2019 Google Inc. All rights reserved
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
#ifndef GOOGLE_API_CODEGEN_GAPIC_GENERATOR_H_
15+
#define GOOGLE_API_CODEGEN_GAPIC_GENERATOR_H_
16+
17+
#include <memory>
18+
#include <sstream>
19+
#include <string>
20+
21+
#include "src/google/protobuf/compiler/code_generator.h"
22+
#include "src/google/protobuf/io/printer.h"
23+
#include "src/google/protobuf/io/zero_copy_stream.h"
24+
#include "src/google/protobuf/descriptor.h"
25+
#include "src/google/protobuf/descriptor.pb.h"
26+
#include "absl/strings/string_view.h"
27+
28+
namespace google {
29+
namespace api {
30+
namespace codegen {
31+
32+
/**
33+
* Code generator that outputs a C++ GAPIC client from proto descriptors.
34+
*/
35+
class GapicGenerator : public google::protobuf::compiler::CodeGenerator {
36+
public:
37+
bool Generate(google::protobuf::FileDescriptor const* file,
38+
std::string const& parameter,
39+
google::protobuf::compiler::GeneratorContext* generator_context,
40+
std::string* error) const override;
41+
};
42+
43+
} // namespace codegen
44+
} // namespace api
45+
} // namespace google
46+
47+
#endif // GOOGLE_API_CODEGEN_GAPIC_GENERATOR_H_

0 commit comments

Comments
 (0)