Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sponsored API annotations to Resources too #409

Merged
merged 1 commit into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/ThisAssembly.Constants/ConstantsGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Devlooped.Sponsors;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
Expand All @@ -16,6 +17,8 @@ namespace ThisAssembly;
[Generator(LanguageNames.CSharp)]
public class ConstantsGenerator : IIncrementalGenerator
{
static readonly Regex SeeExpr = new("<see.+sponsorlink\"/>", RegexOptions.Compiled);

public void Initialize(IncrementalGeneratorInitializationContext context)
{
var files = context.AdditionalTextsProvider
Expand Down Expand Up @@ -121,12 +124,16 @@ void GenerateConstant(SourceProductionContext spc,
// structures via functions.
if (parse.Language == LanguageNames.CSharp)
{
output = SyntaxFactory.ParseCompilationUnit(output, options: cs)
output = SeeExpr.Replace(SyntaxFactory
.ParseCompilationUnit(output, options: cs)
.NormalizeWhitespace()
.GetText()
.ToString();
.ToString(),
$"<see cref=\"{Funding.HelpUrl}\"/>");
}

spc.AddSource($"{root}.{name}.g.cs", SourceText.From(output, Encoding.UTF8));
}


}
11 changes: 11 additions & 0 deletions src/ThisAssembly.Resources/CSharp.sbntxt
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,16 @@ namespace {{ Namespace }};
/// <summary>
/// Provides access to assembly resources.
/// </summary>
{{~ if Remarks ~}}
{{ Remarks }}
/// <see cref="{{ Url }}"/>
{{~ end ~}}
{{~ if Warn ~}}
[Obsolete("{{ Warn }}", false
#if NET6_0_OR_GREATER
, UrlFormat = "{{ Url }}"
#endif
)]
{{~ end ~}}
{{ render RootArea }}
}
3 changes: 3 additions & 0 deletions src/ThisAssembly.Resources/Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ namespace ThisAssembly;
[DebuggerDisplay("Values = {RootArea.Values.Count}")]
record Model(Area RootArea, string? Namespace, bool IsPublic)
{
public string? Warn { get; set; }
public string? Remarks { get; set; }
public string Url => Devlooped.Sponsors.SponsorLink.Funding.HelpUrl;
public string Version => Assembly.GetExecutingAssembly().GetName().Version.ToString(3);
public string Visibility => IsPublic ? "public " : "";
}
Expand Down
50 changes: 40 additions & 10 deletions src/ThisAssembly.Resources/ResourcesGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
using System;
using System.Collections.Immutable;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Devlooped.Sponsors;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
using Scriban;
using static Devlooped.Sponsors.SponsorLink;

namespace ThisAssembly;

[Generator(LanguageNames.CSharp)]
public class ResourcesGenerator : IIncrementalGenerator
{
static readonly Regex SeeExpr = new("<see.+sponsorlink\"/>", RegexOptions.Compiled);

public void Initialize(IncrementalGeneratorInitializationContext context)
{
context.RegisterPostInitializationOutput(
Expand Down Expand Up @@ -52,16 +59,19 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
c.GlobalOptions.TryGetValue("build_property.ThisAssemblyVisibility", out var visibility) && !string.IsNullOrEmpty(visibility) ? visibility : null
));

// this is required to ensure status is registered properly independently of analyzer runs.
var options = context.GetStatusOptions();

context.RegisterSourceOutput(
files.Combine(right),
files.Combine(right).Combine(options.Combine(context.ParseOptionsProvider)),
GenerateSource);
}

