diff --git a/src/Directory.targets b/src/Directory.targets index 190069e0..d2a8362b 100644 --- a/src/Directory.targets +++ b/src/Directory.targets @@ -5,6 +5,7 @@ > This project uses SponsorLink and may issue IDE-only warnings if no active sponsorship is detected. Learn more at https://github.com/devlooped#sponsorlink. + $(PackFolder.StartsWith('analyzers/')) @@ -12,12 +13,14 @@ + + - + + /// Gets the content of the embedded resource at the specified relative path. + /// public static string GetContent(string relativePath) { using var stream = GetStream(relativePath); @@ -17,6 +23,9 @@ public static string GetContent(string relativePath) return reader.ReadToEnd(); } + /// + /// Gets the bytes of the embedded resource at the specified relative path. + /// public static byte[] GetBytes(string relativePath) { using var stream = GetStream(relativePath); @@ -25,6 +34,10 @@ public static byte[] GetBytes(string relativePath) return bytes; } + /// + /// Gets the stream of the embedded resource at the specified relative path. + /// + /// public static Stream GetStream(string relativePath) { #if DEBUG diff --git a/src/Shared/PathSanitizer.cs b/src/Shared/PathSanitizer.cs index 992cda7b..ff8b0d29 100644 --- a/src/Shared/PathSanitizer.cs +++ b/src/Shared/PathSanitizer.cs @@ -1,8 +1,15 @@ using System.Text.RegularExpressions; -static class PathSanitizer +/// +/// Sanitizes paths for use as identifiers. +/// +public static class PathSanitizer { static readonly Regex invalidCharsRegex = new(@"\W"); + + /// + /// Sanitizes the specified path for use as an identifier. + /// public static string Sanitize(string path, string parent) { var partStr = invalidCharsRegex.Replace(path, "_"); diff --git a/src/ThisAssembly.AssemblyInfo/AssemblyInfoGenerator.cs b/src/ThisAssembly.AssemblyInfo/AssemblyInfoGenerator.cs index ffbe6e28..b1abe17a 100644 --- a/src/ThisAssembly.AssemblyInfo/AssemblyInfoGenerator.cs +++ b/src/ThisAssembly.AssemblyInfo/AssemblyInfoGenerator.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Collections.Immutable; +using System.Globalization; using System.Linq; using System.Reflection; using System.Text; @@ -7,8 +8,11 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Text; using Scriban; +using static Devlooped.Sponsors.SponsorLink; +using Resources = Devlooped.Sponsors.Resources; namespace ThisAssembly; @@ -41,7 +45,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // Read the ThisAssemblyNamespace property or default to null var right = context.AnalyzerConfigOptionsProvider .Select((c, t) => c.GlobalOptions.TryGetValue("build_property.ThisAssemblyNamespace", out var ns) && !string.IsNullOrEmpty(ns) ? ns : null) - .Combine(context.ParseOptionsProvider); + .Combine(context.ParseOptionsProvider.Combine(context.GetStatusOptions())); context.RegisterSourceOutput( metadata.Combine(right), @@ -74,11 +78,21 @@ public void Initialize(IncrementalGeneratorInitializationContext context) } static void GenerateSource(SourceProductionContext spc, - (ImmutableArray> attributes, (string? ns, ParseOptions parse)) arg) + (ImmutableArray> attributes, (string? ns, (ParseOptions parse, StatusOptions options))) arg) { - var (attributes, (ns, parse)) = arg; - + var (attributes, (ns, (parse, options))) = arg; var model = new Model(attributes.ToList(), ns); + + var status = Diagnostics.GetOrSetStatus(options); + var warn = IsEditor && + (status == Devlooped.Sponsors.SponsorStatus.Unknown || status == Devlooped.Sponsors.SponsorStatus.Expired); + + if (warn) + { + model.Warn = string.Format(CultureInfo.CurrentCulture, Resources.Editor_Disabled, Funding.Product, Funding.HelpUrl); + model.WarnSummary = Resources.Editor_DisabledRemarks; + } + if (parse is CSharpParseOptions cs && (int)cs.LanguageVersion >= 1100) model.RawStrings = true; diff --git a/src/ThisAssembly.AssemblyInfo/CSharp.sbntxt b/src/ThisAssembly.AssemblyInfo/CSharp.sbntxt index c4c7ed08..6b92e49b 100644 --- a/src/ThisAssembly.AssemblyInfo/CSharp.sbntxt +++ b/src/ThisAssembly.AssemblyInfo/CSharp.sbntxt @@ -6,6 +6,16 @@ // the code is regenerated. // //------------------------------------------------------------------------------ +{{ func obsolete }} +{{~ if Warn ~}} +{{ WarnSummary }} +[Obsolete("{{ Warn }}", false +#if NET6_0_OR_GREATER + , UrlFormat = "{{ Url }}" +#endif +)] +{{~ end ~}} +{{ end }} using System.CodeDom.Compiler; using System.Runtime.CompilerServices; @@ -26,6 +36,7 @@ partial class ThisAssembly public static partial class Info { {{~ for prop in Properties ~}} + {{- obsolete -}} {{~ if RawStrings ~}} public const string {{ prop.Key }} = """ diff --git a/src/ThisAssembly.AssemblyInfo/Model.cs b/src/ThisAssembly.AssemblyInfo/Model.cs index da0ab9c2..2c4fe893 100644 --- a/src/ThisAssembly.AssemblyInfo/Model.cs +++ b/src/ThisAssembly.AssemblyInfo/Model.cs @@ -13,6 +13,9 @@ public Model(IEnumerable> properties, string? ns) public string? Namespace { get; } public bool RawStrings { get; set; } = false; public string Version => Assembly.GetExecutingAssembly().GetName().Version.ToString(3); + public string Url => Devlooped.Sponsors.SponsorLink.Funding.HelpUrl; + public string? Warn { get; set; } + public string? WarnSummary { get; set; } public List> Properties { get; } } diff --git a/src/ThisAssembly.Constants/CSharp.sbntxt b/src/ThisAssembly.Constants/CSharp.sbntxt index a5af0287..ad8aefda 100644 --- a/src/ThisAssembly.Constants/CSharp.sbntxt +++ b/src/ThisAssembly.Constants/CSharp.sbntxt @@ -8,7 +8,7 @@ // the code is regenerated. // //------------------------------------------------------------------------------ -{{ func summary }} +{{- func summary -}} /// {{~ if $0.Comment ~}} /// {{ $0.Comment }} @@ -16,12 +16,24 @@ /// => @"{{ $0.Value }}" {{~ end ~}} /// +{{- end -}} +{{ func obsolete }} +{{ WarnSummary }} +[Obsolete("{{ Warn }}", false +#if NET6_0_OR_GREATER + , UrlFormat = "{{ Url }}" +#endif +)] + {{ end }} {{ func render }} public static partial class {{ $0.Name | string.replace "-" "_" | string.replace " " "_" }} { {{~ for value in $0.Values ~}} - {{- summary value ~}} + {{- summary value -}} + {{~ if Warn ~}} + {{ obsolete }} + {{~ end }} {{~ if RawStrings ~}} public const string {{ value.Name | string.replace "-" "_" | string.replace " " "_" }} = """ diff --git a/src/ThisAssembly.Constants/ConstantsGenerator.cs b/src/ThisAssembly.Constants/ConstantsGenerator.cs index a8aa44ee..93bc0894 100644 --- a/src/ThisAssembly.Constants/ConstantsGenerator.cs +++ b/src/ThisAssembly.Constants/ConstantsGenerator.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Text; @@ -58,13 +58,23 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Select((c, t) => c.GlobalOptions.TryGetValue("build_property.ThisAssemblyNamespace", out var ns) && !string.IsNullOrEmpty(ns) ? ns : null) .Combine(context.ParseOptionsProvider); - context.RegisterSourceOutput( - files.Combine(right), - GenerateConstant); + var inputs = files.Combine(right); + // this is required to ensure status is registered properly independently of analyzer runs. + var options = context.GetStatusOptions(); + context.RegisterSourceOutput(inputs.Combine(options), + (spc, source) => + { + var status = Diagnostics.GetOrSetStatus(source.Right); + var warn = IsEditor && + (status == Devlooped.Sponsors.SponsorStatus.Unknown || status == Devlooped.Sponsors.SponsorStatus.Expired); + + GenerateConstant(spc, source.Left, warn ? string.Format( + CultureInfo.CurrentCulture, Resources.Editor_Disabled, Funding.Product, Funding.HelpUrl) : null); + }); } - void GenerateConstant(SourceProductionContext spc, ((string name, string value, string? comment, string root), (string? ns, ParseOptions parse)) args) + void GenerateConstant(SourceProductionContext spc, ((string name, string value, string? comment, string root), (string? ns, ParseOptions parse)) args, string? warn = default) { var ((name, value, comment, root), (ns, parse)) = args; var cs = (CSharpParseOptions)parse; @@ -83,7 +93,7 @@ void GenerateConstant(SourceProductionContext spc, ((string name, string value, // For now, we only support C# though var file = parse.Language.Replace("#", "Sharp") + ".sbntxt"; var template = Template.Parse(EmbeddedResource.GetContent(file), file); - var model = new Model(rootArea, ns); + var model = new Model(rootArea, ns, warn, Resources.Editor_DisabledRemarks, Funding.HelpUrl); if ((int)cs.LanguageVersion >= 1100) model.RawStrings = true; @@ -98,13 +108,6 @@ void GenerateConstant(SourceProductionContext spc, ((string name, string value, .GetText() .ToString(); } - //else if (language == LanguageNames.VisualBasic) - //{ - // output = Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseCompilationUnit(output) - // .NormalizeWhitespace() - // .GetText() - // .ToString(); - //} spc.AddSource($"{root}.{name}.g.cs", SourceText.From(output, Encoding.UTF8)); } diff --git a/src/ThisAssembly.Constants/Model.cs b/src/ThisAssembly.Constants/Model.cs index 8945f776..68ecf170 100644 --- a/src/ThisAssembly.Constants/Model.cs +++ b/src/ThisAssembly.Constants/Model.cs @@ -9,7 +9,7 @@ namespace ThisAssembly; [DebuggerDisplay("Values = {RootArea.Values.Count}")] -record Model(Area RootArea, string? Namespace) +record Model(Area RootArea, string? Namespace, string? Warn = default, string? WarnSummary = default, string Url = Devlooped.Sponsors.SponsorLink.Funding.HelpUrl) { public bool RawStrings { get; set; } = false; public string Version => Assembly.GetExecutingAssembly().GetName().Version.ToString(3); diff --git a/src/ThisAssembly.Tests/Tests.cs b/src/ThisAssembly.Tests/Tests.cs index b29f5a85..3b596946 100644 --- a/src/ThisAssembly.Tests/Tests.cs +++ b/src/ThisAssembly.Tests/Tests.cs @@ -1,8 +1,9 @@ -using System.Diagnostics.CodeAnalysis; +using System; +using System.Diagnostics.CodeAnalysis; using System.IO; -using Devlooped; using Xunit; using Xunit.Abstractions; +//using ThisAssembly = ThisAssemblyTests [assembly: SuppressMessage("SponsorLink", "SL04")] @@ -10,7 +11,6 @@ namespace ThisAssemblyTests; public record class Tests(ITestOutputHelper Output) { - DateTime dxt = DateTime.Now; [Fact] public void CanReadResourceFile() => Assert.NotNull(ResourceFile.Load("Resources.resx", "Strings")); diff --git a/src/ThisAssembly.Tests/ThisAssembly.Tests.csproj b/src/ThisAssembly.Tests/ThisAssembly.Tests.csproj index 6e72472b..0edd29cf 100644 --- a/src/ThisAssembly.Tests/ThisAssembly.Tests.csproj +++ b/src/ThisAssembly.Tests/ThisAssembly.Tests.csproj @@ -3,7 +3,7 @@ false net8.0 - Devlooped + ThisAssemblyTests A Description with a newline and @@ -17,10 +17,10 @@ net472 ThisAssemblyTests true - CS8981;$(NoWarn) + CS0618;CS8981;TA100;$(NoWarn) - + @@ -87,10 +87,18 @@ - true + + + + $(Version) + + + + +