From bd0566257478e72948bb313da381b54d37c640a8 Mon Sep 17 00:00:00 2001 From: Kieron Lanning Date: Thu, 3 Sep 2026 08:48:37 +0100 Subject: [PATCH 1/3] fix: reverted IsPackable change to core project --- src/Directory.Build.props | 4 +- .../Helpers/AttributeDataModelLibrary.cs | 5 +- .../SourceGeneratorFramework.csproj | 46 ++++--------------- 3 files changed, 11 insertions(+), 44 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 04454a4..1ea4a20 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -3,8 +3,8 @@ net8.0;net9.0;net10.0; netstandard2.1;$(TestingTargetFrameworks) Purview.SourceGeneratorFramework - - false + true https://github.com/purview-dev/purview-sourcegeneratorframework diff --git a/src/src/SourceGeneratorFramework.Generators/Helpers/AttributeDataModelLibrary.cs b/src/src/SourceGeneratorFramework.Generators/Helpers/AttributeDataModelLibrary.cs index c7bab7a..fc88c38 100644 --- a/src/src/SourceGeneratorFramework.Generators/Helpers/AttributeDataModelLibrary.cs +++ b/src/src/SourceGeneratorFramework.Generators/Helpers/AttributeDataModelLibrary.cs @@ -746,12 +746,9 @@ static bool IsSupportedType(ITypeSymbol typeSymbol) return typeSymbol.TypeKind is not TypeKind.Array and not TypeKind.Pointer and not TypeKind.FunctionPointer; } - static bool IsGeneratedAttributeModel(ITypeSymbol typeSymbol) - { - return typeSymbol is not INamedTypeSymbol namedType || namedType.TypeKind != TypeKind.Struct + static bool IsGeneratedAttributeModel(ITypeSymbol typeSymbol) => typeSymbol is not INamedTypeSymbol namedType || namedType.TypeKind != TypeKind.Struct ? false : GetAttribute(namedType, GeneratorTypeLibrary.Attirbutes.GenerateAttribute) is not null; - } static AttributeData? GetAttribute(ISymbol symbol, TypeIdentity attributeType) { diff --git a/src/src/SourceGeneratorFramework/SourceGeneratorFramework.csproj b/src/src/SourceGeneratorFramework/SourceGeneratorFramework.csproj index 0f6c25b..a4c2c91 100644 --- a/src/src/SourceGeneratorFramework/SourceGeneratorFramework.csproj +++ b/src/src/SourceGeneratorFramework/SourceGeneratorFramework.csproj @@ -1,30 +1,14 @@  + true true $(TargetsForTfmSpecificContentInPackage);IncludeSourceGeneratorShared;IncludeAnalyzerAssembly - - - + + + @@ -33,11 +17,7 @@ - + @@ -46,10 +26,7 @@ <_SourceGeneratorSharedPackageFile Include="@(_SourceGeneratorSharedAssembly->'%(RootDir)%(Directory)%(Filename).pdb')" /> <_SourceGeneratorSharedPackageFile Include="@(_SourceGeneratorSharedAssembly->'%(RootDir)%(Directory)%(Filename).xml')" /> - + lib/$(TargetFramework)/ @@ -63,19 +40,12 @@ So this target is added to explicitly include the analyzer assembly in the package, so that it can be used by other projects that reference this package. --> - + - + analyzers/dotnet/cs/ From d8090369cb8029b9bcc29ba65bbeb36cc6fb8e82 Mon Sep 17 00:00:00 2001 From: Kieron Lanning Date: Thu, 3 Sep 2026 10:19:04 +0100 Subject: [PATCH 2/3] build: fixed packing and enforced pack validation --- .github/workflows/pr.yml | 3 + .../Modules/CreateGitHubReleaseModule.cs | 1 + build/PipelineCLI/Modules/PackModule.cs | 9 +- .../Modules/PublishLocalNuGetModule.cs | 1 + .../PipelineCLI/Modules/PublishNuGetModule.cs | 1 + .../PipelineCLI/Modules/ValidatePackModule.cs | 344 ++++++++++++++++++ build/PipelineCLI/Program.cs | 4 + build/PipelineCLI/Settings/BuildSettings.cs | 2 + .../Settings/PackValidationSettings.cs | 28 ++ build/PipelineCLI/appsettings.json | 30 +- src/Directory.Build.props | 2 - .../Helpers/AttributeDataModelLibrary.cs | 3 +- ...rceGeneratorFramework.Testing.TUnit.csproj | 24 +- .../SourceGeneratorFramework.Testing.csproj | 24 +- .../SourceGeneratorFramework.csproj | 62 +++- .../SourceGeneratorShared.Pack.targets | 62 ++++ 16 files changed, 530 insertions(+), 70 deletions(-) create mode 100644 build/PipelineCLI/Modules/ValidatePackModule.cs create mode 100644 build/PipelineCLI/Settings/PackValidationSettings.cs create mode 100644 src/src/SourceGeneratorShared/SourceGeneratorShared.Pack.targets diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index a66914e..6e7d513 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -25,4 +25,7 @@ jobs: dotnet-version: "10.0.x" - name: Run PR pipeline + env: + Build__RunPack: "true" + Build__ValidatePack: "true" run: dotnet run --project build/PipelineCLI/PipelineCLI.csproj --configuration Release diff --git a/build/PipelineCLI/Modules/CreateGitHubReleaseModule.cs b/build/PipelineCLI/Modules/CreateGitHubReleaseModule.cs index 161894b..ae0259a 100644 --- a/build/PipelineCLI/Modules/CreateGitHubReleaseModule.cs +++ b/build/PipelineCLI/Modules/CreateGitHubReleaseModule.cs @@ -9,6 +9,7 @@ namespace Purview.SourceGeneratorFramework.PipelineCLI.Modules; [ModuleCategory("Release")] [DependsOn] +[DependsOn] [DependsOn] public class CreateGitHubReleaseModule(IOptions releaseSettings, IOptions gitSettings) : Module diff --git a/build/PipelineCLI/Modules/PackModule.cs b/build/PipelineCLI/Modules/PackModule.cs index 1959808..166eec0 100644 --- a/build/PipelineCLI/Modules/PackModule.cs +++ b/build/PipelineCLI/Modules/PackModule.cs @@ -11,17 +11,14 @@ namespace Purview.SourceGeneratorFramework.PipelineCLI.Modules; [ModuleCategory("Build")] [DependsOn] [DependsOn] -public sealed class PackModule(IOptions settings, IOptions releaseSettings) - : Module +public sealed class PackModule(IOptions settings) : Module { protected override ModuleConfiguration Configure() => ModuleConfiguration .Create() .WithSkipWhen(_ => - !settings.Value.RunPack || releaseSettings.Value.Mode == ReleaseMode.None - ? SkipDecision.Skip( - "Packing is disabled. Set Build__RunPack=true and Release__Mode to something other than None to enable it." - ) + !settings.Value.RunPack + ? SkipDecision.Skip("Packing is disabled. Set Build__RunPack=true to enable it.") : SkipDecision.DoNotSkip ) .Build(); diff --git a/build/PipelineCLI/Modules/PublishLocalNuGetModule.cs b/build/PipelineCLI/Modules/PublishLocalNuGetModule.cs index ccf35b2..5f1bbde 100644 --- a/build/PipelineCLI/Modules/PublishLocalNuGetModule.cs +++ b/build/PipelineCLI/Modules/PublishLocalNuGetModule.cs @@ -10,6 +10,7 @@ namespace Purview.SourceGeneratorFramework.PipelineCLI.Modules; [ModuleCategory("Build")] [DependsOn] +[DependsOn] public class PublishLocalNuGetModule( IOptions localNuGetFeedSettings, IOptions releaseSettings, diff --git a/build/PipelineCLI/Modules/PublishNuGetModule.cs b/build/PipelineCLI/Modules/PublishNuGetModule.cs index d450448..f2195ab 100644 --- a/build/PipelineCLI/Modules/PublishNuGetModule.cs +++ b/build/PipelineCLI/Modules/PublishNuGetModule.cs @@ -9,6 +9,7 @@ namespace Purview.SourceGeneratorFramework.PipelineCLI.Modules; [ModuleCategory("Release")] [DependsOn] +[DependsOn] [DependsOn] public class PublishNuGetModule( IOptions buildSettings, diff --git a/build/PipelineCLI/Modules/ValidatePackModule.cs b/build/PipelineCLI/Modules/ValidatePackModule.cs new file mode 100644 index 0000000..236a1d6 --- /dev/null +++ b/build/PipelineCLI/Modules/ValidatePackModule.cs @@ -0,0 +1,344 @@ +using ModularPipelines.Attributes; +using ModularPipelines.Configuration; +using ModularPipelines.Context; +using ModularPipelines.Models; +using ModularPipelines.Modules; +using NuGet.Packaging; +using NuGet.Versioning; + +namespace Purview.SourceGeneratorFramework.PipelineCLI.Modules; + +[ModuleCategory("Build")] +[DependsOn] +public sealed class ValidatePackModule( + IOptions buildSettings, + IOptions packValidationSettings +) : Module +{ + protected override ModuleConfiguration Configure() => + ModuleConfiguration + .Create() + .WithSkipWhen(_ => + !buildSettings.Value.ValidatePack + ? SkipDecision.Skip("Pack validation is disabled. Set Build__ValidatePack=true to enable it.") + : SkipDecision.DoNotSkip + ) + .Build(); + + protected override async Task ExecuteAsync( + IModuleContext context, + CancellationToken cancellationToken + ) + { + var artifactsFolder = Path.GetFullPath(buildSettings.Value.ArtifactsFolder); + if (!Directory.Exists(artifactsFolder)) + { + throw new InvalidOperationException( + $"The artifacts folder '{artifactsFolder}' does not exist. Run the pack step first." + ); + } + + var nupkgFiles = Directory.EnumerateFiles(artifactsFolder, "*.nupkg", SearchOption.TopDirectoryOnly).ToArray(); + var snupkgFiles = Directory + .EnumerateFiles(artifactsFolder, "*.snupkg", SearchOption.TopDirectoryOnly) + .ToArray(); + + if (nupkgFiles.Length == 0) + { + throw new InvalidOperationException($"No .nupkg files found in {artifactsFolder}."); + } + + var results = new List(nupkgFiles.Length + snupkgFiles.Length); + var packagePairs = new Dictionary(StringComparer.OrdinalIgnoreCase); + + foreach (var package in nupkgFiles) + { + var result = await ValidateNupkgAsync(package, packValidationSettings.Value, cancellationToken); + results.Add(result); + + var pair = GetOrAddPair(packagePairs, result.PackageKey); + pair.Nupkg = result; + } + + foreach (var package in snupkgFiles) + { + var result = await ValidateSnupkgAsync(package, packValidationSettings.Value, cancellationToken); + results.Add(result); + + var pair = GetOrAddPair(packagePairs, result.PackageKey); + pair.Snupkg = result; + } + + if (packValidationSettings.Value.RequireSymbolPackage) + { + foreach (var pair in packagePairs.Values) + { + if (pair.Nupkg is not null && pair.Snupkg is null) + { + pair.Nupkg.AddError( + $"Package '{pair.Nupkg.PackageId}' {pair.Nupkg.Version.ToNormalizedString()} has no matching .snupkg." + ); + } + + if (pair.Snupkg is not null && pair.Nupkg is null) + { + pair.Snupkg.AddError( + $"Symbol package '{pair.Snupkg.PackageId}' {pair.Snupkg.Version.ToNormalizedString()} has no matching .nupkg." + ); + } + } + } + + var invalid = results.Where(result => result.Errors.Count > 0).ToList(); + foreach (var result in results) + { + if (result.Errors.Count == 0) + { + context.Logger.LogInformation( + "Validated {FileName} ({Kind}): {PackageId} {Version}.", + result.FileName, + result.Kind, + result.PackageId, + result.Version.ToNormalizedString() + ); + } + else + { + foreach (var error in result.Errors) + context.Logger.LogError("{FileName}: {Error}", result.FileName, error); + } + } + + var validCount = results.Count - invalid.Count; + context.Summary.KeyValue("PackValidation", "Valid packages", $"{validCount}/{results.Count}"); + context.Summary.KeyValue("PackValidation", "Invalid packages", $"{invalid.Count}/{results.Count}"); + + if (invalid.Count > 0) + { + var detail = string.Join( + Environment.NewLine, + invalid.Select(result => + $" {result.FileName}:{Environment.NewLine} " + + string.Join(Environment.NewLine + " ", result.Errors) + ) + ); + + throw new InvalidOperationException( + $"Pack validation failed for {invalid.Count} of {results.Count} package(s):{Environment.NewLine}{detail}" + ); + } + + return results.ToArray(); + } + + static async Task ValidateNupkgAsync( + string packagePath, + PackValidationSettings settings, + CancellationToken cancellationToken + ) + { + var errors = new List(); + + try + { + using var reader = new PackageArchiveReader(packagePath); + var nuspec = await reader.GetNuspecReaderAsync(cancellationToken); + var id = nuspec.GetId(); + var version = nuspec.GetVersion(); + + ValidateFileName(packagePath, id, version, ".nupkg", errors); + + var files = reader.GetFiles().ToArray(); + ValidateNoPdbFiles(files, errors); + + var required = GetContentRule(settings.RequiredContent, id); + if (required is not null) + { + foreach (var entry in required) + { + if (!files.Contains(entry, StringComparer.OrdinalIgnoreCase)) + errors.Add($"Required content '{entry}' is missing from the package."); + } + } + + var forbidden = GetContentRule(settings.ForbiddenContent, id); + if (forbidden is not null) + { + foreach (var entry in forbidden) + { + if (files.Contains(entry, StringComparer.OrdinalIgnoreCase)) + errors.Add($"Forbidden content '{entry}' must not be in the package."); + } + } + + var result = new PackValidationResult( + Path.GetFileName(packagePath), + "nupkg", + CreatePackageKey(id, version), + id, + version + ); + result.AddErrors(errors); + return result; + } + catch (Exception ex) when (ex is not OperationCanceledException) + { + var result = new PackValidationResult( + Path.GetFileName(packagePath), + "nupkg", + Path.GetFileName(packagePath) + "|unreadable", + "", + new NuGetVersion(0, 0, 0) + ); + result.AddError($"Failed to read package: {ex.Message}"); + return result; + } + } + + static async Task ValidateSnupkgAsync( + string packagePath, + PackValidationSettings settings, + CancellationToken cancellationToken + ) + { + var errors = new List(); + + try + { + using var reader = new PackageArchiveReader(packagePath); + var nuspec = await reader.GetNuspecReaderAsync(cancellationToken); + var id = nuspec.GetId(); + var version = nuspec.GetVersion(); + + ValidateFileName(packagePath, id, version, ".snupkg", errors); + + var files = reader.GetFiles().ToArray(); + var nonSymbolFiles = files.Where(file => !IsPdbFile(file) && !IsSymbolPackageMetadata(file)).ToArray(); + if (nonSymbolFiles.Length > 0) + errors.Add($"Symbol package contains non-symbol file(s): {string.Join(", ", nonSymbolFiles)}."); + + if (settings.RequireSymbolFiles && !files.Any(IsPdbFile)) + errors.Add("Symbol package contains no .pdb files."); + + var result = new PackValidationResult( + Path.GetFileName(packagePath), + "snupkg", + CreatePackageKey(id, version), + id, + version + ); + result.AddErrors(errors); + return result; + } + catch (Exception ex) when (ex is not OperationCanceledException) + { + var result = new PackValidationResult( + Path.GetFileName(packagePath), + "snupkg", + Path.GetFileName(packagePath) + "|unreadable", + "", + new NuGetVersion(0, 0, 0) + ); + result.AddError($"Failed to read package: {ex.Message}"); + return result; + } + } + + static void ValidateFileName( + string packagePath, + string id, + NuGetVersion version, + string extension, + List errors + ) + { + var expected = $"{id}.{version.ToNormalizedString()}{extension}"; + if (!string.Equals(Path.GetFileName(packagePath), expected, StringComparison.OrdinalIgnoreCase)) + errors.Add( + $"File name '{Path.GetFileName(packagePath)}' does not match the nuspec id/version '{expected}'." + ); + } + + static void ValidateNoPdbFiles(IEnumerable files, List errors) + { + var pdbFiles = files.Where(IsPdbFile).ToArray(); + if (pdbFiles.Length > 0) + errors.Add( + $"Package contains PDB file(s): {string.Join(", ", pdbFiles)}. " + + "PDBs must only be delivered through the .snupkg." + ); + } + + static bool IsPdbFile(string path) => + string.Equals(Path.GetExtension(path), ".pdb", StringComparison.OrdinalIgnoreCase); + + static bool IsSymbolPackageMetadata(string path) => + string.Equals(path, "[Content_Types].xml", StringComparison.OrdinalIgnoreCase) + || path.StartsWith("_rels/", StringComparison.OrdinalIgnoreCase) + || path.StartsWith("package/services/metadata/", StringComparison.OrdinalIgnoreCase) + || path.EndsWith(".nuspec", StringComparison.OrdinalIgnoreCase); + + static string[]? GetContentRule(Dictionary rules, string packageId) + { + if (rules.TryGetValue(packageId, out var exact)) + return exact; + + foreach (var rule in rules) + { + if (string.Equals(rule.Key, packageId, StringComparison.OrdinalIgnoreCase)) + return rule.Value; + } + + return null; + } + + static string CreatePackageKey(string id, NuGetVersion version) => $"{id}|{version.ToNormalizedString()}"; + + static PackagePair GetOrAddPair(Dictionary pairs, string key) + { + if (!pairs.TryGetValue(key, out var pair)) + { + pair = new PackagePair(); + pairs.Add(key, pair); + } + + return pair; + } +} + +public sealed class PackValidationResult +{ + readonly List _errors = []; + + public PackValidationResult(string fileName, string kind, string packageKey, string packageId, NuGetVersion version) + { + FileName = fileName; + Kind = kind; + PackageKey = packageKey; + PackageId = packageId; + Version = version; + } + + public string FileName { get; } + + public string Kind { get; } + + public string PackageKey { get; } + + public string PackageId { get; } + + public NuGetVersion Version { get; } + + public IReadOnlyList Errors => _errors; + + internal void AddError(string error) => _errors.Add(error); + + internal void AddErrors(IEnumerable errors) => _errors.AddRange(errors); +} + +sealed class PackagePair +{ + public PackValidationResult? Nupkg { get; set; } + + public PackValidationResult? Snupkg { get; set; } +} diff --git a/build/PipelineCLI/Program.cs b/build/PipelineCLI/Program.cs index 5d38362..1997d14 100644 --- a/build/PipelineCLI/Program.cs +++ b/build/PipelineCLI/Program.cs @@ -10,6 +10,9 @@ builder.Services.Configure(builder.Configuration.GetSection(BuildSettings.SectionName)); builder.Services.Configure(builder.Configuration.GetSection(NuGetSettings.SectionName)); +builder.Services.Configure( + builder.Configuration.GetSection(PackValidationSettings.SectionName) +); builder.Services.Configure( builder.Configuration.GetSection(PublishLocalNuGetSettings.SectionName) ); @@ -33,6 +36,7 @@ .AddModule() .AddModule() .AddModule() + .AddModule() .AddModule() .AddModule() .AddModule(); diff --git a/build/PipelineCLI/Settings/BuildSettings.cs b/build/PipelineCLI/Settings/BuildSettings.cs index 100dc71..cfb27da 100644 --- a/build/PipelineCLI/Settings/BuildSettings.cs +++ b/build/PipelineCLI/Settings/BuildSettings.cs @@ -31,4 +31,6 @@ public sealed class BuildSettings public bool RunLint { get; init; } = true; public bool RunPack { get; init; } = true; + + public bool ValidatePack { get; init; } = true; } diff --git a/build/PipelineCLI/Settings/PackValidationSettings.cs b/build/PipelineCLI/Settings/PackValidationSettings.cs new file mode 100644 index 0000000..7f1b493 --- /dev/null +++ b/build/PipelineCLI/Settings/PackValidationSettings.cs @@ -0,0 +1,28 @@ +namespace Purview.SourceGeneratorFramework.PipelineCLI.Settings; + +public sealed record PackValidationSettings +{ + public const string SectionName = "PackValidation"; + + /// + /// Every .nupkg must have a matching .snupkg (same id/version) and vice versa. + /// + public bool RequireSymbolPackage { get; init; } = true; + + /// + /// Every .snupkg must contain at least one .pdb file. + /// + public bool RequireSymbolFiles { get; init; } = true; + + /// + /// Package id (case-insensitive) to entry paths that MUST be present in the .nupkg. + /// Entry paths use forward slashes, e.g. "lib/netstandard2.0/Foo.dll". + /// + public Dictionary RequiredContent { get; init; } = []; + + /// + /// Package id (case-insensitive) to entry paths that MUST NOT be present in the .nupkg. + /// Entry paths use forward slashes, e.g. "lib/netstandard2.0/Foo.dll". + /// + public Dictionary ForbiddenContent { get; init; } = []; +} diff --git a/build/PipelineCLI/appsettings.json b/build/PipelineCLI/appsettings.json index 52aabe1..50927c2 100644 --- a/build/PipelineCLI/appsettings.json +++ b/build/PipelineCLI/appsettings.json @@ -7,7 +7,35 @@ "TestFilter": "/*/*/*/*/", "TestProjects": "*", "RunLint": true, - "RunPack": true + "RunPack": true, + "ValidatePack": true + }, + "PackValidation": { + "RequireSymbolPackage": true, + "RequireSymbolFiles": true, + "RequiredContent": { + "purview.sourcegeneratorframework": [ + "lib/netstandard2.0/Purview.SourceGeneratorFramework.dll", + "lib/netstandard2.0/Purview.SourceGeneratorFramework.Shared.dll", + "analyzers/dotnet/cs/Purview.SourceGeneratorFramework.dll", + "analyzers/dotnet/cs/Purview.SourceGeneratorFramework.Generators.dll", + "analyzers/dotnet/cs/Purview.SourceGeneratorFramework.Analyzers.dll", + "analyzers/dotnet/cs/Purview.SourceGeneratorFramework.Shared.dll", + "build/Purview.SourceGeneratorFramework.props", + "build/Purview.SourceGeneratorFramework.targets" + ], + "purview.sourcegeneratorframework.testing": [ + "lib/netstandard2.0/Purview.SourceGeneratorFramework.Testing.dll", + "lib/netstandard2.0/Purview.SourceGeneratorFramework.Shared.dll", + "build/Purview.SourceGeneratorFramework.Testing.props" + ], + "purview.sourcegeneratorframework.testing.tunit": [ + "lib/netstandard2.0/Purview.SourceGeneratorFramework.Testing.TUnit.dll", + "lib/netstandard2.0/Purview.SourceGeneratorFramework.Shared.dll", + "build/Purview.SourceGeneratorFramework.Testing.TUnit.props" + ] + }, + "ForbiddenContent": {} }, "NuGet": { "FeedUrl": "https://api.nuget.org/v3/index.json" diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 1ea4a20..811299e 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -3,8 +3,6 @@ net8.0;net9.0;net10.0; netstandard2.1;$(TestingTargetFrameworks) Purview.SourceGeneratorFramework - true https://github.com/purview-dev/purview-sourcegeneratorframework diff --git a/src/src/SourceGeneratorFramework.Generators/Helpers/AttributeDataModelLibrary.cs b/src/src/SourceGeneratorFramework.Generators/Helpers/AttributeDataModelLibrary.cs index fc88c38..8b5069c 100644 --- a/src/src/SourceGeneratorFramework.Generators/Helpers/AttributeDataModelLibrary.cs +++ b/src/src/SourceGeneratorFramework.Generators/Helpers/AttributeDataModelLibrary.cs @@ -746,7 +746,8 @@ static bool IsSupportedType(ITypeSymbol typeSymbol) return typeSymbol.TypeKind is not TypeKind.Array and not TypeKind.Pointer and not TypeKind.FunctionPointer; } - static bool IsGeneratedAttributeModel(ITypeSymbol typeSymbol) => typeSymbol is not INamedTypeSymbol namedType || namedType.TypeKind != TypeKind.Struct + static bool IsGeneratedAttributeModel(ITypeSymbol typeSymbol) => + typeSymbol is not INamedTypeSymbol namedType || namedType.TypeKind != TypeKind.Struct ? false : GetAttribute(namedType, GeneratorTypeLibrary.Attirbutes.GenerateAttribute) is not null; diff --git a/src/src/SourceGeneratorFramework.Testing.TUnit/SourceGeneratorFramework.Testing.TUnit.csproj b/src/src/SourceGeneratorFramework.Testing.TUnit/SourceGeneratorFramework.Testing.TUnit.csproj index 535b07f..b0ca6f2 100644 --- a/src/src/SourceGeneratorFramework.Testing.TUnit/SourceGeneratorFramework.Testing.TUnit.csproj +++ b/src/src/SourceGeneratorFramework.Testing.TUnit/SourceGeneratorFramework.Testing.TUnit.csproj @@ -1,6 +1,7 @@  $(TargetsForTfmSpecificContentInPackage);IncludeSourceGeneratorShared + $(TargetsForTfmSpecificDebugSymbolsInPackage);IncludeSourceGeneratorSharedSymbols netstandard2.0;$(TestingTargetFrameworks) true $(RootNamespace) @@ -23,26 +24,5 @@ - - - - - - - <_SourceGeneratorSharedPackageFile Include="@(_SourceGeneratorSharedAssembly)" /> - <_SourceGeneratorSharedPackageFile Include="@(_SourceGeneratorSharedAssembly->'%(RootDir)%(Directory)%(Filename).pdb')" /> - <_SourceGeneratorSharedPackageFile Include="@(_SourceGeneratorSharedAssembly->'%(RootDir)%(Directory)%(Filename).xml')" /> - - - lib/$(TargetFramework)/ - - - + diff --git a/src/src/SourceGeneratorFramework.Testing/SourceGeneratorFramework.Testing.csproj b/src/src/SourceGeneratorFramework.Testing/SourceGeneratorFramework.Testing.csproj index e99f426..36b644e 100644 --- a/src/src/SourceGeneratorFramework.Testing/SourceGeneratorFramework.Testing.csproj +++ b/src/src/SourceGeneratorFramework.Testing/SourceGeneratorFramework.Testing.csproj @@ -1,6 +1,7 @@  $(TargetsForTfmSpecificContentInPackage);IncludeSourceGeneratorShared + $(TargetsForTfmSpecificDebugSymbolsInPackage);IncludeSourceGeneratorSharedSymbols netstandard2.0;$(TestingTargetFrameworks) true @@ -21,26 +22,5 @@ - - - - - - - <_SourceGeneratorSharedPackageFile Include="@(_SourceGeneratorSharedAssembly)" /> - <_SourceGeneratorSharedPackageFile Include="@(_SourceGeneratorSharedAssembly->'%(RootDir)%(Directory)%(Filename).pdb')" /> - <_SourceGeneratorSharedPackageFile Include="@(_SourceGeneratorSharedAssembly->'%(RootDir)%(Directory)%(Filename).xml')" /> - - - lib/$(TargetFramework)/ - - - + diff --git a/src/src/SourceGeneratorFramework/SourceGeneratorFramework.csproj b/src/src/SourceGeneratorFramework/SourceGeneratorFramework.csproj index a4c2c91..28a840f 100644 --- a/src/src/SourceGeneratorFramework/SourceGeneratorFramework.csproj +++ b/src/src/SourceGeneratorFramework/SourceGeneratorFramework.csproj @@ -2,13 +2,41 @@ true true + + true + true + snupkg $(TargetsForTfmSpecificContentInPackage);IncludeSourceGeneratorShared;IncludeAnalyzerAssembly + $(TargetsForTfmSpecificDebugSymbolsInPackage);IncludeSourceGeneratorSharedSymbols - - - + + + @@ -16,19 +44,14 @@ - - - - + + + - <_SourceGeneratorSharedPackageFile Include="@(_SourceGeneratorSharedAssembly)" /> - <_SourceGeneratorSharedPackageFile Include="@(_SourceGeneratorSharedAssembly->'%(RootDir)%(Directory)%(Filename).pdb')" /> - <_SourceGeneratorSharedPackageFile Include="@(_SourceGeneratorSharedAssembly->'%(RootDir)%(Directory)%(Filename).xml')" /> - - - lib/$(TargetFramework)/ - + @@ -40,12 +63,19 @@ So this target is added to explicitly include the analyzer assembly in the package, so that it can be used by other projects that reference this package. --> - + - + analyzers/dotnet/cs/ diff --git a/src/src/SourceGeneratorShared/SourceGeneratorShared.Pack.targets b/src/src/SourceGeneratorShared/SourceGeneratorShared.Pack.targets new file mode 100644 index 0000000..253c33c --- /dev/null +++ b/src/src/SourceGeneratorShared/SourceGeneratorShared.Pack.targets @@ -0,0 +1,62 @@ + + + + + + + + + <_SourceGeneratorSharedPackageFile Include="@(_SourceGeneratorSharedAssembly)" /> + <_SourceGeneratorSharedPackageFile Include="@(_SourceGeneratorSharedAssembly->'%(RootDir)%(Directory)%(Filename).xml')" /> + + + lib/$(TargetFramework)/ + + + + + + + + + + + + <_SourceGeneratorSharedSymbolFile Include="@(_SourceGeneratorSharedAssembly->'%(RootDir)%(Directory)%(Filename).pdb')" /> + + + $(TargetFramework) + + + + From 21f7bc8004669e56c4e49a48d92a8fb60e6efc54 Mon Sep 17 00:00:00 2001 From: Kieron Lanning Date: Thu, 3 Sep 2026 10:22:01 +0100 Subject: [PATCH 3/3] chore: bumped version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a1db47d..9a13b25 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { "name": "purview-sourcegeneratorframework", - "version": "1.0.0-prerelease.28", + "version": "1.0.0-prerelease.29", "private": true }