예제 #1
0
        public DefinitionTreeItem(
            DefinitionItem definitionItem,
            ImmutableArray<SourceReferenceTreeItem> referenceItems)
            : base(definitionItem.Tags.GetGlyph().GetGlyphIndex())
        {
            _definitionItem = definitionItem;

            this.Children.AddRange(referenceItems);
            this.DisplayText = CreateDisplayText();
        }
 public RoslynDefinitionBucket(
     StreamingFindReferencesPresenter presenter,
     TableDataSourceFindReferencesContext context,
     DefinitionItem definitionItem)
     : base(name: definitionItem.DisplayParts.JoinText() + " " + definitionItem.GetHashCode(),
            sourceTypeIdentifier: context.SourceTypeIdentifier,
            identifier: context.Identifier)
 {
     _presenter = presenter;
     _context = context;
     DefinitionItem = definitionItem;
 }
        private ImmutableArray<SourceReferenceTreeItem> CreateReferenceItems(
            DefinitionItem definitionItem,
            DefinitionsAndReferences definitionsAndReferences,
            int commonPathElements)
        {
            var result = ImmutableArray.CreateBuilder<SourceReferenceTreeItem>();

            var definitionGlyph = definitionItem.Tags.GetGlyph();

            // Skip the first definition.  We'll present it in the definition item.
            var definitionLocationsAndGlyphs =
                from loc in definitionItem.SourceSpans.Skip(1)
                select ValueTuple.Create(loc, definitionGlyph);

            var referenceLocationsAndGlyphs =
                from r in definitionsAndReferences.References
                where r.Definition == definitionItem
                select ValueTuple.Create(r.SourceSpan, Glyph.Reference);

            var allLocationsAndGlyphs = definitionLocationsAndGlyphs.Concat(referenceLocationsAndGlyphs);

            foreach (var locationAndGlyph in allLocationsAndGlyphs)
            {
                var documentLocation = locationAndGlyph.Item1;
                var glyph = locationAndGlyph.Item2;
                result.Add(new SourceReferenceTreeItem(
                    documentLocation.Document,
                    documentLocation.SourceSpan,
                    glyph.GetGlyphIndex(),
                    commonPathElements));
            }

            var linkedReferences = result.GroupBy(r => r.DisplayText.ToLowerInvariant()).Where(g => g.Count() > 1).SelectMany(g => g);
            foreach (var linkedReference in linkedReferences)
            {
                linkedReference.AddProjectNameDisambiguator();
            }

            result.Sort();
            return result.ToImmutable();
        }
            private static string GetMessage(DefinitionItem definition)
            {
                if (definition.IsExternal)
                {
                    return ServicesVisualStudioNextResources.External_reference_found;
                }

                return string.Format(
                    ServicesVisualStudioNextResources.No_references_found_to_0,
                    definition.DisplayParts.JoinText());
            }
        public static SourceReferenceItem TryCreateSourceReferenceItem(
            this ReferenceLocation referenceLocation,
            DefinitionItem definitionItem)
        {
            var location = referenceLocation.Location;

            Debug.Assert(location.IsInSource);
            if (!location.IsVisibleSourceLocation())
            {
                return null;
            }

            return new SourceReferenceItem(definitionItem, 
                new DocumentSpan(referenceLocation.Document, location.SourceSpan));
        }
        private static void CreateReferences(
            ReferencedSymbol referencedSymbol,
            ImmutableArray<SourceReferenceItem>.Builder references,
            DefinitionItem definitionItem,
            HashSet<DocumentSpan> uniqueSpans)
        {
            foreach (var referenceLocation in referencedSymbol.Locations)
            {
                var sourceReferenceItem = referenceLocation.TryCreateSourceReferenceItem(definitionItem);
                if (sourceReferenceItem == null)
                {
                    continue;
                }

                if (uniqueSpans.Add(sourceReferenceItem.SourceSpan))
                {
                    references.Add(sourceReferenceItem);
                }
            }
        }
 private bool HasEntriesForDefinition(DefinitionItem definition)
 {
     lock (_gate)
     {
         return _entries.Any(e => e.DefinitionBucket.DefinitionItem == definition);
     }
 }
            private async Task OnEntryFoundAsync(
                DefinitionItem definition,
                Func<RoslynDefinitionBucket, Task<Entry>> createEntryAsync)
            {
                CancellationToken.ThrowIfCancellationRequested();

                // First find the bucket corresponding to our definition. If we can't find/create 
                // one, then don't do anything for this reference.
                var definitionBucket = GetOrCreateDefinitionBucket(definition);
                if (definitionBucket == null)
                {
                    return;
                }

                var entry = await createEntryAsync(definitionBucket).ConfigureAwait(false);
                if (entry == null)
                {
                    return;
                }

                // Ok, we got a *reference* to some definition item.  This may have been
                // a reference for some definition that we haven't created any definition
                // entries for (i.e. becuase it had DisplayIfNoReferences = false).  Because
                // we've now found a reference, we want to make sure all tis definition
                // entries are added.
                await AddDefinitionEntriesAsync(definition).ConfigureAwait(false);

                lock (_gate)
                {
                    // Once we can make the new entry, add it to our list.
                    _entries = _entries.Add(entry);
                    CurrentVersionNumber++;
                }

                // Let all our subscriptions know that we've updated.
                _tableDataSink.FactorySnapshotChanged(this);
            }
            private async Task OnEntryFoundAsync(
                DefinitionItem definition, 
                Func<RoslynDefinitionBucket, CancellationToken, Task<Entry>> createEntryAsync)
            {
                var cancellationToken = _cancellationTokenSource.Token;
                cancellationToken.ThrowIfCancellationRequested();

                // First find the bucket corresponding to our definition. If we can't find/create 
                // one, then don't do anything for this reference.
                var definitionBucket = GetOrCreateDefinitionBucket(definition);
                if (definitionBucket == null)
                {
                    return;
                }

                var entry = await createEntryAsync(
                    definitionBucket, cancellationToken).ConfigureAwait(false);
                if (entry == null)
                {
                    return;
                }

                lock (_gate)
                {
                    // Once we can make the new entry, add it to our list.
                    _entries = _entries.Add(entry);
                    CurrentVersionNumber++;
                }

                // Let all our subscriptions know that we've updated.
                _tableDataSink.FactorySnapshotChanged(this);
            }
        private static void CreateReferences(
            ReferencedSymbol referencedSymbol,
            ImmutableArray<SourceReferenceItem>.Builder references,
            DefinitionItem definitionItem,
            HashSet<DocumentLocation> uniqueLocations)
        {
            foreach (var referenceLocation in referencedSymbol.Locations)
            {
                var location = referenceLocation.Location;
                Debug.Assert(location.IsInSource);

                var document = referenceLocation.Document;
                var sourceSpan = location.SourceSpan;

                var documentLocation = new DocumentLocation(document, sourceSpan);
                if (!documentLocation.CanNavigateTo())
                {
                    continue;
                }

                if (uniqueLocations.Add(documentLocation))
                {
                    references.Add(new SourceReferenceItem(definitionItem, documentLocation));
                }
            }
        }
