public void Execute(SourceGeneratorContext context) { string attributeSource = @" [System.AttributeUsage(System.AttributeTargets.Assembly, AllowMultiple=true)] public class MustacheAttribute: System.Attribute { public string Name { get; } public string Template { get; } public string Hash { get; } public MustacheAttribute(string name, string template, string hash) => (Name, Template, Hash) = (name, template, hash); } "; context.AddSource("Mustache_MainAttributes__", SourceText.From(attributeSource, Encoding.UTF8)); Compilation compilation = context.Compilation; IEnumerable <(string, string, string)> options = GetMustacheOptions(compilation); IEnumerable <(string, string)> namesSources = SourceFilesFromMustachePaths(options); foreach ((string name, string source) in namesSources) { context.AddSource($"Mustache{name}", SourceText.From(source, Encoding.UTF8)); } }
public void Execute(SourceGeneratorContext context) { // retreive the populated receiver if (!(context.SyntaxReceiver is SyntaxReceiver receiver)) { return; } try { // 简单测试aop 生成 Action <StringBuilder, IMethodSymbol> beforeCall = (sb, method) => { }; Action <StringBuilder, IMethodSymbol> afterCall = (sb, method) => { sb.Append("r++;"); }; // 获取生成结果 var code = receiver.SyntaxNodes .Select(i => context.Compilation.GetSemanticModel(i.SyntaxTree).GetDeclaredSymbol(i) as INamedTypeSymbol) .Where(i => i != null && !i.IsStatic) .Select(i => ProxyCodeGenerator.GenerateProxyCode(i, beforeCall, afterCall)) .First(); context.AddSource("code.cs", SourceText.From(code, Encoding.UTF8)); } catch (Exception ex) { // 失败汇报 context.ReportDiagnostic(Diagnostic.Create(new DiagnosticDescriptor("n001", ex.ToString(), ex.ToString(), "AOP.Generate", DiagnosticSeverity.Warning, true), Location.Create("code.cs", TextSpan.FromBounds(0, 0), new LinePositionSpan()))); } }
public void Output(string content, string fileName, bool overwriteExisting) { if (overwriteExisting) { _context.AddSource(fileName, SourceText.From(content, Encoding.UTF8)); } }
public void Execute(SourceGeneratorContext context) { var sourceBuilder = new StringBuilder(@" using System; namespace ShowSyntaxTrees { public static class SyntaxTrees { public static void Show() { "); var syntaxTrees = context.Compilation.SyntaxTrees; foreach (var syntaxTree in syntaxTrees) { sourceBuilder.Append($@"Console.WriteLine(@""{syntaxTree.FilePath}"");"); } sourceBuilder.Append(@" } } }"); context.AddSource("syntaxtrees", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8)); }
private void GenerateDictionaty(SourceGeneratorContext context, INamedTypeSymbol type) { var structure = new JsonDictionary(type); var code = DictionaryGenerator.Generate(structure); context.AddSource($"{type.Name}.Generated.cs", SourceText.From(code, Encoding.UTF8)); }
public void Execute(SourceGeneratorContext context) { foreach (var file in context.AdditionalFiles) { context.AddSource(GetGeneratedFileName(file.Path), SourceText.From("", Encoding.UTF8)); } }
public void Execute(SourceGeneratorContext context) { IEnumerable <AdditionalText> settingsFiles = context.AdditionalFiles.Where(at => at.Path.EndsWith(".json")); foreach (var file in settingsFiles) { var fileName = Path.GetFileNameWithoutExtension(file.Path); var jsonDocument = JsonDocument.Parse(file.GetText().ToString()); var sb = new StringBuilder($@" namespace MyGenerated {{ public class {fileName} {{ "); foreach (var prop in jsonDocument.RootElement.EnumerateObject()) { sb.AppendLine($"public {GetPropertyType(prop.Value.ValueKind)} {prop.Name} {{ get; set; }}"); } sb.AppendLine("} }"); var content = sb.ToString(); context.AddSource($"Json_{fileName}.cs", SourceText.From(content, Encoding.UTF8)); } }
public void Execute(SourceGeneratorContext context) { // begin creating the source we'll inject into the users compilation StringBuilder sourceBuilder = new StringBuilder(); // we need to somehow discover the views in a project automatically - for now they listed here var views = new List <string>(); views.Add("MainPage"); views.Add("SecondPage"); foreach (var view in views) { sourceBuilder.Append($@" using Xamarin.Forms; namespace PrismExample.Views {{ public partial class {view} {{ public {view}() {{ InitializeComponent(); }} }} }} "); } // inject the created source into the users compilation context.AddSource("viewGenerated", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8)); }
public void Execute(SourceGeneratorContext context) { // begin creating the source we'll inject into the users compilation var sourceBuilder = new StringBuilder(@" using System; namespace HelloWorldGenerated { public static class HelloWorld { public static void SayHello() { Console.WriteLine(""Hello from generated code!""); Console.WriteLine(""The following syntax trees existed in the compilation that created this program:""); "); // using the context, get a list of syntax trees in the users compilation var syntaxTrees = context.Compilation.SyntaxTrees; // add the filepath of each tree to the class we're building foreach (SyntaxTree tree in syntaxTrees) { sourceBuilder.AppendLine($@"Console.WriteLine(@"" - {tree.FilePath}"");"); } // finish creating the source to inject sourceBuilder.Append(@" } } }"); // inject the created source into the users compilation context.AddSource("helloWorldGenerator", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8)); }
public void Execute(SourceGeneratorContext context) { foreach (AdditionalText bfFile in context.AdditionalFiles.Where(x => x.Path.EndsWith(".bf"))) { try { (IEnumerable <BFOp> operations, BFTranspilerOptions options) = BFParser.Parse(bfFile); if (!operations.Any()) { continue; } BFTranspiler btf = new BFTranspiler(options); string csFile = btf.Transpile(operations); context.AddSource(options.ClassName + ".cs", SourceText.From(csFile, Encoding.UTF8)); } catch (Exception e) { context.ReportDiagnostic( Diagnostic.Create( new DiagnosticDescriptor("P0T4T0", "BFError", "Error when transpiling BF: {0}", "BF.Transpile", DiagnosticSeverity.Error, true), Location.Create(Path.GetFileName(bfFile.Path), new TextSpan(), new LinePositionSpan()), e.Message)); } } }
public void Execute(SourceGeneratorContext context) { try { var registrationSymbols = RegistrationSymbols.FromCompilation(context.Compilation); var containerClasses = context.LocateContainerSymbols(registrationSymbols.ContainerSymbol); var generator = new ContainerClassContentGenerator(context, registrationSymbols); foreach (var containerClass in containerClasses) { var hintName = $"Generated.{containerClass.FullyQualifiedName}"; var content = generator.GenerateClassString(containerClass); WriteOutDebugFile(hintName, content, context); context.AddSource(hintName, SourceText.From(content, Encoding.UTF8)); } } catch (DiagnosticException ex) { context.ReportDiagnostic(ex.Diagnostic); } catch (Exception ex) { var descriptor = new DiagnosticDescriptor(DiagnosticConstants.UnknownExceptionId, "Unexpected error", $"Unknown error during generation: {ex.GetType()} {ex.Message}", DiagnosticConstants.Category, DiagnosticSeverity.Error, true); context.ReportDiagnostic(Diagnostic.Create(descriptor, Location.None)); } }
protected override void Generate(SourceGeneratorContext context, INamedTypeSymbol symbol) { var equalsCandidates = symbol.GetMembers(nameof(Equals)) .Where(member => member is IMethodSymbol method && SymbolEqualityComparer.Default.Equals(method.ReturnType, context.Compilation.GetSpecialType(SpecialType.System_Boolean)) && method.Parameters.Length == 1 && SymbolEqualityComparer.Default.Equals(method.Parameters[0], symbol)); var ghcCandidates = symbol.GetMembers(nameof(GetHashCode)) .Where(member => member is IMethodSymbol method && SymbolEqualityComparer.Default.Equals(method.ReturnType, context.Compilation.GetSpecialType(SpecialType.System_Int32)) && method.Parameters.Length == 0); var builder = new StringBuilder(); if (equalsCandidates.Count() == 0) { var compString = GenerateComparisonOfAllFields(context, symbol); builder.AppendLine(string.Format(symbol.IsValueType ? ValueTypeStandardEqualsTemplate : RefTypeStandardEqualsTemplate, symbol.Name, compString)); } if (ghcCandidates.Count() == 0) { var ghcString = GenerateHashCodeOfAllFields(context, symbol); builder.AppendLine(string.Format(GetHashCodeTemplate, ghcString)); } builder.AppendLine(string.Format(symbol.IsValueType ? ValueTypeEqualsTemplate : RefTypeEqualsTemplate, symbol.Name)); builder.AppendLine(string.Format(EquatableTemplate, symbol.Name)); var source = string.Format(TypeTemplate, symbol.ContainingNamespace, symbol.IsValueType ? "struct" : "class", symbol.Name, builder.ToString()); context.AddSource($"{symbol.Name}.EqualityMembers.cs", SourceText.From(source, Encoding.UTF8)); }
public void Execute(SourceGeneratorContext context) { var resources = context.GetMSBuildItems("PRIResource"); if (resources.Any()) { var sb = new IndentedStringBuilder(); using (sb.BlockInvariant($"namespace {context.GetMSBuildProperty("RootNamespace")}")) { using (sb.BlockInvariant($"internal enum PriResources")) { foreach (var item in resources) { //load document XmlDocument doc = new XmlDocument(); doc.Load(item); //extract all localization keys from Win10 resource file var nodes = doc.SelectNodes("//data") .Cast <XmlElement>() .Select(node => node.GetAttribute("name")) .ToArray(); foreach (var node in nodes) { sb.AppendLineInvariant($"{node},"); } } } } context.AddSource("PriResources", SourceText.From(sb.ToString(), Encoding.UTF8)); } }
public void Execute(SourceGeneratorContext context) { context.AddCompiledOnMetadataAttribute(); var compilation = context.Compilation; var types = CompilationHelper.GetAllTypes(context.Compilation.Assembly); using (var stringWriter = new StringWriter()) using (var indentedTextWriter = new IndentedTextWriter(stringWriter, " ")) { var defaultToStringGenerator = new DefaultToStringGenerator(context); foreach (var type in types) { if (DefaultToStringGenerator.ShouldUseGenerator(type)) { defaultToStringGenerator.WriteType(type, indentedTextWriter); } } indentedTextWriter.Flush(); stringWriter.Flush(); var sourceText = SourceText.From(stringWriter.ToString(), Encoding.UTF8); var hintName = $"AutoToString_{compilation.Assembly.Name}.g.cs"; context.AddSource(hintName, sourceText); } }
public void Execute(SourceGeneratorContext context) { StringBuilder sourceBuilder = new StringBuilder(@" using System; namespace SyntaxTreesGenerated { public static class SyntaxTrees { public static void PrintSyntaxTrees() { Console.WriteLine(""The following syntax trees existed in the compilation that created this program:""); "); foreach (SyntaxTree tree in context.Compilation.SyntaxTrees) { sourceBuilder.AppendLine($@"Console.WriteLine(@""{tree.FilePath}"");"); } sourceBuilder.Append(@" } } }"); context.AddSource("syntaxTreesGenerator", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8)); }
private void GenerateLazyLoader(SourceGeneratorContext context, INamedTypeSymbol type) { var structure = new JsonLazyLoader(type); var code = LazyLoaderGenerator.Generate(structure); context.AddSource($"{type.Name}.Generated.cs", SourceText.From(code, Encoding.UTF8)); }
public void Execute(SourceGeneratorContext context) { // the generator infrastructure will create a receiver and populate it // we can retrieve the populated instance via the context MySyntaxReceiver syntaxReceiver = (MySyntaxReceiver)context.SyntaxReceiver; // get the recorded user class ClassDeclarationSyntax userClass = syntaxReceiver.ClassToAugment; if (userClass is null) { // if we didn't find the user class, there is nothing to do return; } // add the generated implementation to the compilation SourceText sourceText = SourceText.From($@" public partial class {userClass.Identifier} {{ public void GeneratedMethod() {{ // generated code }} }}", Encoding.UTF8); context.AddSource("ExpressionHolder.Generated.cs", sourceText); }
public void WritePrimitivesSerializerClass(SourceGeneratorContext context) { // Write out some functions that are missing from the BinaryPrimitives class. var sourceBuilder = new StringBuilder(); sourceBuilder.Append(@" namespace BitSerialization.Generated { internal static class BitPrimitivesSerializer { public static bool TryWriteByte(global::System.Span<byte> destination, byte value) { if (destination.Length < 1) { return false; } destination[0] = value; return true; } public static bool TryWriteSByte(global::System.Span<byte> destination, sbyte value) { if (destination.Length < 1) { return false; } destination[0] = (byte)value; return true; } public static bool TryReadByte(global::System.ReadOnlySpan<byte> source, out byte value) { if (source.Length < 1) { value = default; return false; } value = source[0]; return true; } public static bool TryReadSByte(global::System.ReadOnlySpan<byte> source, out sbyte value) { if (source.Length < 1) { value = default; return false; } value = (sbyte)source[0]; return true; } } } "); string sourceCode = sourceBuilder.ToString(); context.AddSource("BitPrimitivesSerializer.cs", SourceText.From(sourceCode, Encoding.UTF8)); }
private void Execute(SourceGeneratorContext context, INamedTypeSymbol typeSymbol) { var writer = new TypeBuilderWriter(); var source = writer.Write(typeSymbol); var sourceText = SourceText.From(source, Encoding.UTF8); context.AddSource($"{typeSymbol.Name}Builder.cs", sourceText); }
protected override void Generate(SourceGeneratorContext context, INamedTypeSymbol typeSymbol) { var builder = new IAInputDescBuilder(); ResolveType(builder, (typeSymbol.Name, typeSymbol)); context.AddSource($"{typeSymbol.Name}.IAInputLayout.cs", SourceText.From(builder.ToString(typeSymbol) !, Encoding.UTF8)); }
public void Execute(SourceGeneratorContext context) { _onExecute(context); if (!string.IsNullOrWhiteSpace(_source)) { context.AddSource("source.cs", SourceText.From(_source, Encoding.UTF8)); } }
public void Execute(SourceGeneratorContext context) { Compilation?compilation = context.Compilation; string sourceBuilder = Generate(compilation); context.AddSource("ServiceLocator.cs", SourceText.From(sourceBuilder, Encoding.UTF8)); }
public void Execute(SourceGeneratorContext context) { // Always add the attribute itself to the compilation context.AddSource("CompileTimeExecutorAttribute", SourceText.From(attributeText, Encoding.UTF8)); // retreive the populated receiver if (!(context.SyntaxReceiver is SyntaxReceiver receiver)) { return; } // we're going to create a new compilation that contains the attribute. // TODO: we should allow source generators to provide source during initialize, so that this step isn't required. CSharpParseOptions options = (context.Compilation as CSharpCompilation).SyntaxTrees[0].Options as CSharpParseOptions; Compilation compilation = context.Compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(attributeText, Encoding.UTF8), options)); // get the newly bound attribute, and INotifyPropertyChanged INamedTypeSymbol attributeSymbol = compilation.GetTypeByMetadataName("CompileTimeMethodExecutionGenerator.CompileTimeExecutorAttribute"); foreach (MethodDeclarationSyntax method in receiver.CandidateMethods) { SemanticModel model = compilation.GetSemanticModel(method.SyntaxTree); var methodSymbol = model.GetDeclaredSymbol(method) as IMethodSymbol; foreach (AttributeSyntax attribute in method.AttributeLists .SelectMany(al => al.Attributes) .Where(at => string.Equals("CompileTimeExecutor", at.Name.ToString()))) { string calculatedResult = CalculateResult(method, methodSymbol); context.AddSource($"{methodSymbol.ContainingNamespace.ToDisplayString()}_{methodSymbol.ContainingType.Name}_{method.Identifier.Text}.gen.cs", SourceText.From($@"namespace {methodSymbol.ContainingNamespace.ToDisplayString()} {{ public partial class {methodSymbol.ContainingType.Name} {{ public string {method.Identifier.Text}CompileTime() {{ return ""{calculatedResult}""; }} }} }}", Encoding.UTF8)); } } }
public void Execute(SourceGeneratorContext context) { var source = GetGeneratedSource(context.Compilation); if (source != null) { context.AddSource("generated.cs", SourceText.From(source, Encoding.UTF8)); } }
public void Execute(SourceGeneratorContext context) { // add the attribute text context.AddSource("AutoNotifyAttribute", SourceText.From(attributeText, Encoding.UTF8)); // retreive the populated receiver if (!(context.SyntaxReceiver is SyntaxReceiver receiver)) { return; } // we're going to create a new compilation that contains the attribute. // TODO: we should allow source generators to provide source during initialize, so that this step isn't required. CSharpParseOptions options = (context.Compilation as CSharpCompilation).SyntaxTrees[0].Options as CSharpParseOptions; Compilation compilation = context.Compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(attributeText, Encoding.UTF8), options)); // get the newly bound attribute, and INotifyPropertyChanged INamedTypeSymbol attributeSymbol = compilation.GetTypeByMetadataName("AutoNotify.AutoNotifyAttribute"); INamedTypeSymbol notifySymbol = compilation.GetTypeByMetadataName("System.ComponentModel.INotifyPropertyChanged"); // loop over the candidate fields, and keep the ones that are actually annotated List <IFieldSymbol> fieldSymbols = new List <IFieldSymbol>(); foreach (FieldDeclarationSyntax field in receiver.CandidateFields) { SemanticModel model = compilation.GetSemanticModel(field.SyntaxTree); foreach (VariableDeclaratorSyntax variable in field.Declaration.Variables) { // Get the symbol being decleared by the field, and keep it if its annotated IFieldSymbol fieldSymbol = model.GetDeclaredSymbol(variable) as IFieldSymbol; if (fieldSymbol.GetAttributes().Any(ad => ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.Default))) { fieldSymbols.Add(fieldSymbol); } } } // group the fields by class, and generate the source foreach (IGrouping <INamedTypeSymbol, IFieldSymbol> group in fieldSymbols.GroupBy(f => f.ContainingType)) { string classSource = ProcessClass(group.Key, group.ToList(), attributeSymbol, notifySymbol, context); context.AddSource($"{group.Key.Name}_autoNotify.cs", SourceText.From(classSource, Encoding.UTF8)); } }
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(SourceGeneratorContext context) { context.AddSource(AttributeFullName, SourceText.From(AttributeText, Encoding.UTF8)); // TODO : Improve CSharpParseOptions options = (context.Compilation as CSharpCompilation)?.SyntaxTrees[0]?.Options as CSharpParseOptions ?? throw new InvalidOperationException(); Compilation compilation = context.Compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(AttributeText, Encoding.UTF8), options)); if (!(context.SyntaxReceiver is EnumSyntaxReceiver receiver)) { return; } var attributeSymbol = compilation.GetTypeByMetadataName(AttributeFullName) ?? throw new NullReferenceException($@"[{AttributeFullName}] is missing from the compilation"); var eligibleEnums = receiver.EnumCandidates .Where(enumItem => { var model = compilation.GetSemanticModel(enumItem.SyntaxTree); var symb = model.GetDeclaredSymbol(enumItem); return(symb is not null && symb.GetAttributes().Any(x => x.AttributeClass?.Equals(attributeSymbol, SymbolEqualityComparer.Default) == true)); }); var preProcessedEnums = eligibleEnums .Select(x => (EnumDeclaration: x, Processor: new EnumProcessor(x, compilation))) .ToList(); //foreach (var (enumItem, _) in preProcessedEnums) //{ // var proc = new EnumProcessor(enumItem, compilation); // var src = GenerateEnumExtension(proc); // context.AddSource(proc.EnumType.Name, src); //} context.AddSource(nameof(GenerateAllEnumValues), GenerateAllEnumValues(preProcessedEnums)); context.AddSource(nameof(GenerateAllEnumNames), GenerateAllEnumNames(preProcessedEnums)); context.AddSource(nameof(GenerateTryParseEnum), GenerateTryParseEnum(preProcessedEnums)); }
private static Compilation GenerateHelperClasses(SourceGeneratorContext context) { var compilation = context.Compilation; var options = (compilation as CSharpCompilation)?.SyntaxTrees[0].Options as CSharpParseOptions; var tempCompilation = compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(ServiceLocatorStub, Encoding.UTF8), options)) .AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(TransientAttribute, Encoding.UTF8), options)); context.AddSource("TransientAttribute.cs", SourceText.From(TransientAttribute, Encoding.UTF8)); return(tempCompilation); }
public void RunGeneration() { using var scope = CreateServiceProvider().CreateScope(); var serviceProvider = scope.ServiceProvider; var externalContextProvider = serviceProvider.GetRequiredService <IContextCollectionProvider>(); // First we validate all the captured syntax are valid foreach (var syntaxNode in _capture.CapturedNodes) { // We rely on lazy evaluation so that if the first group fails, we just short cut out var diagnosticsGroup = RunSyntaxAnalyzerGroup(serviceProvider, syntaxNode, externalContextProvider); diagnosticsGroup = diagnosticsGroup.Concat(RunSymbolAnalyzerGroup(serviceProvider, syntaxNode, externalContextProvider)); foreach (var diagnostics in diagnosticsGroup) { if (ReportDiagnostics(diagnostics)) { return; } } } // Then finally we run the generation // TODO : Handle Exceptions try { var generators = serviceProvider.GetServices <SourceGenerator>(); foreach (var generator in generators) { generator.Context = new InternalGeneratingContext { ContextCollectionSource = externalContextProvider, SourceAddition = serviceProvider.GetRequiredService <ISourceAddition>(), SymbolProvider = serviceProvider.GetRequiredService <ITypeSymbolProvider>() }; foreach (var syntaxNode in _capture.CapturedNodes) { var context = new GenerationContext(syntaxNode, GetSemanticModel(syntaxNode), _generatorContext.AdditionalFiles, _generatorContext.AnalyzerConfigOptions, _generatorContext.CancellationToken); generator.GenerateContext(context); } foreach (var source in generator.GeneratedSource) { _generatorContext.AddSource(source.HintName, source.SourceText); } } } catch (Exception e) { GetExceptionDiagnostic(e); // should we rethrow? } }
public void Execute(SourceGeneratorContext context) { context.AddSource(GeneratedClassName, SourceText.From(@" internal class " + GeneratedClassName + @" { public static string GetMessage() { return ""Hello, World!""; } } ", encoding: Encoding.UTF8)); }