public void Execute(GeneratorExecutionContext context) { context.ReportDiagnostic( Diagnostic.Create( DiagnosticDescriptors.Warning, Location.None, $"ISourceGenerator.Execute {Assembly.GetExecutingAssembly().Location}")); // the generator infrastructure will create a receiver and populate it // we can retrieve the populated instance via the context if (context.SyntaxContextReceiver is not MySyntaxReceiver syntaxReceiver) { return; } List <(string GeneratorName, HbsLoadType loadType, AdditionalText file)> templates = GetLoadOptions(context).Where(r => "AutoInterfaceImplement".Equals(r.GeneratorName)).ToList(); var startupTemplateFile = templates.FirstOrDefault(r => r.loadType.Equals(HbsLoadType.Startup)).file; var partialTemplateFiles = templates.Where(r => r.loadType.Equals(HbsLoadType.Partial)).Select(r => r.file); if (startupTemplateFile is null) { return; } foreach (var partialTemplateFile in partialTemplateFiles) { var partialTemplateName = Path.GetFileNameWithoutExtension(partialTemplateFile.Path); var partialTemplateText = partialTemplateFile.GetText()?.ToString() ?? string.Empty; Handlebars.RegisterTemplate(partialTemplateName, partialTemplateText); } Handlebars.RegisterHelper("ifCond", (output, options, context, arguments) => { if (arguments.Length < 3) { return; } var arg0 = arguments[0]; var arg1 = arguments[1]; var arg2 = arguments[2]; switch (arg1) { case "Equals": if (arg0.Equals(arg2)) { options.Template(output, context); } else { options.Inverse(output, context); } break; } }); var startupTemplateText = startupTemplateFile.GetText()?.ToString() ?? string.Empty; if (string.IsNullOrWhiteSpace(startupTemplateText)) { context.ReportDiagnostic( Diagnostic.Create( DiagnosticDescriptors.Warning, Location.None, $"template file '{startupTemplateFile.Path}' is empty")); return; } var startupTemplate = Handlebars.Compile(startupTemplateText); var autoImplementationInterfaces = syntaxReceiver.AutoImplementationInterfaces; var classHbsContexts = new List <ClassHbsContext>(); foreach (var namedTypeSymbol in autoImplementationInterfaces) { var classHbsContext = new ClassHbsContext { NameSpaceQualifiedIdentifier = namedTypeSymbol.ContainingNamespace.ToDisplayString(), Identifier = namedTypeSymbol.Name, Properties = new List <PropertyHbsContext>() }; var propertySymbols = namedTypeSymbol.AllInterfaces .Concat(new INamedTypeSymbol[] { namedTypeSymbol }) .SelectMany(interfaceSymbol => interfaceSymbol.GetMembers() .OfType <IPropertySymbol>()); var propertyInfos = propertySymbols.Select( propertySymbol => { var accessibilities = new Accessibility[] { propertySymbol.DeclaredAccessibility, propertySymbol.GetMethod?.DeclaredAccessibility ?? Accessibility.Public, propertySymbol.SetMethod?.DeclaredAccessibility ?? Accessibility.Public }; var isPublic = accessibilities.All(a => a.Equals(Accessibility.Public)); var accessorList = (propertySymbol.GetMethod, propertySymbol.SetMethod) switch { (IMethodSymbol get, IMethodSymbol set) => new HashSet <string>() { "get", "set" }, (IMethodSymbol get, null) => new HashSet <string>() { "get" }, (null, IMethodSymbol set) => new HashSet <string>() { "set" }, (_, _) => new HashSet <string>() }; return(new PropertyDeclaration { IsPublic = isPublic, AccessorList = accessorList, IsClassMember = false, IsMerged = false, Symbol = propertySymbol }); }).ToList(); var classMembers = propertyInfos .Where(r => r.IsPublic) .GroupBy(r => r.Symbol.Name) .Select(g1 => g1 .GroupBy(r => r.Symbol.Type.ToDisplayString()) .Select(g2 => new { PropertyDeclaration = g2.First(), InterfaceCount = g2.Count() }) .OrderByDescending(r => r.InterfaceCount) .FirstOrDefault().PropertyDeclaration) .ToList(); (from c in classMembers join p in propertyInfos.Where(r => r.IsPublic) on new { c.Symbol.Name, Type = c.Symbol.Type.ToDisplayString() } equals new { p.Symbol.Name, Type = p.Symbol.Type.ToDisplayString() } into g select MergeAccessorList(c, g)) .ToList(); propertyInfos = propertyInfos.Where(p => !p.IsMerged).ToList(); foreach (var propertyInfo in propertyInfos) { var propertyHbsContext = new PropertyHbsContext { Accessors = propertyInfo.AccessorList, TypeIdentifier = propertyInfo.Symbol.Type.ToDisplayString() }; if (propertyInfo.IsClassMember) { propertyHbsContext.AccessModifiers = "public "; propertyHbsContext.Identifier = propertyInfo.Symbol.Name; } else { propertyHbsContext.AccessModifiers = string.Empty; propertyHbsContext.Identifier = propertyInfo.Symbol.ToDisplayString(); } classHbsContext.Properties.Add(propertyHbsContext); } classHbsContexts.Add(classHbsContext); var classSourceCode = startupTemplate(classHbsContext); context.AddSource($"{classHbsContext.NameSpaceQualifiedIdentifier}.AutoImplementation{classHbsContext.Identifier}.cs", SourceText.From(classSourceCode, Encoding.UTF8)); } }