Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update generator public API names: #47222

Merged
merged 8 commits into from
Aug 29, 2020
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
44 changes: 22 additions & 22 deletions docs/features/source-generators.cookbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ Create a generator that will create the missing type when run:
[Generator]
public class CustomGenerator : ISourceGenerator
{
public void Initialize(InitializationContext context) {}
public void Initialize(GeneratorInitializationContext context) {}

public void Execute(SourceGeneratorContext context)
public void Execute(GeneratorExecutionContext context)
{
context.AddSource("myGeneratedFile.cs", SourceText.From(@"
namespace GeneratedNamespace
Expand All @@ -108,17 +108,17 @@ namespace GeneratedNamespace

**User scenario:** As a generator author I want to be able to transform an external non-C# file into an equivalent C# representation.

**Solution:** Use the additional files property of the `SourceGeneratorContext` to retrieve the contents of the file, convert it to the C# representation and return it.
**Solution:** Use the additional files property of the `GeneratorExecutionContext` to retrieve the contents of the file, convert it to the C# representation and return it.

**Example:**

```csharp
[Generator]
public class FileTransformGenerator : ISourceGenerator
{
public void Initialize(InitializationContext context) {}
public void Initialize(GeneratorInitializationContext context) {}

public void Execute(SourceGeneratorContext context)
public void Execute(GeneratorExecutionContext context)
{
// find anything that matches our files
var myFiles = context.AnalyzerOptions.AdditionalFiles.Where(at => at.Path.EndsWith(".xml"));
Expand Down Expand Up @@ -163,13 +163,13 @@ public partial class UserClass
[Generator]
public class AugmentingGenerator : ISourceGenerator
{
public void Initialize(InitializationContext context)
public void Initialize(GeneratorInitializationContext context)
{
// Register a factory that can create our custom syntax receiver
context.RegisterForSyntaxNotifications(() => new MySyntaxReceiver());
}

public void Execute(SourceGeneratorContext context)
public void Execute(GeneratorExecutionContext context)
{
// the generator infrastructure will create a receiver and populate it
// we can retrieve the populated instance via the context
Expand Down Expand Up @@ -216,7 +216,7 @@ public partial class {userClass.Identifier}

**User Scenario:** As a generator author I want to be able to add diagnostics to the users compilation.

**Solution:** Diagnostics can be added to the compilation via `SourceGeneratorContext.ReportDiagnostic()`. These can be in response to the content of the users compilation:
**Solution:** Diagnostics can be added to the compilation via `GeneratorExecutionContext.ReportDiagnostic()`. These can be in response to the content of the users compilation:
for instance if the generator is expecting a well formed `AdditionalFile` but can not parse it, the generator could emit a warning notifying the user that generation can not proceed.

For code-based issues, the generator author should also consider implementing a [diagnostic analyzer](https://docs.microsoft.com/en-us/visualstudio/code-quality/roslyn-analyzers-overview?view=vs-2019) that identifies the problem, and offers a code-fix to resolve it.
Expand All @@ -235,7 +235,7 @@ public class MyXmlGenerator : ISourceGenerator
DiagnosticSeverity.Warning,
isEnabledByDefault: true);

public void Execute(SourceGeneratorContext context)
public void Execute(GeneratorExecutionContext context)
{
// Using the context, get any additional files that end in .xml
IEnumerable<AdditionalText> xmlFiles = context.AdditionalFiles.Where(at => at.Path.EndsWith(".xml", StringComparison.OrdinalIgnoreCase));
Expand All @@ -258,7 +258,7 @@ public class MyXmlGenerator : ISourceGenerator
}
}

public void Initialize(InitializationContext context)
public void Initialize(GeneratorInitializationContext context)
{
}
}
Expand Down Expand Up @@ -390,7 +390,7 @@ using System.Linq;
[Generator]
public class SerializingGenerator : ISourceGenerator
{
public void Execute(SourceGeneratorContext context)
public void Execute(GeneratorExecutionContext context)
{
// check that the users compilation references the expected library
if (!context.Compilation.ReferencedAssemblyNames.Any(ai => ai.Name.Equals("Newtonsoft.Json", StringComparison.OrdinalIgnoreCase)))
Expand All @@ -399,7 +399,7 @@ public class SerializingGenerator : ISourceGenerator
}
}

public void Initialize(InitializationContext context)
public void Initialize(GeneratorInitializationContext context)
{
}
}
Expand Down Expand Up @@ -436,7 +436,7 @@ The author would then have to package the `Newtonsoft.Json` library alongside th
[Generator]
public class JsonUsingGenerator : ISourceGenerator
{
public void Execute(SourceGeneratorContext context)
public void Execute(GeneratorExecutionContext context)
{
// use the newtonsoft.json library, but don't add any source code that depends on it

Expand All @@ -453,7 +453,7 @@ namespace GeneratedNamespace

}

public void Initialize(InitializationContext context)
public void Initialize(GeneratorInitializationContext context)
{
}
}
Expand All @@ -469,7 +469,7 @@ namespace GeneratedNamespace
- As a generator author I want to access key-value pairs that customize the generator output.
- As a user of a generator I want to be able to customize the generated code and override defaults.

**Solution**: Generators can access analyzer config values via the `AnalyzerConfigOptions` property of the `SourceGeneratorContext`. Analyzer config values can either be accessed in the context of a `SyntaxTree`, `AdditionalFile` or globally via `GlobalOptions`. Global options are 'ambient' in that they don't apply to any specific context, but will be included when requesting option within a specific context.
**Solution**: Generators can access analyzer config values via the `AnalyzerConfigOptions` property of the `GeneratorExecutionContext`. Analyzer config values can either be accessed in the context of a `SyntaxTree`, `AdditionalFile` or globally via `GlobalOptions`. Global options are 'ambient' in that they don't apply to any specific context, but will be included when requesting option within a specific context.

A generator is free to use a global option to customize its output. For example, consider a generator that can optionally emit logging. The author may choose to check the value of a global analyzer config value in order to control whether or not to emit the logging code. A user can then choose to enable the setting per project via an `.editorconfig` file:

Expand All @@ -481,7 +481,7 @@ mygenerator_emit_logging = true
[Generator]
public class MyGenerator : ISourceGenerator
{
public void Execute(SourceGeneratorContext context)
public void Execute(GeneratorExecutionContext context)
{
// control logging via analyzerconfig
bool emitLogging = false;
Expand All @@ -493,7 +493,7 @@ public class MyGenerator : ISourceGenerator
// add the source with or without logging...
}

public void Initialize(InitializationContext context)
public void Initialize(GeneratorInitializationContext context)
{
}
}
Expand All @@ -518,7 +518,7 @@ For example, consider a generator that creates source based on additional files,
</ItemGroup>
```

The value of `MyGenerator_EnableLogging` property will then be emitted to a generated analyzer config file before build, with a name of `build_property.MyGenerator_EnableLogging`. The generator is then able read this property from via the `AnalyzerConfigOptions` property of the `SourceGeneratorContext`:
The value of `MyGenerator_EnableLogging` property will then be emitted to a generated analyzer config file before build, with a name of `build_property.MyGenerator_EnableLogging`. The generator is then able read this property from via the `AnalyzerConfigOptions` property of the `GeneratorExecutionContext`:

```c#
context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.MyGenerator_EnableLogging", out var emitLoggingSwitch);
Expand Down Expand Up @@ -592,7 +592,7 @@ MyGenerator.cs:
[Generator]
public class MyGenerator : ISourceGenerator
{
public void Execute(SourceGeneratorContext context)
public void Execute(GeneratorExecutionContext context)
{
// global logging from project file
bool emitLoggingGlobal = false;
Expand All @@ -614,7 +614,7 @@ public class MyGenerator : ISourceGenerator
}
}

public void Initialize(InitializationContext context)
public void Initialize(GeneratorInitializationContext context)
{
}
}
Expand All @@ -633,13 +633,13 @@ It is anticipated there will be a mechanism for providing symbol mapping for lig
[Generator]
public class InteractiveGenerator : ISourceGenerator
{
public void Initialize(InitializationContext context)
public void Initialize(GeneratorInitializationContext context)
{
// Register for additional file callbacks
context.RegisterForAdditionalFileChanges(OnAdditionalFilesChanged);
}

public void Execute(SourceGeneratorContext context)
public void Execute(GeneratorExecutionContext context)
{
// generators must always support a total generation pass
}
Expand Down
14 changes: 7 additions & 7 deletions docs/features/source-generators.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ namespace Microsoft.CodeAnalysis
{
public interface ISourceGenerator
{
void Initialize(InitializationContext context);
void Execute(SourceGeneratorContext context);
void Initialize(GeneratorInitializationContext context);
void Execute(GeneratorExecutionContext context);
}
}
```
Expand All @@ -43,11 +43,11 @@ Since generators are loaded from external assemblies, a generator cannot be used
the assembly in which it is defined.

`ISourceGenerator` has an `Initialize` method that is called by the host (either the IDE or
the command-line compiler) exactly once. `Initialize` passes an instance of `InitializationContext`
the command-line compiler) exactly once. `Initialize` passes an instance of `GeneratorInitializationContext`
which can be used by the generator to register a set of callbacks that affect how future generation
passes will occur.

The main generation pass occurs via the `Execute` method. `Execute` passes an instance of `SourceGeneratorContext`
The main generation pass occurs via the `Execute` method. `Execute` passes an instance of `GeneratorExecutionContext`
that provides access to the current `Compilation` and allows the generator to alter the resulting output `Compilation`
by adding source and reporting diagnostics.

Expand All @@ -57,7 +57,7 @@ collection, allowing for generation decisions to based on more than just the use
```csharp
namespace Microsoft.CodeAnalysis
{
public readonly struct SourceGeneratorContext
public readonly struct GeneratorExecutionContext
{
public ImmutableArray<AdditionalText> AdditionalFiles { get; }

Expand Down Expand Up @@ -124,7 +124,7 @@ file might look something like:
```csharp
namespace Microsoft.CodeAnalysis
{
public struct InitializationContext
public struct GeneratorInitializationContext
{
public void RegisterForAdditionalFileChanges(EditCallback<AdditionalFileEdit> callback){ }
}
Expand All @@ -148,7 +148,7 @@ generator.

By default, generated texts will be persisted to a `GeneratedFiles/{GeneratorAssemblyName}`
sub-folder within `CommandLineArguments.OutputDirectory`. The `fileNameHint` from
`SourceGeneratorContext.AddSource` will be used to create a unique name, with appropriate
`GeneratorExecutionContext.AddSource` will be used to create a unique name, with appropriate
collision renaming applied if required. For instance, on Windows a call to
`AddSource("MyCode", ...);` from `MyGenerator.dll` for a C# project might be
persisted as `obj/debug/GeneratedFiles/MyGenerator.dll/MyCode.cs`.
Expand Down
4 changes: 2 additions & 2 deletions src/Compilers/CSharp/Portable/CommandLine/CSharpCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,8 @@ private protected override Compilation RunGenerators(Compilation input, ParseOpt
return input;
}

var driver = new CSharpGeneratorDriver(parseOptions, generators, analyzerConfigProvider, additionalTexts);
driver.RunFullGeneration(input, out var compilationOut, out var generatorDiagnostics);
var driver = CSharpGeneratorDriver.Create(generators, additionalTexts, (CSharpParseOptions)parseOptions, analyzerConfigProvider);
driver.RunGeneratorsAndUpdateCompilation(input, out var compilationOut, out var generatorDiagnostics);
diagnostics.AddRange(generatorDiagnostics);
return compilationOut;
}
Expand Down
1 change: 0 additions & 1 deletion src/Compilers/CSharp/Portable/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ Microsoft.CodeAnalysis.CSharp.CSharpDiagnosticFormatter
Microsoft.CodeAnalysis.CSharp.CSharpExtensions
Microsoft.CodeAnalysis.CSharp.CSharpFileSystemExtensions
Microsoft.CodeAnalysis.CSharp.CSharpGeneratorDriver
Microsoft.CodeAnalysis.CSharp.CSharpGeneratorDriver.CSharpGeneratorDriver(Microsoft.CodeAnalysis.ParseOptions parseOptions, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ISourceGenerator> generators, Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptionsProvider optionsProvider, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.AdditionalText> additionalTexts) -> void
Microsoft.CodeAnalysis.CSharp.CSharpParseOptions
Microsoft.CodeAnalysis.CSharp.CSharpParseOptions.CSharpParseOptions(Microsoft.CodeAnalysis.CSharp.LanguageVersion languageVersion = Microsoft.CodeAnalysis.CSharp.LanguageVersion.Default, Microsoft.CodeAnalysis.DocumentationMode documentationMode = Microsoft.CodeAnalysis.DocumentationMode.Parse, Microsoft.CodeAnalysis.SourceCodeKind kind = Microsoft.CodeAnalysis.SourceCodeKind.Regular, System.Collections.Generic.IEnumerable<string> preprocessorSymbols = null) -> void
Microsoft.CodeAnalysis.CSharp.CSharpParseOptions.Equals(Microsoft.CodeAnalysis.CSharp.CSharpParseOptions other) -> bool
Expand Down
3 changes: 3 additions & 0 deletions src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Microsoft.CodeAnalysis.CSharp.CSharpGeneratorDriver.CSharpGeneratorDriver(Microsoft.CodeAnalysis.CSharp.CSharpParseOptions parseOptions, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ISourceGenerator> generators, Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptionsProvider optionsProvider, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.AdditionalText> additionalTexts) -> void
Microsoft.CodeAnalysis.CSharp.Conversion.IsConditionalExpression.get -> bool
Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax.AddModifiers(params Microsoft.CodeAnalysis.SyntaxToken[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax.WithModifiers(Microsoft.CodeAnalysis.SyntaxTokenList modifiers) -> Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax
Expand Down Expand Up @@ -119,6 +120,8 @@ override Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.Modif
*REMOVED*static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.FunctionPointerType(Microsoft.CodeAnalysis.SeparatedSyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax> parameters = default(Microsoft.CodeAnalysis.SeparatedSyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax>)) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
*REMOVED*static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.FunctionPointerType(Microsoft.CodeAnalysis.SyntaxToken callingConvention, Microsoft.CodeAnalysis.SeparatedSyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax> parameters) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
*REMOVED*static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.FunctionPointerType(Microsoft.CodeAnalysis.SyntaxToken delegateKeyword, Microsoft.CodeAnalysis.SyntaxToken asteriskToken, Microsoft.CodeAnalysis.SyntaxToken callingConvention, Microsoft.CodeAnalysis.SyntaxToken lessThanToken, Microsoft.CodeAnalysis.SeparatedSyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax> parameters, Microsoft.CodeAnalysis.SyntaxToken greaterThanToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
static Microsoft.CodeAnalysis.CSharp.CSharpGeneratorDriver.Create(System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.ISourceGenerator> generators, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.AdditionalText> additionalTexts = null, Microsoft.CodeAnalysis.CSharp.CSharpParseOptions parseOptions = null, Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptionsProvider optionsProvider = null) -> Microsoft.CodeAnalysis.CSharp.CSharpGeneratorDriver
static Microsoft.CodeAnalysis.CSharp.CSharpGeneratorDriver.Create(params Microsoft.CodeAnalysis.ISourceGenerator[] generators) -> Microsoft.CodeAnalysis.CSharp.CSharpGeneratorDriver
static Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.Create(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode root, Microsoft.CodeAnalysis.CSharp.CSharpParseOptions options = null, string path = "", System.Text.Encoding encoding = null) -> Microsoft.CodeAnalysis.SyntaxTree
static Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.Create(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode root, Microsoft.CodeAnalysis.CSharp.CSharpParseOptions options, string path, System.Text.Encoding encoding, System.Collections.Immutable.ImmutableDictionary<string, Microsoft.CodeAnalysis.ReportDiagnostic> diagnosticOptions, bool? isGeneratedCode) -> Microsoft.CodeAnalysis.SyntaxTree
static Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseText(Microsoft.CodeAnalysis.Text.SourceText text, Microsoft.CodeAnalysis.CSharp.CSharpParseOptions options = null, string path = "", System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.SyntaxTree
Expand Down
Loading