/// <summary> /// Generates source code to optimize serialization and deserialization with JsonSerializer. /// </summary> /// <param name="executionContext"></param> public void Execute(GeneratorExecutionContext executionContext) { #if LAUNCH_DEBUGGER if (!Diagnostics.Debugger.IsAttached) { Diagnostics.Debugger.Launch(); } #endif SyntaxReceiver receiver = (SyntaxReceiver)executionContext.SyntaxReceiver; List <ClassDeclarationSyntax>?contextClasses = receiver.ClassDeclarationSyntaxList; if (contextClasses == null) { return; } Parser parser = new(executionContext); SourceGenerationSpec?spec = parser.GetGenerationSpec(receiver.ClassDeclarationSyntaxList); if (spec != null) { _rootTypes = spec.ContextGenerationSpecList[0].RootSerializableTypes; Emitter emitter = new(executionContext, spec); emitter.Emit(); } }
// Finds all the classes annotated with the BitStruct attribute. private List <INamedTypeSymbol> FindAllBitStructClasses(SourceGeneratorContext context, INamedTypeSymbol bitStructAttributeSymbol) { // retreive the populated receiver SyntaxReceiver receiver = context.SyntaxReceiver as SyntaxReceiver; if (receiver == null) { return(null); } List <INamedTypeSymbol> result = new List <INamedTypeSymbol>(); foreach (TypeDeclarationSyntax classDeclarationSyntax in receiver.CandidateClasses) { SemanticModel model = context.Compilation.GetSemanticModel(classDeclarationSyntax.SyntaxTree); INamedTypeSymbol classSymbol = model.GetDeclaredSymbol(classDeclarationSyntax); if (SourceGenUtils.HasAttribute(classSymbol, bitStructAttributeSymbol)) { result.Add(classSymbol); } } return(result); }
public void Execute(SourceGeneratorContext context) { SyntaxReceiver receiver = context.SyntaxReceiver as SyntaxReceiver; foreach (string name in receiver.Namespaces) { string code = GetCodeForNamespace(name); context.AddSource($"{name}.Console.Generated", SourceText.From(code, Encoding.UTF8)); } }
public void Execute(GeneratorExecutionContext context) { SyntaxReceiver rx = (SyntaxReceiver)context.SyntaxContextReceiver !; foreach ((string name, string template, string hash) in rx.TemplateInfo) { string source = SourceFileFromMustachePath(name, template, hash); context.AddSource($"Mustache{name}", source); } }
public void OnVisitSyntaxNode_SyntaxWithFullyQualifiedIDisposableBase_AddsSingleCandidate() { // Arrange var tree = CSharpSyntaxTree.ParseText(@" public class TestClass : System.IDisposable { } "); var classNode = tree.GetRoot().DescendantNodes().OfType <ClassDeclarationSyntax>().First(); var syntaxReceiver = new SyntaxReceiver(); // Act syntaxReceiver.OnVisitSyntaxNode(classNode); // Assert Assert.Single(syntaxReceiver.CandidateClasses); }
public void OnVisitSyntaxNode_SyntaxWithUninterestingBase_FindsNoCandidates() { // Arrange var tree = CSharpSyntaxTree.ParseText(@" public class TestClass : IEnumerable { } "); var classNode = tree.GetRoot().DescendantNodes().OfType <ClassDeclarationSyntax>().First(); var syntaxReceiver = new SyntaxReceiver(); // Act syntaxReceiver.OnVisitSyntaxNode(classNode); // Assert Assert.False(syntaxReceiver.CandidateClasses.Any()); }
public void Execute(GeneratorExecutionContext context) { SyntaxReceiver rx = (SyntaxReceiver)context.SyntaxContextReceiver !; HashSet <string> generatedInterfaces = new HashSet <string>(); foreach (string interfaceFullTypeName in rx.InterfacesToGenerate) { INamedTypeSymbol?interfaceSymbol = context.Compilation.GetTypeByMetadataName(interfaceFullTypeName); if (interfaceSymbol == null) { continue; } if (generatedInterfaces.Contains(interfaceFullTypeName)) { continue; } ImportedControlGenerator.GenerateSourceFile(context, interfaceFullTypeName); generatedInterfaces.Add(interfaceFullTypeName); // Generate any ancestor types INamedTypeSymbol?ancestorType = GetBaseInterface(interfaceSymbol); while (ancestorType != null) { var symbolDisplayFormat = new SymbolDisplayFormat( typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces); string ancestorFullTypeName = ancestorType.ToDisplayString(symbolDisplayFormat); if (ancestorFullTypeName == "Microsoft.StandardUI.Controls.IStandardControl" || generatedInterfaces.Contains(ancestorFullTypeName)) { break; } ImportedControlGenerator.GenerateSourceFile(context, ancestorFullTypeName); generatedInterfaces.Add(ancestorFullTypeName); ancestorType = GetBaseInterface(ancestorType); } } }
/// <summary> /// Generates source code to optimize serialization and deserialization with JsonSerializer. /// </summary> /// <param name="executionContext"></param> public void Execute(GeneratorExecutionContext executionContext) { SyntaxReceiver receiver = (SyntaxReceiver)executionContext.SyntaxReceiver; List <CompilationUnitSyntax> compilationUnits = receiver.CompilationUnits; if (compilationUnits == null) { return; } Parser parser = new(executionContext.Compilation); _rootTypes = parser.GetRootSerializableTypes(receiver.CompilationUnits); if (_rootTypes != null) { Emitter emitter = new(executionContext, _rootTypes); emitter.Emit(); } }
public void OnVisitSyntaxNode_MultipleVisitsWithInterestingClass_YieldsMultipleCandidates() { // Arrange var tree = CSharpSyntaxTree.ParseText(@" public class TestClass : System.IDisposable { } "); var classNode = tree.GetRoot().DescendantNodes().OfType <ClassDeclarationSyntax>().First(); var syntaxReceiver = new SyntaxReceiver(); // Act syntaxReceiver.OnVisitSyntaxNode(classNode); syntaxReceiver.OnVisitSyntaxNode(classNode); syntaxReceiver.OnVisitSyntaxNode(classNode); // Assert Assert.Equal(3, syntaxReceiver.CandidateClasses.Count); }
/// <summary> /// Generates source code to optimize serialization and deserialization with JsonSerializer. /// </summary> /// <param name="executionContext"></param> public void Execute(GeneratorExecutionContext executionContext) { SyntaxReceiver receiver = (SyntaxReceiver)executionContext.SyntaxReceiver; List <ClassDeclarationSyntax>?contextClasses = receiver.ClassDeclarationSyntaxList; if (contextClasses == null) { return; } Parser parser = new(executionContext); SourceGenerationSpec?spec = parser.GetGenerationSpec(receiver.ClassDeclarationSyntaxList); if (spec != null) { _rootTypes = spec.ContextGenerationSpecList[0].RootSerializableTypes; Emitter emitter = new(executionContext, spec); emitter.Emit(); } }
public void Execute(GeneratorExecutionContext context) { #if DEBUG if (!Debugger.IsAttached) { //Debugger.Launch(); } #endif SyntaxReceiver rx = (SyntaxReceiver)context.SyntaxContextReceiver !; foreach (TypeInfo targetType in rx.GeneratedTypes) { if (targetType.Type?.IsAbstract == true) { continue; } StringBuilder sb = new(); const string suffix = "GeneratedExtensions"; string targetTypeFullName = $"{targetType.Type}"; string targetTypeName = targetType.Type !.Name; var extensionClass = context.Compilation.GetTypeByMetadataName($"XamlTest.{targetTypeName}{suffix}"); if (extensionClass is null) { continue; } string variableTargetTypeName = char.ToLowerInvariant(targetType.Type.Name[0]) + targetType.Type.Name.Substring(1); string className = $"{targetType.Type.Name}{suffix}Tests"; sb.AppendLine($@" using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Threading.Tasks; using System; namespace XamlTest.Tests.Generated {{ [TestClass] public partial class {className} {{ [NotNull] private static IApp? App {{ get; set; }} [NotNull] private static IWindow? Window {{ get; set; }} private static Func<string, string> GetWindowContent {{ get; set; }} = x => x; private static Func<string, Task<IVisualElement<{targetTypeFullName}>>> GetElement {{ get; set; }} = async x => await Window.GetElement<{targetTypeFullName}>(x); static partial void OnClassInitialize(); [ClassInitialize] public static async Task ClassInitialize(TestContext context) {{ OnClassInitialize(); App = XamlTest.App.StartRemote(logMessage: msg => context.WriteLine(msg)); await App.InitializeWithDefaults(Assembly.GetExecutingAssembly().Location); string content = @$""<{targetTypeName} x:Name=""""Test{targetTypeName}""""/>""; content = GetWindowContent(content); Window = await App.CreateWindowWithContent(content); }} [ClassCleanup] public static void TestCleanup() {{ App.Dispose(); }} "); foreach (IMethodSymbol getMethod in GetTestMethods(extensionClass)) { string methodReturnType = ((INamedTypeSymbol)getMethod.ReturnType).TypeArguments[0].ToString(); sb.AppendLine($@" [TestMethod] public async Task CanInvoke_{getMethod.Name}_ReturnsValue() {{ // Arrange await using TestRecorder recorder = new(App); //Act IVisualElement<{targetTypeFullName}> {variableTargetTypeName} = await GetElement(""Test{targetTypeName}""); var actual = await {variableTargetTypeName}.{getMethod.Name}(); //Assert //{GetAssertion(getMethod.Name.Substring(3), methodReturnType)} recorder.Success(); }} "); } sb.AppendLine($@" }} }}"); //System.IO.File.WriteAllText($@"D:\Dev\XAMLTest\XAMLTest.UnitTestGenerator\obj\{className}.cs", sb.ToString()); context.AddSource($"{className}.cs", sb.ToString()); }
private static Dictionary <INamedTypeSymbol, IList <AttributeData> > GetClassAttributePairs(GeneratorExecutionContext context, SyntaxReceiver receiver) { var compilation = context.Compilation; var classSymbols = new Dictionary <INamedTypeSymbol, IList <AttributeData> >(); foreach (var clazz in receiver.CandidateClasses) { var model = compilation.GetSemanticModel(clazz.SyntaxTree); var classSymbol = model.GetDeclaredSymbol(clazz); var attributes = classSymbol.GetAttributes(); if (attributes.Any(ad => ad.AttributeClass.Name == nameof(GenerateAutoFilterAttribute))) { classSymbols.Add((INamedTypeSymbol)classSymbol, attributes.ToList()); } } return(classSymbols); }
private static void WriteMembers(SyntaxReceiver syntaxReceiver, CSharpCompilation compilation, in GeneratorExecutionContext context)
private void ProcessRoute(GeneratorExecutionContext context, SyntaxReceiver receiver, CSharpParseOptions options) { Compilation routeAttributeCompilation = context.Compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(routeAttributeText, Encoding.UTF8), options)); INamedTypeSymbol routeAttributeSymbol = routeAttributeCompilation.GetTypeByMetadataName("PlatformExtensions.RouteAttribute"); // loop over the candidate fields, and keep the ones that are actually annotated List<(IMethodSymbol symbol, MethodDeclarationSyntax method)> routeAttributeSymbols = new (); bool isAsync = false; foreach (MethodDeclarationSyntax method in receiver.CandidateMethods) { SemanticModel routeModel = routeAttributeCompilation.GetSemanticModel(method.SyntaxTree); // Get the symbol being decleared by the field, and keep it if its annotated IMethodSymbol methodSymbol = routeModel.GetDeclaredSymbol(method); if (methodSymbol.GetAttributes().Any(ad => ad.AttributeClass.Equals(routeAttributeSymbol, SymbolEqualityComparer.Default))) { routeAttributeSymbols.Add((methodSymbol, method)); if (!isAsync && method.ReturnType is GenericNameSyntax rt) { isAsync = rt.Identifier.ValueText == "Task"; } } } IEnumerable<IGrouping<INamedTypeSymbol, (IMethodSymbol symbol, MethodDeclarationSyntax method)>> classes = routeAttributeSymbols.GroupBy(f => f.symbol.ContainingType); if (classes.Count() != 1) { throw new Exception("One and only one application class should be defined"); } var item = classes.FirstOrDefault(); INamedTypeSymbol classSymbol = item.Key; string namespaceName = classSymbol.ContainingNamespace.ToDisplayString(); var assembly = Assembly.GetExecutingAssembly(); var fileName = "Ben.AspNetCore.PlatformExtensions.Application.cs"; var stream = assembly.GetManifestResourceStream(fileName); if (stream == null) throw new FileNotFoundException("Cannot find mappings file.", fileName); // begin building the generated source StringBuilder source = new StringBuilder($@" using System; using System.Buffers; using System.IO.Pipelines; using System.Runtime.CompilerServices; using System.Threading.Tasks; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; using PlatformExtensions; namespace {namespaceName} {{ public partial class {classSymbol.Name} : IHttpConnection {{ "); using (var reader = new StreamReader(stream, Encoding.UTF8)) { source.Append(reader.ReadToEnd()); } var snippetFileName = $"Ben.AspNetCore.PlatformExtensions.Application.{(isAsync? "Async" : "Sync")}.cs"; stream = assembly.GetManifestResourceStream(snippetFileName); if (stream == null) throw new FileNotFoundException("Cannot find mappings file.", snippetFileName); using (var reader = new StreamReader(stream, Encoding.UTF8)) { source.Append(reader.ReadToEnd()); } if (!isAsync) { source.Append(@" private void ProcessRequest(ref BufferWriter<WriterAdapter> writer) { var requestType = _requestType; "); foreach (var group in classes) { var isFirst = true; foreach (var methodData in group) { source.Append(@$" {(!isFirst ? "else " : "")}if (requestType == RequestType.{methodData.symbol.Name}) {{ {methodData.symbol.Name}_Routed(ref writer{(methodData.symbol.ReturnType.SpecialType == SpecialType.System_String ? "" : ", Writer")}{(methodData.method.ParameterList.Parameters.Count > 0 ? ", _queries" : "")});
public static CompilationDatum Generate(SyntaxReceiver syntaxReceiver, CSharpCompilation compilation, in GeneratorExecutionContext context)