IRemoteFindUsagesService.cs 7.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// 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.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.FindUsages;
using Microsoft.CodeAnalysis.Remote;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.Editor.FindUsages
{
    internal interface IRemoteFindUsagesService
    {
        Task FindReferencesAsync(
            PinnedSolutionInfo solutionInfo,
            SerializableSymbolAndProjectId symbolAndProjectIdArg,
            SerializableFindReferencesSearchOptions options,
            CancellationToken cancellationToken);
25 26 27

        Task FindImplementationsAsync(
            PinnedSolutionInfo solutionInfo,
28
            SerializableSymbolAndProjectId symbolAndProjectIdArg,
29
            CancellationToken cancellationToken);
30 31
    }

32
    internal class FindUsagesServerCallback
33 34 35 36 37
    {
        private readonly Solution _solution;
        private readonly IFindUsagesContext _context;
        private readonly Dictionary<int, DefinitionItem> _idToDefinition = new Dictionary<int, DefinitionItem>();

38
        public FindUsagesServerCallback(Solution solution, IFindUsagesContext context)
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 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
        {
            _solution = solution;
            _context = context;
        }

        public Task AddItemsAsync(int count)
            => _context.ProgressTracker.AddItemsAsync(count);

        public Task ItemCompletedAsync()
            => _context.ProgressTracker.ItemCompletedAsync();

        public Task ReportMessageAsync(string message)
            => _context.ReportMessageAsync(message);

        [Obsolete]
        public Task ReportProgressAsync(int current, int maximum)
            => _context.ReportProgressAsync(current, maximum);

        public Task SetSearchTitleAsync(string title)
            => _context.SetSearchTitleAsync(title);

        public Task OnDefinitionFoundAsync(SerializableDefinitionItem definition)
        {
            var id = definition.Id;
            var rehydrated = definition.Rehydrate(_solution);

            lock (_idToDefinition)
            {
                _idToDefinition.Add(id, rehydrated);
            }

            return _context.OnDefinitionFoundAsync(rehydrated);
        }

        public Task OnReferenceFoundAsync(SerializableSourceReferenceItem reference)
            => _context.OnReferenceFoundAsync(reference.Rehydrate(_solution, GetDefinition(reference.DefinitionId)));

        private DefinitionItem GetDefinition(int definitionId)
        {
            lock (_idToDefinition)
            {
                Contract.ThrowIfFalse(_idToDefinition.ContainsKey(definitionId));
                return _idToDefinition[definitionId];
            }
        }
    }

    internal class SerializableDocumentSpan
    {
        public DocumentId DocumentId;
        public TextSpan SourceSpan;

        public static SerializableDocumentSpan Dehydrate(DocumentSpan documentSpan)
            => new SerializableDocumentSpan
            {
                DocumentId = documentSpan.Document.Id,
                SourceSpan = documentSpan.SourceSpan,
            };

        public DocumentSpan Rehydrate(Solution solution)
            => new DocumentSpan(solution.GetDocument(DocumentId), SourceSpan);
    }

    internal class SerializableTaggedText
    {
        public string Tag;
        public string Text;
        public TaggedTextStyle Style;
        public string NavigationTarget;
        public string NavigationHint;

        public static SerializableTaggedText Dehydrate(TaggedText text)
            => new SerializableTaggedText
            {
                Tag = text.Tag,
                Text = text.Text,
                Style = text.Style,
                NavigationTarget = text.NavigationTarget,
                NavigationHint = text.NavigationHint,
            };

        public TaggedText Rehydrate()
            => new TaggedText(Tag, Text, Style, NavigationTarget, NavigationHint);
    }

    internal class SerializableDefinitionItem
    {
        public int Id;
        public string[] Tags;
        public SerializableTaggedText[] DisplayParts;
        public SerializableTaggedText[] NameDisplayParts;
        public SerializableTaggedText[] OriginationParts;
        public SerializableDocumentSpan[] SourceSpans;
        public (string key, string value)[] Properties;
        public (string key, string value)[] DisplayableProperties;
        public bool DisplayIfNoReferences;

        public static SerializableDefinitionItem Dehydrate(int id, DefinitionItem item)
            => new SerializableDefinitionItem
            {
                Id = id,
                Tags = item.Tags.ToArray(),
                DisplayParts = item.DisplayParts.Select(p => SerializableTaggedText.Dehydrate(p)).ToArray(),
                NameDisplayParts = item.NameDisplayParts.Select(p => SerializableTaggedText.Dehydrate(p)).ToArray(),
                OriginationParts = item.OriginationParts.Select(p => SerializableTaggedText.Dehydrate(p)).ToArray(),
                SourceSpans = item.SourceSpans.Select(ss => SerializableDocumentSpan.Dehydrate(ss)).ToArray(),
                Properties = item.Properties.Select(kvp => (kvp.Key, kvp.Value)).ToArray(),
                DisplayableProperties = item.DisplayableProperties.Select(kvp => (kvp.Key, kvp.Value)).ToArray(),
                DisplayIfNoReferences = item.DisplayIfNoReferences,
            };

        public DefinitionItem Rehydrate(Solution solution)
            => new DefinitionItem.DefaultDefinitionItem(
                Tags.ToImmutableArray(),
                DisplayParts.SelectAsArray(dp => dp.Rehydrate()),
                NameDisplayParts.SelectAsArray(dp => dp.Rehydrate()),
                OriginationParts.SelectAsArray(dp => dp.Rehydrate()),
                SourceSpans.SelectAsArray(ss => ss.Rehydrate(solution)),
                Properties.ToImmutableDictionary(t => t.key, t => t.value),
                DisplayableProperties.ToImmutableDictionary(t => t.key, t => t.value),
                DisplayIfNoReferences);
    }

    internal class SerializableSourceReferenceItem
    {
        public int DefinitionId;
        public SerializableDocumentSpan SourceSpan;
166
        public SerializableSymbolUsageInfo SymbolUsageInfo;
167 168 169 170 171 172 173 174 175
        public (string Key, string Value)[] AdditionalProperties;

        public static SerializableSourceReferenceItem Dehydrate(
            int definitionId, SourceReferenceItem item)
        {
            return new SerializableSourceReferenceItem
            {
                DefinitionId = definitionId,
                SourceSpan = SerializableDocumentSpan.Dehydrate(item.SourceSpan),
176
                SymbolUsageInfo = SerializableSymbolUsageInfo.Dehydrate(item.SymbolUsageInfo),
177 178 179 180 181 182 183 184 185
                AdditionalProperties = item.AdditionalProperties.Select(kvp => (kvp.Key, kvp.Value)).ToArray(),
            };
        }

        public SourceReferenceItem Rehydrate(Solution solution, DefinitionItem definition)
        {
            return new SourceReferenceItem(
                definition,
                SourceSpan.Rehydrate(solution),
186
                SymbolUsageInfo.Rehydrate(),
187 188 189 190
                AdditionalProperties.ToImmutableDictionary(t => t.Key, t => t.Value));
        }
    }
}