CSharpSyntaxTreeFactoryService.RecoverableSyntaxTree.cs 8.1 KB
Newer Older
1
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.
P
Pilchie 已提交
2 3

using System;
4 5
using System.Collections.Generic;
using System.Collections.Immutable;
6
using System.Diagnostics;
7
using System.Linq;
8
using System.Text;
P
Pilchie 已提交
9 10 11 12 13 14 15 16 17 18 19
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.CSharp
{
    internal partial class CSharpSyntaxTreeFactoryServiceFactory
    {
20
        private partial class CSharpSyntaxTreeFactoryService
P
Pilchie 已提交
21 22 23 24 25 26 27
        {
            /// <summary>
            /// Represents a syntax tree that only has a weak reference to its 
            /// underlying data.  This way it can be passed around without forcing
            /// the underlying full tree to stay alive.  Think of it more as a 
            /// key that can be used to identify a tree rather than the tree itself.
            /// </summary>
28
            internal sealed class RecoverableSyntaxTree : CSharpSyntaxTree, IRecoverableSyntaxTree<CompilationUnitSyntax>, ICachedObjectOwner
P
Pilchie 已提交
29
            {
30 31 32 33
                private readonly RecoverableSyntaxRoot<CompilationUnitSyntax> _recoverableRoot;
                private readonly SyntaxTreeInfo _info;
                private readonly IProjectCacheHostService _projectCacheService;
                private readonly ProjectId _cacheKey;
P
Pilchie 已提交
34

35 36 37
                object ICachedObjectOwner.CachedObject { get; set; }

                private RecoverableSyntaxTree(AbstractSyntaxTreeFactoryService service, ProjectId cacheKey, CompilationUnitSyntax root, SyntaxTreeInfo info)
P
Pilchie 已提交
38
                {
39 40 41 42
                    _recoverableRoot = new RecoverableSyntaxRoot<CompilationUnitSyntax>(service, root, this);
                    _info = info;
                    _projectCacheService = service.LanguageServices.WorkspaceServices.GetService<IProjectCacheHostService>();
                    _cacheKey = cacheKey;
43 44
                }

45
                private RecoverableSyntaxTree(RecoverableSyntaxTree original, SyntaxTreeInfo info)
46
                {
47 48 49 50
                    _recoverableRoot = original._recoverableRoot.WithSyntaxTree(this);
                    _info = info;
                    _projectCacheService = original._projectCacheService;
                    _cacheKey = original._cacheKey;
51 52
                }

53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
                internal static SyntaxTree CreateRecoverableTree(
                    AbstractSyntaxTreeFactoryService service,
                    ProjectId cacheKey,
                    string filePath,
                    ParseOptions options,
                    ValueSource<TextAndVersion> text,
                    Encoding encoding,
                    CompilationUnitSyntax root,
                    ImmutableDictionary<string, ReportDiagnostic> diagnosticOptions)
                {
                    return new RecoverableSyntaxTree(
                        service,
                        cacheKey,
                        root,
                        new SyntaxTreeInfo(
                            filePath,
                            options,
                            text,
                            encoding,
                            root.FullSpan.Length,
                            diagnosticOptions ?? EmptyDiagnosticOptions));
P
Pilchie 已提交
74 75 76 77
                }

                public override string FilePath
                {
78
                    get { return _info.FilePath; }
P
Pilchie 已提交
79 80 81 82
                }

                public override CSharpParseOptions Options
                {
83
                    get { return (CSharpParseOptions)_info.Options; }
P
Pilchie 已提交
84 85
                }

86 87
                public override ImmutableDictionary<string, ReportDiagnostic> DiagnosticOptions => _info.DiagnosticOptions;

P
Pilchie 已提交
88 89
                public override int Length
                {
90
                    get { return _info.Length; }
P
Pilchie 已提交
91 92 93 94
                }

                public override bool TryGetText(out SourceText text)
                {
95
                    return _info.TryGetText(out text);
P
Pilchie 已提交
96 97 98 99
                }

                public override SourceText GetText(CancellationToken cancellationToken)
                {
100
                    return _info.TextSource.GetValue(cancellationToken).Text;
P
Pilchie 已提交
101 102 103 104
                }

                public override Task<SourceText> GetTextAsync(CancellationToken cancellationToken)
                {
105
                    return _info.GetTextAsync(cancellationToken);
106 107
                }

108 109 110 111 112
                public override Encoding Encoding
                {
                    get { return _info.Encoding; }
                }

113 114
                private CompilationUnitSyntax CacheRootNode(CompilationUnitSyntax node)
                {
115
                    return _projectCacheService.CacheObjectIfCachingEnabledForKey(_cacheKey, this, node);
P
Pilchie 已提交
116 117 118 119
                }

                public override bool TryGetRoot(out CSharpSyntaxNode root)
                {
C
Cyrus Najmabadi 已提交
120
                    var status = _recoverableRoot.TryGetValue(out var node);
P
Pilchie 已提交
121
                    root = node;
122
                    CacheRootNode(node);
P
Pilchie 已提交
123 124 125
                    return status;
                }

C
CyrusNajmabadi 已提交
126
                public override CSharpSyntaxNode GetRoot(CancellationToken cancellationToken = default)
P
Pilchie 已提交
127
                {
128
                    return CacheRootNode(_recoverableRoot.GetValue(cancellationToken));
P
Pilchie 已提交
129 130 131 132
                }

                public override async Task<CSharpSyntaxNode> GetRootAsync(CancellationToken cancellationToken)
                {
133
                    return CacheRootNode(await _recoverableRoot.GetValueAsync(cancellationToken).ConfigureAwait(false));
P
Pilchie 已提交
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
                }

                public override bool HasCompilationUnitRoot
                {
                    get { return true; }
                }

                public override SyntaxReference GetReference(SyntaxNode node)
                {
                    if (node != null)
                    {
                        // many people will take references to nodes in this tree.  
                        // We don't actually want those references to keep the tree alive.
                        if (node.Span.Length == 0)
                        {
                            return new PathSyntaxReference(node);
                        }
                        else
                        {
                            return new PositionalSyntaxReference(node);
                        }
                    }
                    else
                    {
                        return new NullSyntaxReference(this);
                    }
                }

                CompilationUnitSyntax IRecoverableSyntaxTree<CompilationUnitSyntax>.CloneNodeAsRoot(CompilationUnitSyntax root)
                {
                    return CloneNodeAsRoot(root);
                }

167 168
                public override SyntaxTree WithRootAndOptions(SyntaxNode root, ParseOptions options)
                {
C
CyrusNajmabadi 已提交
169
                    if (ReferenceEquals(_info.Options, options) && this.TryGetRoot(out var oldRoot) && ReferenceEquals(root, oldRoot))
170 171 172 173
                    {
                        return this;
                    }

174
                    return Create((CSharpSyntaxNode)root, this.Options, _info.FilePath);
175 176 177
                }

                public override SyntaxTree WithFilePath(string path)
P
Pilchie 已提交
178
                {
179
                    if (path == this.FilePath)
180 181 182 183
                    {
                        return this;
                    }

184
                    return new RecoverableSyntaxTree(this, _info.WithFilePath(path));
P
Pilchie 已提交
185
                }
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200

                public override SyntaxTree WithDiagnosticOptions(ImmutableDictionary<string, ReportDiagnostic> options)
                {
                    if (options == null)
                    {
                        options = EmptyDiagnosticOptions;
                    }

                    if (ReferenceEquals(_info.DiagnosticOptions, options))
                    {
                        return this;
                    }

                    return new RecoverableSyntaxTree(this, _info.WithDiagnosticOptions(options));
                }
P
Pilchie 已提交
201 202 203
            }
        }
    }
204
}