static void GenerateSource(SourceProductionContext spc,
((ImmutableArray<(string resourceName, string? kind, string? comment)> files,
ImmutableArray<string> extensions), (string? ns, string? visibility)) args)
(((ImmutableArray<(string resourceName, string? kind, string? comment)> files,
ImmutableArray<string> extensions), (string? ns, string? visibility)), (StatusOptions options, ParseOptions parse)) args)
{
var ((files, extensions), (ns, visibility)) = args;
var (((files, extensions), (ns, visibility)), (options, parse)) = args;

var file = "CSharp.sbntxt";
var template = Template.Parse(EmbeddedResource.GetContent(file), file);
Expand All @@ -70,6 +80,23 @@ static void GenerateSource(SourceProductionContext spc,
.GroupBy(f => Path.Combine(
Path.GetDirectoryName(f.resourceName),
Path.GetFileNameWithoutExtension(f.resourceName)));

string? warn = default;
string? remarks = default;
if (IsEditor)
{
var status = Diagnostics.GetOrSetStatus(options);
if (status == SponsorStatus.Unknown || status == SponsorStatus.Expired)
{
warn = string.Format(CultureInfo.CurrentCulture, Resources.Editor_Disabled, Funding.Product, Funding.HelpUrl);
remarks = Resources.Editor_DisabledRemarks;
}
else if (status == SponsorStatus.Grace && Diagnostics.TryGet() is { } grace && grace.Properties.TryGetValue(nameof(SponsorStatus.Grace), out var days))
{
remarks = string.Format(CultureInfo.CurrentCulture, Resources.Editor_GraceRemarks, days);
}
}

foreach (var group in groupsWithoutExtensions)
{
var basePath = group.Key;
Expand All @@ -90,16 +117,19 @@ static void GenerateSource(SourceProductionContext spc,
.ToList();

var root = Area.Load(basePath, resources);
var model = new Model(root, ns, "public".Equals(visibility, StringComparison.OrdinalIgnoreCase));

var model = new Model(root, ns, "public".Equals(visibility, StringComparison.OrdinalIgnoreCase))
{
Warn = warn,
Remarks = remarks,
};
var output = template.Render(model, member => member.Name);

// Apply formatting since indenting isn't that nice in Scriban when rendering nested
// structures via functions.
output = Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParseCompilationUnit(output)
output = SeeExpr.Replace(SyntaxFactory
.ParseCompilationUnit(output, options: parse as CSharpParseOptions)
.NormalizeWhitespace()
.GetText()
.ToString();
.ToString(),
$"<see cref=\"{Funding.HelpUrl}\"/>");

spc.AddSource(
$"{basePath.Replace('\\', '.').Replace('/', '.')}.g.cs",
Expand Down
2 changes: 1 addition & 1 deletion src/ThisAssembly.Resources/ThisAssembly.Resources.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>

<PropertyGroup>
<EmbeddedResourceStringExtensions>.txt|.cs|.sql|.json|.md</EmbeddedResourceStringExtensions>
<EmbeddedResourceStringExtensions>.txt|.cs|.sql|.json|.md|.resx</EmbeddedResourceStringExtensions>
</PropertyGroup>

</Project>
10 changes: 7 additions & 3 deletions src/ThisAssembly.Strings/StringsGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
using System.Globalization;
using System.IO;
using System.Linq;
using System.Resources;
using System.Text;
using System.Text.RegularExpressions;
using Devlooped.Sponsors;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
Expand All @@ -16,6 +16,8 @@ namespace ThisAssembly;
[Generator(LanguageNames.CSharp)]
public class StringsGenerator : IIncrementalGenerator
{
static readonly Regex SeeExpr = new("<see.+sponsorlink\"/>", RegexOptions.Compiled);

public void Initialize(IncrementalGeneratorInitializationContext context)
{
// Read the ThisAssemblyNamespace property or default to null
Expand Down Expand Up @@ -83,10 +85,12 @@ static void GenerateSource(SourceProductionContext spc,

var output = template.Render(model, member => member.Name);

output = SyntaxFactory.ParseCompilationUnit(output, options: parse as CSharpParseOptions)
output = SeeExpr.Replace(SyntaxFactory
.ParseCompilationUnit(output, options: parse as CSharpParseOptions)
.NormalizeWhitespace()
.GetText()
.ToString();
.ToString(),
$"<see cref=\"{Funding.HelpUrl}\"/>");

spc.AddSource(resourceName, SourceText.From(output, Encoding.UTF8));
}
Expand Down