File: Language\Extensions\FunctionsDirectivePass.cs
Web Access
Project: src\src\Razor\src\Compiler\Microsoft.CodeAnalysis.Razor.Compiler\src\Microsoft.CodeAnalysis.Razor.Compiler.csproj (Microsoft.CodeAnalysis.Razor.Compiler)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Generic;
using System.Threading;
using Microsoft.AspNetCore.Razor.Language.Components;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
using Microsoft.AspNetCore.Razor.PooledObjects;
 
namespace Microsoft.AspNetCore.Razor.Language.Extensions;
 
public sealed class FunctionsDirectivePass : IntermediateNodePassBase, IRazorDirectiveClassifierPass
{
    private static readonly Comparer<int?> s_nullableIntComparer = Comparer<int?>.Default;
 
    protected override void ExecuteCore(
        RazorCodeDocument codeDocument,
        DocumentIntermediateNode documentNode,
        CancellationToken cancellationToken)
    {
        var @class = documentNode.FindPrimaryClass();
        if (@class == null)
        {
            return;
        }
 
        using var directiveNodes = new PooledArrayBuilder<IntermediateNodeReference<DirectiveIntermediateNode>>();
 
        documentNode.CollectDirectiveReferences(FunctionsDirective.Directive, ref directiveNodes.AsRef());
 
        if (codeDocument.FileKind.IsComponent())
        {
            documentNode.CollectDirectiveReferences(ComponentCodeDirective.Directive, ref directiveNodes.AsRef());
        }
 
        // Now we have all the directive nodes, we want to add them to the end of the class node in document order.
        // So, we sort them by their absolute index.
        directiveNodes.Sort(CompareAbsoluteIndices);
 
        foreach (var directiveReference in directiveNodes)
        {
            var node = directiveReference.Node;
            @class.Children.AddRange(node.Children);
 
            // We don't want to keep the original directive node around anymore.
            // Otherwise this can cause unintended side effects in the subsequent passes.
            directiveReference.Remove();
        }
 
        static int CompareAbsoluteIndices(
            IntermediateNodeReference<DirectiveIntermediateNode> n1,
            IntermediateNodeReference<DirectiveIntermediateNode> n2)
        {
            return s_nullableIntComparer.Compare(n1.Node.Source?.AbsoluteIndex, n2.Node.Source?.AbsoluteIndex);
        }
    }
}