File: Syntax\CSharpSyntaxTree.ParsedSyntaxTree.cs
Web Access
Project: src\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp)
// 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;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.CSharp
{
    public partial class CSharpSyntaxTree
    {
        private class ParsedSyntaxTree : CSharpSyntaxTree
        {
            private readonly CSharpParseOptions _options;
            private readonly string _path;
            private readonly CSharpSyntaxNode _root;
            private readonly bool _hasCompilationUnitRoot;
            private readonly Encoding? _encodingOpt;
            private readonly SourceHashAlgorithm _checksumAlgorithm;
            private readonly ImmutableDictionary<string, ReportDiagnostic> _diagnosticOptions;
            private SourceText? _lazyText;
 
            internal ParsedSyntaxTree(
                SourceText? textOpt,
                Encoding? encodingOpt,
                SourceHashAlgorithm checksumAlgorithm,
                string? path,
                CSharpParseOptions options,
                CSharpSyntaxNode root,
                Syntax.InternalSyntax.DirectiveStack directives,
                ImmutableDictionary<string, ReportDiagnostic>? diagnosticOptions,
                bool cloneRoot)
                : base(directives)
            {
                Debug.Assert(root != null);
                Debug.Assert(options != null);
                Debug.Assert(textOpt == null || textOpt.Encoding == encodingOpt && textOpt.ChecksumAlgorithm == checksumAlgorithm);
 
                _lazyText = textOpt;
                _encodingOpt = encodingOpt ?? textOpt?.Encoding;
                _checksumAlgorithm = checksumAlgorithm;
                _options = options;
                _path = path ?? string.Empty;
                _root = cloneRoot ? this.CloneNodeAsRoot(root) : root;
                _hasCompilationUnitRoot = root.Kind() == SyntaxKind.CompilationUnit;
                _diagnosticOptions = diagnosticOptions ?? EmptyDiagnosticOptions;
            }
 
            public override string FilePath
            {
                get { return _path; }
            }
 
            public override SourceText GetText(CancellationToken cancellationToken)
            {
                if (_lazyText == null)
                {
                    Interlocked.CompareExchange(ref _lazyText, this.GetRoot(cancellationToken).GetText(_encodingOpt, _checksumAlgorithm), null);
                }
 
                return _lazyText;
            }
 
            public override bool TryGetText([NotNullWhen(true)] out SourceText? text)
            {
                text = _lazyText;
                return text != null;
            }
 
            public override Encoding? Encoding
            {
                get { return _encodingOpt; }
            }
 
            public override int Length
            {
                get { return _root.FullSpan.Length; }
            }
 
            public override CSharpSyntaxNode GetRoot(CancellationToken cancellationToken)
            {
                return _root;
            }
 
            public override bool TryGetRoot(out CSharpSyntaxNode root)
            {
                root = _root;
                return true;
            }
 
            public override bool HasCompilationUnitRoot
            {
                get
                {
                    return _hasCompilationUnitRoot;
                }
            }
 
            public override CSharpParseOptions Options
            {
                get
                {
                    return _options;
                }
            }
 
            [Obsolete("Obsolete due to performance problems, use CompilationOptions.SyntaxTreeOptionsProvider instead", error: false)]
            public override ImmutableDictionary<string, ReportDiagnostic> DiagnosticOptions => _diagnosticOptions;
 
            public override SyntaxReference GetReference(SyntaxNode node)
            {
                return new SimpleSyntaxReference(node);
            }
 
            public override SyntaxTree WithRootAndOptions(SyntaxNode root, ParseOptions options)
            {
                if (ReferenceEquals(_root, root) && ReferenceEquals(_options, options))
                {
                    return this;
                }
 
                return new ParsedSyntaxTree(
                    textOpt: null,
                    _encodingOpt,
                    _checksumAlgorithm,
                    _path,
                    (CSharpParseOptions)options,
                    (CSharpSyntaxNode)root,
                    ReferenceEquals(_root, root) ? _lazyDirectives : default,
                    _diagnosticOptions,
                    cloneRoot: true);
            }
 
            public override SyntaxTree WithFilePath(string path)
            {
                if (_path == path)
                {
                    return this;
                }
 
                return new ParsedSyntaxTree(
                    _lazyText,
                    _encodingOpt,
                    _checksumAlgorithm,
                    path,
                    _options,
                    _root,
                    _lazyDirectives,
                    _diagnosticOptions,
                    cloneRoot: true);
            }
 
            [Obsolete("Obsolete due to performance problems, use CompilationOptions.SyntaxTreeOptionsProvider instead", error: false)]
            public override SyntaxTree WithDiagnosticOptions(ImmutableDictionary<string, ReportDiagnostic> options)
            {
                if (options is null)
                {
                    options = EmptyDiagnosticOptions;
                }
 
                if (ReferenceEquals(_diagnosticOptions, options))
                {
                    return this;
                }
 
                return new ParsedSyntaxTree(
                    _lazyText,
                    _encodingOpt,
                    _checksumAlgorithm,
                    _path,
                    _options,
                    _root,
                    _lazyDirectives,
                    options,
                    cloneRoot: true);
            }
        }
    }
}