public void Initialize()

in src/tools/Avalonia.Generators/NameGenerator/AvaloniaNameIncrementalGenerator.cs [19:201]


    public void Initialize(IncrementalGeneratorInitializationContext context)
    {
        // Map MSBuild properties onto readonly GeneratorOptions.
        var options = context.AnalyzerConfigOptionsProvider
            .Select(static (options, _) => new GeneratorOptions(options.GlobalOptions))
            .WithTrackingName(TrackingNames.XamlGeneratorOptionsProvider);

        // Filter additional texts, we only need Avalonia XAML files.
        var xamlFiles = context.AdditionalTextsProvider
            .Combine(options.Combine(context.AnalyzerConfigOptionsProvider))
            .Where(static pair =>
            {
                var text = pair.Left;
                var (options, optionsProvider) = pair.Right;
                var filePath = text.Path;

                if (!(filePath.EndsWith(".xaml", StringComparison.OrdinalIgnoreCase) ||
                      filePath.EndsWith(".paml", StringComparison.OrdinalIgnoreCase) ||
                      filePath.EndsWith(".axaml", StringComparison.OrdinalIgnoreCase)))
                {
                    return false;
                }

                if (!options.AvaloniaNameGeneratorFilterByPath.Matches(filePath))
                {
                    return false;
                }

                if (!optionsProvider.GetOptions(pair.Left).TryGetValue(SourceItemGroupMetadata, out var itemGroup)
                    || itemGroup != "AvaloniaXaml")
                {
                    return false;
                }

                return true;
            })
            .Select(static (pair, _) => pair.Left)
            .WithTrackingName(TrackingNames.InputXamlFilesProvider);

        // Actual parsing step. We input XAML files one by one, but don't resolve any types.
        // That's why we use NoOp type system here, allowing parsing to run detached from C# compilation.
        // Otherwise we would need to re-parse XAML on any C# file changed.
        var parsedXamlClasses = xamlFiles
            .Select(static (file, cancellationToken) =>
            {
                cancellationToken.ThrowIfCancellationRequested();
                var text = file.GetText(cancellationToken);
                var diagnostics = new List<DiagnosticDescriptor>();
                if (text is not null)
                {
                    try
                    {
                        var xaml = text.ToString();
                        var viewResolver = new XamlXViewResolver(s_noopCompiler);
                        var view = viewResolver.ResolveView(xaml, cancellationToken);
                        if (view is null)
                        {
                            return null;
                        }

                        var nameResolver = new XamlXNameResolver();
                        var xmlNames = nameResolver.ResolveXmlNames(view.Xaml, cancellationToken);

                        return new XmlClassInfo(
                            new ResolvedXmlView(view, xmlNames),
                            new EquatableList<DiagnosticDescriptor>(diagnostics));
                    }
                    catch (OperationCanceledException)
                    {
                        throw;
                    }
                    catch (Exception ex)
                    {
                        diagnostics.Add(GeneratorExtensions.NameGeneratorUnhandledError(ex));
                        return new XmlClassInfo(null, new EquatableList<DiagnosticDescriptor>(diagnostics));
                    }
                }

                return null;
            })
            .Where(request => request is not null)
            .WithTrackingName(TrackingNames.ParsedXamlClasses);

        // IMPORTANT: we shouldn't cache CompilationProvider as a whole,
        // But we also should keep in mind that CompilationProvider can frequently re-trigger generator.
        var compiler = context.CompilationProvider
            .Select(static (compilation, _) =>
            {
                var roslynTypeSystem = new RoslynTypeSystem(compilation);
                return MiniCompiler.CreateRoslyn(roslynTypeSystem, MiniCompiler.AvaloniaXmlnsDefinitionAttribute);
            })
            .WithTrackingName(TrackingNames.XamlTypeSystem);

        // Note: this step will be re-executed on any C# file changes.
        // As much as possible heavy tasks should be moved outside of this step, like XAML parsing.
        var resolvedNames = parsedXamlClasses
            .Combine(compiler)
            .Select(static (pair, ct) =>
            {
                var (classInfo, compiler) = pair;
                var hasDevToolsReference = compiler.TypeSystem.FindAssembly("Avalonia.Diagnostics") is not null;
                var nameResolver = new XamlXNameResolver();

                var diagnostics =  new List<DiagnosticDescriptor>(classInfo!.Diagnostics);
                ResolvedView? view = null;
                if (classInfo.XmlView is { } xmlView)
                {
                    var type = compiler.TypeSystem.FindType(xmlView.FullName);

                    if (type is null)
                    {
                        diagnostics.Add(GeneratorExtensions.NameGeneratorInvalidType(xmlView.FullName));
                    }
                    else if (type.IsAvaloniaStyledElement())
                    {
                        var resolvedNames = new List<ResolvedName>();
                        foreach (var xmlName in xmlView.XmlNames)
                        {
                            ct.ThrowIfCancellationRequested();

                            try
                            {
                                var clrType = compiler.ResolveXamlType(xmlName.XmlType);
                                if (!clrType.IsAvaloniaStyledElement())
                                {
                                    continue;
                                }

                                resolvedNames.Add(nameResolver
                                    .ResolveName(clrType, xmlName.Name, xmlName.FieldModifier));
                            }
                            catch (Exception ex)
                            {
                                diagnostics.Add(GeneratorExtensions.NameGeneratorUnhandledError(ex));
                            }
                        }

                        view = new ResolvedView(xmlView, type.IsAvaloniaWindow(), new EquatableList<ResolvedName>(resolvedNames));
                    }
                }

                return new ResolvedClassInfo(view, hasDevToolsReference, new EquatableList<DiagnosticDescriptor>(diagnostics));
            })
            .WithTrackingName(TrackingNames.ResolvedNamesProvider);

        context.RegisterSourceOutput(resolvedNames.Combine(options), static (context, pair) =>
        {
            var (info, options) = pair;

            foreach (var diagnostic in info!.Diagnostics)
            {
                context.Report(diagnostic);
            }

            if (info.View is { } view && options.AvaloniaNameGeneratorFilterByNamespace.Matches(view.Namespace))
            {
                ICodeGenerator codeGenerator = options.AvaloniaNameGeneratorBehavior switch
                {
                    Behavior.OnlyProperties => new OnlyPropertiesCodeGenerator(
                        options.AvaloniaNameGeneratorClassFieldModifier),
                    Behavior.InitializeComponent => new InitializeComponentCodeGenerator(
                        options.AvaloniaNameGeneratorAttachDevTools && info.CanAttachDevTools && view.IsWindow,
                        options.AvaloniaNameGeneratorClassFieldModifier),
                    _ => throw new ArgumentOutOfRangeException()
                };
                var fileName = options.AvaloniaNameGeneratorViewFileNamingStrategy switch
                {
                    ViewFileNamingStrategy.ClassName => $"{view.ClassName}.g.cs",
                    ViewFileNamingStrategy.NamespaceAndClassName => $"{view.Namespace}.{view.ClassName}.g.cs",
                    _ => throw new ArgumentOutOfRangeException(
                        nameof(ViewFileNamingStrategy), options.AvaloniaNameGeneratorViewFileNamingStrategy,
                        "Unknown naming strategy!")
                };

                var generatedPartialClass = codeGenerator.GenerateCode(
                    info.View.ClassName,
                    info.View.Namespace,
                    info.View.Names);

                context.AddSource(fileName, generatedPartialClass);
            }
        });
    }