/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/VisualStudio/Core/Def/ValueTracking/ValueTrackedTreeItemViewModel.cs
202 строки
7 KB
Tomáš Matoušek
More improvements to source packages (#78587)
16 май 2025, 01:46
Не верифицирован
16 май 2025, 01:46
015a854
Код
Авторство
О чём код?
// 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.Collections.Immutable; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Navigation; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.ValueTracking; using Microsoft.VisualStudio.Language.Intellisense; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Utilities; using Roslyn.Utilities; namespace Microsoft.VisualStudio.LanguageServices.ValueTracking; internal sealed class ValueTrackedTreeItemViewModel : TreeItemViewModel { private bool _childrenCalculated; private readonly Solution _solution; private readonly IGlyphService _glyphService; private readonly IValueTrackingService _valueTrackingService; private readonly ValueTrackedItem _trackedItem; private readonly IGlobalOptionService _globalOptions; private readonly IAsynchronousOperationListener _listener; private readonly IUIThreadOperationExecutor _threadOperationExecutor; public override bool IsNodeExpanded { get => base.IsNodeExpanded; set { base.IsNodeExpanded = value; CalculateChildren(); } } private ValueTrackedTreeItemViewModel( ValueTrackedItem trackedItem, ImmutableArray<ClassifiedSpan> classifiedSpans, Solution solution, ValueTrackingTreeViewModel treeViewModel, IGlyphService glyphService, IValueTrackingService valueTrackingService, IGlobalOptionService globalOptions, IThreadingContext threadingContext, string fileName, ImmutableArray<TreeItemViewModel> children, IAsynchronousOperationListener listener, IUIThreadOperationExecutor threadOperationExecutor) : base( trackedItem.Span, trackedItem.SourceText, trackedItem.DocumentId, fileName, trackedItem.Glyph, classifiedSpans, treeViewModel, glyphService, threadingContext, solution.Workspace, children) { _trackedItem = trackedItem; _solution = solution; _glyphService = glyphService; _valueTrackingService = valueTrackingService; _globalOptions = globalOptions; _listener = listener; _threadOperationExecutor = threadOperationExecutor; if (children.IsEmpty) { // Add an empty item so the treeview has an expansion showing to calculate // the actual children of the node ChildItems.Add(EmptyTreeViewItem.Instance); ChildItems.CollectionChanged += (s, a) => { NotifyPropertyChanged(nameof(ChildItems)); }; } } internal static async ValueTask<TreeItemViewModel> CreateAsync( Solution solution, ValueTrackedItem item, ImmutableArray<TreeItemViewModel> children, ValueTrackingTreeViewModel treeViewModel, IGlyphService glyphService, IValueTrackingService valueTrackingService, IGlobalOptionService globalOptions, IThreadingContext threadingContext, IAsynchronousOperationListener listener, IUIThreadOperationExecutor threadOperationExecutor, CancellationToken cancellationToken) { var document = solution.GetRequiredDocument(item.DocumentId); var fileName = document.FilePath ?? document.Name; var options = globalOptions.GetClassificationOptions(document.Project.Language); var documentSpan = new DocumentSpan(document, item.Span); var classificationResult = await ClassifiedSpansAndHighlightSpanFactory.ClassifyAsync( documentSpan, classifiedSpans: null, options, cancellationToken).ConfigureAwait(false); var classifiedSpans = classificationResult.ClassifiedSpans; return new ValueTrackedTreeItemViewModel( item, classifiedSpans, solution, treeViewModel, glyphService, valueTrackingService, globalOptions, threadingContext, fileName, children, listener, threadOperationExecutor); } private void CalculateChildren() { ThreadHelper.ThrowIfNotOnUIThread(); if (_childrenCalculated || IsLoading) { return; } TreeViewModel.LoadingCount++; IsLoading = true; ChildItems.Clear(); var computingItem = new ComputingTreeViewItem(); ChildItems.Add(computingItem); Task.Run(async () => { try { var children = await CalculateChildrenAsync(ThreadingContext.DisposalToken).ConfigureAwait(false); await ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(); ChildItems.Clear(); foreach (var child in children) { ChildItems.Add(child); } } finally { await ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(); TreeViewModel.LoadingCount--; _childrenCalculated = true; IsLoading = false; } }, ThreadingContext.DisposalToken); } public override void NavigateTo() { var token = _listener.BeginAsyncOperation(nameof(NavigateTo)); NavigateToAsync().ReportNonFatalErrorAsync().CompletesAsyncOperation(token); } private async Task NavigateToAsync() { using var context = _threadOperationExecutor.BeginExecute( ServicesVSResources.Value_Tracking, ServicesVSResources.Navigating, allowCancellation: true, showProgress: false); var navigationService = Workspace.Services.GetService<IDocumentNavigationService>(); if (navigationService is null) return; // While navigating do not activate the tab, which will change focus from the tool window var options = new NavigationOptions(PreferProvisionalTab: true, ActivateTab: false); await navigationService.TryNavigateToSpanAsync( this.ThreadingContext, Workspace, DocumentId, _trackedItem.Span, options, context.UserCancellationToken).ConfigureAwait(false); } private async Task<ImmutableArray<TreeItemViewModel>> CalculateChildrenAsync(CancellationToken cancellationToken) { var valueTrackedItems = await _valueTrackingService.TrackValueSourceAsync( _solution, _trackedItem, cancellationToken).ConfigureAwait(false); return await valueTrackedItems.SelectAsArrayAsync(static (item, self, cancellationToken) => CreateAsync( self._solution, item, children: [], self.TreeViewModel, self._glyphService, self._valueTrackingService, self._globalOptions, self.ThreadingContext, self._listener, self._threadOperationExecutor, cancellationToken), this, cancellationToken).ConfigureAwait(false); } }