File: DirectiveSyntaxExtensions.cs
Web Access
Project: ..\..\..\src\CodeStyle\CSharp\Analyzers\Microsoft.CodeAnalysis.CSharp.CodeStyle.csproj (Microsoft.CodeAnalysis.CSharp.CodeStyle)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Syntax;
 
namespace Microsoft.CodeAnalysis.CSharp.Extensions
{
    internal static partial class DirectiveSyntaxExtensions
    {
        private static readonly ConditionalWeakTable<SyntaxNode, DirectiveInfo> s_rootToDirectiveInfo =
            new();
 
        private static SyntaxNode GetAbsoluteRoot(this SyntaxNode node)
        {
            while (node != null && (node.Parent != null || node is StructuredTriviaSyntax))
            {
                if (node.Parent != null)
                {
                    node = node.Parent;
                }
                else
                {
                    node = node.ParentTrivia.Token.Parent;
                }
            }
 
            return node;
        }
 
        private static DirectiveInfo GetDirectiveInfo(SyntaxNode node, CancellationToken cancellationToken)
        {
            var root = node.GetAbsoluteRoot();
            var info = s_rootToDirectiveInfo.GetValue(root, r =>
            {
                var directiveMap = new Dictionary<DirectiveTriviaSyntax, DirectiveTriviaSyntax>(
                    DirectiveSyntaxEqualityComparer.Instance);
                var conditionalMap = new Dictionary<DirectiveTriviaSyntax, IReadOnlyList<DirectiveTriviaSyntax>>(
                    DirectiveSyntaxEqualityComparer.Instance);
 
                var walker = new DirectiveWalker(directiveMap, conditionalMap, cancellationToken);
                walker.Visit(r);
                walker.Finish();
 
                return new DirectiveInfo(directiveMap, conditionalMap, inactiveRegionLines: null);
            });
 
            return info;
        }
 
        internal static DirectiveTriviaSyntax GetMatchingDirective(this DirectiveTriviaSyntax directive, CancellationToken cancellationToken)
        {
            if (directive == null)
            {
                throw new ArgumentNullException(nameof(directive));
            }
 
            var directiveSyntaxMap = GetDirectiveInfo(directive, cancellationToken).DirectiveMap;
            directiveSyntaxMap.TryGetValue(directive, out var result);
 
            return result;
        }
 
        internal static IReadOnlyList<DirectiveTriviaSyntax> GetMatchingConditionalDirectives(this DirectiveTriviaSyntax directive, CancellationToken cancellationToken)
        {
            if (directive == null)
            {
                throw new ArgumentNullException(nameof(directive));
            }
 
            var directiveConditionalMap = GetDirectiveInfo(directive, cancellationToken).ConditionalMap;
            directiveConditionalMap.TryGetValue(directive, out var result);
 
            return result;
        }
    }
}