From 8719e4712a98300b71c250136fb96f0a2b86b088 Mon Sep 17 00:00:00 2001 From: Daniel Cazzulino Date: Tue, 18 Feb 2025 05:20:18 -0300 Subject: [PATCH] Avoid conflicts with multiple helper classes from multiple assemblies Since we were adding the EmbeddedResource helper as a global, project-wide class, if multiple projects happened to use resources, collisions would start to arise, with no way to disambiguate. Since the code in the helper is actually pretty straightforward and will very likely be inlined into the IL in the end anyway, we instead just add its code as part of the resource area being emitted itself. This might result in a slightly larger assembly if there are a ton of areas, but that's a somewhat unlikely scenario. Fixes #442 --- .../SponsorLink.Analyzer.Tests.targets | 4 +- src/ThisAssembly.Resources/CSharp.sbntxt | 59 +++++++++++++++++-- .../ResourcesGenerator.cs | 5 -- 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/src/SponsorLink/SponsorLink.Analyzer.Tests.targets b/src/SponsorLink/SponsorLink.Analyzer.Tests.targets index 1ce67f6e..bd19e461 100644 --- a/src/SponsorLink/SponsorLink.Analyzer.Tests.targets +++ b/src/SponsorLink/SponsorLink.Analyzer.Tests.targets @@ -7,12 +7,12 @@ - + - + diff --git a/src/ThisAssembly.Resources/CSharp.sbntxt b/src/ThisAssembly.Resources/CSharp.sbntxt index dae7ce5a..688301f4 100644 --- a/src/ThisAssembly.Resources/CSharp.sbntxt +++ b/src/ThisAssembly.Resources/CSharp.sbntxt @@ -29,27 +29,72 @@ {{~ end ~}} public static partial class {{ $0.Name }} { + #if DEBUG + static readonly string baseDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? ""; + #endif + {{~ if $0.IsText ~}} private static string text; /// /// Gets the resource as plain text. /// - public static string Text => - text ??= EmbeddedResource.GetContent(@"{{ $0.Path }}"); + public static string Text => text ??= GetContent(@"{{ $0.Path }}"); {{~ end ~}} /// /// Gets the resource as a byte array. /// - public static byte[] GetBytes() => - EmbeddedResource.GetBytes(@"{{ $0.Path }}"); + public static byte[] GetBytes() => GetBytes(@"{{ $0.Path }}"); /// /// Gets the resource as a stream. /// - public static Stream GetStream() => - EmbeddedResource.GetStream(@"{{ $0.Path }}"); + public static Stream GetStream() => GetStream(@"{{ $0.Path }}"); + + /// + /// Gets the content of the embedded resource at the specified relative path. + /// + static string GetContent(string relativePath) + { + using var stream = GetStream(relativePath); + using var reader = new StreamReader(stream); + return reader.ReadToEnd(); + } + + /// + /// Gets the bytes of the embedded resource at the specified relative path. + /// + static byte[] GetBytes(string relativePath) + { + using var stream = GetStream(relativePath); + var bytes = new byte[stream.Length]; + stream.Read(bytes, 0, bytes.Length); + return bytes; + } + + /// + /// Gets the stream of the embedded resource at the specified relative path. + /// + /// + static Stream GetStream(string relativePath) + { + var baseName = Assembly.GetExecutingAssembly().GetName().Name; + var resourceName = relativePath + .TrimStart('.') + .Replace('/', '.') + .Replace('\\', '.'); + + var manifestResourceName = Assembly.GetExecutingAssembly() + .GetManifestResourceNames().FirstOrDefault(x => x.EndsWith(resourceName, StringComparison.Ordinal)); + + if (string.IsNullOrEmpty(manifestResourceName)) + throw new InvalidOperationException($"Did not find required resource ending in '{resourceName}' in assembly '{baseName}'."); + + return + Assembly.GetExecutingAssembly().GetManifestResourceStream(manifestResourceName) ?? + throw new InvalidOperationException($"Did not find required resource '{manifestResourceName}' in assembly '{baseName}'."); + } } {{ end }} {{ func render }} @@ -70,6 +115,8 @@ using System; using System.IO; +using System.Linq; +using System.Reflection; {{ if Namespace }} namespace {{ Namespace }}; {{~ end ~}} diff --git a/src/ThisAssembly.Resources/ResourcesGenerator.cs b/src/ThisAssembly.Resources/ResourcesGenerator.cs index fa170a92..89f3697d 100644 --- a/src/ThisAssembly.Resources/ResourcesGenerator.cs +++ b/src/ThisAssembly.Resources/ResourcesGenerator.cs @@ -18,11 +18,6 @@ public class ResourcesGenerator : IIncrementalGenerator { public void Initialize(IncrementalGeneratorInitializationContext context) { - context.RegisterPostInitializationOutput( - spc => spc.AddSource( - "ThisAssembly.EmbeddedResource.cs", - SourceText.From(EmbeddedResource.GetContent("EmbeddedResource.cs"), Encoding.UTF8))); - var files = context.AdditionalTextsProvider .Combine(context.AnalyzerConfigOptionsProvider) .Where(x =>