public void Error_During_Generation_With_Dependent_Source() { var source = @" #pragma warning disable CS0649 class C { public D d; } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics( // (5,12): error CS0246: The type or namespace name 'D' could not be found (are you missing a using directive or an assembly reference?) // public D d; Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "D").WithArguments("D").WithLocation(5, 12) ); Assert.Single(compilation.SyntaxTrees); var exception = new InvalidOperationException("generate error"); var generator = new CallbackGenerator((ic) => { }, (sgc) => throw exception, source: "public class D { }"); 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( // (5,12): error CS0246: The type or namespace name 'D' could not be found (are you missing a using directive or an assembly reference?) // public D d; Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "D").WithArguments("D").WithLocation(5, 12) ); generatorDiagnostics.Verify( // warning CS8785: Generator 'CallbackGenerator' failed to generate source. It will not contribute to the output and compilation errors may occur as a result. Exception was 'InvalidOperationException' with message 'generate error' Diagnostic("CS" + (int)ErrorCode.WRN_GeneratorFailedDuringGeneration).WithArguments("CallbackGenerator", "InvalidOperationException", "generate error").WithLocation(1, 1) ); }
/// <summary> /// Runs a Roslyn generator over a set of source files. /// </summary> public static async Task <(ImmutableArray <Diagnostic>, ImmutableArray <GeneratedSourceResult>)> RunGenerator( ISourceGenerator generator, IEnumerable <Assembly>?references, IEnumerable <string> sources, AnalyzerConfigOptionsProvider?optionsProvider = null, bool includeBaseReferences = true, CancellationToken cancellationToken = default) { Project proj = CreateTestProject(references, includeBaseReferences); proj = proj.WithDocuments(sources); Assert.True(proj.Solution.Workspace.TryApplyChanges(proj.Solution)); Compilation?comp = await proj !.GetCompilationAsync(CancellationToken.None).ConfigureAwait(false); CSharpGeneratorDriver cgd = CSharpGeneratorDriver.Create(new[] { generator }, optionsProvider: optionsProvider); GeneratorDriver gd = cgd.RunGenerators(comp !, cancellationToken); GeneratorDriverRunResult r = gd.GetRunResult(); return(r.Results[0].Diagnostics, r.Results[0].GeneratedSources); }
/// <summary> /// Verifies the output of a source generator. /// </summary> /// <typeparam name="TGenerator">The generator type to use.</typeparam> /// <param name="source">The input source to process.</param> /// <param name="diagnosticsIds">The expected diagnostics ids to be generated.</param> private static void VerifyGeneratedDiagnostics <TGenerator>(string source, params string[] diagnosticsIds) where TGenerator : class, IIncrementalGenerator, new() { SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source); IEnumerable <MetadataReference> references = from assembly in AppDomain.CurrentDomain.GetAssemblies() where !assembly.IsDynamic let reference = MetadataReference.CreateFromFile(assembly.Location) select reference; CSharpCompilation compilation = CSharpCompilation.Create("original", new SyntaxTree[] { syntaxTree }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); IIncrementalGenerator generator = new TGenerator(); CSharpGeneratorDriver driver = CSharpGeneratorDriver.Create(generator); driver.RunGeneratorsAndUpdateCompilation(compilation, out Compilation outputCompilation, out ImmutableArray <Diagnostic> diagnostics); HashSet <string> resultingIds = diagnostics.Select(diagnostic => diagnostic.Id).ToHashSet(); Assert.IsTrue(resultingIds.SetEquals(diagnosticsIds)); }
public void Test(string source, string expectedGeneratedFileName, string expectedGeneratedSource) { var inputCompilation = CreateCompilation(source); var generator = new PrimitiveGenerator(); var driver = CSharpGeneratorDriver.Create(generator).RunGeneratorsAndUpdateCompilation(inputCompilation, out _, out _); var runResult = driver.GetRunResult(); Assert.True(runResult.Diagnostics.IsEmpty); Assert.Single(runResult.Results); var generatorResult = runResult.Results[0]; Assert.Equal(generator, generatorResult.Generator); Assert.True(generatorResult.Diagnostics.IsEmpty); Assert.Null(generatorResult.Exception); Assert.Single(generatorResult.GeneratedSources); var generatedSource = generatorResult.GeneratedSources[0]; Assert.Equal(expectedGeneratedFileName, generatedSource.HintName); var generatedSourceText = generatedSource.SourceText.ToString(); Assert.Equal(expectedGeneratedSource, generatedSourceText); }
private static (Compilation Input, Compilation Output) CreateInputOutputCompilation() { Compilation inputCompilation = CreateCompilation(@" namespace TestCode { public class Dto1 { public System.Int32 NumberProp { get; set; } } public class Dto2 { public System.String Property { get; set; } public Dto1 OtherDto { get; set; } } public class Program2 { public void SomeMethod2(LaDeak.JsonMergePatch.Abstractions.Patch<Dto2> data) { } } } "); JsonMergePatchSourceGenerator generator = new JsonMergePatchSourceGenerator(); GeneratorDriver driver = CSharpGeneratorDriver.Create(generator); driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out var outputCompilation, out var diagnostics); return(inputCompilation, outputCompilation); }
private static Compilation Compile(string source) { var opt = new CSharpParseOptions(languageVersion: LanguageVersion.Preview, kind: SourceCodeKind.Regular, documentationMode: DocumentationMode.Parse); var copt = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); var dotnetCoreDirectory = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(); var compilation = CSharpCompilation.Create("test", syntaxTrees: new[] { SyntaxFactory.ParseSyntaxTree(source, opt) }, references: new[] { AssemblyMetadata.CreateFromFile(typeof(object).Assembly.Location).GetReference(), MetadataReference.CreateFromFile(Path.Combine(dotnetCoreDirectory, "netstandard.dll")), MetadataReference.CreateFromFile(Path.Combine(dotnetCoreDirectory, "System.Runtime.dll")), }, options: copt); // apply the source generator var driver = new CSharpGeneratorDriver(opt, ImmutableArray.Create <ISourceGenerator>(new MemberAccessGenerator.MemberAccessGenerator()), null, ImmutableArray <AdditionalText> .Empty); driver.RunFullGeneration(compilation, out var resultCompilation, out _); return(resultCompilation); }
public Compilation Generate(string dllName, ISourceGenerator sourceGenerator) { var analyzerOptionsConfigProvider = new TestAnalyzerOptionsConfigProvider(globalOptions); var driver = CSharpGeneratorDriver.Create(new[] { sourceGenerator }, optionsProvider: analyzerOptionsConfigProvider); var inputCompilation = this.Create(dllName); driver.AddAdditionalTexts(additionalTexts.ToImmutableArray()); driver.RunGeneratorsAndUpdateCompilation( inputCompilation, out var outputCompilation, out var diags ); foreach (var diag in diags) { if (diag.Severity == DiagnosticSeverity.Error) { throw new ArgumentException(diag.GetMessage()); } } return(outputCompilation); }
public void GenerateGetServicesForNamedServicesWithScopes() { // Given var input = CompilationBuilder.CreateAssemblyWithCode( @"namespace Demo.Domain { public interface IFoo { } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export(Lifetime.Scoped, ServiceId = ""1"")] public sealed class Foo : IFoo { } }"); var sourceGenerator = new IocContainerGenerator(); var runtime = CSharpGeneratorDriver.Create(sourceGenerator); // When runtime.RunGeneratorsAndUpdateCompilation( compilation: input, outputCompilation: out var output, diagnostics: out var diagnostics); // Then Assert.False(diagnostics.HasErrors()); Assert.True(output.ContainsTypeWithMethodImplementation( "IocContainer", @"public T? GetService<T>(string serviceId) where T : class { var scope = GetActiveScope(); var service = scope.GetService<T>(serviceId); return service; }")); }
public string GetGeneratedOutput(string source) { CSharpCompilation compilation = Compile(source); ThrowIfInvalid(compilation, before: true); ISourceGenerator generator = new TGenerator(); var driver = CSharpGeneratorDriver.Create(generator); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generatedDiagnostics); // Intentionally writing the output before potentially generating an exception if diagnostics are presented. string output = outputCompilation.SyntaxTrees.Last().ToString(); _output.WriteLine($"Generated output:" + Environment.NewLine + output); if (generatedDiagnostics.Length != 0) { _output.WriteLine("Generated diagnostics:"); _output.WriteLine(string.Join(Environment.NewLine, generatedDiagnostics.Select(d => d.ToString()))); generatedDiagnostics = generatedDiagnostics.Where(d => d.Severity is DiagnosticSeverity.Warning or DiagnosticSeverity.Error).ToImmutableArray(); // Throw only when there are warnings or errors. if (generatedDiagnostics.Length != 0) { // The tests does not expect any diagnostics before running the generator! string errors = string.Join(Environment.NewLine, generatedDiagnostics); throw new InvalidOperationException($"Unexpected diagnostics from source generators: {errors}"); } } ThrowIfInvalid(outputCompilation, before: false); return(output); }
public void TwoSuitableMethodsDiagnostic() { var sourceCode = @"using DevExpress.Mvvm.CodeGenerators; using System.Threading.Tasks; namespace Test { [GenerateViewModel] partial class TwoSuitableMethods { [GenerateProperty(OnChangedMethod = ""TwoChangedMethods"", OnChangingMethod = ""TwoChangingMethods"")] int value; public void TwoChangedMethods() { } public void TwoChangedMethods(int arg) { } public void TwoChangingMethods() { } public void TwoChangingMethods(int arg) { } } public class Program { public static void Main(string[] args) { } } } "; Compilation inputCompilation = Helper.CreateCompilation(sourceCode); ViewModelGenerator generator = new ViewModelGenerator(); GeneratorDriver driver = CSharpGeneratorDriver.Create(generator); _ = driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out var outputCompilation, out var diagnostics); Assert.AreEqual(3, outputCompilation.SyntaxTrees.Count()); Assert.AreEqual(2, diagnostics.Count()); foreach (var diagnostic in diagnostics) { Assert.AreEqual(GeneratorDiagnostics.TwoSuitableMethods.Id, diagnostic.Id); } }
static string GetGeneratedOutput(string source) { var references = from assembly in AppDomain.CurrentDomain.GetAssemblies() where !assembly.IsDynamic && !string.IsNullOrWhiteSpace(assembly.Location) select MetadataReference.CreateFromFile(assembly.Location); var compilation = CSharpCompilation.Create("generated.dll", syntaxTrees: null, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); ISourceGenerator generator = new Generator(); AdditionalText additionalText = new AdditionalTextString("Test.txt", source); RsAnalyzerConfigOptions options = new AnalyzerConfigOptions( KeyValuePair.Create("build_metadata.AdditionalFiles.SourceItemType", "Transplate")); var driver = CSharpGeneratorDriver.Create( new[] { generator }, new[] { additionalText }, parseOptions: null, new AnalyzerConfigOptionsProvider(KeyValuePair.Create(additionalText, options))); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generateDiagnostics); Assert.False(generateDiagnostics.Any(d => d.Severity == DiagnosticSeverity.Error), "Failed: " + generateDiagnostics.FirstOrDefault()?.GetMessage()); return(outputCompilation.SyntaxTrees.Last().ToString()); }
static (ImmutableArray <Diagnostic>, Compilation) GetGeneratedOutput(string source, [CallerMemberName] string?test = null) { var syntaxTree = CSharpSyntaxTree.ParseText(source, path: test + ".cs"); var references = new List <MetadataReference>(); var assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var assembly in assemblies) { if (!assembly.IsDynamic && !string.IsNullOrEmpty(assembly.Location)) { references.Add(MetadataReference.CreateFromFile(assembly.Location)); } } var compilation = CSharpCompilation.Create(test, new SyntaxTree[] { syntaxTree, CSharpSyntaxTree.ParseText(File.ReadAllText("Avatar/Avatar.cs"), path: "Avatar.cs"), CSharpSyntaxTree.ParseText(File.ReadAllText("Avatar/Avatar.StaticFactory.cs"), path: "Avatar.StaticFactory.cs"), }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); var diagnostics = compilation.GetDiagnostics().RemoveAll(d => d.Severity == DiagnosticSeverity.Hidden || d.Severity == DiagnosticSeverity.Info); if (diagnostics.Any()) { return(diagnostics, compilation); } var generator = new AvatarGenerator(); var driver = CSharpGeneratorDriver.Create(generator); driver.RunGeneratorsAndUpdateCompilation(compilation, out var output, out diagnostics); return(diagnostics, output); }
public void GenerateServiceCacheForNamedServices() { // Given var input = CompilationBuilder.CreateAssemblyWithCode( @"namespace Demo.Domain { public interface IFoo { } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export(ServiceId = ""1"")] public sealed class Foo : IFoo { } }"); var sourceGenerator = new ServiceCacheGenerator(); var testEnvironment = CSharpGeneratorDriver.Create(sourceGenerator); // When testEnvironment.RunGeneratorsAndUpdateCompilation( compilation: input, outputCompilation: out var output, diagnostics: out var diagnostics); // Then Assert.False(diagnostics.HasErrors()); Assert.True(output.ContainsClass("ServiceCache")); Assert.True(output.ContainsTypeWithMethodImplementation( "ServiceCache", @"public object GetOrAdd(Type key, string serviceId, Func<string, object> valueFactory) { var cache = NamedServiceCache.GetOrAdd(key, new ConcurrentDictionary<string, object>()); return cache.GetOrAdd(serviceId, valueFactory); }")); }
public void Generator_HintName_Is_Appended_With_GeneratorName() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); var generator = new SingleFileTestGenerator("public class D {}", "source.cs"); var generator2 = new SingleFileTestGenerator2("public class E {}", "source.cs"); GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { generator, generator2 }, parseOptions: parseOptions); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generatorDiagnostics); outputCompilation.VerifyDiagnostics(); generatorDiagnostics.Verify(); Assert.Equal(3, outputCompilation.SyntaxTrees.Count()); var filePaths = outputCompilation.SyntaxTrees.Skip(1).Select(t => t.FilePath).ToArray(); Assert.Equal(new[] {
public void TryApply_Edits_Fails_If_FullGeneration_Has_Not_Run() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); AdditionalFileAddedGenerator testGenerator = new AdditionalFileAddedGenerator() { CanApplyChanges = false }; GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { testGenerator }, parseOptions: parseOptions); // try apply edits should fail if we've not run a full compilation yet driver = driver.TryApplyEdits(compilation, out var outputCompilation, out var succeeded); Assert.False(succeeded); Assert.Equal(compilation, outputCompilation); }
public void Generator_Is_Only_Initialized_Once() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); 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), 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 _); Assert.Equal(1, initCount); Assert.Equal(3, executeCount); }
public void DtoWithProperties_WrapperTypeAddedToSource() { Compilation inputCompilation = CreateCompilation(@" namespace TestCode3 { public class Dto4 { public System.String Property { get; set; } } public class Program2 { public void SomeMethod2(LaDeak.JsonMergePatch.Abstractions.Patch<Dto4> data) { } } } "); JsonMergePatchSourceGenerator generator = new JsonMergePatchSourceGenerator(); GeneratorDriver driver = CSharpGeneratorDriver.Create(generator); driver = driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out var outputCompilation, out var diagnostics); Assert.True(diagnostics.IsEmpty); Assert.True(outputCompilation.SyntaxTrees.Count() == 3); Assert.True(outputCompilation.GetDiagnostics().IsEmpty); }
public void Cancellation_During_Execution_Doesnt_Report_As_Generator_Error() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); CancellationTokenSource cts = new CancellationTokenSource(); var testGenerator = new CallbackGenerator( onInit: (i) => { }, onExecute: (e) => { cts.Cancel(); } ); // test generator cancels the token. Check that the call to this generator doesn't make it look like it errored. var testGenerator2 = new CallbackGenerator2( onInit: (i) => { }, onExecute: (e) => { e.AddSource("a", SourceText.From("public class E {}", Encoding.UTF8)); } ); GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create <ISourceGenerator>(testGenerator, testGenerator2), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray <AdditionalText> .Empty); var oldDriver = driver; Assert.Throws <OperationCanceledException>(() => driver = driver.RunFullGeneration(compilation, out var outputCompilation, out var outputDiagnostics, cts.Token) ); Assert.Same(oldDriver, driver); }
public static async Task <IEnumerable <SyntaxTree> > GenerateAsync <T>(string source) where T : IIncrementalGenerator, new() { var document = CreateProject(source).Documents.Single(); var tree = await document.GetSyntaxTreeAsync(); if (tree is null) { throw new InvalidOperationException("Could not get the syntax tree of the sources"); } var compilation = (CSharpCompilation)(await document.Project.GetCompilationAsync()) !; if (compilation is null) { throw new InvalidOperationException("Could not compile the sources"); } var diagnostics = compilation.GetDiagnostics(); // Assert.Empty(diagnostics.Where(x => x.Severity >= DiagnosticSeverity.Warning)); IIncrementalGenerator generator = new T(); var driver = CSharpGeneratorDriver.Create( ImmutableArray.Create(generator.AsSourceGenerator()), ImmutableArray <AdditionalText> .Empty, compilation.SyntaxTrees[0].Options as CSharpParseOptions ); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out diagnostics); Assert.Empty(diagnostics.Where(x => x.Severity >= DiagnosticSeverity.Warning)); // the syntax tree added by the generator will be the last one in the compilation return(outputCompilation.SyntaxTrees.Where( z => !z.FilePath.Contains("AssemblyRegistrationOptions") && !z.FilePath.Contains("GeneratedAssemblyJsonRpcHandlers") )); }
public static string GetGeneratedOutput <TGenerator>(string sourceCode) where TGenerator : class, ISourceGenerator, new() { SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(sourceCode); IEnumerable <MetadataReference> references = AppDomain.CurrentDomain.GetAssemblies() .Where(assembly => !assembly.IsDynamic) .Select(assembly => MetadataReference.CreateFromFile(assembly.Location)) .Cast <MetadataReference>(); var compilation = CSharpCompilation .Create ( assemblyName: "SourceGeneratorTests", syntaxTrees: new[] { syntaxTree }, references: references, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) ); var generator = new TGenerator(); CSharpGeneratorDriver .Create(generator) .RunGeneratorsAndUpdateCompilation ( compilation, out Compilation outputCompilation, out ImmutableArray <Diagnostic> diagnostics ); // optional diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error).Should().BeEmpty(); return(outputCompilation.SyntaxTrees.Skip(1).LastOrDefault()?.ToString()); }
private string GetGeneratedOutput(string source, NullableContextOptions nullableContextOptions) { var syntaxTree = CSharpSyntaxTree.ParseText(source); var references = new List <MetadataReference>(); Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var assembly in assemblies) { if (!assembly.IsDynamic && !string.IsNullOrWhiteSpace(assembly.Location)) { references.Add(MetadataReference.CreateFromFile(assembly.Location)); } } var compilation = CSharpCompilation.Create( "foo", new SyntaxTree[] { syntaxTree }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, nullableContextOptions: nullableContextOptions)); // var compileDiagnostics = compilation.GetDiagnostics(); // Assert.IsFalse(compileDiagnostics.Any(d => d.Severity == DiagnosticSeverity.Error), "Failed: " + compileDiagnostics.FirstOrDefault()?.GetMessage()); ISourceGenerator generator = new Generator(); var driver = CSharpGeneratorDriver.Create(generator); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generateDiagnostics); Assert.IsFalse(generateDiagnostics.Any(d => d.Severity == DiagnosticSeverity.Error), "Failed: " + generateDiagnostics.FirstOrDefault()?.GetMessage()); string output = outputCompilation.SyntaxTrees.Last().ToString(); Console.WriteLine(output); return(output); }
public void GenerateScopeGetServiceMethod() { // Given var input = CompilationBuilder.CreateAssemblyWithCode( @"namespace Demo.Domain { public interface IFoo { } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export(Lifetime.Scoped)] public sealed class Foo : IFoo { } }"); var sourceGenerator = new ScopeGenerator(); var testEnvironment = CSharpGeneratorDriver.Create(sourceGenerator); // When testEnvironment.RunGeneratorsAndUpdateCompilation( compilation: input, outputCompilation: out var output, diagnostics: out var diagnostics); // Then Assert.False(diagnostics.HasErrors()); Assert.True(output.ContainsTypeWithMethodImplementation( "Scope", @"public T? GetService<T>() where T : class { var factory = Factory as IServiceFactory<T>; return factory?.CreateOrGetService(); }")); }
public void Generator_Is_Only_Initialized_Once() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); int initCount = 0, executeCount = 0; var generator = new CallbackGenerator((ic) => initCount++, (sgc) => executeCount++, source: "public class C { }"); GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { generator }, parseOptions: parseOptions); driver = driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out _); driver = driver.RunGeneratorsAndUpdateCompilation(outputCompilation, out outputCompilation, out _); driver.RunGeneratorsAndUpdateCompilation(outputCompilation, out outputCompilation, out _); Assert.Equal(1, initCount); Assert.Equal(3, executeCount); }
public void TryApply_Edits_Fails_If_FullGeneration_Has_Not_Run() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); AdditionalFileAddedGenerator testGenerator = new AdditionalFileAddedGenerator() { CanApplyChanges = false }; 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); Assert.False(succeeded); Assert.Equal(compilation, outputCompilation); }
public void GenerateServiceFactoryForClassWithSingleInterface() { // Given var input = CompilationBuilder.CreateAssemblyWithCode( @"namespace Demo.Domain { public interface IFoo { } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export] public sealed class Foo : IFoo { } }"); var sourceGenerator = new ServiceFactoryGenerator(); var testEnvironment = CSharpGeneratorDriver.Create(sourceGenerator); // When testEnvironment.RunGeneratorsAndUpdateCompilation( compilation: input, outputCompilation: out var output, diagnostics: out var diagnostics); // Then Assert.False(diagnostics.HasErrors()); Assert.True(output.ContainsTypeWithMethodImplementation( "ServiceFactory", @"Demo.Domain.IFoo IServiceFactory<Demo.Domain.IFoo>.CreateOrGetService() { var service = new Demo.Domain.Foo(); return service; }")); }
public void Execute_ShouldWarnOnNonCSharCompilation() { Compilation compilation = VisualBasicCompilation.Create ( "cica", new[] { VisualBasicSyntaxTree.ParseText ( @" Imports System.Collections Imports Solti.Utils.Proxy Imports Solti.Utils.Proxy.Attributes Imports Solti.Utils.Proxy.Generators <Assembly:EmbedGeneratedType(GetType(DuckGenerator(Of IEnumerable, IEnumerable)))> " ) }, Runtime .Assemblies .Select(asm => asm.Location) .Append(typeof(EmbedGeneratedTypeAttribute).Assembly.Location) .Distinct() .Select(location => MetadataReference.CreateFromFile(location)), new VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary) ); GeneratorDriver driver = CSharpGeneratorDriver.Create(new ProxyEmbedder()); driver.RunGeneratorsAndUpdateCompilation(compilation, out compilation, out ImmutableArray <Diagnostic> diags); Assert.That(diags.Any(diag => diag.Id == "PGE00" && diag.Severity == DiagnosticSeverity.Warning && diag.GetMessage() == SGResources.LNG_NOT_SUPPORTED)); Assert.That(diags.Length, Is.EqualTo(1)); }
public void Syntax_Receiver_Visits_Syntax_Added_In_PostInit() { var source = @" class C { int Property { get; set; } void Function() { var x = 5; x += 4; } } "; var source2 = @" class D { int Property { get; set; } void Function() { var x = 5; x += 4; } } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation( source, options: TestOptions.DebugDll, parseOptions: parseOptions ); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); ISyntaxReceiver?receiver = null; var testGenerator = new CallbackGenerator( onInit: (i) => { i.RegisterForSyntaxNotifications(() => new TestSyntaxReceiver()); i.RegisterForPostInitialization((pic) => pic.AddSource("postInit", source2)); }, onExecute: (e) => receiver = e.SyntaxReceiver ); GeneratorDriver driver = CSharpGeneratorDriver.Create( new[] { testGenerator }, parseOptions: parseOptions ); driver.RunGeneratorsAndUpdateCompilation(compilation, out _, out _); Assert.NotNull(receiver); Assert.IsType <TestSyntaxReceiver>(receiver); TestSyntaxReceiver testReceiver = (TestSyntaxReceiver)receiver !; var classDeclarations = testReceiver.VisitedNodes .OfType <ClassDeclarationSyntax>() .Select(c => c.Identifier.Text); Assert.Equal(new[] { "C", "D" }, classDeclarations); }
public void Syntax_Receiver_Exception_During_Visit_Stops_Visits_On_Other_Trees() { var source1 = @" class C { int Property { get; set; } } "; var source2 = @" class D { public void Method() { } } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation( new[] { source1, source2 }, options: TestOptions.DebugDll, parseOptions: parseOptions ); compilation.VerifyDiagnostics(); Assert.Equal(2, compilation.SyntaxTrees.Count()); TestSyntaxReceiver receiver1 = new TestSyntaxReceiver( tag: 0, callback: (a) => { if (a is PropertyDeclarationSyntax) { throw new Exception("Test Exception"); } } ); var testGenerator1 = new CallbackGenerator( onInit: (i) => i.RegisterForSyntaxNotifications(() => receiver1), onExecute: (e) => { } ); TestSyntaxReceiver receiver2 = new TestSyntaxReceiver(tag: 1); var testGenerator2 = new CallbackGenerator2( onInit: (i) => i.RegisterForSyntaxNotifications(() => receiver2), onExecute: (e) => { } ); GeneratorDriver driver = CSharpGeneratorDriver.Create( new[] { testGenerator1, testGenerator2 }, parseOptions: parseOptions ); driver = driver.RunGeneratorsAndUpdateCompilation( compilation, out var outputCompilation, out var outputDiagnostics ); var results = driver.GetRunResult(); Assert.DoesNotContain(receiver1.VisitedNodes, n => n is MethodDeclarationSyntax); Assert.Contains(receiver2.VisitedNodes, n => n is MethodDeclarationSyntax); }
public void Syntax_Receiver_Exception_During_Visit_Doesnt_Stop_Other_Receivers() { var source = @" class C { int Property { get; set; } void Function() { var x = 5; x += 4; } } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation( source, options: TestOptions.DebugDll, parseOptions: parseOptions ); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); var exception = new Exception("Test Exception"); var testGenerator = new CallbackGenerator( onInit: (i) => i.RegisterForSyntaxNotifications( () => new TestSyntaxReceiver( tag: 0, callback: (a) => { if (a is AssignmentExpressionSyntax) { throw exception; } } ) ), onExecute: (e) => { } ); ISyntaxReceiver?receiver = null; var testGenerator2 = new CallbackGenerator2( onInit: (i) => i.RegisterForSyntaxNotifications(() => new TestSyntaxReceiver(tag: 1)), onExecute: (e) => { receiver = e.SyntaxReceiver; e.AddSource("test", SourceText.From("public class D{}", Encoding.UTF8)); } ); GeneratorDriver driver = CSharpGeneratorDriver.Create( new[] { testGenerator, testGenerator2 }, parseOptions: parseOptions ); driver = driver.RunGeneratorsAndUpdateCompilation( compilation, out var outputCompilation, out var outputDiagnostics ); var results = driver.GetRunResult(); Assert.Single(results.GeneratedTrees); Assert.Single(results.Diagnostics); Assert.Equal(2, results.Results.Length); Assert.Single(results.Results[0].Diagnostics); Assert.NotNull(results.Results[0].Exception); Assert.Equal("Test Exception", results.Results[0].Exception?.Message); Assert.Empty(results.Results[1].Diagnostics); var testReceiver = (TestSyntaxReceiver)receiver !; Assert.Equal(1, testReceiver.Tag); Assert.Equal(21, testReceiver.VisitedNodes.Count); outputDiagnostics.Verify( Diagnostic("CS" + (int)ErrorCode.WRN_GeneratorFailedDuringGeneration) .WithArguments("CallbackGenerator", "Exception", "Test Exception") .WithLocation(1, 1) ); }
public void Syntax_Receiver_Exception_During_Creation() { var source = @" class C { int Property { get; set; } void Function() { var x = 5; x += 4; } } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation( source, options: TestOptions.DebugDll, parseOptions: parseOptions ); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); var exception = new Exception("Test Exception"); var testGenerator = new CallbackGenerator( onInit: (i) => i.RegisterForSyntaxNotifications( (SyntaxReceiverCreator)(() => throw exception) ), onExecute: (e) => { Assert.True(false); } ); GeneratorDriver driver = CSharpGeneratorDriver.Create( new[] { testGenerator }, parseOptions: parseOptions ); driver = driver.RunGeneratorsAndUpdateCompilation( compilation, out var outputCompilation, out var outputDiagnostics ); var results = driver.GetRunResult(); Assert.Empty(results.GeneratedTrees); Assert.Single(results.Diagnostics); Assert.Single(results.Results); Assert.Single(results.Results[0].Diagnostics); Assert.NotNull(results.Results[0].Exception); Assert.Equal("Test Exception", results.Results[0].Exception?.Message); outputDiagnostics.Verify( Diagnostic("CS" + (int)ErrorCode.WRN_GeneratorFailedDuringGeneration) .WithArguments("CallbackGenerator", "Exception", "Test Exception") .WithLocation(1, 1) ); }