Skip to content

Commit

Permalink
Handle deprecated options in grpc services and methods, enum types an…
Browse files Browse the repository at this point in the history
…d values, messages (#908)

Similar to #909, a new kind of golden test is added here where the test input is
not a hand-crafted message descriptor but an actual .proto file.
  • Loading branch information
osa1 authored Jan 8, 2024
1 parent 9a408a7 commit a293fb9
Show file tree
Hide file tree
Showing 12 changed files with 278 additions and 5 deletions.
4 changes: 4 additions & 0 deletions protoc_plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@
protobuf library. ([#503], [#907])
* Generate doc comments for enum types and values, rpc services and methods.
([#900], [#909])
* `deprecated` options in messages, grpc services and methods, and enum types
and values are now handled to generate Dart `@deprecated` annotations.
([#900], [#908])

[#738]: https://github.com/google/protobuf.dart/issues/738
[#903]: https://github.com/google/protobuf.dart/pull/903
[#503]: https://github.com/google/protobuf.dart/issues/503
[#907]: https://github.com/google/protobuf.dart/pull/907
[#900]: https://github.com/google/protobuf.dart/issues/900
[#909]: https://github.com/google/protobuf.dart/pull/909
[#908]: https://github.com/google/protobuf.dart/pull/908

## 21.1.2

Expand Down
1 change: 1 addition & 0 deletions protoc_plugin/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ TEST_PROTO_LIST = \
google/protobuf/wrappers \
custom_option \
dart_name \
deprecations \
doc_comments \
default_value_escape \
entity \
Expand Down
8 changes: 8 additions & 0 deletions protoc_plugin/lib/src/client_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ class ClientApiGenerator {
if (commentBlock != null) {
out.println(commentBlock);
}
if (service._descriptor.options.deprecated) {
out.println(
'@$coreImportPrefix.Deprecated(\'This service is deprecated\')');
}
out.addBlock('class ${className}Api {', '}', () {
out.println('$_clientType _client;');
out.println('${className}Api(this._client);');
Expand Down Expand Up @@ -73,6 +77,10 @@ class ClientApiGenerator {
if (commentBlock != null) {
out.println(commentBlock);
}
if (m.options.deprecated) {
out.println(
'@$coreImportPrefix.Deprecated(\'This method is deprecated\')');
}
out.addBlock(
'$asyncImportPrefix.Future<$outputType> $methodName('
'$protobufImportPrefix.ClientContext? ctx, $inputType request) =>',
Expand Down
8 changes: 8 additions & 0 deletions protoc_plugin/lib/src/enum_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ class EnumGenerator extends ProtobufContainer {
if (commentBlock != null) {
out.println(commentBlock);
}
if (_descriptor.options.deprecated) {
out.println('@$coreImportPrefix.Deprecated(\'This enum is deprecated\')');
}
out.addAnnotatedBlock(
'class $classname extends $protobufImportPrefix.ProtobufEnum {',
'}\n', [
Expand All @@ -129,6 +132,11 @@ class EnumGenerator extends ProtobufContainer {
out.println(commentBlock);
}

if (val.options.deprecated) {
out.println(
'@$coreImportPrefix.Deprecated(\'This enum value is deprecated\')');
}

out.printlnAnnotated(
'static const $classname $name = '
'$classname._(${val.number}, $conditionalValName);',
Expand Down
18 changes: 16 additions & 2 deletions protoc_plugin/lib/src/grpc_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ class GrpcServiceGenerator {
}

void _generateClient(IndentingWriter out) {
if (_descriptor.options.deprecated) {
out.println(
'@$coreImportPrefix.Deprecated(\'This service is deprecated\')');
}
out.println(
'@$protobufImportPrefix.GrpcServiceName(\'$_fullServiceName\')');
out.addBlock('class $_clientClassname extends $_client {', '}', () {
Expand Down Expand Up @@ -170,6 +174,8 @@ class _GrpcMethod {
final String _clientReturnType;
final String _serverReturnType;

final bool _deprecated;

_GrpcMethod._(
this._grpcName,
this._dartName,
Expand All @@ -180,7 +186,8 @@ class _GrpcMethod {
this._responseType,
this._argumentType,
this._clientReturnType,
this._serverReturnType);
this._serverReturnType,
this._deprecated);

factory _GrpcMethod(GrpcServiceGenerator service, GenerationContext ctx,
MethodDescriptorProto method) {
Expand All @@ -204,6 +211,8 @@ class _GrpcMethod {
final serverReturnType =
serverStreaming ? '$_stream<$responseType>' : '$_future<$responseType>';

final deprecated = method.options.deprecated;

return _GrpcMethod._(
grpcName,
dartName,
Expand All @@ -214,7 +223,8 @@ class _GrpcMethod {
responseType,
argumentType,
clientReturnType,
serverReturnType);
serverReturnType,
deprecated);
}

void generateClientMethodDescriptor(IndentingWriter out) {
Expand All @@ -228,6 +238,10 @@ class _GrpcMethod {

void generateClientStub(IndentingWriter out) {
out.println();
if (_deprecated) {
out.println(
'@$coreImportPrefix.Deprecated(\'This method is deprecated\')');
}
out.addBlock(
'$_clientReturnType $_dartName($_argumentType request, {${GrpcServiceGenerator._callOptions}? options}) {',
'}', () {
Expand Down
4 changes: 4 additions & 0 deletions protoc_plugin/lib/src/message_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,10 @@ class MessageGenerator extends ProtobufContainer {
if (commentBlock != null) {
out.println(commentBlock);
}
if (_descriptor.options.deprecated) {
out.println(
'@$coreImportPrefix.Deprecated(\'This message is deprecated\')');
}
out.addAnnotatedBlock(
'class $classname extends $protobufImportPrefix.$extendedClass$mixinClause {',
'}', [
Expand Down
22 changes: 22 additions & 0 deletions protoc_plugin/test/deprecations_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:io';

import 'package:test/test.dart';

import 'golden_file.dart';

void main() {
test('Deprecated annotation generation for messages', () {
final actual = File('out/protos/deprecations.pb.dart').readAsStringSync();
expectMatchesGoldenFile(actual, 'test/goldens/deprecations');
});

test('Deprecated annotation generation for enums', () {
final actual = File('out/protos/constructor_args/deprecations.pbenum.dart')
.readAsStringSync();
expectMatchesGoldenFile(actual, 'test/goldens/deprecations.pbenum');
});
}
144 changes: 144 additions & 0 deletions protoc_plugin/test/goldens/deprecations
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
//
// Generated code. Do not modify.
// source: deprecations.proto
//
// @dart = 2.12

// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import

import 'dart:async' as $async;
import 'dart:core' as $core;

import 'package:protobuf/protobuf.dart' as $pb;

export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions;

export 'deprecations.pbenum.dart';

@$core.Deprecated('This message is deprecated')
class HelloRequest extends $pb.GeneratedMessage {
factory HelloRequest() => create();
HelloRequest._() : super();
factory HelloRequest.fromBuffer($core.List<$core.int> i,
[$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(i, r);
factory HelloRequest.fromJson($core.String i,
[$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(i, r);

static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'HelloRequest',
package: const $pb.PackageName(_omitMessageNames ? '' : 'service2'),
createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'name')
..hasRequiredFields = false;

@$core.Deprecated('Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
HelloRequest clone() => HelloRequest()..mergeFromMessage(this);
@$core.Deprecated('Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
HelloRequest copyWith(void Function(HelloRequest) updates) =>
super.copyWith((message) => updates(message as HelloRequest))
as HelloRequest;

$pb.BuilderInfo get info_ => _i;

@$core.pragma('dart2js:noInline')
static HelloRequest create() => HelloRequest._();
HelloRequest createEmptyInstance() => create();
static $pb.PbList<HelloRequest> createRepeated() =>
$pb.PbList<HelloRequest>();
@$core.pragma('dart2js:noInline')
static HelloRequest getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<HelloRequest>(create);
static HelloRequest? _defaultInstance;

@$core.Deprecated('This field is deprecated.')
@$pb.TagNumber(1)
$core.String get name => $_getSZ(0);
@$core.Deprecated('This field is deprecated.')
@$pb.TagNumber(1)
set name($core.String v) {
$_setString(0, v);
}

@$core.Deprecated('This field is deprecated.')
@$pb.TagNumber(1)
$core.bool hasName() => $_has(0);
@$core.Deprecated('This field is deprecated.')
@$pb.TagNumber(1)
void clearName() => clearField(1);
}

class HelloReply extends $pb.GeneratedMessage {
factory HelloReply() => create();
HelloReply._() : super();
factory HelloReply.fromBuffer($core.List<$core.int> i,
[$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(i, r);
factory HelloReply.fromJson($core.String i,
[$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(i, r);

static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'HelloReply',
package: const $pb.PackageName(_omitMessageNames ? '' : 'service2'),
createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'message')
..hasRequiredFields = false;

@$core.Deprecated('Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
HelloReply clone() => HelloReply()..mergeFromMessage(this);
@$core.Deprecated('Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
HelloReply copyWith(void Function(HelloReply) updates) =>
super.copyWith((message) => updates(message as HelloReply)) as HelloReply;

$pb.BuilderInfo get info_ => _i;

@$core.pragma('dart2js:noInline')
static HelloReply create() => HelloReply._();
HelloReply createEmptyInstance() => create();
static $pb.PbList<HelloReply> createRepeated() => $pb.PbList<HelloReply>();
@$core.pragma('dart2js:noInline')
static HelloReply getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<HelloReply>(create);
static HelloReply? _defaultInstance;

@$pb.TagNumber(1)
$core.String get message => $_getSZ(0);
@$pb.TagNumber(1)
set message($core.String v) {
$_setString(0, v);
}

@$pb.TagNumber(1)
$core.bool hasMessage() => $_has(0);
@$pb.TagNumber(1)
void clearMessage() => clearField(1);
}

@$core.Deprecated('This service is deprecated')
class GreeterApi {
$pb.RpcClient _client;
GreeterApi(this._client);

@$core.Deprecated('This method is deprecated')
$async.Future<HelloReply> sayHello(
$pb.ClientContext? ctx, HelloRequest request) =>
_client.invoke<HelloReply>(
ctx, 'Greeter', 'SayHello', request, HelloReply());
}

const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
const _omitMessageNames =
$core.bool.fromEnvironment('protobuf.omit_message_names');
34 changes: 34 additions & 0 deletions protoc_plugin/test/goldens/deprecations.pbenum
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// Generated code. Do not modify.
// source: deprecations.proto
//
// @dart = 2.12

// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import

import 'dart:core' as $core;

import 'package:protobuf/protobuf.dart' as $pb;

@$core.Deprecated('This enum is deprecated')
class A extends $pb.ProtobufEnum {
@$core.Deprecated('This enum value is deprecated')
static const A A1 = A._(0, _omitEnumNames ? '' : 'A1');
static const A A2 = A._(1, _omitEnumNames ? '' : 'A2');

static const $core.List<A> values = <A>[
A1,
A2,
];

static final $core.Map<$core.int, A> _byValue =
$pb.ProtobufEnum.initByValue(values);
static A? valueOf($core.int value) => _byValue[value];

const A._($core.int v, $core.String n) : super(v, n);
}

const _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names');
6 changes: 4 additions & 2 deletions protoc_plugin/test/goldens/doc_comments
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import 'dart:core' as $core;

import 'package:protobuf/protobuf.dart' as $pb;

export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions;

export 'doc_comments.pbenum.dart';

/// This is a message.
Expand All @@ -29,7 +31,7 @@ class HelloRequest extends $pb.GeneratedMessage {

static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'HelloRequest',
package: const $pb.PackageName(_omitMessageNames ? '' : 'service'),
package: const $pb.PackageName(_omitMessageNames ? '' : 'service1'),
createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'name')
..hasRequiredFields = false;
Expand Down Expand Up @@ -83,7 +85,7 @@ class HelloReply extends $pb.GeneratedMessage {

static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'HelloReply',
package: const $pb.PackageName(_omitMessageNames ? '' : 'service'),
package: const $pb.PackageName(_omitMessageNames ? '' : 'service1'),
createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'message')
..hasRequiredFields = false;
Expand Down
Loading

0 comments on commit a293fb9

Please sign in to comment.