Skip to content

Commit

Permalink
Add Grace period info reporting
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
kzu committed Sep 13, 2024
1 parent eb4ffc8 commit 46e9abe
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 10 deletions.
45 changes: 37 additions & 8 deletions samples/dotnet/SponsorLink/DiagnosticsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -29,6 +28,7 @@ class DiagnosticsManager
// <Constant Include="Funding.Product" Value="[PRODUCT_NAME]" />
// <Constant Include="Funding.AnalyzerPrefix" Value="[PREFIX]" />
{ 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.
Expand Down Expand Up @@ -76,12 +76,16 @@ public SponsorStatus GetOrSetStatus(Func<AnalyzerOptions?> options)
=> GetOrSetStatus(() => options().GetSponsorAdditionalFiles(), () => options()?.AnalyzerConfigOptionsProvider.GlobalOptions);

/// <summary>
/// Attemps to remove a diagnostic for the given product.
/// Attemps to get the diagnostic for the given product.
/// </summary>
/// <param name="product">The product diagnostic that might have been pushed previously.</param>
/// <returns>The removed diagnostic, or <see langword="null" /> if none was previously pushed.</returns>
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)
{
Expand Down Expand Up @@ -126,10 +130,16 @@ SponsorStatus GetOrSetStatus(Func<ImmutableArray<AdditionalText>> 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<string, string?>().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<string, string?>()
.Add(nameof(SponsorStatus), nameof(SponsorStatus.Grace))
.Add(nameof(SponsorStatus.Grace), days.ToString()),
days, Funding.Product, Sponsorables.Keys.Humanize(Resources.Or)),
SponsorStatus.Grace);
}
}
Expand All @@ -142,19 +152,25 @@ SponsorStatus GetOrSetStatus(Func<ImmutableArray<AdditionalText>> 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<string, string?>().Add(nameof(SponsorStatus), nameof(SponsorStatus.Expiring))),
properties: ImmutableDictionary.Create<string, string?>()
.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<string, string?>().Add(nameof(SponsorStatus), nameof(SponsorStatus.Expired))),
properties: ImmutableDictionary.Create<string, string?>()
.Add(nameof(SponsorStatus), nameof(SponsorStatus.Expired))
// add how many days ago expiration happened
.Add(nameof(SponsorStatus.Expired), days.ToString())),
SponsorStatus.Expired);
}
}
Expand Down Expand Up @@ -205,6 +221,19 @@ SponsorStatus GetOrSetStatus(Func<ImmutableArray<AdditionalText>> 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,
Expand Down
10 changes: 10 additions & 0 deletions samples/dotnet/SponsorLink/Resources.es-AR.resx
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,14 @@ Por favor considerá apoyar el proyecto patrocinando en {0} y ejecutando posteri
<data name="Contributor_Title" xml:space="preserve">
<value>Sos un contribuidor al proyecto, sos groso 💟!</value>
</data>
<data name="Grace_Description" xml:space="preserve">
<value>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}'.</value>
</data>
<data name="Grace_Message" xml:space="preserve">
<value>El período de prueba finaliza en {0} día(s). Disfrutá y por favor considerá apoyar {1} patrocinando {2} 🙏</value>
</data>
<data name="Grace_Title" xml:space="preserve">
<value>Estado de patrocinio desconocido, período de prueba</value>
</data>
</root>
10 changes: 10 additions & 0 deletions samples/dotnet/SponsorLink/Resources.es.resx
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,14 @@ Por favor considera apoyar el proyecto patrocinando en {0} y ejecutando posterio
<data name="Contributor_Title" xml:space="preserve">
<value>Eres un contribuidor al proyecto, eres lo máximo 💟!</value>
</data>
<data name="Grace_Description" xml:space="preserve">
<value>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}'.</value>
</data>
<data name="Grace_Message" xml:space="preserve">
<value>El período de prueba finaliza en {0} día(s). Disfrute y por favor considere apoyar {1} patrocinando {2} 🙏</value>
</data>
<data name="Grace_Title" xml:space="preserve">
<value>Estado de patrocinio desconocido, período de prueba</value>
</data>
</root>
13 changes: 13 additions & 0 deletions samples/dotnet/SponsorLink/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,17 @@ Please consider supporting the project by sponsoring at {0} and running 'sponsor
<data name="Contributor_Title" xml:space="preserve">
<value>You are a contributor to the project, you rock 💟!</value>
</data>
<data name="Editor_Disabled" xml:space="preserve">
<value>Editor usage of {0} requires an active sponsorship. Learn more at {1}.</value>
</data>
<data name="Grace_Description" xml:space="preserve">
<value>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.</value>
</data>
<data name="Grace_Message" xml:space="preserve">
<value>Grace period ends in {0} days. Enjoy and please consider supporting {1} by sponsoring {2} 🙏</value>
</data>
<data name="Grace_Title" xml:space="preserve">
<value>Unknown sponsor status, grace period</value>
</data>
</root>
4 changes: 3 additions & 1 deletion samples/dotnet/SponsorLink/SponsorLink.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
<FundingPrefix Condition="'$(FundingPrefix)' == ''">$([System.Text.RegularExpressions.Regex]::Replace("$(FundingProduct)", "[^A-Z]", ""))</FundingPrefix>
<!-- Default grace days for an expired sponsor manifest -->
<FundingGrace Condition="'$(FundingGrace)' == ''">21</FundingGrace>
<!-- Url to use as the helpUrl in diagnostics, to learn more about SL -->
<FundingHelpUrl Condition="'$(FundingHelpUrl)' == ''">https://github.com/devlooped#sponsorlink</FundingHelpUrl>
</PropertyGroup>

<ItemGroup>
Expand All @@ -32,7 +34,7 @@
<ItemGroup>
<EmbeddedResource Update="Resources.es-AR.resx" ManifestResourceName="Devlooped.Sponsors.%(Filename)" />
<EmbeddedResource Update="Resources.es.resx" ManifestResourceName="Devlooped.Sponsors.%(Filename)" />
<EmbeddedResource Update="Resources.resx" Type="Resx" ManifestResourceName="Devlooped.Sponsors.%(Filename)" StronglyTypedManifestPrefix="Devlooped.Sponsors" StronglyTypedClassName="%(Filename)" StronglyTypedNamespace="Devlooped.Sponsors" StronglyTypedLanguage="$(Language)" />
<EmbeddedResource Update="Resources.resx" ManifestResourceName="Devlooped.Sponsors.%(Filename)" StronglyTypedManifestPrefix="Devlooped.Sponsors" StronglyTypedClassName="%(Filename)" StronglyTypedNamespace="Devlooped.Sponsors" StronglyTypedLanguage="$(Language)" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion samples/dotnet/SponsorLink/SponsorLinkAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 46e9abe

Please sign in to comment.