WithoutReferencesFindUsagesContext.cs 4.1 KB
Newer Older
1 2 3 4 5
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

using System;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
6
using Microsoft.CodeAnalysis.DocumentHighlighting;
7
using Microsoft.CodeAnalysis.FindUsages;
T
Tomas Matousek 已提交
8
using Microsoft.CodeAnalysis.PooledObjects;
9 10 11 12 13
using Microsoft.VisualStudio.Shell.FindAllReferences;
using Roslyn.Utilities;

namespace Microsoft.VisualStudio.LanguageServices.FindUsages
{
C
CyrusNajmabadi 已提交
14
    internal partial class StreamingFindUsagesPresenter
C
CyrusNajmabadi 已提交
15
    {
C
CyrusNajmabadi 已提交
16 17 18 19 20 21
        /// <summary>
        /// Context to be used for FindImplementations/GoToDef (as opposed to FindReferences).
        /// This context will not group entries by definition, and will instead just create
        /// entries for the definitions themselves.
        /// </summary>
        private class WithoutReferencesFindUsagesContext : AbstractTableDataSourceFindUsagesContext
22
        {
C
CyrusNajmabadi 已提交
23 24 25 26 27 28
            public WithoutReferencesFindUsagesContext(
                StreamingFindUsagesPresenter presenter,
                IFindAllReferencesWindow findReferencesWindow)
                : base(presenter, findReferencesWindow)
            {
            }
29

C
CyrusNajmabadi 已提交
30 31 32
            // We should never be called in a context where we get references.
            protected override Task OnReferenceFoundWorkerAsync(SourceReferenceItem reference)
                => throw new InvalidOperationException();
33

C
CyrusNajmabadi 已提交
34 35
            // Nothing to do on completion.
            protected override Task OnCompletedAsyncWorkerAsync()
36
                => Task.CompletedTask;
37

C
CyrusNajmabadi 已提交
38
            protected override async Task OnDefinitionFoundWorkerAsync(DefinitionItem definition)
C
CyrusNajmabadi 已提交
39
            {
C
CyrusNajmabadi 已提交
40 41 42
                var definitionBucket = GetOrCreateDefinitionBucket(definition);

                var entries = ArrayBuilder<Entry>.GetInstance();
C
CyrusNajmabadi 已提交
43 44 45 46 47 48 49 50 51 52 53

                if (definition.SourceSpans.Length == 1)
                {
                    // If we only have a single location, then use the DisplayParts of the
                    // definition as what to show.  That way we show enough information for things
                    // methods.  i.e. we'll show "void TypeName.MethodName(args...)" allowing
                    // the user to see the type the method was created in.
                    var entry = await CreateEntryAsync(definitionBucket, definition).ConfigureAwait(false);
                    entries.Add(entry);
                }
                else
C
CyrusNajmabadi 已提交
54
                {
C
CyrusNajmabadi 已提交
55 56 57 58 59
                    // If we have multiple spans (i.e. for partial types), then create a 
                    // DocumentSpanEntry for each.  That way we can easily see the source
                    // code where each location is to help the user decide which they want
                    // to navigate to.
                    foreach (var sourceSpan in definition.SourceSpans)
60
                    {
C
CyrusNajmabadi 已提交
61
                        var entry = await CreateDocumentSpanEntryAsync(
62
                            definitionBucket, sourceSpan, HighlightSpanKind.Definition).ConfigureAwait(false);
63 64
                        entries.Add(entry);
                    }
C
CyrusNajmabadi 已提交
65
                }
C
CyrusNajmabadi 已提交
66

C
CyrusNajmabadi 已提交
67 68 69
                if (entries.Count > 0)
                {
                    lock (Gate)
C
CyrusNajmabadi 已提交
70
                    {
C
CyrusNajmabadi 已提交
71 72
                        EntriesWhenGroupingByDefinition = EntriesWhenGroupingByDefinition.AddRange(entries);
                        EntriesWhenNotGroupingByDefinition = EntriesWhenNotGroupingByDefinition.AddRange(entries);
C
CyrusNajmabadi 已提交
73
                    }
C
CyrusNajmabadi 已提交
74

C
CyrusNajmabadi 已提交
75
                    NotifyChange();
C
CyrusNajmabadi 已提交
76
                }
C
CyrusNajmabadi 已提交
77 78

                entries.Free();
79
            }
C
CyrusNajmabadi 已提交
80

C
CyrusNajmabadi 已提交
81 82 83 84
            private async Task<Entry> CreateEntryAsync(
                RoslynDefinitionBucket definitionBucket, DefinitionItem definition)
            {
                var documentSpan = definition.SourceSpans[0];
85
                var (guid, projectName, sourceText) = await GetGuidAndProjectNameAndSourceTextAsync(documentSpan.Document).ConfigureAwait(false);
C
CyrusNajmabadi 已提交
86

87
                return new DefinitionItemEntry(this, definitionBucket, documentSpan, projectName, guid, sourceText);
C
CyrusNajmabadi 已提交
88
            }
C
CyrusNajmabadi 已提交
89 90
        }
    }
T
Tomas Matousek 已提交
91
}