diff --git a/README.md b/README.md index 6926624..c1662a5 100644 --- a/README.md +++ b/README.md @@ -246,28 +246,11 @@ When your source generator is being used in the wild it can happen there are exc -## Project Layout - -This library is made up of quite a few different components leveraging various techniques to help -make the experience of integrating the library simple. Below I break down the purpose of each project and what they provide to you as the end users. - -### Source.Generator.Foundations - -A very small library that only appears to contain a C# analyzer for adding errors and warnings when trying to use this library. However once compiled this dll will have embedded as a resource every other project that is needed during compilation. - - -### Source.Generator.Foundations.Contracts - -Contains common classes and utility methods that can be leveraged by source generators. - -### Source.Generator.Foundations.MSBuild - -Contains a custom MSBuild C# target implementation used to figure out which assemblies should be embedded as resources and which should be ignored. For example this will not embed any resources that are part of `.netstandard`. - -### Source.Generator.Foundations.Shared - -A shared project that every project that references this will have the files copied to it. +## Projects Using SGF + * [ByronMayne.AutoFactories](https://github.com/ByronMayne/AutoFactories) + * [AssetRipper.AssetRipper](https://github.com/AssetRipper/AssetRipper) +*Want to add your project here? Just make a PR* ## Attribution Icon by Drywall icons created by HAJICON - Flaticon \ No newline at end of file diff --git a/src/SourceGenerator.Foundations.Contracts/ISgfInitializationContext.cs b/src/SourceGenerator.Foundations.Contracts/ISgfInitializationContext.cs new file mode 100644 index 0000000..0f65866 --- /dev/null +++ b/src/SourceGenerator.Foundations.Contracts/ISgfInitializationContext.cs @@ -0,0 +1,95 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using System; + +namespace SGF +{ + /// + /// An abstraction on top of that allow for some extra api + /// and features not exposed in the public base. + /// + public interface ISgfInitializationContext + { + /// + /// Gets access to the provider of + /// + IncrementalValuesProvider AdditionalTextsProvider { get; } + + /// + /// Gets access to the provider for + /// + IncrementalValueProvider AnalyzerConfigOptionsProvider { get; } + + /// + /// Gets access to the provider for + /// + IncrementalValueProvider CompilationProvider { get; } + + /// + /// Gets access to the provider for + /// + IncrementalValuesProvider MetadataReferencesProvider { get; } + + /// + /// Gets access to the provider for + /// + IncrementalValueProvider ParseOptionsProvider { get; } + + /// + /// Gets access to the provider for + /// + SyntaxValueProvider SyntaxProvider { get; } + + /// + /// Gets the original that was produced by + /// roslyn. This should only be used in cases where you are interacting with third party api that needs it. The + /// issue is that SGF provides type loading an exception handling that MUST run before your code otherwise the generator + /// will crash. + /// + IncrementalGeneratorInitializationContext OriginalContext { get; } + + /// + /// Register a callback that roduce source that is semantically 'invisible'; that is the added code has a runtime effect, + /// but adds no user visible types in completion or intellisense etc. + /// + /// The source type + /// The source provider + /// The action that will be invoked + void RegisterImplementationSourceOutput(IncrementalValueProvider source, Action action); + + /// + /// Register a callback that roduce source that is semantically 'invisible'; that is the added code has a runtime effect, + /// but adds no user visible types in completion or intellisense etc. + /// + /// The source type + /// The source provider + /// The action that will be invoked + void RegisterImplementationSourceOutput(IncrementalValuesProvider sources, Action action); + + /// + /// Register a callback that produces source that will be added regardless of changes to any of the providers. This source does not have access to analyzer + /// information so it must be constant. Unlike other callbacks types added here can be referenced as it's added to the compiliation info. This is often used + /// for creating that are used by the source generator. + /// + /// + void RegisterPostInitializationOutput(Action callback); + + /// + /// Registers a callback that produces source that effects comepliation and intelliesense. This callback will effect IDE evaluation time so + /// preformance is critical. + /// + /// The source type + /// The source to add + /// The action to be preformed + void RegisterSourceOutput(IncrementalValueProvider source, Action action); + + /// + /// Registers a callback that produces source that effects comepliation and intelliesense. This callback will effect IDE evaluation time so + /// preformance is critical. + /// + /// The source type + /// The source to add + /// The action to be preformed + void RegisterSourceOutput(IncrementalValuesProvider sourcess, Action action); + } +} \ No newline at end of file diff --git a/src/SourceGenerator.Foundations.Contracts/ISgfSourceProductionContext.cs b/src/SourceGenerator.Foundations.Contracts/ISgfSourceProductionContext.cs new file mode 100644 index 0000000..9455331 --- /dev/null +++ b/src/SourceGenerator.Foundations.Contracts/ISgfSourceProductionContext.cs @@ -0,0 +1,52 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; +using System.Threading; + +namespace SGF +{ + /// + /// Provides an abstraction of + /// + public interface ISgfSourceProductionContext + { + /// + /// + /// + CancellationToken CancellationToken { get; } + + /// + /// Gets the number of source files that were added + /// + int SourceCount { get; } + + /// + /// Gets the original that was created. This should only be used + /// when required by third party apis. Using this side steps the exception handling and assembly + /// resolution that comes with SGF. + /// + SourceProductionContext OriginalContext { get; } + + /// + /// Adds source code in the form of a to the compilation. + /// + /// An identifier that can be used to reference this source text, must be unique within this generator + /// The source code to add to the compilation + void AddSource(string hintName, SourceText sourceText); + + /// + /// Adds a to the compilation + /// + /// An identifier that can be used to reference this source text, must be unique within this generator + /// The to add to the compilation + void AddSource(string hintName, string source); + + /// + /// Adds a to the users compilation + /// + /// The diagnostic that should be added to the compilation + /// + /// The severity of the diagnostic may cause the compilation to fail, depending on the settings. + /// + void ReportDiagnostic(Diagnostic diagnostic); + } +} \ No newline at end of file diff --git a/src/SourceGenerator.Foundations.Contracts/SgfInitializationContext.cs b/src/SourceGenerator.Foundations.Contracts/SgfInitializationContext.cs index e5834f1..61d5309 100644 --- a/src/SourceGenerator.Foundations.Contracts/SgfInitializationContext.cs +++ b/src/SourceGenerator.Foundations.Contracts/SgfInitializationContext.cs @@ -6,22 +6,37 @@ namespace SGF { + /// /// Middleware wrapper around a to allow for /// wrapping with exception handling and provide a better user experience /// - public readonly struct SgfInitializationContext + public readonly struct SgfInitializationContext : ISgfInitializationContext { private readonly ILogger m_logger; private readonly IncrementalGeneratorInitializationContext m_context; + /// public SyntaxValueProvider SyntaxProvider => m_context.SyntaxProvider; + + /// public IncrementalValueProvider CompilationProvider => m_context.CompilationProvider; + + /// public IncrementalValueProvider ParseOptionsProvider => m_context.ParseOptionsProvider; + + /// public IncrementalValuesProvider AdditionalTextsProvider => m_context.AdditionalTextsProvider; + + /// public IncrementalValueProvider AnalyzerConfigOptionsProvider => m_context.AnalyzerConfigOptionsProvider; + + /// public IncrementalValuesProvider MetadataReferencesProvider => m_context.MetadataReferencesProvider; + /// + IncrementalGeneratorInitializationContext ISgfInitializationContext.OriginalContext => m_context; + public SgfInitializationContext( IncrementalGeneratorInitializationContext context, ILogger logger) @@ -30,6 +45,7 @@ public SgfInitializationContext( m_context = context; } + /// public void RegisterSourceOutput(IncrementalValueProvider source, Action action) { ILogger logger = m_logger; @@ -48,6 +64,7 @@ void wrappedAction(SourceProductionContext context, TSource source) m_context.RegisterSourceOutput(source, wrappedAction); } + /// public void RegisterSourceOutput(IncrementalValuesProvider source, Action action) { ILogger logger = m_logger; @@ -65,6 +82,7 @@ void wrappedAction(SourceProductionContext context, TSource source) m_context.RegisterSourceOutput(source, wrappedAction); } + /// public void RegisterImplementationSourceOutput(IncrementalValueProvider source, Action action) { ILogger logger = m_logger; @@ -84,8 +102,7 @@ void wrappedAction(SourceProductionContext context, TSource source) m_context.RegisterImplementationSourceOutput(source, wrappedAction); } - - + /// public void RegisterImplementationSourceOutput(IncrementalValuesProvider source, Action action) { ILogger logger = m_logger; @@ -104,9 +121,10 @@ void wrappedAction(SourceProductionContext context, TSource source) m_context.RegisterImplementationSourceOutput(source, wrappedAction); } + /// public void RegisterPostInitializationOutput(Action callback) { - ILogger logger = m_logger; + ILogger logger = m_logger; void wrappedCallback(IncrementalGeneratorPostInitializationContext context) { try @@ -121,6 +139,9 @@ void wrappedCallback(IncrementalGeneratorPostInitializationContext context) m_context.RegisterPostInitializationOutput(wrappedCallback); } + /// + /// Logs an exception to the lagger to be presented in the IDE. + /// private static void LogException(ILogger logger, Exception exception, MethodInfo actionInfo) { string methodName = actionInfo.Name; diff --git a/src/SourceGenerator.Foundations.Contracts/SgfSourceProductionContext.cs b/src/SourceGenerator.Foundations.Contracts/SgfSourceProductionContext.cs index baeb07d..0c34a33 100644 --- a/src/SourceGenerator.Foundations.Contracts/SgfSourceProductionContext.cs +++ b/src/SourceGenerator.Foundations.Contracts/SgfSourceProductionContext.cs @@ -1,26 +1,24 @@ -using Microsoft.CodeAnalysis.Text; -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; using SGF.Diagnostics; using System.Text; using System.Threading; -using System.Reflection; -using System; namespace SGF { /// /// Wrapper around a used to help capture errors and report logs /// - public struct SgfSourceProductionContext + public struct SgfSourceProductionContext : ISgfSourceProductionContext { private readonly ILogger m_logger; private readonly SourceProductionContext m_context; - /// - /// Gets the number of source files that were added - /// + /// public int SourceCount { get; private set; } + /// + SourceProductionContext ISgfSourceProductionContext.OriginalContext => m_context; /// /// A token that will be canceled when generation should stop @@ -32,21 +30,14 @@ internal SgfSourceProductionContext(SourceProductionContext context, ILogger log SourceCount = 0; m_logger = logger; m_context = context; - + } - /// - /// Adds source code in the form of a to the compilation. - /// - /// An identifier that can be used to reference this source text, must be unique within this generator - /// The source code to add to the compilation - public void AddSource(string hintName, string source) => AddSource(hintName, SourceText.From(source, Encoding.UTF8)); + /// + public void AddSource(string hintName, string source) + => AddSource(hintName, SourceText.From(source, Encoding.UTF8)); - /// - /// Adds a to the compilation - /// - /// An identifier that can be used to reference this source text, must be unique within this generator - /// The to add to the compilation + /// public void AddSource(string hintName, SourceText sourceText) { SourceCount++; @@ -54,13 +45,8 @@ public void AddSource(string hintName, SourceText sourceText) m_context.AddSource(hintName, sourceText); } - /// - /// Adds a to the users compilation - /// - /// The diagnostic that should be added to the compilation - /// - /// The severity of the diagnostic may cause the compilation to fail, depending on the settings. - /// - public void ReportDiagnostic(Diagnostic diagnostic) => m_context.ReportDiagnostic(diagnostic); + /// + public void ReportDiagnostic(Diagnostic diagnostic) + => m_context.ReportDiagnostic(diagnostic); } } \ No newline at end of file