Imported Upstream version 1.18.0
[platform/upstream/grpc.git] / src / compiler / python_generator_helpers.h
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18
19 #ifndef GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_HELPERS_H
20 #define GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_HELPERS_H
21
22 #include <cstring>
23 #include <fstream>
24 #include <iostream>
25 #include <vector>
26
27 #include "src/compiler/config.h"
28 #include "src/compiler/generator_helpers.h"
29 #include "src/compiler/python_generator.h"
30 #include "src/compiler/python_private_generator.h"
31
32 using grpc::protobuf::Descriptor;
33 using grpc::protobuf::FileDescriptor;
34 using grpc::protobuf::MethodDescriptor;
35 using grpc::protobuf::ServiceDescriptor;
36 using grpc::protobuf::compiler::GeneratorContext;
37 using grpc::protobuf::io::CodedOutputStream;
38 using grpc::protobuf::io::Printer;
39 using grpc::protobuf::io::StringOutputStream;
40 using grpc::protobuf::io::ZeroCopyOutputStream;
41 using grpc_generator::StringReplace;
42 using grpc_generator::StripProto;
43 using std::vector;
44
45 namespace grpc_python_generator {
46
47 namespace {
48
49 typedef vector<const Descriptor*> DescriptorVector;
50 typedef vector<grpc::string> StringVector;
51
52 // TODO(https://github.com/google/protobuf/issues/888):
53 // Export `ModuleName` from protobuf's
54 // `src/google/protobuf/compiler/python/python_generator.cc` file.
55 grpc::string ModuleName(const grpc::string& filename,
56                         const grpc::string& import_prefix) {
57   grpc::string basename = StripProto(filename);
58   basename = StringReplace(basename, "-", "_");
59   basename = StringReplace(basename, "/", ".");
60   return import_prefix + basename + "_pb2";
61 }
62
63 // TODO(https://github.com/google/protobuf/issues/888):
64 // Export `ModuleAlias` from protobuf's
65 // `src/google/protobuf/compiler/python/python_generator.cc` file.
66 grpc::string ModuleAlias(const grpc::string& filename,
67                          const grpc::string& import_prefix) {
68   grpc::string module_name = ModuleName(filename, import_prefix);
69   // We can't have dots in the module name, so we replace each with _dot_.
70   // But that could lead to a collision between a.b and a_dot_b, so we also
71   // duplicate each underscore.
72   module_name = StringReplace(module_name, "_", "__");
73   module_name = StringReplace(module_name, ".", "_dot_");
74   return module_name;
75 }
76
77 bool GetModuleAndMessagePath(const Descriptor* type, grpc::string* out,
78                              grpc::string generator_file_name,
79                              bool generate_in_pb2_grpc,
80                              grpc::string& import_prefix) {
81   const Descriptor* path_elem_type = type;
82   DescriptorVector message_path;
83   do {
84     message_path.push_back(path_elem_type);
85     path_elem_type = path_elem_type->containing_type();
86   } while (path_elem_type);  // implicit nullptr comparison; don't be explicit
87   grpc::string file_name = type->file()->name();
88   static const int proto_suffix_length = strlen(".proto");
89   if (!(file_name.size() > static_cast<size_t>(proto_suffix_length) &&
90         file_name.find_last_of(".proto") == file_name.size() - 1)) {
91     return false;
92   }
93
94   grpc::string module;
95   if (generator_file_name != file_name || generate_in_pb2_grpc) {
96     module = ModuleAlias(file_name, import_prefix) + ".";
97   } else {
98     module = "";
99   }
100   grpc::string message_type;
101   for (DescriptorVector::reverse_iterator path_iter = message_path.rbegin();
102        path_iter != message_path.rend(); ++path_iter) {
103     message_type += (*path_iter)->name() + ".";
104   }
105   // no pop_back prior to C++11
106   message_type.resize(message_type.size() - 1);
107   *out = module + message_type;
108   return true;
109 }
110
111 template <typename DescriptorType>
112 StringVector get_all_comments(const DescriptorType* descriptor) {
113   StringVector comments;
114   grpc_generator::GetComment(
115       descriptor, grpc_generator::COMMENTTYPE_LEADING_DETACHED, &comments);
116   grpc_generator::GetComment(descriptor, grpc_generator::COMMENTTYPE_LEADING,
117                              &comments);
118   grpc_generator::GetComment(descriptor, grpc_generator::COMMENTTYPE_TRAILING,
119                              &comments);
120   return comments;
121 }
122
123 }  // namespace
124
125 }  // namespace grpc_python_generator
126
127 #endif  // GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_HELPERS_H