File: Workspace\LanguageServices\CSharpSyntaxTreeFactoryService.ParsedSyntaxTree.cs
Web Access
Project: ..\..\..\src\Workspaces\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.Workspaces.csproj (Microsoft.CodeAnalysis.CSharp.Workspaces)
// 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.
 
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Threading;
using Microsoft.CodeAnalysis.Text;
 
namespace Microsoft.CodeAnalysis.CSharp
{
    internal partial class CSharpSyntaxTreeFactoryService
    {
        /// <summary>
        /// Parsed <see cref="CSharpSyntaxTree"/> that creates <see cref="SourceText"/> with given encoding and checksum algorithm.
        /// </summary>
        private sealed class ParsedSyntaxTree : CSharpSyntaxTree
        {
            private readonly CSharpSyntaxNode _root;
            private readonly SourceHashAlgorithm _checksumAlgorithm;
 
            public override Encoding? Encoding { get; }
            public override CSharpParseOptions Options { get; }
            public override string FilePath { get; }
 
            private SourceText? _lazyText;
 
            public ParsedSyntaxTree(SourceText? lazyText, CSharpSyntaxNode root, CSharpParseOptions options, string filePath, Encoding? encoding, SourceHashAlgorithm checksumAlgorithm)
            {
                _lazyText = lazyText;
                _root = CloneNodeAsRoot(root);
                _checksumAlgorithm = checksumAlgorithm;
 
                Encoding = encoding;
                Options = options;
                FilePath = filePath;
            }
 
            public override SourceText GetText(CancellationToken cancellationToken)
            {
                if (_lazyText == null)
                {
                    Interlocked.CompareExchange(ref _lazyText, GetRoot(cancellationToken).GetText(Encoding, _checksumAlgorithm), null);
                }
 
                return _lazyText;
            }
 
            public override bool TryGetText([NotNullWhen(true)] out SourceText? text)
            {
                text = _lazyText;
                return text != null;
            }
 
            public override int Length
                => _root.FullSpan.Length;
 
            public override bool HasCompilationUnitRoot
                => true;
 
            public override CSharpSyntaxNode GetRoot(CancellationToken cancellationToken)
                => _root;
 
            public override bool TryGetRoot([NotNullWhen(true)] out CSharpSyntaxNode? root)
            {
                root = _root;
                return true;
            }
 
            public override SyntaxTree WithRootAndOptions(SyntaxNode root, ParseOptions options)
                => (root == _root && options == Options) ? this : new ParsedSyntaxTree((root == _root) ? _lazyText : null, (CSharpSyntaxNode)root, (CSharpParseOptions)options, FilePath, Encoding, _checksumAlgorithm);
 
            public override SyntaxTree WithFilePath(string path)
                => (path == FilePath) ? this : new ParsedSyntaxTree(_lazyText, _root, Options, path, Encoding, _checksumAlgorithm);
 
            public override SyntaxReference GetReference(SyntaxNode node)
                => new NodeSyntaxReference(node);
        }
    }
}