From 46e9abe02e5a6abadda66ef050ddc5b9859aa2b8 Mon Sep 17 00:00:00 2001 From: Daniel Cazzulino Date: Fri, 13 Sep 2024 15:54:46 -0300 Subject: [PATCH] Add Grace period info reporting Unfortunately, this does not seem to be surfaced in the editor *at all*. Tried using Warning in descriptor and Info in effective severity, but still no luck. --- .../dotnet/SponsorLink/DiagnosticsManager.cs | 45 +++++++++++++++---- .../dotnet/SponsorLink/Resources.es-AR.resx | 10 +++++ samples/dotnet/SponsorLink/Resources.es.resx | 10 +++++ samples/dotnet/SponsorLink/Resources.resx | 13 ++++++ samples/dotnet/SponsorLink/SponsorLink.csproj | 4 +- .../dotnet/SponsorLink/SponsorLinkAnalyzer.cs | 2 +- 6 files changed, 74 insertions(+), 10 deletions(-) diff --git a/samples/dotnet/SponsorLink/DiagnosticsManager.cs b/samples/dotnet/SponsorLink/DiagnosticsManager.cs index f14835dc..48533a13 100644 --- a/samples/dotnet/SponsorLink/DiagnosticsManager.cs +++ b/samples/dotnet/SponsorLink/DiagnosticsManager.cs @@ -8,7 +8,6 @@ using System.IO; using System.Linq; using Humanizer; -using Humanizer.Localisation; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; using static Devlooped.Sponsors.SponsorLink; @@ -29,6 +28,7 @@ class DiagnosticsManager // // { SponsorStatus.Unknown, CreateUnknown([.. Sponsorables.Keys], Funding.Product, Funding.Prefix) }, + { SponsorStatus.Grace, CreateGrace([.. Sponsorables.Keys], Funding.Product, Funding.Prefix) }, { SponsorStatus.User, CreateSponsor([.. Sponsorables.Keys], Funding.Prefix) }, { SponsorStatus.Contributor, CreateContributor([.. Sponsorables.Keys], Funding.Prefix) }, // NOTE: organization is a special case of sponsor, but we report it as hidden since the user isn't directly involved. @@ -76,12 +76,16 @@ public SponsorStatus GetOrSetStatus(Func options) => GetOrSetStatus(() => options().GetSponsorAdditionalFiles(), () => options()?.AnalyzerConfigOptionsProvider.GlobalOptions); /// - /// Attemps to remove a diagnostic for the given product. + /// Attemps to get the diagnostic for the given product. /// /// The product diagnostic that might have been pushed previously. /// The removed diagnostic, or if none was previously pushed. - public Diagnostic? Pop(string product = Funding.Product) + public Diagnostic? TryGet(string product = Funding.Product) { + // Don't pop grace diagnostics, as we report them more than once. + if (GetStatus() == SponsorStatus.Grace && Diagnostics.TryGetValue(product, out var grace)) + return grace; + if (Diagnostics.TryRemove(product, out var diagnostic) && GetStatus(diagnostic) != SponsorStatus.Grace) { @@ -126,10 +130,16 @@ SponsorStatus GetOrSetStatus(Func> getAdditionalF if (installed != default && ((DateTime.Now - installed).TotalDays <= Funding.Grace)) { + // get days until grace expiration + var days = Math.Abs((int)(installed.Date.AddDays(Funding.Grace) - DateTime.Now.Date).TotalDays); // report unknown, either unparsed manifest or one with no expiration (which we never emit). - return Push(Diagnostic.Create(KnownDescriptors[SponsorStatus.Unknown], null, - properties: ImmutableDictionary.Create().Add(nameof(SponsorStatus), nameof(SponsorStatus.Grace)), - Funding.Product, Sponsorables.Keys.Humanize(Resources.Or)), + return Push(Diagnostic.Create(KnownDescriptors[SponsorStatus.Grace], null, + effectiveSeverity: DiagnosticSeverity.Info, + additionalLocations: null, + properties: ImmutableDictionary.Create() + .Add(nameof(SponsorStatus), nameof(SponsorStatus.Grace)) + .Add(nameof(SponsorStatus.Grace), days.ToString()), + days, Funding.Product, Sponsorables.Keys.Humanize(Resources.Or)), SponsorStatus.Grace); } } @@ -142,19 +152,25 @@ SponsorStatus GetOrSetStatus(Func> getAdditionalF } else if (exp < DateTime.Now) { + var days = Math.Abs((int)(exp.AddDays(Funding.Grace) - DateTime.Now).TotalDays); // report expired or expiring soon if still within the configured days of grace period if (exp.AddDays(Funding.Grace) < DateTime.Now) { // report expiring soon return Push(Diagnostic.Create(KnownDescriptors[SponsorStatus.Expiring], null, - properties: ImmutableDictionary.Create().Add(nameof(SponsorStatus), nameof(SponsorStatus.Expiring))), + properties: ImmutableDictionary.Create() + .Add(nameof(SponsorStatus), nameof(SponsorStatus.Expiring)) + .Add(nameof(SponsorStatus.Expiring), days.ToString())), SponsorStatus.Expiring); } else { // report expired return Push(Diagnostic.Create(KnownDescriptors[SponsorStatus.Expired], null, - properties: ImmutableDictionary.Create().Add(nameof(SponsorStatus), nameof(SponsorStatus.Expired))), + properties: ImmutableDictionary.Create() + .Add(nameof(SponsorStatus), nameof(SponsorStatus.Expired)) + // add how many days ago expiration happened + .Add(nameof(SponsorStatus.Expired), days.ToString())), SponsorStatus.Expired); } } @@ -205,6 +221,19 @@ SponsorStatus GetOrSetStatus(Func> getAdditionalF helpLinkUri: Funding.HelpUrl, WellKnownDiagnosticTags.NotConfigurable, "CompilationEnd"); + internal static DiagnosticDescriptor CreateGrace(string[] sponsorable, string product, string prefix) => new( + $"{prefix}101", + Resources.Grace_Title, + Resources.Grace_Message, + "SponsorLink", + DiagnosticSeverity.Warning, + isEnabledByDefault: true, + description: string.Format(CultureInfo.CurrentCulture, Resources.Grace_Description, + string.Join(", ", sponsorable.Select(x => $"https://github.com/sponsors/{x}")), + string.Join(" ", sponsorable.Select(x => "@" + x))), + helpLinkUri: Funding.HelpUrl, + WellKnownDiagnosticTags.NotConfigurable); + internal static DiagnosticDescriptor CreateExpiring(string[] sponsorable, string prefix) => new( $"{prefix}101", Resources.Expiring_Title, diff --git a/samples/dotnet/SponsorLink/Resources.es-AR.resx b/samples/dotnet/SponsorLink/Resources.es-AR.resx index f7655afa..a7969bf3 100644 --- a/samples/dotnet/SponsorLink/Resources.es-AR.resx +++ b/samples/dotnet/SponsorLink/Resources.es-AR.resx @@ -169,4 +169,14 @@ Por favor considerá apoyar el proyecto patrocinando en {0} y ejecutando posteri Sos un contribuidor al proyecto, sos groso 💟! + + Patrocinar los proyectos en que dependés asegura que se mantengan activos, y que recibas el apoyo que necesitás. También es muy económico y está disponible en todo el mundo! +Por favor considerá apoyar el proyecto patrocinando en {0} y ejecutando posteriormente 'sponsor sync {1}'. + + + El período de prueba finaliza en {0} día(s). Disfrutá y por favor considerá apoyar {1} patrocinando {2} 🙏 + + + Estado de patrocinio desconocido, período de prueba + \ No newline at end of file diff --git a/samples/dotnet/SponsorLink/Resources.es.resx b/samples/dotnet/SponsorLink/Resources.es.resx index 2bc3e380..0fe7b96f 100644 --- a/samples/dotnet/SponsorLink/Resources.es.resx +++ b/samples/dotnet/SponsorLink/Resources.es.resx @@ -169,4 +169,14 @@ Por favor considera apoyar el proyecto patrocinando en {0} y ejecutando posterio Eres un contribuidor al proyecto, eres lo máximo 💟! + + Patrocinar los proyectos en que dependes asegura que se mantengan activos, y que recibas el apoyo que necesitas. También es muy económico y está disponible en todo el mundo! +Por favor considera apoyar el proyecto patrocinando en {0} y ejecutando posteriormente 'sponsor sync {1}'. + + + El período de prueba finaliza en {0} día(s). Disfrute y por favor considere apoyar {1} patrocinando {2} 🙏 + + + Estado de patrocinio desconocido, período de prueba + \ No newline at end of file diff --git a/samples/dotnet/SponsorLink/Resources.resx b/samples/dotnet/SponsorLink/Resources.resx index d9935ca2..dc79c191 100644 --- a/samples/dotnet/SponsorLink/Resources.resx +++ b/samples/dotnet/SponsorLink/Resources.resx @@ -170,4 +170,17 @@ Please consider supporting the project by sponsoring at {0} and running 'sponsor You are a contributor to the project, you rock 💟! + + Editor usage of {0} requires an active sponsorship. Learn more at {1}. + + + Sponsoring projects you depend on ensures they remain active, and that you get the support you need. It's also super affordable and available worldwide! +Please consider supporting the project by sponsoring at {0} and running 'sponsor sync {1}' afterwards. + + + Grace period ends in {0} days. Enjoy and please consider supporting {1} by sponsoring {2} 🙏 + + + Unknown sponsor status, grace period + \ No newline at end of file diff --git a/samples/dotnet/SponsorLink/SponsorLink.csproj b/samples/dotnet/SponsorLink/SponsorLink.csproj index c7c4f12f..d63116a3 100644 --- a/samples/dotnet/SponsorLink/SponsorLink.csproj +++ b/samples/dotnet/SponsorLink/SponsorLink.csproj @@ -17,6 +17,8 @@ $([System.Text.RegularExpressions.Regex]::Replace("$(FundingProduct)", "[^A-Z]", "")) 21 + + https://github.com/devlooped#sponsorlink @@ -32,7 +34,7 @@ - + diff --git a/samples/dotnet/SponsorLink/SponsorLinkAnalyzer.cs b/samples/dotnet/SponsorLink/SponsorLinkAnalyzer.cs index 1a097505..9caa9a24 100644 --- a/samples/dotnet/SponsorLink/SponsorLinkAnalyzer.cs +++ b/samples/dotnet/SponsorLink/SponsorLinkAnalyzer.cs @@ -57,7 +57,7 @@ public override void Initialize(AnalysisContext context) { if (ctx.Options.AnalyzerConfigOptionsProvider.GlobalOptions.TryGetValue("build_property." + prop, out var package) && package?.Length > 0 && - Diagnostics.Pop() is { } diagnostic) + Diagnostics.TryGet() is { } diagnostic) { ctx.ReportDiagnostic(diagnostic); break;