Skip to content

Commit

Permalink
feat: Add the Obsolete attribute to all types generated for a depreca…
Browse files Browse the repository at this point in the history
…ted service
  • Loading branch information
jskeet committed Jan 29, 2024
1 parent ea6d495 commit f840c24
Show file tree
Hide file tree
Showing 8 changed files with 32 additions and 1 deletion.
16 changes: 16 additions & 0 deletions Google.Api.Generator.Utils/Roslyn/RoslynExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,9 @@ public static PropertyDeclarationSyntax WithAttribute(this PropertyDeclarationSy
public static EnumMemberDeclarationSyntax WithAttribute(this EnumMemberDeclarationSyntax enumDeclaration, AttributeSyntax attr) =>
enumDeclaration.WithAttributeLists(enumDeclaration.AttributeLists.Add(AttributeList(SingletonSeparatedList(attr))));

public static ClassDeclarationSyntax WithAttribute(this ClassDeclarationSyntax classDeclaration, AttributeSyntax attr) =>
classDeclaration.WithAttributeLists(classDeclaration.AttributeLists.Add(AttributeList(SingletonSeparatedList(attr))));

public static RoslynBuilder.ArgumentsFunc<MethodDeclarationSyntax> WithAttribute(this MethodDeclarationSyntax method, TypeSyntax attrType) =>
args => method.WithAttribute(RoslynBuilder.AttributeWithArgs(attrType, args));

Expand All @@ -361,6 +364,9 @@ public static RoslynBuilder.ArgumentsFunc<PropertyDeclarationSyntax> WithAttribu
public static RoslynBuilder.ArgumentsFunc<EnumMemberDeclarationSyntax> WithAttribute(this EnumMemberDeclarationSyntax enumDeclaration, TypeSyntax attrType) =>
args => enumDeclaration.WithAttribute(RoslynBuilder.AttributeWithArgs(attrType, args));

public static RoslynBuilder.ArgumentsFunc<ClassDeclarationSyntax> WithAttribute(this ClassDeclarationSyntax classDeclaration, TypeSyntax attrType) =>
args => classDeclaration.WithAttribute(RoslynBuilder.AttributeWithArgs(attrType, args));

/// <summary>
/// Returns the specified method declaration syntax, potentially (if <paramref name="condition"/> is true) adding an attribute specified
/// by <paramref name="attrType"/>. This is a function so that if obtaining the attribute type has side-effects,
Expand All @@ -381,6 +387,16 @@ public static RoslynBuilder.ArgumentsFunc<PropertyDeclarationSyntax> MaybeWithAt
? args => property.WithAttribute(RoslynBuilder.AttributeWithArgs(attrType(), args))
: args => property;

/// <summary>
/// Returns the specified property declaration syntax, potentially (if <paramref name="condition"/> is true) adding an attribute specified
/// by <paramref name="attrType"/>. This is a function so that if obtaining the attribute type has side-effects,
/// those side effects will not have an impact unless the attribute is added.
/// </summary>
public static RoslynBuilder.ArgumentsFunc<ClassDeclarationSyntax> MaybeWithAttribute(this ClassDeclarationSyntax clazz, bool condition, Func<TypeSyntax> attrType) =>
condition
? args => clazz.WithAttribute(RoslynBuilder.AttributeWithArgs(attrType(), args))
: args => clazz;

public static BinaryExpressionSyntax Is(this ExpressionSyntax expr, TypeSyntax type) => BinaryExpression(SyntaxKind.IsExpression, expr, type);

public static BinaryExpressionSyntax Is(this ParameterSyntax expr, TypeSyntax type) => IdentifierName(expr.Identifier).Is(type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ private ServiceAbstractClientClassCodeGenerator(SourceFileContext ctx, ServiceDe
private ClassDeclarationSyntax Generate()
{
var cls = Class(Public | Abstract | Partial, _svc.ClientAbstractTyp)
.MaybeWithAttribute(_svc.IsDeprecated, () => _ctx.Type<ObsoleteAttribute>())()
.WithXmlDoc(
XmlDoc.Summary($"{_svc.DocumentationName} client wrapper, for convenient use."),
XmlDoc.RemarksPreFormatted(_svc.DocLines));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
using Grpc.Core;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using System;
using System.Threading;
using System.Threading.Tasks;
using static Google.Api.Generator.Utils.Roslyn.Modifier;
Expand All @@ -45,6 +45,7 @@ private ClassDeclarationSyntax Generate()
{
var baseTyp = Typ.Generic(typeof(ClientBuilderBase<>), _svc.ClientAbstractTyp);
var cls = Class(Public | Sealed | Partial, _svc.BuilderTyp, baseTypes: _ctx.Type(baseTyp))
.MaybeWithAttribute(_svc.IsDeprecated, () => _ctx.Type<ObsoleteAttribute>())()
.WithXmlDoc(XmlDoc.Summary("Builder class for ", _ctx.Type(_svc.ClientAbstractTyp), " to provide simple configuration of credentials, endpoint etc."));
using (_ctx.InClass(cls))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ private static MethodDeclarationSyntax GenerateMethod(SourceFileContext ctx, Ser
);

return Method(Public | Static, serviceCollection, name)(services, action)
.MaybeWithAttribute(service.IsDeprecated, () => ctx.Type<ObsoleteAttribute>())()
.WithBody(services.Call("AddSingleton")(lambda))
.WithXmlDoc(
XmlDoc.Summary("Adds a singleton ", ctx.Type(service.ClientAbstractTyp), " to ", services, "."),
Expand Down
6 changes: 6 additions & 0 deletions Google.Api.Generator/Generation/ServiceDetails.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ public ServiceDetails(ProtoCatalog catalog, string ns, ServiceDescriptor desc, S
.Where(mixin => mixin.GapicClientType.Namespace != ns)
.ToList() ?? Enumerable.Empty<MixinDetails>();
Transports = transports;
IsDeprecated = desc.GetOptions()?.Deprecated == true;
}

/// <summary>The lines of service documentation from the proto.</summary>
Expand Down Expand Up @@ -204,6 +205,11 @@ public ServiceDetails(ProtoCatalog catalog, string ns, ServiceDescriptor desc, S
/// </summary>
public ClientLibrarySettings LibrarySettings { get; }

/// <summary>
/// Whether the service itself is deprecated.
/// </summary>
public bool IsDeprecated { get; }

/// <summary>
/// The details of a service responsible for LRO polling for a non-standard LRO implementation.
/// (Multiple other services may have methods that return operations polled by the service.)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ private ServiceImplClientClassGenerator(SourceFileContext ctx, ServiceDetails sv
private ClassDeclarationSyntax Generate()
{
var cls = Class(Public | Sealed | Partial, _svc.ClientImplTyp, baseTypes: _ctx.Type(_svc.ClientAbstractTyp))
.MaybeWithAttribute(_svc.IsDeprecated, () => _ctx.Type<ObsoleteAttribute>())()
.WithXmlDoc(
XmlDoc.Summary($"{_svc.DocumentationName} client wrapper implementation, for convenient use."),
XmlDoc.RemarksPreFormatted(_svc.DocLines));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ private ServiceSettingsCodeGenerator(SourceFileContext ctx, ServiceDetails svc)
private ClassDeclarationSyntax Generate()
{
var cls = Class(Public | Sealed | Partial, _svc.SettingsTyp, baseTypes: _ctx.Type<ServiceSettingsBase>())
.MaybeWithAttribute(_svc.IsDeprecated, () => _ctx.Type<ObsoleteAttribute>())()
.WithXmlDoc(XmlDoc.Summary("Settings for ", _ctx.Type(_svc.ClientAbstractTyp), " instances."));
using (_ctx.InClass(cls))
{
Expand Down
4 changes: 4 additions & 0 deletions Google.Api.Generator/Generation/SnippetCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public static CompilationUnitSyntax Generate(SourceFileContext ctx, ServiceDetai
using (ctx.InNamespace(ns))
{
var cls = Class(Public | Sealed, svc.ServiceSnippetsTyp)
.MaybeWithAttribute(svc.IsDeprecated, () => ctx.Type<ObsoleteAttribute>())()
.WithXmlDoc(XmlDoc.Summary("Generated snippets."));
using (ctx.InClass(cls))
{
Expand Down Expand Up @@ -237,12 +238,15 @@ private SnippetMetadata GenerateMetadata() =>
var ns = Namespace(TargetMethod.Svc.SnippetsNamespace);
using (ctx.InNamespace(ns))
{
// We can't apply the Obsolete attribute multiple times on a class, so instead
// we apply it to each snippet.
var cls = Class(Public | Sealed | Partial, TargetMethod.Svc.SnippetsTyp);
using (ctx.InClass(cls))
{
cls = cls.AddMembers(
// Do not include doc markers. Full snippets use region tags and metadata.
MethodGenerator(ctx, false)
.MaybeWithAttribute(TargetMethod.Svc.IsDeprecated, () => ctx.Type<ObsoleteAttribute>())()
.WithXmlDoc(
XmlDoc.Summary($"Snippet for {TargetMethodName}"),
XmlDoc.RemarksPreFormatted(GeneratedNotice)));
Expand Down

0 comments on commit f840c24

Please sign in to comment.