[CodeGen][CPP] Added support for service "deprecated" option (#38493)

In proto we can add deprecated option in service definition
example:
```
service Greeter {
   option deprecated = true;
```
This PR help in translating this to marking generated service class as deprecated (which enables warning while using)

`class [[deprecated]] Greeter final {`

Sample warning

```
/usr/local/google/home/bpawan/workspace/code/grpc/examples/cpp/helloworld/greeter_async_client.cc:104:28: warning: 'Greeter' is deprecated [-Wdeprecated-declarations]
  104 |   std::unique_ptr<Greeter::Stub> stub_;
```

Encapsulated support with compiler flag "allow_deprecated" which will be by default false . Hence will not be impacted existing users

Closes #38493

COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/38493 from pawbhard:deprecated-support bd143e37ac
PiperOrigin-RevId: 723134226
pull/38684/head
Pawan Bhardwaj 3 weeks ago committed by Copybara-Service
parent e601b6caa2
commit 860e87da67
  1. 4
      bazel/cc_grpc_library.bzl
  2. 5
      bazel/generate_cc.bzl
  3. 4
      bazel/grpc_build_system.bzl
  4. 5
      bazel/protobuf.bzl
  5. 12
      src/compiler/cpp_generator.cc
  6. 2
      src/compiler/cpp_generator.h
  7. 10
      src/compiler/cpp_plugin.h
  8. 1
      src/compiler/protobuf_plugin.h
  9. 1
      src/compiler/schema_interface.h
  10. 1
      src/proto/grpc/testing/BUILD
  11. 2
      src/proto/grpc/testing/compiler_test.proto
  12. 2
      test/cpp/codegen/compiler_test_golden

@ -25,6 +25,7 @@ def cc_grpc_library(
proto_only = False,
well_known_protos = False,
generate_mocks = False,
allow_deprecated = False,
use_external = False, # @unused
grpc_only = False,
**kwargs):
@ -56,6 +57,8 @@ def cc_grpc_library(
(passed in srcs parameter) instead. False by default.
generate_mocks (bool): when True, Google Mock code for client stub is
generated. False by default.
allow_deprecated (bool): when True, Generated class will marked
deprecated if deprecated option is set in proto.
use_external (bool): Not used.
grpc_only (bool): if True, generate only grpc library, expecting
protobuf messages library (cc_proto_library target) to be passed as
@ -105,6 +108,7 @@ def cc_grpc_library(
plugin = Label("//src/compiler:grpc_cpp_plugin"),
well_known_protos = well_known_protos,
generate_mocks = generate_mocks,
allow_deprecated = allow_deprecated,
**kwargs
)

@ -121,6 +121,7 @@ def generate_cc_impl(ctx):
ctx.attr.flags,
dir_out,
ctx.attr.generate_mocks,
ctx.attr.allow_deprecated,
)
tools = [ctx.executable.plugin]
else:
@ -186,6 +187,10 @@ _generate_cc = rule(
default = False,
mandatory = False,
),
"allow_deprecated": attr.bool(
default = False,
mandatory = False,
),
"_protoc": attr.label(
default = Label("@com_google_protobuf//:protoc"),
executable = True,

@ -302,7 +302,8 @@ def grpc_cc_grpc_library(
srcs = [],
deps = [],
visibility = None,
generate_mocks = False):
generate_mocks = False,
allow_deprecated = False):
"""A wrapper around cc_grpc_library that forces grpc_only=True.
Callers are expected to have their own proto_library() and
@ -315,6 +316,7 @@ def grpc_cc_grpc_library(
deps = deps,
visibility = visibility,
generate_mocks = generate_mocks,
allow_deprecated = allow_deprecated,
grpc_only = True,
)

@ -125,6 +125,7 @@ def get_plugin_args(
flags,
dir_out,
generate_mocks,
allow_deprecated = False,
plugin_name = "PLUGIN"):
"""Returns arguments configuring protoc to use a plugin for a language.
@ -133,6 +134,8 @@ def get_plugin_args(
flags: The plugin flags to be passed to protoc.
dir_out: The output directory for the plugin.
generate_mocks: A bool indicating whether to generate mocks.
allow_deprecated: A bool indicating whether to mark generated class deprecated
based on deprecated proto option in service file.
plugin_name: A name of the plugin, it is required to be unique when there
are more than one plugin used in a single protoc command.
Returns:
@ -141,6 +144,8 @@ def get_plugin_args(
augmented_flags = list(flags)
if generate_mocks:
augmented_flags.append("generate_mock_code=true")
if allow_deprecated:
augmented_flags.append("allow_deprecated=true")
augmented_dir_out = dir_out
if augmented_flags:

@ -1404,9 +1404,15 @@ void PrintHeaderService(grpc_generator::Printer* printer,
(*vars)["Service"] = service->name();
printer->Print(service->GetLeadingComments("//").c_str());
printer->Print(*vars,
"class $Service$ final {\n"
" public:\n");
if (params.allow_deprecated && service->is_deprecated()) {
printer->Print(*vars,
"class [[deprecated]] $Service$ final {\n"
" public:\n");
} else {
printer->Print(*vars,
"class $Service$ final {\n"
" public:\n");
}
printer->Indent();
// Service metadata

@ -68,6 +68,8 @@ struct Parameters {
bool allow_sync_server_api;
// Whether to generate completion queue API.
bool allow_cq_api;
// whether to add deprecated warning for services
bool allow_deprecated;
};
// Return the prologue of the generated header file.

@ -67,6 +67,7 @@ class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
generator_parameters.include_import_headers = false;
generator_parameters.allow_sync_server_api = true;
generator_parameters.allow_cq_api = true;
generator_parameters.allow_deprecated = false;
ProtoBufFile pbfile(file);
@ -129,6 +130,15 @@ class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
*error = std::string("Invalid parameter: ") + *parameter_string;
return false;
}
} else if (param[0] == "allow_deprecated") {
if (param[1] == "true") {
generator_parameters.allow_deprecated = true;
} else if (param[1] == "false") {
generator_parameters.allow_deprecated = false;
} else {
*error = std::string("Invalid parameter: ") + *parameter_string;
return false;
}
} else {
*error = std::string("Unknown parameter: ") + *parameter_string;
return false;

@ -108,6 +108,7 @@ class ProtoBufService : public grpc_generator::Service {
: service_(service) {}
std::string name() const { return std::string(service_->name()); }
bool is_deprecated() const { return service_->options().deprecated(); }
int method_count() const { return service_->method_count(); }
std::unique_ptr<const grpc_generator::Method> method(int i) const {

@ -81,6 +81,7 @@ struct Service : public CommentHolder {
virtual ~Service() {}
virtual std::string name() const = 0;
virtual bool is_deprecated() const = 0;
virtual int method_count() const = 0;
virtual std::unique_ptr<const Method> method(int i) const = 0;

@ -52,6 +52,7 @@ grpc_cc_proto_library(
grpc_cc_grpc_library(
name = "compiler_test_cc_grpc",
srcs = ["compiler_test_proto"],
allow_deprecated = True,
generate_mocks = True,
deps = ["compiler_test_cc_proto"],
)

@ -64,6 +64,8 @@ service ServiceA {
service ServiceB {
// ServiceB trailing comment 1
option deprecated = true;
// MethodB1 leading comment 1
rpc MethodB1(Request) returns (Response);
// MethodB1 trailing comment 1

@ -712,7 +712,7 @@ class ServiceA final {
};
// ServiceB leading comment 1
class ServiceB final {
class [[deprecated]] ServiceB final {
public:
static constexpr char const* service_full_name() {
return "grpc.testing.ServiceB";

Loading…
Cancel
Save