protected override void Initialize() { using (UnconfiguredProjectAsynchronousTasksService.LoadedProject()) { // this.IsApplicable may take a project lock, so we can't do it inline with this method // which is holding a private lock. It turns out that doing it asynchronously isn't a problem anyway, // so long as we guard against races with the Dispose method. UnconfiguredProjectAsynchronousTasksService.LoadedProjectAsync( async delegate { await TaskScheduler.Default.SwitchTo(alwaysYield: true); UnconfiguredProjectAsynchronousTasksService. UnloadCancellationToken.ThrowIfCancellationRequested(); lock (SyncObject) { Verify.NotDisposed(this); var intermediateBlock = new BufferBlock < IProjectVersionedValue < IProjectSubscriptionUpdate> >(); _projectSubscriptionLink = ProjectSubscriptionService.JointRuleSource.SourceBlock.LinkTo( intermediateBlock, ruleNames: UnresolvedReferenceRuleNames.Union(ResolvedReferenceRuleNames), suppressVersionOnlyUpdates: false); var actionBlock = new ActionBlock < IProjectVersionedValue < Tuple <IProjectSubscriptionUpdate, IProjectCatalogSnapshot, IProjectSharedFoldersSnapshot> > > (new Action < IProjectVersionedValue < Tuple <IProjectSubscriptionUpdate, IProjectCatalogSnapshot, IProjectSharedFoldersSnapshot> > >( ProjectSubscriptionService_Changed), new ExecutionDataflowBlockOptions() { NameFormat = "ReferencesSubtree Input: {1}" }); _projectSyncLink = ProjectDataSources.SyncLinkTo( intermediateBlock.SyncLinkOptions(), ProjectSubscriptionService.ProjectCatalogSource.SourceBlock.SyncLinkOptions(), ProjectSubscriptionService.SharedFoldersSource.SourceBlock.SyncLinkOptions(), actionBlock); } }, registerFaultHandler: true); } }
/// <summary> /// Generates the original references directory tree. /// </summary> protected override void Initialize() { using (UnconfiguredProjectAsynchronousTasksService.LoadedProject()) { base.Initialize(); // this.IsApplicable may take a project lock, so we can't do it inline with this method // which is holding a private lock. It turns out that doing it asynchronously isn't a problem anyway, // so long as we guard against races with the Dispose method. UnconfiguredProjectAsynchronousTasksService.LoadedProjectAsync( async delegate { await TaskScheduler.Default.SwitchTo(alwaysYield: true); UnconfiguredProjectAsynchronousTasksService .UnloadCancellationToken.ThrowIfCancellationRequested(); lock (SyncObject) { foreach (var provider in SubTreeProviders) { provider.Value.DependenciesChanged += OnDependenciesChanged; } Verify.NotDisposed(this); var nowait = SubmitTreeUpdateAsync( (treeSnapshot, configuredProjectExports, cancellationToken) => { var dependenciesNode = CreateDependenciesFolder(null); dependenciesNode = CreateOrUpdateSubTreeProviderNodes(dependenciesNode, cancellationToken); return(Task.FromResult(new TreeUpdateResult(dependenciesNode, true))); }); } }, registerFaultHandler: true); } }
protected override void Initialize() { #pragma warning disable RS0030 // symbol LoadedProject is banned using (UnconfiguredProjectAsynchronousTasksService.LoadedProject()) { base.Initialize(); // this.IsApplicable may take a project lock, so we can't do it inline with this method // which is holding a private lock. It turns out that doing it asynchronously isn't a problem anyway, // so long as we guard against races with the Dispose method. UnconfiguredProjectAsynchronousTasksService.LoadedProjectAsync( async delegate { await TaskScheduler.Default.SwitchTo(alwaysYield: true); UnconfiguredProjectAsynchronousTasksService .UnloadCancellationToken.ThrowIfCancellationRequested(); lock (SyncObject) { Verify.NotDisposed(this); // Issue this token before hooking the SnapshotChanged event to prevent a race // where a snapshot tree is replaced by the initial, empty tree created below. // The handler will cancel this token before submitting its update. CancellationToken initialTreeCancellationToken = _treeUpdateCancellationSeries.CreateNext(); _ = SubmitTreeUpdateAsync( delegate { IProjectTree dependenciesNode = CreateDependenciesFolder(); return(Task.FromResult(new TreeUpdateResult(dependenciesNode))); }, initialTreeCancellationToken); ITargetBlock <SnapshotChangedEventArgs> actionBlock = DataflowBlockSlim.CreateActionBlock <SnapshotChangedEventArgs>( e => OnDependenciesSnapshotChanged(_dependenciesSnapshotProvider, e), "DependenciesProjectTreeProviderSource {1}", skipIntermediateInputData: true); _snapshotEventListener = _dependenciesSnapshotProvider.SnapshotChangedSource.LinkTo(actionBlock, new DataflowLinkOptions() { PropagateCompletion = true }); } }, registerFaultHandler: true); } #pragma warning restore RS0030 // symbol LoadedProject is banned IProjectTree CreateDependenciesFolder() { var values = new ReferencesProjectTreeCustomizablePropertyValues { Caption = Resources.DependenciesNodeName, Icon = ManagedImageMonikers.ReferenceGroup.ToProjectSystemType(), ExpandedIcon = ManagedImageMonikers.ReferenceGroup.ToProjectSystemType(), Flags = DependencyTreeFlags.DependenciesRootNodeFlags }; // Allow property providers to perform customization. // These are ordered from lowest priority to highest, allowing higher priority // providers to override lower priority providers. foreach (IProjectTreePropertiesProvider provider in _projectTreePropertiesProviders.ExtensionValues()) { provider.CalculatePropertyValues(null, values); } // Note that all the parameters are specified so we can force this call to an // overload of NewTree available prior to 15.5 versions of CPS. Once a 15.5 build // is publicly available we can move this to an overload with default values for // most of the parameters, and we'll only need to pass the interesting ones. return(NewTree( caption: values.Caption, filePath: null, browseObjectProperties: null, icon: values.Icon, expandedIcon: values.ExpandedIcon, visible: true, flags: values.Flags)); } }
/// <summary> /// Generates the original references directory tree. /// </summary> protected override void Initialize() { #pragma warning disable RS0030 // symbol LoadedProject is banned using (UnconfiguredProjectAsynchronousTasksService.LoadedProject()) #pragma warning restore RS0030 { #pragma warning disable RS0030 // https://github.com/dotnet/roslyn-analyzers/issues/3295 base.Initialize(); #pragma warning restore RS0030 // this.IsApplicable may take a project lock, so we can't do it inline with this method // which is holding a private lock. It turns out that doing it asynchronously isn't a problem anyway, // so long as we guard against races with the Dispose method. #pragma warning disable RS0030 // symbol LoadedProjectAsync is banned UnconfiguredProjectAsynchronousTasksService.LoadedProjectAsync( #pragma warning restore RS0030 async delegate { await TaskScheduler.Default.SwitchTo(alwaysYield: true); UnconfiguredProjectAsynchronousTasksService .UnloadCancellationToken.ThrowIfCancellationRequested(); lock (SyncObject) { Verify.NotDisposed(this); // Issue this token before hooking the SnapshotChanged event to prevent a race // where a snapshot tree is replaced by the initial, empty tree created below. // The handler will cancel this token before submitting its update. CancellationToken initialTreeCancellationToken = _treeUpdateCancellationSeries.CreateNext(); _ = SubmitTreeUpdateAsync( delegate { IProjectTree dependenciesNode = CreateDependenciesNode(); return(Task.FromResult(new TreeUpdateResult(dependenciesNode))); }, initialTreeCancellationToken); ITargetBlock <SnapshotChangedEventArgs> actionBlock = DataflowBlockFactory.CreateActionBlock <SnapshotChangedEventArgs>( OnDependenciesSnapshotChangedAsync, _project, nameFormat: "DependenciesProjectTreeProviderSource {1}", skipIntermediateInputData: true); _snapshotEventListener = _dependenciesSnapshotProvider.SnapshotChangedSource.LinkTo(actionBlock, DataflowOption.PropagateCompletion); } }, registerFaultHandler: true); } IProjectTree CreateDependenciesNode() { var values = new ReferencesProjectTreeCustomizablePropertyValues { Caption = Resources.DependenciesNodeName, Icon = KnownMonikers.ReferenceGroup.ToProjectSystemType(), ExpandedIcon = KnownMonikers.ReferenceGroup.ToProjectSystemType(), Flags = ProjectTreeFlags.Create(ProjectTreeFlags.Common.BubbleUp) + ProjectTreeFlags.Create(ProjectTreeFlags.Common.ReferencesFolder) + ProjectTreeFlags.Create(ProjectTreeFlags.Common.VirtualFolder) + DependencyTreeFlags.DependenciesRootNode }; // Allow property providers to perform customization. // These are ordered from lowest priority to highest, allowing higher priority // providers to override lower priority providers. foreach (IProjectTreePropertiesProvider provider in _projectTreePropertiesProviders.ExtensionValues()) { provider.CalculatePropertyValues(ProjectTreeCustomizablePropertyContext.Instance, values); } return(NewTree( caption: values.Caption, icon: values.Icon, expandedIcon: values.ExpandedIcon, flags: values.Flags)); } }