예제 #11
0
 public virtual Task OnDefinitionFoundAsync(DefinitionItem definition) => SpecializedTasks.EmptyTask;
예제 #12
0
 public SourceReferenceItem(DefinitionItem definition, DocumentSpan sourceSpan)
 {
     Definition = definition;
     SourceSpan = sourceSpan;
 }
예제 #13
0
 public virtual void OnDefinitionFound(DefinitionItem definition)
 {
 }
            public override void OnDefinitionFound(DefinitionItem definition)
            {
                lock (_gate)
                {
                    _definitions.Add(definition);
                }

                foreach (var location in definition.SourceSpans)
                {
                    OnEntryFound(definition,
                        (db, c) => CreateDocumentLocationEntryAsync(
                            db, location, isDefinitionLocation: true, cancellationToken: c));
                }
            }
            public override async Task OnDefinitionFoundAsync(DefinitionItem definition)
            {
                lock (_gate)
                {
                    _definitions.Add(definition);
                }

                // If this is a definition we always want to show, then create entries
                // for all the definition locations immediately.
                if (definition.DisplayIfNoReferences)
                {
                    await AddDefinitionEntriesAsync(definition).ConfigureAwait(false);
                }
            }
 private async void OnEntryFound(
     DefinitionItem definition,
     Func<RoslynDefinitionBucket, CancellationToken, Task<Entry>> createEntryAsync)
 {
     try
     {
         // We're told about this reference synchronously, but we need to get the 
         // SourceText for the definition/reference's Document so that we can determine 
         // things like it's line/column/text.  We don't want to block this method getting
         // that data, so instead we just fire off the async work to get the text
         // and use it.  Because we're starting some async work, let the test harness
         // know so that it doesn't verify results until this completes.
         using (var token = Presenter._asyncListener.BeginAsyncOperation(nameof(OnReferenceFound)))
         {
             await OnEntryFoundAsync(definition, createEntryAsync).ConfigureAwait(false);
         }
     }
     catch (Exception e) when (FatalError.ReportWithoutCrashUnlessCanceled(e))
     {
     }
 }
            private async Task AddDefinitionEntriesAsync(DefinitionItem definition)
            {
                CancellationToken.ThrowIfCancellationRequested();

                // Don't do anything if we already have entries for this definition 
                // (i.e. another thread beat us to this).
                if (HasEntriesForDefinition(definition))
                {
                    return;
                }

                // First find the bucket corresponding to our definition. If we can't find/create 
                // one, then don't do anything for this reference.
                var definitionBucket = GetOrCreateDefinitionBucket(definition);
                if (definitionBucket == null)
                {
                    return;
                }

                // We could do this inside the lock.  but that would mean async activity in a 
                // lock, and i'd like to avoid that.  That does mean that we might do extra
                // work if multiple threads end up down htis path.  But only one of them will
                // win when we access the lock below.
                var builder = ImmutableArray.CreateBuilder<Entry>();
                foreach (var definitionLocation in definition.SourceSpans)
                {
                    var definitionEntry = await CreateDocumentLocationEntryAsync(
                        definitionBucket, definitionLocation, isDefinitionLocation: true).ConfigureAwait(false);
                    if (definitionEntry != null)
                    {
                        builder.Add(definitionEntry);
                    }
                }

                lock (_gate)
                {
                    // Do one final check to ensure that no other thread beat us here.
                    if (!HasEntriesForDefinition(definition))
                    {
                        _entries = _entries.AddRange(builder);
                        CurrentVersionNumber++;
                    }
                }

                // Let all our subscriptions know that we've updated.
                _tableDataSink.FactorySnapshotChanged(this);
            }
            private RoslynDefinitionBucket GetOrCreateDefinitionBucket(DefinitionItem definition)
            {
                lock (_gate)
                {
                    RoslynDefinitionBucket bucket;
                    if (!_definitionToBucket.TryGetValue(definition, out bucket))
                    {
                        bucket = new RoslynDefinitionBucket(Presenter, this, definition);
                        _definitionToBucket.Add(definition, bucket);
                    }

                    return bucket;
                }
            }
예제 #19
0
 public SourceReferenceItem(DefinitionItem definition, DocumentLocation location)
 {
     Definition = definition;
     Location = location;
 }