Skip to content
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
5 changes: 5 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
root = true

[*]
# This only shows when calling AnalyzerConfigOptionsProvider.GetOptions(additionalText)
example_editorconfig_value = true
31 changes: 18 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:

env:
BUILD_CONFIG: 'Release'
SOLUTION: 'SourceGeneratorContext.sln'
SOLUTION: '*.sln'

runs-on: ubuntu-latest

Expand All @@ -33,7 +33,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
dotnet-version: '9.0.x'

- name: Restore dependencies
run: dotnet restore $SOLUTION
Expand All @@ -44,27 +44,32 @@ jobs:
- name: Run tests
run: dotnet test --configuration $BUILD_CONFIG --no-restore --no-build --verbosity normal

- name: Pack NuGet packages
run: |
dotnet pack $SOLUTION --configuration $BUILD_CONFIG --no-build --output ./artifacts
echo "=== Packages created ==="
ls -la ./artifacts/

- name: Get tag for current commit
id: get_tag
# Check for tags when triggered by main branch push (with tag) or direct tag push
# Can't use github.ref_name because it's "main" when pushing branch+tag together
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
run: |
TAG=$(git tag --points-at HEAD | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | head -n 1)
echo "tag=$TAG" >> $GITHUB_OUTPUT
echo "Found tag: $TAG"

- name: Pack NuGet package
if: steps.get_tag.outputs.tag != ''
run: dotnet pack $SOLUTION --configuration $BUILD_CONFIG --no-build --output ./artifacts
uses: olegtarasov/[email protected]

- name: Publish to NuGet
- name: Extract release notes from CHANGELOG.md
if: steps.get_tag.outputs.tag != ''
run: dotnet nuget push ./artifacts/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
id: extract_notes
uses: mindsers/changelog-reader-action@v2
with:
version: ${{ steps.get_tag.outputs.tag }}
path: ./CHANGELOG.md

