未验证 提交 847b97ba 编写于 作者: M msftbot[bot] 提交者: GitHub

Merge pull request #44971 from dotnet/merges/release/dev16.7-preview3-to-master

Merge release/dev16.7-preview3 to master
......@@ -399,7 +399,7 @@ protected override bool TryGetCompilerDiagnosticCode(string diagnosticId, out ui
}
}
private protected override Compilation RunGenerators(Compilation input, ParseOptions parseOptions, ImmutableArray<ISourceGenerator> generators, ImmutableArray<AdditionalText> additionalTexts, DiagnosticBag diagnostics)
private protected override Compilation RunGenerators(Compilation input, ParseOptions parseOptions, ImmutableArray<ISourceGenerator> generators, AnalyzerConfigOptionsProvider analyzerConfigProvider, ImmutableArray<AdditionalText> additionalTexts, DiagnosticBag diagnostics)
{
// https://github.com/dotnet/roslyn/issues/42565: for now we gate behind langver == preview. We'll remove this before final shipping, as the feature is langver agnostic
if (((CSharpParseOptions)parseOptions).LanguageVersion != LanguageVersion.Preview)
......@@ -407,7 +407,7 @@ private protected override Compilation RunGenerators(Compilation input, ParseOpt
return input;
}
var driver = new CSharpGeneratorDriver(parseOptions, generators, additionalTexts);
var driver = new CSharpGeneratorDriver(parseOptions, generators, analyzerConfigProvider, additionalTexts);
driver.RunFullGeneration(input, out var compilationOut, out var generatorDiagnostics);
diagnostics.AddRange(generatorDiagnostics);
return compilationOut;
......
......@@ -33,7 +33,7 @@ abstract Microsoft.CodeAnalysis.CSharp.Syntax.BaseObjectCreationExpressionSyntax
abstract Microsoft.CodeAnalysis.CSharp.Syntax.BaseObjectCreationExpressionSyntax.Initializer.get -> Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax
abstract Microsoft.CodeAnalysis.CSharp.Syntax.BaseObjectCreationExpressionSyntax.NewKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken
Microsoft.CodeAnalysis.CSharp.CSharpGeneratorDriver
Microsoft.CodeAnalysis.CSharp.CSharpGeneratorDriver.CSharpGeneratorDriver(Microsoft.CodeAnalysis.ParseOptions parseOptions, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ISourceGenerator> generators, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.AdditionalText> additionalTexts) -> void
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.Syntax.FunctionPointerTypeSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.AddParameters(params Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.AsteriskToken.get -> Microsoft.CodeAnalysis.SyntaxToken
......
......@@ -19,8 +19,8 @@ namespace Microsoft.CodeAnalysis.CSharp
{
public sealed class CSharpGeneratorDriver : GeneratorDriver
{
public CSharpGeneratorDriver(ParseOptions parseOptions, ImmutableArray<ISourceGenerator> generators, ImmutableArray<AdditionalText> additionalTexts)
: base(parseOptions, generators, additionalTexts)
public CSharpGeneratorDriver(ParseOptions parseOptions, ImmutableArray<ISourceGenerator> generators, AnalyzerConfigOptionsProvider optionsProvider, ImmutableArray<AdditionalText> additionalTexts)
: base(parseOptions, generators, optionsProvider, additionalTexts)
{
}
......
......@@ -28,6 +28,7 @@
using Microsoft.DiaSymReader;
using Roslyn.Test.PdbUtilities;
using Roslyn.Test.Utilities;
using Roslyn.Test.Utilities.TestGenerators;
using Roslyn.Utilities;
using Xunit;
using static Microsoft.CodeAnalysis.CommonDiagnosticAnalyzers;
......@@ -12232,7 +12233,7 @@ class C
}");
var generatedSource = "public class D { }";
var generator = new SimpleGenerator(generatedSource, "generatedSource.cs");
var generator = new SingleFileTestGenerator(generatedSource, "generatedSource.cs");
VerifyOutput(dir, src, includeCurrentAssemblyAsAnalyzerReference: false, additionalFlags: new[] { "/langversion:preview", "/debug:embedded", "/out:embed.exe" }, generators: new[] { generator }, analyzers: null);
......@@ -12256,8 +12257,8 @@ public void SourceGenerators_EmbeddedSources_MultipleFiles(string source1, strin
class C
{
}");
var generator = new SimpleGenerator(source1, source1Name);
var generator2 = new SimpleGenerator2(source2, source2Name);
var generator = new SingleFileTestGenerator(source1, source1Name);
var generator2 = new SingleFileTestGenerator2(source2, source2Name);
VerifyOutput(dir, src, includeCurrentAssemblyAsAnalyzerReference: false, additionalFlags: new[] { "/langversion:preview", "/debug:embedded", "/out:embed.exe" }, generators: new[] { generator, generator2 }, analyzers: null);
......@@ -12287,11 +12288,123 @@ class C
[*.cs]
key = value");
var generator = new SimpleGenerator("public class D {}", "generated.cs");
var generator = new SingleFileTestGenerator("public class D {}", "generated.cs");
VerifyOutput(dir, src, includeCurrentAssemblyAsAnalyzerReference: false, additionalFlags: new[] { "/langversion:preview", "/analyzerconfig:" + analyzerConfig.Path }, generators: new[] { generator }, analyzers: null);
}
[Fact]
public void SourceGeneratorsCanReadAnalyzerConfig()
{
var dir = Temp.CreateDirectory();
var src = dir.CreateFile("temp.cs").WriteAllText(@"
class C
{
}");
var analyzerConfig1 = dir.CreateFile(".globaleditorconfig").WriteAllText(@"
is_global = true
key1 = value1
[*.cs]
key2 = value2
[*.vb]
key3 = value3");
var analyzerConfig2 = dir.CreateFile(".editorconfig").WriteAllText(@"
[*.cs]
key4 = value4
[*.vb]
key5 = value5");
var subDir = dir.CreateDirectory("subDir");
var analyzerConfig3 = subDir.CreateFile(".editorconfig").WriteAllText(@"
[*.cs]
key6 = value6
[*.vb]
key7 = value7");
var generator = new CallbackGenerator((ic) => { }, (gc) =>
{
// can get the global options
var globalOptions = gc.AnalyzerConfigOptions.GlobalOptions;
Assert.True(globalOptions.TryGetValue("key1", out var keyValue));
Assert.Equal("value1", keyValue);
Assert.False(globalOptions.TryGetValue("key2", out _));
Assert.False(globalOptions.TryGetValue("key3", out _));
Assert.False(globalOptions.TryGetValue("key4", out _));
Assert.False(globalOptions.TryGetValue("key5", out _));
Assert.False(globalOptions.TryGetValue("key6", out _));
Assert.False(globalOptions.TryGetValue("key7", out _));
// can get the options for class C
var classOptions = gc.AnalyzerConfigOptions.GetOptions(gc.Compilation.SyntaxTrees.First());
Assert.True(classOptions.TryGetValue("key1", out keyValue));
Assert.Equal("value1", keyValue);
Assert.False(classOptions.TryGetValue("key2", out _));
Assert.False(classOptions.TryGetValue("key3", out _));
Assert.True(classOptions.TryGetValue("key4", out keyValue));
Assert.Equal("value4", keyValue);
Assert.False(classOptions.TryGetValue("key5", out _));
Assert.False(classOptions.TryGetValue("key6", out _));
Assert.False(classOptions.TryGetValue("key7", out _));
});
var args = new[] {
"/langversion:preview",
"/analyzerconfig:" + analyzerConfig1.Path,
"/analyzerconfig:" + analyzerConfig2.Path,
"/analyzerconfig:" + analyzerConfig3.Path,
"/t:library",
src.Path
};
var cmd = CreateCSharpCompiler(null, dir.Path, args, generators: ImmutableArray.Create<ISourceGenerator>(generator));
var outWriter = new StringWriter(CultureInfo.InvariantCulture);
var exitCode = cmd.Run(outWriter);
Assert.Equal(0, exitCode);
// test for both the original tree and the generated one
var provider = cmd.AnalyzerOptions.AnalyzerConfigOptionsProvider;
// get the global options
var globalOptions = provider.GlobalOptions;
Assert.True(globalOptions.TryGetValue("key1", out var keyValue));
Assert.Equal("value1", keyValue);
Assert.False(globalOptions.TryGetValue("key2", out _));
Assert.False(globalOptions.TryGetValue("key3", out _));
Assert.False(globalOptions.TryGetValue("key4", out _));
Assert.False(globalOptions.TryGetValue("key5", out _));
Assert.False(globalOptions.TryGetValue("key6", out _));
Assert.False(globalOptions.TryGetValue("key7", out _));
// get the options for class C
var classOptions = provider.GetOptions(cmd.Compilation.SyntaxTrees.First());
Assert.True(classOptions.TryGetValue("key1", out keyValue));
Assert.Equal("value1", keyValue);
Assert.False(classOptions.TryGetValue("key2", out _));
Assert.False(classOptions.TryGetValue("key3", out _));
Assert.True(classOptions.TryGetValue("key4", out keyValue));
Assert.Equal("value4", keyValue);
Assert.False(classOptions.TryGetValue("key5", out _));
Assert.False(classOptions.TryGetValue("key6", out _));
Assert.False(classOptions.TryGetValue("key7", out _));
// get the options for generated class D
var generatedOptions = provider.GetOptions(cmd.Compilation.SyntaxTrees.Last());
Assert.True(generatedOptions.TryGetValue("key1", out keyValue));
Assert.Equal("value1", keyValue);
Assert.False(generatedOptions.TryGetValue("key2", out _));
Assert.False(generatedOptions.TryGetValue("key3", out _));
Assert.True(classOptions.TryGetValue("key4", out keyValue));
Assert.Equal("value4", keyValue);
Assert.False(generatedOptions.TryGetValue("key5", out _));
Assert.False(generatedOptions.TryGetValue("key6", out _));
Assert.False(generatedOptions.TryGetValue("key7", out _));
}
[DiagnosticAnalyzer(LanguageNames.CSharp)]
private sealed class FieldAnalyzer : DiagnosticAnalyzer
{
......@@ -12412,6 +12525,69 @@ class C
Assert.Contains("'option1'", output, StringComparison.Ordinal);
Assert.Contains("'file.cs'", output, StringComparison.Ordinal);
}
[Fact]
public void GlobalAnalyzerConfigWithOptions()
{
var dir = Temp.CreateDirectory();
var src = dir.CreateFile("test.cs").WriteAllText(@"
class C
{
}");
var additionalFile = dir.CreateFile("file.txt");
var analyzerConfig = dir.CreateFile(".editorconfig").WriteAllText(@"
[*.cs]
key1 = value1
[*.txt]
key2 = value2");
var globalConfig = dir.CreateFile(".globalconfig").WriteAllText(@"
is_global = true
key3 = value3");
var cmd = CreateCSharpCompiler(null, dir.Path, new[] {
"/nologo",
"/t:library",
"/analyzerconfig:" + analyzerConfig.Path,
"/analyzerconfig:" + globalConfig.Path,
"/analyzer:" + Assembly.GetExecutingAssembly().Location,
"/nowarn:8032,Warning01",
"/additionalfile:" + additionalFile.Path,
src.Path });
var outWriter = new StringWriter(CultureInfo.InvariantCulture);
var exitCode = cmd.Run(outWriter);
Assert.Equal("", outWriter.ToString());
Assert.Equal(0, exitCode);
var comp = cmd.Compilation;
var tree = comp.SyntaxTrees.Single();
var provider = cmd.AnalyzerOptions.AnalyzerConfigOptionsProvider;
var options = provider.GetOptions(tree);
Assert.NotNull(options);
Assert.True(options.TryGetValue("key1", out string val));
Assert.Equal("value1", val);
Assert.False(options.TryGetValue("key2", out _));
Assert.True(options.TryGetValue("key3", out val));
Assert.Equal("value3", val);
options = provider.GetOptions(cmd.AnalyzerOptions.AdditionalFiles.Single());
Assert.NotNull(options);
Assert.False(options.TryGetValue("key1", out _));
Assert.True(options.TryGetValue("key2", out val));
Assert.Equal("value2", val);
Assert.True(options.TryGetValue("key3", out val));
Assert.Equal("value3", val);
options = provider.GlobalOptions;
Assert.NotNull(options);
Assert.False(options.TryGetValue("key1", out _));
Assert.False(options.TryGetValue("key2", out _));
Assert.True(options.TryGetValue("key3", out val));
Assert.Equal("value3", val);
}
}
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
......@@ -12530,41 +12706,4 @@ public override void CreateAnalyzerWithinCompilation(CompilationStartAnalysisCon
);
}
}
[Generator]
internal class SimpleGenerator : ISourceGenerator
{
private readonly string _sourceToAdd;
private readonly string _fileName;
/// <remarks>
/// Required for reflection based tests
/// </remarks>
public SimpleGenerator()
{
_sourceToAdd = string.Empty;
}
public SimpleGenerator(string sourceToAdd, string fileName)
{
_sourceToAdd = sourceToAdd;
_fileName = fileName;
}
public void Execute(SourceGeneratorContext context)
{
context.AddSource(_fileName, SourceText.From(_sourceToAdd, Encoding.UTF8));
}
public void Initialize(InitializationContext context)
{
}
}
internal class SimpleGenerator2 : SimpleGenerator
{
public SimpleGenerator2(string sourceToAdd, string fileName) : base(sourceToAdd, fileName)
{
}
}
}
......@@ -1595,7 +1595,7 @@ private class NestedGeneratedCode{0} {{ }}
analyzerConfigOptions = new CompilerAnalyzerConfigOptions(ImmutableDictionary<string, string>.Empty.Add("generated_code", "auto"));
analyzerConfigOptionsPerTreeBuilder.Add(tree, analyzerConfigOptions);
var analyzerConfigOptionsProvider = new CompilerAnalyzerConfigOptionsProvider(analyzerConfigOptionsPerTreeBuilder.ToImmutable());
var analyzerConfigOptionsProvider = new CompilerAnalyzerConfigOptionsProvider(analyzerConfigOptionsPerTreeBuilder.ToImmutable(), CompilerAnalyzerConfigOptions.Empty);
var analyzerOptions = new AnalyzerOptions(additionalFiles: ImmutableArray<AdditionalText>.Empty, analyzerConfigOptionsProvider);
// Verify no compiler diagnostics.
......
......@@ -490,7 +490,8 @@ void M()
// Verify CS0168 reported by CSharpCompilerDiagnosticAnalyzer is not affected by "dotnet_analyzer_diagnostic = none"
var analyzerConfigOptions = new CompilerAnalyzerConfigOptions(ImmutableDictionary<string, string>.Empty.Add("dotnet_analyzer_diagnostic.severity", "none"));
var analyzerConfigOptionsProvider = new CompilerAnalyzerConfigOptionsProvider(
ImmutableDictionary<object, AnalyzerConfigOptions>.Empty.Add(compilation.SyntaxTrees.Single(), analyzerConfigOptions));
ImmutableDictionary<object, AnalyzerConfigOptions>.Empty.Add(compilation.SyntaxTrees.Single(), analyzerConfigOptions),
CompilerAnalyzerConfigOptions.Empty);
var analyzerOptions = new AnalyzerOptions(ImmutableArray<AdditionalText>.Empty, analyzerConfigOptionsProvider);
compilationWithAnalyzers = compilation.WithAnalyzers(analyzers, analyzerOptions);
analyzerDiagnostics = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync();
......@@ -535,7 +536,8 @@ static async Task verifyDiagnosticsAsync(Compilation compilation, DiagnosticAnal
{
var analyzerConfigOptions = new CompilerAnalyzerConfigOptions(ImmutableDictionary<string, string>.Empty.Add(options.Value.key, options.Value.value));
var analyzerConfigOptionsProvider = new CompilerAnalyzerConfigOptionsProvider(
ImmutableDictionary<object, AnalyzerConfigOptions>.Empty.Add(compilation.SyntaxTrees.Single(), analyzerConfigOptions));
ImmutableDictionary<object, AnalyzerConfigOptions>.Empty.Add(compilation.SyntaxTrees.Single(), analyzerConfigOptions),
CompilerAnalyzerConfigOptions.Empty);
analyzerOptions = new AnalyzerOptions(ImmutableArray<AdditionalText>.Empty, analyzerConfigOptionsProvider);
}
else
......
......@@ -13,8 +13,10 @@
using System.Xml;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities.TestGenerators;
using Xunit;
#nullable enable
......@@ -35,7 +37,7 @@ class C { }
Assert.Single(compilation.SyntaxTrees);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray<ISourceGenerator>.Empty, ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray<ISourceGenerator>.Empty, CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out var outputCompilation, out var diagnostics);
Assert.Empty(diagnostics);
......@@ -58,7 +60,7 @@ class C { }
int initCount = 0, executeCount = 0;
var generator = new CallbackGenerator((ic) => initCount++, (sgc) => executeCount++);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out var outputCompilation, out var diagnostics);
Assert.Equal(1, initCount);
......@@ -80,7 +82,7 @@ class C { }
int initCount = 0, executeCount = 0;
var generator = new CallbackGenerator((ic) => initCount++, (sgc) => executeCount++);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
Assert.Equal(0, initCount);
Assert.Equal(0, executeCount);
......@@ -101,7 +103,7 @@ class C { }
int initCount = 0, executeCount = 0;
var generator = new CallbackGenerator((ic) => initCount++, (sgc) => executeCount++, source: "public class C { }");
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver = driver.RunFullGeneration(compilation, out var outputCompilation, out _);
driver = driver.RunFullGeneration(outputCompilation, out outputCompilation, out _);
driver.RunFullGeneration(outputCompilation, out outputCompilation, out _);
......@@ -129,7 +131,7 @@ class GeneratedClass { }
SingleFileTestGenerator testGenerator = new SingleFileTestGenerator(generatorSource);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out var outputCompilation, out _);
Assert.Equal(2, outputCompilation.SyntaxTrees.Count());
......@@ -155,7 +157,7 @@ class GeneratedClass { }
SingleFileTestGenerator testGenerator = new SingleFileTestGenerator(generatorSource);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver = driver.RunFullGeneration(compilation, out var outputCompilation1, out _);
driver = driver.RunFullGeneration(compilation, out var outputCompilation2, out _);
driver = driver.RunFullGeneration(compilation, out var outputCompilation3, out _);
......@@ -191,7 +193,7 @@ class C
var generator = new SingleFileTestGenerator("public class D { }");
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out var outputCompilation, out var generatorDiagnostics);
outputCompilation.VerifyDiagnostics();
......@@ -212,7 +214,7 @@ class C { }
AdditionalFileAddedGenerator testGenerator = new AdditionalFileAddedGenerator() { CanApplyChanges = false };
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
// try apply edits should fail if we've not run a full compilation yet
driver = driver.TryApplyEdits(compilation, out var outputCompilation, out var succeeded);
......@@ -234,7 +236,7 @@ class C { }
AdditionalFileAddedGenerator testGenerator = new AdditionalFileAddedGenerator();
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
// run an initial generation pass
driver = driver.RunFullGeneration(compilation, out var outputCompilation, out _);
......@@ -260,7 +262,7 @@ class C { }
AdditionalFileAddedGenerator testGenerator = new AdditionalFileAddedGenerator() { CanApplyChanges = false };
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out var outputCompilation, out _);
Assert.Single(outputCompilation.SyntaxTrees);
......@@ -290,7 +292,7 @@ class C { }
AdditionalFileAddedGenerator testGenerator = new AdditionalFileAddedGenerator();
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
// run initial generation pass
driver = driver.RunFullGeneration(compilation, out var outputCompilation, out _);
......@@ -322,6 +324,7 @@ class C { }
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions,
generators: ImmutableArray.Create<ISourceGenerator>(testGenerator),
optionsProvider: CompilerAnalyzerConfigOptionsProvider.Empty,
additionalTexts: ImmutableArray.Create<AdditionalText>(new InMemoryAdditionalText("a\\file1.cs", "")));
// run initial generation pass
......@@ -368,6 +371,7 @@ class C { }
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions,
generators: ImmutableArray.Create<ISourceGenerator>(testGenerator),
optionsProvider: CompilerAnalyzerConfigOptionsProvider.Empty,
additionalTexts: ImmutableArray.Create<AdditionalText>(new InMemoryAdditionalText("a\\file1.cs", "")));
driver = driver.RunFullGeneration(compilation, out var outputCompilation, out _);
......@@ -414,6 +418,7 @@ class C { }
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions,
generators: ImmutableArray.Create<ISourceGenerator>(testGenerator),
optionsProvider: CompilerAnalyzerConfigOptionsProvider.Empty,
additionalTexts: ImmutableArray.Create<AdditionalText>(new InMemoryAdditionalText("a\\file1.cs", "")));
driver.RunFullGeneration(compilation, out var outputCompilation, out _);
......@@ -446,6 +451,7 @@ class C { }
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions,
generators: ImmutableArray.Create<ISourceGenerator>(testGenerator1),
optionsProvider: CompilerAnalyzerConfigOptionsProvider.Empty,
additionalTexts: ImmutableArray<AdditionalText>.Empty);
driver = driver.RunFullGeneration(compilation, out var outputCompilation, out _);
......@@ -487,7 +493,7 @@ class C { }
var generator = new CallbackGenerator((ic) => throw exception, (sgc) => { });
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out var outputCompilation, out var generatorDiagnostics);
outputCompilation.VerifyDiagnostics();
......@@ -512,7 +518,7 @@ class C { }
var exception = new InvalidOperationException("init error");
var generator = new CallbackGenerator((ic) => throw exception, (sgc) => { }, source: "class D { }");
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out var outputCompilation, out _);
Assert.Single(outputCompilation.SyntaxTrees);
......@@ -534,7 +540,7 @@ class C { }
var generator = new CallbackGenerator((ic) => { }, (sgc) => throw exception);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out var outputCompilation, out var generatorDiagnostics);
outputCompilation.VerifyDiagnostics();
......@@ -561,7 +567,7 @@ class C { }
var generator = new CallbackGenerator((ic) => { }, (sgc) => throw exception);
var generator2 = new CallbackGenerator2((ic) => { }, (sgc) => { }, source: "public class D { }");
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator, generator2), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator, generator2), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out var outputCompilation, out var generatorDiagnostics);
outputCompilation.VerifyDiagnostics();
......@@ -597,7 +603,7 @@ class C
var generator = new CallbackGenerator((ic) => { }, (sgc) => throw exception, source: "public class D { }");
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out var outputCompilation, out var generatorDiagnostics);
outputCompilation.VerifyDiagnostics(
......@@ -628,7 +634,7 @@ class C { }
var generator = new CallbackGenerator((ic) => { }, (sgc) => sgc.ReportDiagnostic(diagnostic));
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out var outputCompilation, out var generatorDiagnostics);
outputCompilation.VerifyDiagnostics();
......@@ -659,7 +665,7 @@ class C { }
Assert.Throws<ArgumentException>("hintName", () => sgc.AddSource("test.cs", SourceText.From("public class D{}", Encoding.UTF8)));
});
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out var outputCompilation, out var generatorDiagnostics);
outputCompilation.VerifyDiagnostics();
generatorDiagnostics.Verify();
......@@ -680,7 +686,7 @@ class C { }
var generator = new SingleFileTestGenerator("public class D {}", "source.cs");
var generator2 = new SingleFileTestGenerator2("public class E {}", "source.cs");
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator, generator2), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(generator, generator2), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out var outputCompilation, out var generatorDiagnostics);
outputCompilation.VerifyDiagnostics();
generatorDiagnostics.Verify();
......
......@@ -9,6 +9,8 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Diagnostics;
using Roslyn.Test.Utilities.TestGenerators;
using Xunit;
#nullable enable
......@@ -37,7 +39,7 @@ class C { }
onExecute: (e) => receiver = e.SyntaxReceiver
);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out _, out _);
Assert.NotNull(receiver);
......@@ -63,7 +65,7 @@ class C { }
onExecute: (e) => receiver = e.SyntaxReceiver
);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out var outputCompilation, out _);
Assert.Null(receiver);
......@@ -86,7 +88,7 @@ class C { }
onExecute: (e) => { }
);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out _, out _);
void Initialize(InitializationContext initContext)
......@@ -127,7 +129,7 @@ void Function()
onExecute: (e) => receiver = e.SyntaxReceiver
);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver.RunFullGeneration(compilation, out _, out _);
Assert.NotNull(receiver);
......@@ -167,7 +169,7 @@ void Function()
onExecute: (e) => receiver = e.SyntaxReceiver
);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), ImmutableArray<AdditionalText>.Empty);
GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create<ISourceGenerator>(testGenerator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray<AdditionalText>.Empty);
driver = driver.RunFullGeneration(compilation, out _, out _);
Assert.NotNull(receiver);
......
......@@ -722,10 +722,11 @@ public virtual int Run(TextWriter consoleOutput, CancellationToken cancellationT
/// <param name="input">The compilation before any source generation has occurred.</param>
/// <param name="parseOptions">The <see cref="ParseOptions"/> to use when parsing any generated sources.</param>
/// <param name="generators">The generators to run</param>
/// <param name="analyzerConfigOptionsProvider">A provider that returns analyzer config options</param>
/// <param name="additionalTexts">Any additional texts that should be passed to the generators when run.</param>
/// <param name="generatorDiagnostics">Any diagnostics that were produced during generation</param>
/// <returns>A compilation that represents the original compilation with any additional, generated texts added to it.</returns>
private protected virtual Compilation RunGenerators(Compilation input, ParseOptions parseOptions, ImmutableArray<ISourceGenerator> generators, ImmutableArray<AdditionalText> additionalTexts, DiagnosticBag generatorDiagnostics) { return input; }
private protected virtual Compilation RunGenerators(Compilation input, ParseOptions parseOptions, ImmutableArray<ISourceGenerator> generators, AnalyzerConfigOptionsProvider analyzerConfigOptionsProvider, ImmutableArray<AdditionalText> additionalTexts, DiagnosticBag generatorDiagnostics) { return input; }
private int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, CancellationToken cancellationToken)
{
......@@ -807,25 +808,11 @@ private int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, Cancellat
var additionalTexts = ImmutableArray<AdditionalText>.CastUp(additionalTextFiles);
// At this point we have a compilation with nothing yet computed.
// We pass it to the generators, which will realize any symbols they require.
compilation = RunGenerators(compilation, Arguments.ParseOptions, generators, additionalTexts, diagnostics);
if (generators.Length > 0)
{
var generatedSyntaxTrees = compilation.SyntaxTrees.Skip(Arguments.SourceFiles.Length);
if (!sourceFileAnalyzerConfigOptions.IsDefault)
{
sourceFileAnalyzerConfigOptions = sourceFileAnalyzerConfigOptions.AddRange(generatedSyntaxTrees.Select(f => analyzerConfigSet.GetOptionsForSourcePath(f.FilePath)));
}
embeddedTexts = embeddedTexts.AddRange(generatedSyntaxTrees.Select(t => EmbeddedText.FromSource(t.FilePath, t.GetText())));
}
CompileAndEmit(
touchedFilesLogger,
ref compilation,
analyzers,
generators,
additionalTexts,
analyzerConfigSet,
sourceFileAnalyzerConfigOptions,
......@@ -868,38 +855,45 @@ private int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, Cancellat
return exitCode;
}
private static CompilerAnalyzerConfigOptionsProvider CreateAnalyzerConfigOptionsProvider(
private static CompilerAnalyzerConfigOptionsProvider UpdateAnalyzerConfigOptionsProvider(
CompilerAnalyzerConfigOptionsProvider existing,
IEnumerable<SyntaxTree> syntaxTrees,
ImmutableArray<AnalyzerConfigOptionsResult> sourceFileAnalyzerConfigOptions,
ImmutableArray<AdditionalText> additionalFiles,
ImmutableArray<AnalyzerConfigOptionsResult> additionalFileOptions)
ImmutableArray<AdditionalText> additionalFiles = default,
ImmutableArray<AnalyzerConfigOptionsResult> additionalFileOptions = default)
{
var builder = ImmutableDictionary.CreateBuilder<object, AnalyzerConfigOptions>();
int i = 0;
foreach (var syntaxTree in syntaxTrees)
{
var options = sourceFileAnalyzerConfigOptions[i].AnalyzerOptions;
// Optimization: don't create a bunch of entries pointing to a no-op
if (options.Count > 0)
{
Debug.Assert(existing.GetOptions(syntaxTree) == CompilerAnalyzerConfigOptions.Empty);
builder.Add(syntaxTree, new CompilerAnalyzerConfigOptions(options));
}
i++;
}
for (i = 0; i < additionalFiles.Length; i++)
if (!additionalFiles.IsDefault)
{
var options = additionalFileOptions[i].AnalyzerOptions;
// Optimization: don't create a bunch of entries pointing to a no-op
if (options.Count > 0)
for (i = 0; i < additionalFiles.Length; i++)
{
builder.Add(additionalFiles[i], new CompilerAnalyzerConfigOptions(options));
var options = additionalFileOptions[i].AnalyzerOptions;
// Optimization: don't create a bunch of entries pointing to a no-op
if (options.Count > 0)
{
Debug.Assert(existing.GetOptions(additionalFiles[i]) == CompilerAnalyzerConfigOptions.Empty);
builder.Add(additionalFiles[i], new CompilerAnalyzerConfigOptions(options));
}
}
}
return new CompilerAnalyzerConfigOptionsProvider(builder.ToImmutable());
return existing.WithAdditionalTreeOptions(builder.ToImmutable());
}
/// <summary>
......@@ -911,6 +905,7 @@ private int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, Cancellat
TouchedFileLogger touchedFilesLogger,
ref Compilation compilation,
ImmutableArray<DiagnosticAnalyzer> analyzers,
ImmutableArray<ISourceGenerator> generators,
ImmutableArray<AdditionalText> additionalTextFiles,
AnalyzerConfigSet analyzerConfigSet,
ImmutableArray<AnalyzerConfigOptionsResult> sourceFileAnalyzerConfigOptions,
......@@ -933,15 +928,13 @@ private int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, Cancellat
}
DiagnosticBag analyzerExceptionDiagnostics = null;
if (!analyzers.IsEmpty)
if (!analyzers.IsEmpty || !generators.IsEmpty)
{
analyzerCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
analyzerExceptionDiagnostics = new DiagnosticBag();
var analyzerConfigProvider = CompilerAnalyzerConfigOptionsProvider.Empty;
if (Arguments.AnalyzerConfigPaths.Length > 0)
{
analyzerConfigProvider = analyzerConfigProvider.WithGlobalOptions(new CompilerAnalyzerConfigOptions(analyzerConfigSet.GetOptionsForSourcePath(string.Empty).AnalyzerOptions));
// TODO(https://github.com/dotnet/roslyn/issues/31916): The compiler currently doesn't support
// configuring diagnostic reporting on additional text files individually.
ImmutableArray<AnalyzerConfigOptionsResult> additionalFileAnalyzerOptions =
......@@ -952,34 +945,60 @@ private int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, Cancellat
diagnostics.AddRange(result.Diagnostics);
}
analyzerConfigProvider = CreateAnalyzerConfigOptionsProvider(
analyzerConfigProvider = UpdateAnalyzerConfigOptionsProvider(
analyzerConfigProvider,
compilation.SyntaxTrees,
sourceFileAnalyzerConfigOptions,
additionalTextFiles,
additionalFileAnalyzerOptions);
}
if (!generators.IsEmpty)
{
// At this point we have a compilation with nothing yet computed.
// We pass it to the generators, which will realize any symbols they require.
compilation = RunGenerators(compilation, Arguments.ParseOptions, generators, analyzerConfigProvider, additionalTextFiles, diagnostics);
var generatedSyntaxTrees = compilation.SyntaxTrees.Skip(Arguments.SourceFiles.Length);
if (Arguments.AnalyzerConfigPaths.Length > 0)
{
var generatedSourceFileAnalyzerConfigOptions = generatedSyntaxTrees.SelectAsArray(f => analyzerConfigSet.GetOptionsForSourcePath(f.FilePath));
analyzerConfigProvider = UpdateAnalyzerConfigOptionsProvider(
analyzerConfigProvider,
generatedSyntaxTrees,
generatedSourceFileAnalyzerConfigOptions);
}
embeddedTexts = embeddedTexts.AddRange(generatedSyntaxTrees.Select(t => EmbeddedText.FromSource(t.FilePath, t.GetText())));
}
AnalyzerOptions analyzerOptions = CreateAnalyzerOptions(
additionalTextFiles, analyzerConfigProvider);
// PERF: Avoid executing analyzers that report only Hidden and/or Info diagnostics, which don't appear in the build output.
// 1. Always filter out 'Hidden' analyzer diagnostics in build.
// 2. Filter out 'Info' analyzer diagnostics if they are not required to be logged in errorlog.
var severityFilter = SeverityFilter.Hidden;
if (Arguments.ErrorLogPath == null)
severityFilter |= SeverityFilter.Info;
analyzerDriver = AnalyzerDriver.CreateAndAttachToCompilation(
compilation,
analyzers,
analyzerOptions,
new AnalyzerManager(analyzers),
analyzerExceptionDiagnostics.Add,
Arguments.ReportAnalyzer,
severityFilter,
out compilation,
analyzerCts.Token);
reportAnalyzer = Arguments.ReportAnalyzer && !analyzers.IsEmpty;
additionalTextFiles, analyzerConfigProvider);
if (!analyzers.IsEmpty)
{
analyzerCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
analyzerExceptionDiagnostics = new DiagnosticBag();
// PERF: Avoid executing analyzers that report only Hidden and/or Info diagnostics, which don't appear in the build output.
// 1. Always filter out 'Hidden' analyzer diagnostics in build.
// 2. Filter out 'Info' analyzer diagnostics if they are not required to be logged in errorlog.
var severityFilter = SeverityFilter.Hidden;
if (Arguments.ErrorLogPath == null)
severityFilter |= SeverityFilter.Info;
analyzerDriver = AnalyzerDriver.CreateAndAttachToCompilation(
compilation,
analyzers,
analyzerOptions,
new AnalyzerManager(analyzers),
analyzerExceptionDiagnostics.Add,
Arguments.ReportAnalyzer,
severityFilter,
out compilation,
analyzerCts.Token);
reportAnalyzer = Arguments.ReportAnalyzer && !analyzers.IsEmpty;
}
}
compilation.GetDiagnostics(CompilationStage.Declare, includeEarlierStages: false, diagnostics, cancellationToken);
......
......@@ -11,6 +11,11 @@ namespace Microsoft.CodeAnalysis.Diagnostics
/// </summary>
public abstract class AnalyzerConfigOptionsProvider
{
/// <summary>
/// Gets global options that do not apply to any specific file
/// </summary>
public abstract AnalyzerConfigOptions GlobalOptions { get; }
/// <summary>
/// Get options for a given <paramref name="tree"/>.
/// </summary>
......
......@@ -8,24 +8,35 @@
namespace Microsoft.CodeAnalysis.Diagnostics
{
internal sealed partial class CompilerAnalyzerConfigOptionsProvider : AnalyzerConfigOptionsProvider
internal sealed class CompilerAnalyzerConfigOptionsProvider : AnalyzerConfigOptionsProvider
{
private readonly ImmutableDictionary<object, AnalyzerConfigOptions> _treeDict;
public static CompilerAnalyzerConfigOptionsProvider Empty { get; }
= new CompilerAnalyzerConfigOptionsProvider(
ImmutableDictionary<object, AnalyzerConfigOptions>.Empty);
ImmutableDictionary<object, AnalyzerConfigOptions>.Empty,
CompilerAnalyzerConfigOptions.Empty);
public CompilerAnalyzerConfigOptionsProvider(
ImmutableDictionary<object, AnalyzerConfigOptions> treeDict)
internal CompilerAnalyzerConfigOptionsProvider(
ImmutableDictionary<object, AnalyzerConfigOptions> treeDict,
AnalyzerConfigOptions globalOptions)
{
_treeDict = treeDict;
GlobalOptions = globalOptions;
}
public override AnalyzerConfigOptions GlobalOptions { get; }
public override AnalyzerConfigOptions GetOptions(SyntaxTree tree)
=> _treeDict.TryGetValue(tree, out var options) ? options : CompilerAnalyzerConfigOptions.Empty;
public override AnalyzerConfigOptions GetOptions(AdditionalText textFile)
=> _treeDict.TryGetValue(textFile, out var options) ? options : CompilerAnalyzerConfigOptions.Empty;
internal CompilerAnalyzerConfigOptionsProvider WithAdditionalTreeOptions(ImmutableDictionary<object, AnalyzerConfigOptions> treeDict)
=> new CompilerAnalyzerConfigOptionsProvider(_treeDict.AddRange(treeDict), GlobalOptions);
internal CompilerAnalyzerConfigOptionsProvider WithGlobalOptions(AnalyzerConfigOptions globalOptions)
=> new CompilerAnalyzerConfigOptionsProvider(_treeDict, globalOptions);
}
}
......@@ -32,12 +32,14 @@ Microsoft.CodeAnalysis.Operations.IRelationalPatternOperation.OperatorKind.get -
Microsoft.CodeAnalysis.Operations.IRelationalPatternOperation.Value.get -> Microsoft.CodeAnalysis.IOperation
Microsoft.CodeAnalysis.Operations.ITypePatternOperation
Microsoft.CodeAnalysis.Operations.ITypePatternOperation.MatchedType.get -> Microsoft.CodeAnalysis.ITypeSymbol
Microsoft.CodeAnalysis.SourceGeneratorContext.AnalyzerConfigOptions.get -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptionsProvider
Microsoft.CodeAnalysis.Operations.IWithOperation
Microsoft.CodeAnalysis.Operations.IWithOperation.CloneMethod.get -> Microsoft.CodeAnalysis.IMethodSymbol
Microsoft.CodeAnalysis.Operations.IWithOperation.Initializer.get -> Microsoft.CodeAnalysis.Operations.IObjectOrCollectionInitializerOperation
Microsoft.CodeAnalysis.Operations.IWithOperation.Value.get -> Microsoft.CodeAnalysis.IOperation
Microsoft.CodeAnalysis.SymbolKind.FunctionPointer = 20 -> Microsoft.CodeAnalysis.SymbolKind
Microsoft.CodeAnalysis.TypeKind.FunctionPointer = 13 -> Microsoft.CodeAnalysis.TypeKind
abstract Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptionsProvider.GlobalOptions.get -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions
static Microsoft.CodeAnalysis.AnalyzerConfigSet.Create<TList>(TList analyzerConfigs, out System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostic> diagnostics) -> Microsoft.CodeAnalysis.AnalyzerConfigSet
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitBinaryPattern(Microsoft.CodeAnalysis.Operations.IBinaryPatternOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitNegatedPattern(Microsoft.CodeAnalysis.Operations.INegatedPatternOperation operation) -> void
......
......@@ -41,9 +41,9 @@ internal GeneratorDriver(GeneratorDriverState state)
_state = state;
}
internal GeneratorDriver(ParseOptions parseOptions, ImmutableArray<ISourceGenerator> generators, ImmutableArray<AdditionalText> additionalTexts)
internal GeneratorDriver(ParseOptions parseOptions, ImmutableArray<ISourceGenerator> generators, AnalyzerConfigOptionsProvider optionsProvider, ImmutableArray<AdditionalText> additionalTexts)
{
_state = new GeneratorDriverState(parseOptions, generators, additionalTexts, ImmutableArray.Create(new GeneratorState[generators.Length]), ImmutableArray<PendingEdit>.Empty, editsFailed: true);
_state = new GeneratorDriverState(parseOptions, optionsProvider, generators, additionalTexts, ImmutableArray.Create(new GeneratorState[generators.Length]), ImmutableArray<PendingEdit>.Empty, editsFailed: true);
}
public GeneratorDriver RunFullGeneration(Compilation compilation, out Compilation outputCompilation, out ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken = default)
......@@ -107,7 +107,7 @@ public GeneratorDriver RunFullGeneration(Compilation compilation, out Compilatio
// we create a new context for each run of the generator. We'll never re-use existing state, only replace anything we have
_ = receivers.TryGetValue(generator, out var syntaxReceiverOpt);
var context = new SourceGeneratorContext(compilation, state.AdditionalTexts.NullToEmpty(), syntaxReceiverOpt, diagnosticsBag);
var context = new SourceGeneratorContext(compilation, state.AdditionalTexts.NullToEmpty(), state.OptionsProvider, syntaxReceiverOpt, diagnosticsBag);
generator.Execute(context);
stateBuilder[i] = generatorState.WithSources(ParseAdditionalSources(generator, context.AdditionalSources.ToImmutableAndFree(), cancellationToken));
}
......
......@@ -7,6 +7,7 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.Text;
using Microsoft.CodeAnalysis.Diagnostics;
#nullable enable
namespace Microsoft.CodeAnalysis
......@@ -14,6 +15,7 @@ namespace Microsoft.CodeAnalysis
internal readonly struct GeneratorDriverState
{
internal GeneratorDriverState(ParseOptions parseOptions,
AnalyzerConfigOptionsProvider optionsProvider,
ImmutableArray<ISourceGenerator> generators,
ImmutableArray<AdditionalText> additionalTexts,
ImmutableArray<GeneratorState> generatorStates,
......@@ -25,6 +27,7 @@ namespace Microsoft.CodeAnalysis
AdditionalTexts = additionalTexts;
Edits = edits;
ParseOptions = parseOptions;
OptionsProvider = optionsProvider;
EditsFailed = editsFailed;
Debug.Assert(Generators.Length == GeneratorStates.Length);
......@@ -53,6 +56,11 @@ namespace Microsoft.CodeAnalysis
/// </summary>
internal readonly ImmutableArray<AdditionalText> AdditionalTexts;
/// <summary>
/// Gets a provider for analyzer options
/// </summary>
internal readonly AnalyzerConfigOptionsProvider OptionsProvider;
/// <summary>
/// An ordered list of <see cref="PendingEdit"/>s that are waiting to be applied to the compilation.
/// </summary>
......@@ -69,7 +77,6 @@ namespace Microsoft.CodeAnalysis
internal readonly ParseOptions ParseOptions;
internal GeneratorDriverState With(
ParseOptions? parseOptions = null,
ImmutableArray<ISourceGenerator>? generators = null,
ImmutableArray<GeneratorState>? generatorStates = null,
ImmutableArray<AdditionalText>? additionalTexts = null,
......@@ -77,7 +84,8 @@ namespace Microsoft.CodeAnalysis
bool? editsFailed = null)
{
return new GeneratorDriverState(
parseOptions ?? this.ParseOptions,
this.ParseOptions,
this.OptionsProvider,
generators ?? this.Generators,
additionalTexts ?? this.AdditionalTexts,
generatorStates ?? this.GeneratorStates,
......
......@@ -5,6 +5,7 @@
using System;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Text;
#nullable enable
......@@ -17,10 +18,11 @@ namespace Microsoft.CodeAnalysis
{
private readonly DiagnosticBag _diagnostics;
internal SourceGeneratorContext(Compilation compilation, ImmutableArray<AdditionalText> additionalTexts, ISyntaxReceiver? syntaxReceiver, DiagnosticBag diagnostics, CancellationToken cancellationToken = default)
internal SourceGeneratorContext(Compilation compilation, ImmutableArray<AdditionalText> additionalTexts, AnalyzerConfigOptionsProvider optionsProvider, ISyntaxReceiver? syntaxReceiver, DiagnosticBag diagnostics, CancellationToken cancellationToken = default)
{
Compilation = compilation;
AdditionalFiles = additionalTexts;
AnalyzerConfigOptions = optionsProvider;
SyntaxReceiver = syntaxReceiver;
CancellationToken = cancellationToken;
AdditionalSources = new AdditionalSourcesCollection();
......@@ -42,6 +44,11 @@ internal SourceGeneratorContext(Compilation compilation, ImmutableArray<Addition
/// </summary>
public ImmutableArray<AdditionalText> AdditionalFiles { get; }
/// <summary>
/// Allows access to options provided by an analyzer config
/// </summary>
public AnalyzerConfigOptionsProvider AnalyzerConfigOptions { get; }
/// <summary>
/// If the generator registered an <see cref="ISyntaxReceiver"/> during initialization, this will be the instance created for this generation pass.
/// </summary>
......
......@@ -8,9 +8,10 @@
using System.IO;
using System.Text;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests.SourceGeneration
namespace Roslyn.Test.Utilities.TestGenerators
{
internal class SingleFileTestGenerator : ISourceGenerator
{
......
......@@ -7,6 +7,7 @@
using System;
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
......@@ -42,14 +43,14 @@ Compilation ICompilationFactoryService.CreateSubmissionCompilation(string assemb
CompilationOptions ICompilationFactoryService.GetDefaultCompilationOptions()
=> s_defaultOptions;
GeneratorDriver? ICompilationFactoryService.CreateGeneratorDriver(ParseOptions parseOptions, ImmutableArray<ISourceGenerator> generators, ImmutableArray<AdditionalText> additionalTexts)
GeneratorDriver? ICompilationFactoryService.CreateGeneratorDriver(ParseOptions parseOptions, ImmutableArray<ISourceGenerator> generators, AnalyzerConfigOptionsProvider optionsProvider, ImmutableArray<AdditionalText> additionalTexts)
{
// https://github.com/dotnet/roslyn/issues/42565: for now we gate behind langver == preview. We'll remove this before final shipping, as the feature is langver agnostic
if (((CSharpParseOptions)parseOptions).LanguageVersion != LanguageVersion.Preview)
{
return null;
}
return new CSharpGeneratorDriver(parseOptions, generators, additionalTexts);
return new CSharpGeneratorDriver(parseOptions, generators, optionsProvider, additionalTexts);
}
}
}
......@@ -6,6 +6,7 @@
using System;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.Host
{
......@@ -14,6 +15,6 @@ internal interface ICompilationFactoryService : ILanguageService
Compilation CreateCompilation(string assemblyName, CompilationOptions options);
Compilation CreateSubmissionCompilation(string assemblyName, CompilationOptions options, Type? hostObjectType);
CompilationOptions GetDefaultCompilationOptions();
GeneratorDriver? CreateGeneratorDriver(ParseOptions parseOptions, ImmutableArray<ISourceGenerator> generators, ImmutableArray<AdditionalText> additionalTexts);
GeneratorDriver? CreateGeneratorDriver(ParseOptions parseOptions, ImmutableArray<ISourceGenerator> generators, AnalyzerConfigOptionsProvider optionsProvider, ImmutableArray<AdditionalText> additionalTexts);
}
}
......@@ -293,6 +293,9 @@ private sealed class WorkspaceAnalyzerConfigOptionsProvider : AnalyzerConfigOpti
public WorkspaceAnalyzerConfigOptionsProvider(ProjectState projectState)
=> _projectState = projectState;
public override AnalyzerConfigOptions GlobalOptions
=> new WorkspaceAnalyzerConfigOptions(_projectState._lazyAnalyzerConfigSet.GetValue(CancellationToken.None).GetOptionsForSourcePath(string.Empty));
public override AnalyzerConfigOptions GetOptions(SyntaxTree tree)
=> new WorkspaceAnalyzerConfigOptions(_projectState._lazyAnalyzerConfigSet.GetValue(CancellationToken.None).GetOptionsForSourcePath(tree.FilePath));
......
......@@ -700,6 +700,7 @@ public CompilationInfo(Compilation compilation, bool hasSuccessfullyLoaded)
compilationFactory.CreateGeneratorDriver(
this.ProjectState.ParseOptions!,
generators,
this.ProjectState.AnalyzerOptions.AnalyzerConfigOptionsProvider,
additionalTexts));
}
......
......@@ -4,6 +4,7 @@
Imports System.Collections.Immutable
Imports System.Composition
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Host
Imports Microsoft.CodeAnalysis.Host.Mef
......@@ -47,7 +48,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return s_defaultOptions
End Function
Public Function CreateGeneratorDriver(parseOptions As ParseOptions, generators As ImmutableArray(Of ISourceGenerator), additionalTexts As ImmutableArray(Of AdditionalText)) As GeneratorDriver Implements ICompilationFactoryService.CreateGeneratorDriver
Public Function CreateGeneratorDriver(parseOptions As ParseOptions, generators As ImmutableArray(Of ISourceGenerator), optionsProvider As AnalyzerConfigOptionsProvider, additionalTexts As ImmutableArray(Of AdditionalText)) As GeneratorDriver Implements ICompilationFactoryService.CreateGeneratorDriver
Return Nothing
End Function
End Class
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册