- name: Create GitHub Release
if: steps.get_tag.outputs.tag != ''
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ steps.get_tag.outputs.tag }}
generate_release_notes: true
body: ${{ steps.extract_notes.outputs.changes }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
28 changes: 28 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Publish to NuGet

on:
workflow_dispatch:

permissions:
contents: read

jobs:
publish:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'

- name: Restore, Build, and Pack
run: |
dotnet restore *.sln
dotnet build *.sln --configuration Release --no-restore
dotnet pack *.sln --configuration Release --no-build --output ./artifacts

- name: Publish to NuGet
run: dotnet nuget push ./artifacts/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,13 @@ CodeCoverage/
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
nunit-*.xml

# Visual Studio Code
.vscode/

# Rider
.idea/

# Visual Studio
.vs/
52 changes: 52 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added
- `SourceGeneratorContext` library to help creators of source generators.
- `[SourceGeneratorContext]` attribute to mark partial classes for generation.
- Generate doc-comments to partial classes showing different portions of the context available to source generators.
- IncludeAll
- include all available details.
- IncludeAttributeContextTargetSymbol
- GeneratorAttributeSyntaxContext.TargetSymbol details
- IncludeAttributeContextTypeSymbol
- GeneratorAttributeSyntaxContext.TargetSymbol as ITypeSymbol details
- IncludeAttributeContextNamedTypeSymbol
- GeneratorAttributeSyntaxContext.TargetSymbol as INamedTypeSymbol details
- IncludeAttributeContextTargetNode
- GeneratorAttributeSyntaxContext.TargetNode details
- IncludeAttributeContextAttributes
- GeneratorAttributeSyntaxContext.Attributes details
- IncludeAttributeContextAllAttributes
- GeneratorAttributeSyntaxContext.GetAttributes() details
- IncludeGlobalOptions
- AnalyzerConfigOptionsProvider's GlobalOptions details
- IncludeCompilation
- CompilationProvider's Compilation details
- IncludeCompilationOptions
- CompilationProvider's Compilation.Options details
- IncludeCompilationAssembly
- CompilationProvider's Compilation.Assembly details
- IncludeCompilationReferences
- Counts of CompilationProvider's:
- Compilation.References
- Compilation.DirectiveReferences
- Compilation.ExternalReferences
- Compilation.ReferencedAssemblyNames
- IncludeParseOptions
- ParseOptionsProvider's ParseOptions details
- IncludeAdditionalTexts
- AdditionalTextsProvider's AdditionalText details
- IncludeAdditionalTextsOptions
- AdditionalTextsProvider's AdditionalText details combined with AnalyzerConfigOptionsProvider's AnalyzerConfigOptions for the AdditionalText
- IncludeMetadataReferences
- MetadataReferencesProvider's MetadataReference details
- Diagnostic log of the source generation process and timing included.

[Unreleased]: https://github.com/datacute/SourceGeneratorContext/compare/main...develop
19 changes: 19 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project>

<Import Project="version.props" />

<PropertyGroup>
<Authors>Stephen Denne</Authors>
<Copyright>Copyright © Stephen Denne 2024, 2025</Copyright>
<Company>Datacute</Company>
<PackageProjectUrl>https://github.com/datacute/SourceGeneratorContext</PackageProjectUrl>
<PackageReleaseNotes>See full release notes and changelog: $(PackageProjectUrl)/blob/main/CHANGELOG.md</PackageReleaseNotes>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
</PropertyGroup>

<PropertyGroup>
<NoPackageAnalysis>true</NoPackageAnalysis>
<PackageOutputPath>$(MSBuildThisFileDirectory)\artifacts</PackageOutputPath>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>12</LangVersion>
<AssemblyName>Datacute.SourceGeneratorContext.Attribute</AssemblyName>
<RootNamespace>Datacute.SourceGeneratorContext</RootNamespace>
<Nullable>enable</Nullable>
<AssemblyVersion>1.0.0</AssemblyVersion>
</PropertyGroup>

<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

</Project>
134 changes: 134 additions & 0 deletions SourceGeneratorContext.Attribute/SourceGeneratorContextAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
using System;
// ReSharper disable UnusedAutoPropertyAccessor.Global Properties getters are not used as the source generator reads the source code.
// ReSharper disable UnusedParameter.Local Unused parameters are used to demonstrate behaviour.

namespace Datacute.SourceGeneratorContext;

/// <summary>
/// Add this attribute to a partial class to generate doc-comments detailing the source generation context.
/// </summary>
[System.Diagnostics.Conditional("DATACUTE_SOURCEGENERATORCONTEXTATTRIBUTE_USAGES")]
[AttributeUsage(
validOn: AttributeTargets.Class |
AttributeTargets.Interface |
AttributeTargets.Struct, // Method and Property should be allowed too
Inherited = true, // Inherited to show how SyntaxProvider.ForAttributeWithMetadataName doesn't support inheritance
AllowMultiple = true)] // AllowMultiple to show the differences when multiple attributes are applied
public class SourceGeneratorContextAttribute : Attribute
{
/// <remarks>
/// There is a huge amount of information available, but Visual Studio does not scroll doc-comments.
/// So either IncludeAll and view the generated source, or set one of the named parameters to control what gets output:
/// <code>
/// [SourceGeneratorContext(IncludeAll = true)]
/// internal partial class Example;
/// </code>
/// </remarks>
public SourceGeneratorContextAttribute()
{
}

/// <summary>
/// Set to true to include all available details.
/// </summary>
public bool IncludeAll { get; set; }

/// <summary>
/// Set to true to include the GeneratorAttributeSyntaxContext.TargetSymbol details.
/// </summary>
public bool IncludeAttributeContextTargetSymbol { get; set; }

/// <summary>
/// Set to true to include the GeneratorAttributeSyntaxContext.TargetSymbol as ITypeSymbol details.
/// </summary>
public bool IncludeAttributeContextTypeSymbol { get; set; }

/// <summary>
/// Set to true to include the GeneratorAttributeSyntaxContext.TargetSymbol as INamedTypeSymbol details.
/// </summary>
public bool IncludeAttributeContextNamedTypeSymbol { get; set; }

/// <summary>
/// Set to true to include the GeneratorAttributeSyntaxContext.TargetNode details.
/// </summary>
public bool IncludeAttributeContextTargetNode { get; set; }

/// <summary>
/// Set to true to include the GeneratorAttributeSyntaxContext.Attributes details.
/// </summary>
public bool IncludeAttributeContextAttributes { get; set; }

/// <summary>
/// Set to true to include the GeneratorAttributeSyntaxContext.GetAttributes() details.
/// </summary>
public bool IncludeAttributeContextAllAttributes { get; set; }

/// <summary>
/// Set to true to include the AnalyzerConfigOptionsProvider's GlobalOptions details.
/// </summary>
public bool IncludeGlobalOptions { get; set; }

/// <summary>
/// Set to true to include the CompilationProvider's Compilation details.
/// </summary>
public bool IncludeCompilation { get; set; }

/// <summary>
/// Set to true to include the CompilationProvider's Compilation.Options details.
/// </summary>
public bool IncludeCompilationOptions { get; set; }

/// <summary>
/// Set to true to include the CompilationProvider's Compilation.Assembly details.
/// </summary>
public bool IncludeCompilationAssembly { get; set; }

/// <summary>
/// Set to true to include the Counts of CompilationProvider's Compilation.References, Compilation.DirectiveReferences, Compilation.ExternalReferences, and Compilation.ReferencedAssemblyNames.
/// </summary>
public bool IncludeCompilationReferences { get; set; }

/// <summary>
/// Set to true to include the ParseOptionsProvider's ParseOptions details.
/// </summary>
public bool IncludeParseOptions { get; set; }

/// <summary>
/// Set to true to include the AdditionalTextsProvider's AdditionalText details.
/// </summary>
public bool IncludeAdditionalTexts { get; set; }

/// <summary>
/// Set to true to include the AdditionalTextsProvider's AdditionalText details combined with AnalyzerConfigOptionsProvider's AnalyzerConfigOptions for the AdditionalText.
/// </summary>
public bool IncludeAdditionalTextsOptions { get; set; }

/// <summary>
/// Set to true to include the MetadataReferencesProvider's MetadataReference details.
/// </summary>
public bool IncludeMetadataReferences { get; set; }


#region Demonstration purposes only

/// <summary>
/// Example of a named parameter.
/// </summary>
public string ExampleNamedParameter { get; set; } =
string.Empty; // only used for demonstrating working with Named Parameters

/// <summary>
/// Example of an optional parameter.
/// </summary>
/// <param name="exampleOptionalParameter"></param>
public
SourceGeneratorContextAttribute(
string? exampleOptionalParameter =
null) // only used for demonstrating working with Constructor Arguments
{
// The constructor arguments do not need to be assigned to fields or properties
// as the source of the supplied values is what is available to the source generator
}

#endregion
}
42 changes: 42 additions & 0 deletions SourceGeneratorContext.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.13.35825.156 d17.13
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceGeneratorContext", "SourceGeneratorContext\SourceGeneratorContext.csproj", "{DB6CCC3F-D197-48F7-B166-E9194233939D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceGeneratorContext.Attribute", "SourceGeneratorContext.Attribute\SourceGeneratorContext.Attribute.csproj", "{394AEA19-BF98-4427-BE95-BBD90A7D65A5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceGeneratorContextExample", "SourceGeneratorContextExample\SourceGeneratorContextExample.csproj", "{56E79762-6BB4-4042-9EAB-2D819C2FDAB0}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}"
ProjectSection(SolutionItems) = preProject
CHANGELOG.md = CHANGELOG.md
Directory.Build.props = Directory.Build.props
LICENSE = LICENSE
version.props = version.props
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DB6CCC3F-D197-48F7-B166-E9194233939D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DB6CCC3F-D197-48F7-B166-E9194233939D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DB6CCC3F-D197-48F7-B166-E9194233939D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DB6CCC3F-D197-48F7-B166-E9194233939D}.Release|Any CPU.Build.0 = Release|Any CPU
{394AEA19-BF98-4427-BE95-BBD90A7D65A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{394AEA19-BF98-4427-BE95-BBD90A7D65A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{394AEA19-BF98-4427-BE95-BBD90A7D65A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{394AEA19-BF98-4427-BE95-BBD90A7D65A5}.Release|Any CPU.Build.0 = Release|Any CPU
{56E79762-6BB4-4042-9EAB-2D819C2FDAB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{56E79762-6BB4-4042-9EAB-2D819C2FDAB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{56E79762-6BB4-4042-9EAB-2D819C2FDAB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{56E79762-6BB4-4042-9EAB-2D819C2FDAB0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
Loading