diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItem/AnalyzerItem.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItem/AnalyzerItem.cs
index f076af2f03f5b..1af836885084e 100644
--- a/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItem/AnalyzerItem.cs
+++ b/src/VisualStudio/Core/Impl/SolutionExplorer/AnalyzerItem/AnalyzerItem.cs
@@ -9,83 +9,42 @@
using Microsoft.VisualStudio.Imaging;
using Microsoft.VisualStudio.Imaging.Interop;
-namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer
+namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer;
+
+internal partial class AnalyzerItem(
+ AnalyzersFolderItem analyzersFolder,
+ AnalyzerReference analyzerReference,
+ IContextMenuController contextMenuController) : BaseItem(GetNameText(analyzerReference))
{
- internal partial class AnalyzerItem : BaseItem
- {
- private readonly AnalyzersFolderItem _analyzersFolder;
- private readonly AnalyzerReference _analyzerReference;
- private readonly IContextMenuController _contextMenuController;
+ public AnalyzersFolderItem AnalyzersFolder { get; } = analyzersFolder;
+ public AnalyzerReference AnalyzerReference { get; } = analyzerReference;
+ public override IContextMenuController ContextMenuController { get; } = contextMenuController;
- public AnalyzerItem(AnalyzersFolderItem analyzersFolder, AnalyzerReference analyzerReference, IContextMenuController contextMenuController)
- : base(GetNameText(analyzerReference))
- {
- _analyzersFolder = analyzersFolder;
- _analyzerReference = analyzerReference;
- _contextMenuController = contextMenuController;
- }
+ public override ImageMoniker IconMoniker => KnownMonikers.CodeInformation;
- public override ImageMoniker IconMoniker
- {
- get
- {
- return KnownMonikers.CodeInformation;
- }
- }
+ public override ImageMoniker OverlayIconMoniker
+ => this.AnalyzerReference is UnresolvedAnalyzerReference
+ ? KnownMonikers.OverlayWarning
+ : default;
- public override ImageMoniker OverlayIconMoniker
- {
- get
- {
- if (_analyzerReference is UnresolvedAnalyzerReference)
- {
- return KnownMonikers.OverlayWarning;
- }
- else
- {
- return default;
- }
- }
- }
+ public override object GetBrowseObject()
+ => new BrowseObject(this);
- public override object GetBrowseObject()
- {
- return new BrowseObject(this);
- }
+ ///
+ /// Remove this AnalyzerItem from it's folder.
+ ///
+ public void Remove()
+ => this.AnalyzersFolder.RemoveAnalyzer(this.AnalyzerReference.FullPath);
- public AnalyzerReference AnalyzerReference
- {
- get { return _analyzerReference; }
- }
-
- public override IContextMenuController ContextMenuController
- {
- get { return _contextMenuController; }
- }
-
- public AnalyzersFolderItem AnalyzersFolder
- {
- get { return _analyzersFolder; }
- }
-
- ///
- /// Remove this AnalyzerItem from it's folder.
- ///
- public void Remove()
+ private static string GetNameText(AnalyzerReference analyzerReference)
+ {
+ if (analyzerReference is UnresolvedAnalyzerReference)
{
- _analyzersFolder.RemoveAnalyzer(_analyzerReference.FullPath);
+ return analyzerReference.FullPath;
}
-
- private static string GetNameText(AnalyzerReference analyzerReference)
+ else
{
- if (analyzerReference is UnresolvedAnalyzerReference)
- {
- return analyzerReference.FullPath;
- }
- else
- {
- return analyzerReference.Display;
- }
+ return analyzerReference.Display;
}
}
}
diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/BaseItem.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/BaseItem.cs
index eb4e8e26026af..1d6e7acd2c146 100644
--- a/src/VisualStudio/Core/Impl/SolutionExplorer/BaseItem.cs
+++ b/src/VisualStudio/Core/Impl/SolutionExplorer/BaseItem.cs
@@ -33,11 +33,11 @@ internal abstract class BaseItem :
{
public virtual event PropertyChangedEventHandler PropertyChanged { add { } remove { } }
- private readonly string _name;
+ protected readonly string Name;
public BaseItem(string name)
{
- _name = name;
+ Name = name;
}
public IEnumerable Children => [];
@@ -61,9 +61,9 @@ public BaseItem(string name)
public virtual ImageMoniker StateIconMoniker => default;
public string? StateToolTipText => null;
public override string ToString() => Text;
- public string Text => _name;
+ public string Text => Name;
public object? ToolTipContent => null;
- public string ToolTipText => _name;
+ public string ToolTipText => Name;
private static readonly HashSet s_supportedPatterns =
[
diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/BaseDiagnosticAndGeneratorItemSource.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/BaseDiagnosticAndGeneratorItemSource.cs
index ef558ad59cd77..480ad20740cd3 100644
--- a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/BaseDiagnosticAndGeneratorItemSource.cs
+++ b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/BaseDiagnosticAndGeneratorItemSource.cs
@@ -123,7 +123,7 @@ private BulkObservableCollection CreateDiagnosticAndGeneratorItems(Pro
collection.AddRange(
AnalyzerReference.GetGenerators(language)
- .Select(g => new SourceGeneratorItem(projectId, g, AnalyzerReference)));
+ .Select(g => new SourceGeneratorItem(projectId, SourceGeneratorIdentity.Create(g, AnalyzerReference), AnalyzerReference.FullPath)));
return collection;
}
diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/CpsDiagnosticItemSource.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/CpsDiagnosticItemSource.cs
index 41eb9357fd5c9..8c5a577299f15 100644
--- a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/CpsDiagnosticItemSource.cs
+++ b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/CpsDiagnosticItemSource.cs
@@ -11,112 +11,119 @@
using Microsoft.Internal.VisualStudio.PlatformUI;
using Microsoft.VisualStudio.Shell;
-namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer
+namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer;
+
+internal sealed partial class CpsDiagnosticItemSource : BaseDiagnosticAndGeneratorItemSource, INotifyPropertyChanged
{
- internal partial class CpsDiagnosticItemSource : BaseDiagnosticAndGeneratorItemSource, INotifyPropertyChanged
+ private readonly IVsHierarchyItem _item;
+ private readonly string _projectDirectoryPath;
+
+ ///
+ /// The analyzer reference that has been found. Once it's been assigned a non-null value, it'll never be assigned null again.
+ ///
+ private AnalyzerReference? _analyzerReference;
+
+ public event PropertyChangedEventHandler? PropertyChanged;
+
+ public CpsDiagnosticItemSource(
+ Workspace workspace,
+ string projectPath,
+ ProjectId projectId,
+ IVsHierarchyItem item,
+ IAnalyzersCommandHandler commandHandler,
+ IDiagnosticAnalyzerService analyzerService)
+ : base(workspace, projectId, commandHandler, analyzerService)
{
- private readonly IVsHierarchyItem _item;
- private readonly string _projectDirectoryPath;
-
- ///
- /// The analyzer reference that has been found. Once it's been assigned a non-null value, it'll never be assigned null again.
- ///
- private AnalyzerReference? _analyzerReference;
-
- public event PropertyChangedEventHandler? PropertyChanged;
+ _item = item;
+ _projectDirectoryPath = Path.GetDirectoryName(projectPath);
- public CpsDiagnosticItemSource(Workspace workspace, string projectPath, ProjectId projectId, IVsHierarchyItem item, IAnalyzersCommandHandler commandHandler, IDiagnosticAnalyzerService analyzerService)
- : base(workspace, projectId, commandHandler, analyzerService)
+ _analyzerReference = TryGetAnalyzerReference(Workspace.CurrentSolution);
+ if (_analyzerReference == null)
{
- _item = item;
- _projectDirectoryPath = Path.GetDirectoryName(projectPath);
-
- _analyzerReference = TryGetAnalyzerReference(Workspace.CurrentSolution);
- if (_analyzerReference == null)
+ // The ProjectId that was given to us was found by enumerating the list of projects in the solution,
+ // thus the project must have already been added to the workspace at some point. As long as the project
+ // is still there, we're going to assume the reason we don't have the reference yet is because while we
+ // have a project, we don't have all the references added yet. We'll wait until we see the reference and
+ // then connect to it.
+ if (workspace.CurrentSolution.ContainsProject(projectId))
{
- // The ProjectId that was given to us was found by enumerating the list of projects in the solution, thus the project must have already
- // been added to the workspace at some point. As long as the project is still there, we're going to assume the reason we don't have the reference
- // yet is because while we have a project, we don't have all the references added yet. We'll wait until we see the reference and then connect to it.
- if (workspace.CurrentSolution.ContainsProject(projectId))
- {
- Workspace.WorkspaceChanged += OnWorkspaceChangedLookForAnalyzer;
- item.PropertyChanged += IVsHierarchyItem_PropertyChanged;
+ Workspace.WorkspaceChanged += OnWorkspaceChangedLookForAnalyzer;
+ item.PropertyChanged += IVsHierarchyItem_PropertyChanged;
- // Now that we've subscribed, check once more in case we missed the event
- var analyzerReference = TryGetAnalyzerReference(Workspace.CurrentSolution);
+ // Now that we've subscribed, check once more in case we missed the event
+ var analyzerReference = TryGetAnalyzerReference(Workspace.CurrentSolution);
- if (analyzerReference != null)
- {
- _analyzerReference = analyzerReference;
- UnsubscribeFromEvents();
- }
+ if (analyzerReference != null)
+ {
+ _analyzerReference = analyzerReference;
+ UnsubscribeFromEvents();
}
}
}
+ }
- private void UnsubscribeFromEvents()
- {
- Workspace.WorkspaceChanged -= OnWorkspaceChangedLookForAnalyzer;
- _item.PropertyChanged -= IVsHierarchyItem_PropertyChanged;
- }
+ private void UnsubscribeFromEvents()
+ {
+ Workspace.WorkspaceChanged -= OnWorkspaceChangedLookForAnalyzer;
+ _item.PropertyChanged -= IVsHierarchyItem_PropertyChanged;
+ }
- private void IVsHierarchyItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ private void IVsHierarchyItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ // IVsHierarchyItem implements ISupportDisposalNotification, which allows us to know when it's been removed
+ if (e.PropertyName == nameof(ISupportDisposalNotification.IsDisposed))
{
- // IVsHierarchyItem implements ISupportDisposalNotification, which allows us to know when it's been removed
- if (e.PropertyName == nameof(ISupportDisposalNotification.IsDisposed))
- {
- UnsubscribeFromEvents();
- }
+ UnsubscribeFromEvents();
}
+ }
- public IContextMenuController DiagnosticItemContextMenuController => CommandHandler.DiagnosticContextMenuController;
+ public IContextMenuController DiagnosticItemContextMenuController => CommandHandler.DiagnosticContextMenuController;
- public override object SourceItem => _item;
+ public override object SourceItem => _item;
- public override AnalyzerReference? AnalyzerReference => _analyzerReference;
+ public override AnalyzerReference? AnalyzerReference => _analyzerReference;
- private void OnWorkspaceChangedLookForAnalyzer(object sender, WorkspaceChangeEventArgs e)
+ private void OnWorkspaceChangedLookForAnalyzer(object sender, WorkspaceChangeEventArgs e)
+ {
+ // If the project has gone away in this change, it's not coming back, so we can stop looking at this point
+ if (!e.NewSolution.ContainsProject(ProjectId))
{
- // If the project has gone away in this change, it's not coming back, so we can stop looking at this point
- if (!e.NewSolution.ContainsProject(ProjectId))
- {
- UnsubscribeFromEvents();
- return;
- }
+ UnsubscribeFromEvents();
+ return;
+ }
- // Was this a change to our project, or a global change?
- if (e.ProjectId == ProjectId ||
- e.Kind == WorkspaceChangeKind.SolutionChanged)
+ // Was this a change to our project, or a global change?
+ if (e.ProjectId == ProjectId ||
+ e.Kind == WorkspaceChangeKind.SolutionChanged)
+ {
+ var analyzerReference = TryGetAnalyzerReference(e.NewSolution);
+ if (analyzerReference != null)
{
- var analyzerReference = TryGetAnalyzerReference(e.NewSolution);
- if (analyzerReference != null)
- {
- _analyzerReference = analyzerReference;
- UnsubscribeFromEvents();
+ _analyzerReference = analyzerReference;
+ UnsubscribeFromEvents();
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(HasItems)));
- }
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(HasItems)));
}
}
+ }
- private AnalyzerReference? TryGetAnalyzerReference(Solution solution)
- {
- var project = solution.GetProject(ProjectId);
-
- if (project == null)
- {
- return null;
- }
+ private AnalyzerReference? TryGetAnalyzerReference(Solution solution)
+ {
+ var project = solution.GetProject(ProjectId);
- var canonicalName = _item.CanonicalName;
- var analyzerFilePath = CpsUtilities.ExtractAnalyzerFilePath(_projectDirectoryPath, canonicalName);
+ if (project == null)
+ {
+ return null;
+ }
- if (string.IsNullOrEmpty(analyzerFilePath))
- {
- return null;
- }
+ var canonicalName = _item.CanonicalName;
+ var analyzerFilePath = CpsUtilities.ExtractAnalyzerFilePath(_projectDirectoryPath, canonicalName);
- return project.AnalyzerReferences.FirstOrDefault(r => string.Equals(r.FullPath, analyzerFilePath, StringComparison.OrdinalIgnoreCase));
+ if (string.IsNullOrEmpty(analyzerFilePath))
+ {
+ return null;
}
+
+ return project.AnalyzerReferences.FirstOrDefault(r => string.Equals(r.FullPath, analyzerFilePath, StringComparison.OrdinalIgnoreCase));
}
}
diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/CpsDiagnosticItemSourceProvider.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/CpsDiagnosticItemSourceProvider.cs
index b4720a60d12de..dbc662bb2739a 100644
--- a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/CpsDiagnosticItemSourceProvider.cs
+++ b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/CpsDiagnosticItemSourceProvider.cs
@@ -7,162 +7,162 @@
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host.Mef;
+using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.Internal.VisualStudio.PlatformUI;
using Microsoft.VisualStudio.ProjectSystem;
using Microsoft.VisualStudio.ProjectSystem.Properties;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Utilities;
-namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer
+namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer;
+
+using OrderAttribute = Microsoft.VisualStudio.Utilities.OrderAttribute;
+using Workspace = Microsoft.CodeAnalysis.Workspace;
+
+[Export(typeof(IAttachedCollectionSourceProvider))]
+[Name(nameof(CpsDiagnosticItemSourceProvider))]
+[Order]
+[AppliesToProject($"({ProjectCapabilities.CSharp} | {ProjectCapabilities.VB}) & {ProjectCapabilities.Cps}")]
+[method: ImportingConstructor]
+[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
+internal sealed class CpsDiagnosticItemSourceProvider(
+ IThreadingContext threadingContext,
+ [Import(typeof(AnalyzersCommandHandler))] IAnalyzersCommandHandler commandHandler,
+ IDiagnosticAnalyzerService diagnosticAnalyzerService,
+ VisualStudioWorkspace workspace,
+ IAsynchronousOperationListenerProvider listenerProvider)
+ : AttachedCollectionSourceProvider
{
- using OrderAttribute = Microsoft.VisualStudio.Utilities.OrderAttribute;
- using Workspace = Microsoft.CodeAnalysis.Workspace;
-
- [Export(typeof(IAttachedCollectionSourceProvider))]
- [Name(nameof(CpsDiagnosticItemSourceProvider))]
- [Order]
- [AppliesToProject($"({ProjectCapabilities.CSharp} | {ProjectCapabilities.VB}) & {ProjectCapabilities.Cps}")]
- internal sealed class CpsDiagnosticItemSourceProvider : AttachedCollectionSourceProvider
- {
- private readonly IAnalyzersCommandHandler _commandHandler;
- private readonly IDiagnosticAnalyzerService _diagnosticAnalyzerService;
- private readonly Workspace _workspace;
-
- private IHierarchyItemToProjectIdMap? _projectMap;
-
- [ImportingConstructor]
- [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
- public CpsDiagnosticItemSourceProvider(
- [Import(typeof(AnalyzersCommandHandler))] IAnalyzersCommandHandler commandHandler,
- IDiagnosticAnalyzerService diagnosticAnalyzerService,
- VisualStudioWorkspace workspace)
- {
- _commandHandler = commandHandler;
- _diagnosticAnalyzerService = diagnosticAnalyzerService;
- _workspace = workspace;
- }
+ private readonly IThreadingContext _threadingContext = threadingContext;
+ private readonly IAnalyzersCommandHandler _commandHandler = commandHandler;
+ private readonly IDiagnosticAnalyzerService _diagnosticAnalyzerService = diagnosticAnalyzerService;
+ private readonly Workspace _workspace = workspace;
+ private readonly IAsynchronousOperationListenerProvider _listenerProvider = listenerProvider;
- protected override IAttachedCollectionSource? CreateCollectionSource(IVsHierarchyItem? item, string relationshipName)
+ private IHierarchyItemToProjectIdMap? _projectMap;
+
+ protected override IAttachedCollectionSource? CreateCollectionSource(IVsHierarchyItem? item, string relationshipName)
+ {
+ if (item?.HierarchyIdentity?.NestedHierarchy != null &&
+ !item.IsDisposed &&
+ relationshipName == KnownRelationships.Contains)
{
- if (item?.HierarchyIdentity?.NestedHierarchy != null &&
- !item.IsDisposed &&
- relationshipName == KnownRelationships.Contains)
+ if (NestedHierarchyHasProjectTreeCapability(item, "AnalyzerDependency"))
{
- if (NestedHierarchyHasProjectTreeCapability(item, "AnalyzerDependency"))
+ var projectRootItem = FindProjectRootItem(item, out var targetFrameworkMoniker);
+ if (projectRootItem != null)
{
- var projectRootItem = FindProjectRootItem(item, out var targetFrameworkMoniker);
- if (projectRootItem != null)
+ var hierarchyMapper = TryGetProjectMap();
+ if (hierarchyMapper != null &&
+ hierarchyMapper.TryGetProjectId(projectRootItem, targetFrameworkMoniker, out var projectId))
{
- var hierarchyMapper = TryGetProjectMap();
- if (hierarchyMapper != null &&
- hierarchyMapper.TryGetProjectId(projectRootItem, targetFrameworkMoniker, out var projectId))
+ var hierarchy = projectRootItem.HierarchyIdentity.NestedHierarchy;
+ var itemId = projectRootItem.HierarchyIdentity.NestedItemID;
+ if (hierarchy.GetCanonicalName(itemId, out var projectCanonicalName) == VSConstants.S_OK)
{
- var hierarchy = projectRootItem.HierarchyIdentity.NestedHierarchy;
- var itemId = projectRootItem.HierarchyIdentity.NestedItemID;
- if (hierarchy.GetCanonicalName(itemId, out var projectCanonicalName) == VSConstants.S_OK)
- {
- return new CpsDiagnosticItemSource(_workspace, projectCanonicalName, projectId, item, _commandHandler, _diagnosticAnalyzerService);
- }
+ return new CpsDiagnosticItemSource(
+ _workspace, projectCanonicalName, projectId, item, _commandHandler, _diagnosticAnalyzerService);
}
}
}
}
-
- return null;
}
- ///
- /// Starting at the given item, walks up the tree to find the item representing the project root.
- /// If the item is located under a target-framework specific node, the corresponding
- /// TargetFrameworkMoniker will be found as well.
- ///
- private static IVsHierarchyItem? FindProjectRootItem(IVsHierarchyItem item, out string? targetFrameworkMoniker)
+ return null;
+ }
+
+ ///
+ /// Starting at the given item, walks up the tree to find the item representing the project root.
+ /// If the item is located under a target-framework specific node, the corresponding
+ /// TargetFrameworkMoniker will be found as well.
+ ///
+ private static IVsHierarchyItem? FindProjectRootItem(IVsHierarchyItem item, out string? targetFrameworkMoniker)
+ {
+ targetFrameworkMoniker = null;
+
+ for (var parent = item; parent != null; parent = parent.Parent)
{
- targetFrameworkMoniker = null;
+ targetFrameworkMoniker ??= GetTargetFrameworkMoniker(parent);
- for (var parent = item; parent != null; parent = parent.Parent)
+ if (NestedHierarchyHasProjectTreeCapability(parent, "ProjectRoot"))
{
- targetFrameworkMoniker ??= GetTargetFrameworkMoniker(parent);
-
- if (NestedHierarchyHasProjectTreeCapability(parent, "ProjectRoot"))
- {
- return parent;
- }
+ return parent;
}
-
- return null;
}
- ///
- /// Given an item determines if it represents a particular target framework.
- /// If so, it returns the corresponding TargetFrameworkMoniker.
- ///
- private static string? GetTargetFrameworkMoniker(IVsHierarchyItem item)
- {
- if (TryGetFlags(item, out var flags) &&
- flags.Contains("TargetNode"))
- {
- const string prefix = "$TFM:";
- var flag = flags.FirstOrDefault(f => f.StartsWith(prefix));
+ return null;
+ }
- return flag?.Substring(prefix.Length);
- }
+ ///
+ /// Given an item determines if it represents a particular target framework.
+ /// If so, it returns the corresponding TargetFrameworkMoniker.
+ ///
+ private static string? GetTargetFrameworkMoniker(IVsHierarchyItem item)
+ {
+ if (TryGetFlags(item, out var flags) &&
+ flags.Contains("TargetNode"))
+ {
+ const string prefix = "$TFM:";
+ var flag = flags.FirstOrDefault(f => f.StartsWith(prefix));
- return null;
+ return flag?.Substring(prefix.Length);
}
- private static bool NestedHierarchyHasProjectTreeCapability(IVsHierarchyItem item, string capability)
- {
- if (TryGetFlags(item, out var flags))
- return flags.Contains(capability);
+ return null;
+ }
- return false;
- }
+ private static bool NestedHierarchyHasProjectTreeCapability(IVsHierarchyItem item, string capability)
+ {
+ if (TryGetFlags(item, out var flags))
+ return flags.Contains(capability);
+
+ return false;
+ }
- public static bool TryGetFlags(IVsHierarchyItem item, out ProjectTreeFlags flags)
+ public static bool TryGetFlags(IVsHierarchyItem item, out ProjectTreeFlags flags)
+ {
+ if (item.HierarchyIdentity.IsRoot)
{
- if (item.HierarchyIdentity.IsRoot)
+ if (item.HierarchyIdentity.NestedHierarchy is IVsBrowseObjectContext { UnconfiguredProject.Services.ProjectTreeService.CurrentTree.Tree: { } tree })
{
- if (item.HierarchyIdentity.NestedHierarchy is IVsBrowseObjectContext { UnconfiguredProject.Services.ProjectTreeService.CurrentTree.Tree: { } tree })
- {
- flags = tree.Flags;
- return true;
- }
+ flags = tree.Flags;
+ return true;
}
- else
+ }
+ else
+ {
+ var itemId = item.HierarchyIdentity.ItemID;
+
+ // Browse objects are created lazily, and we want to avoid creating them when possible.
+ // This method is typically invoked for every hierarchy item in the tree, via Solution Explorer APIs.
+ // Rather than create a browse object for every node, we find the project root node and use that.
+ // In this way, we only ever create one browse object per project.
+ var root = item;
+ while (!root.HierarchyIdentity.IsRoot)
{
- var itemId = item.HierarchyIdentity.ItemID;
-
- // Browse objects are created lazily, and we want to avoid creating them when possible.
- // This method is typically invoked for every hierarchy item in the tree, via Solution Explorer APIs.
- // Rather than create a browse object for every node, we find the project root node and use that.
- // In this way, we only ever create one browse object per project.
- var root = item;
- while (!root.HierarchyIdentity.IsRoot)
- {
- root = root.Parent;
- }
+ root = root.Parent;
+ }
- if (root.HierarchyIdentity.NestedHierarchy is IVsBrowseObjectContext { UnconfiguredProject.Services.ProjectTreeService.CurrentTree.Tree: { } tree })
+ if (root.HierarchyIdentity.NestedHierarchy is IVsBrowseObjectContext { UnconfiguredProject.Services.ProjectTreeService.CurrentTree.Tree: { } tree })
+ {
+ if (tree?.TryFind((IntPtr)itemId, out var subtree) == true)
{
- if (tree?.TryFind((IntPtr)itemId, out var subtree) == true)
- {
- flags = subtree.Flags;
- return true;
- }
+ flags = subtree.Flags;
+ return true;
}
}
-
- flags = default;
- return false;
}
- private IHierarchyItemToProjectIdMap? TryGetProjectMap()
- {
- _projectMap ??= _workspace.Services.GetService();
+ flags = default;
+ return false;
+ }
- return _projectMap;
- }
+ private IHierarchyItemToProjectIdMap? TryGetProjectMap()
+ {
+ _projectMap ??= _workspace.Services.GetService();
+
+ return _projectMap;
}
}
diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/DiagnosticItem.BrowseObject.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/DiagnosticItem.BrowseObject.cs
index 59d281e2075bf..1b0b3c71760c5 100644
--- a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/DiagnosticItem.BrowseObject.cs
+++ b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/DiagnosticItem.BrowseObject.cs
@@ -105,12 +105,7 @@ public string Tags
[BrowseObjectDisplayName(nameof(SolutionExplorerShim.Effective_severity))]
public string EffectiveSeverity
- {
- get
- {
- return MapReportDiagnosticToText(_diagnosticItem.EffectiveSeverity);
- }
- }
+ => MapReportDiagnosticToText(_diagnosticItem.EffectiveSeverity);
public override string GetClassName()
{
diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/DiagnosticItem.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/DiagnosticItem.cs
index 5a6eed07e4a9f..f2b62fd23e1a2 100644
--- a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/DiagnosticItem.cs
+++ b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/DiagnosticItem.cs
@@ -2,6 +2,7 @@
// 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.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
@@ -12,81 +13,95 @@
using Microsoft.Internal.VisualStudio.PlatformUI;
using Microsoft.VisualStudio.Imaging;
using Microsoft.VisualStudio.Imaging.Interop;
+using Roslyn.Utilities;
-namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer
+namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer;
+
+internal sealed partial class DiagnosticItem(
+ ProjectId projectId,
+ AnalyzerReference analyzerReference,
+ DiagnosticDescriptor descriptor,
+ ReportDiagnostic effectiveSeverity,
+ IAnalyzersCommandHandler commandHandler)
+ : BaseItem(descriptor.Id + ": " + descriptor.Title), IEquatable
{
- internal partial class DiagnosticItem : BaseItem
- {
- private readonly AnalyzerReference _analyzerReference;
- private readonly IAnalyzersCommandHandler _commandHandler;
+ private readonly AnalyzerReference _analyzerReference = analyzerReference;
+ private readonly IAnalyzersCommandHandler _commandHandler = commandHandler;
- public ProjectId ProjectId { get; }
- public DiagnosticDescriptor Descriptor { get; }
- public ReportDiagnostic EffectiveSeverity { get; private set; }
+ public ProjectId ProjectId { get; } = projectId;
+ public DiagnosticDescriptor Descriptor { get; } = descriptor;
+ public ReportDiagnostic EffectiveSeverity { get; private set; } = effectiveSeverity;
- public override event PropertyChangedEventHandler? PropertyChanged;
+ public override event PropertyChangedEventHandler? PropertyChanged;
- public DiagnosticItem(ProjectId projectId, AnalyzerReference analyzerReference, DiagnosticDescriptor descriptor, ReportDiagnostic effectiveSeverity, IAnalyzersCommandHandler commandHandler)
- : base(descriptor.Id + ": " + descriptor.Title)
- {
- ProjectId = projectId;
- _analyzerReference = analyzerReference;
- Descriptor = descriptor;
- EffectiveSeverity = effectiveSeverity;
- _commandHandler = commandHandler;
- }
+ public override ImageMoniker IconMoniker
+ => MapEffectiveSeverityToIconMoniker(this.EffectiveSeverity);
- public override ImageMoniker IconMoniker
- => MapEffectiveSeverityToIconMoniker(EffectiveSeverity);
+ public override IContextMenuController ContextMenuController => _commandHandler.DiagnosticContextMenuController;
- public override IContextMenuController ContextMenuController => _commandHandler.DiagnosticContextMenuController;
+ public override object GetBrowseObject()
+ => new BrowseObject(this);
- public override object GetBrowseObject()
+ internal void UpdateEffectiveSeverity(ReportDiagnostic newEffectiveSeverity)
+ {
+ if (EffectiveSeverity != newEffectiveSeverity)
{
- return new BrowseObject(this);
+ EffectiveSeverity = newEffectiveSeverity;
+
+ NotifyPropertyChanged(nameof(EffectiveSeverity));
+ NotifyPropertyChanged(nameof(IconMoniker));
}
+ }
- internal void UpdateEffectiveSeverity(ReportDiagnostic newEffectiveSeverity)
+ private static ImageMoniker MapEffectiveSeverityToIconMoniker(ReportDiagnostic effectiveSeverity)
+ => effectiveSeverity switch
{
- if (EffectiveSeverity != newEffectiveSeverity)
- {
- EffectiveSeverity = newEffectiveSeverity;
+ ReportDiagnostic.Error => KnownMonikers.CodeErrorRule,
+ ReportDiagnostic.Warn => KnownMonikers.CodeWarningRule,
+ ReportDiagnostic.Info => KnownMonikers.CodeInformationRule,
+ ReportDiagnostic.Hidden => KnownMonikers.CodeHiddenRule,
+ ReportDiagnostic.Suppress => KnownMonikers.CodeSuppressedRule,
+ _ => default,
+ };
+
+ private void NotifyPropertyChanged(string propertyName)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
- NotifyPropertyChanged(nameof(EffectiveSeverity));
- NotifyPropertyChanged(nameof(IconMoniker));
- }
- }
+ internal void SetRuleSetSeverity(ReportDiagnostic value, string pathToRuleSet)
+ {
+ var ruleSetDocument = XDocument.Load(pathToRuleSet);
- private static ImageMoniker MapEffectiveSeverityToIconMoniker(ReportDiagnostic effectiveSeverity)
- => effectiveSeverity switch
- {
- ReportDiagnostic.Error => KnownMonikers.CodeErrorRule,
- ReportDiagnostic.Warn => KnownMonikers.CodeWarningRule,
- ReportDiagnostic.Info => KnownMonikers.CodeInformationRule,
- ReportDiagnostic.Hidden => KnownMonikers.CodeHiddenRule,
- ReportDiagnostic.Suppress => KnownMonikers.CodeSuppressedRule,
- _ => default,
- };
-
- private void NotifyPropertyChanged(string propertyName)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
+ ruleSetDocument.SetSeverity(_analyzerReference.Display, Descriptor.Id, value);
- internal void SetRuleSetSeverity(ReportDiagnostic value, string pathToRuleSet)
- {
- var ruleSetDocument = XDocument.Load(pathToRuleSet);
+ ruleSetDocument.Save(pathToRuleSet);
+ }
- ruleSetDocument.SetSeverity(_analyzerReference.Display, Descriptor.Id, value);
+ internal Task GetSolutionWithUpdatedAnalyzerConfigSeverityAsync(ReportDiagnostic value, Project project, CancellationToken cancellationToken)
+ {
+ var effectiveSeverity = value.ToDiagnosticSeverity() ?? Descriptor.DefaultSeverity;
+ var diagnostic = Diagnostic.Create(Descriptor, Location.None, effectiveSeverity, additionalLocations: null, properties: null);
+ return ConfigurationUpdater.ConfigureSeverityAsync(value, diagnostic, project, cancellationToken);
+ }
- ruleSetDocument.Save(pathToRuleSet);
- }
+ public override int GetHashCode()
+ => Hash.Combine(this.Name,
+ Hash.Combine(this.ProjectId,
+ Hash.Combine(this.Descriptor.GetHashCode(), (int)this.EffectiveSeverity)));
- internal Task GetSolutionWithUpdatedAnalyzerConfigSeverityAsync(ReportDiagnostic value, Project project, CancellationToken cancellationToken)
- {
- var effectiveSeverity = value.ToDiagnosticSeverity() ?? Descriptor.DefaultSeverity;
- var diagnostic = Diagnostic.Create(Descriptor, Location.None, effectiveSeverity, additionalLocations: null, properties: null);
- return ConfigurationUpdater.ConfigureSeverityAsync(value, diagnostic, project, cancellationToken);
- }
+ public override bool Equals(object obj)
+ => Equals(obj as DiagnosticItem);
+
+ public bool Equals(DiagnosticItem? other)
+ {
+ if (this == other)
+ return true;
+
+ return other != null &&
+ this.Name == other.Name &&
+ this.ProjectId == other.ProjectId &&
+ this.Descriptor.Equals(other.Descriptor) &&
+ this.EffectiveSeverity == other.EffectiveSeverity;
}
}
diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/LegacyDiagnosticItemSource.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/LegacyDiagnosticItemSource.cs
index 611598537081e..e90f43a88cefe 100644
--- a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/LegacyDiagnosticItemSource.cs
+++ b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/LegacyDiagnosticItemSource.cs
@@ -4,19 +4,26 @@
using Microsoft.CodeAnalysis.Diagnostics;
-namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer
+namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer;
+
+internal sealed partial class LegacyDiagnosticItemSource : BaseDiagnosticAndGeneratorItemSource
{
- internal partial class LegacyDiagnosticItemSource : BaseDiagnosticAndGeneratorItemSource
+ private readonly AnalyzerItem _item;
+
+ public LegacyDiagnosticItemSource(
+ AnalyzerItem item,
+ IAnalyzersCommandHandler commandHandler,
+ IDiagnosticAnalyzerService diagnosticAnalyzerService)
+ : base(
+ item.AnalyzersFolder.Workspace,
+ item.AnalyzersFolder.ProjectId,
+ commandHandler,
+ diagnosticAnalyzerService)
{
- private readonly AnalyzerItem _item;
+ _item = item;
+ }
- public LegacyDiagnosticItemSource(AnalyzerItem item, IAnalyzersCommandHandler commandHandler, IDiagnosticAnalyzerService diagnosticAnalyzerService)
- : base(item.AnalyzersFolder.Workspace, item.AnalyzersFolder.ProjectId, commandHandler, diagnosticAnalyzerService)
- {
- _item = item;
- }
+ public override object SourceItem => _item;
- public override object SourceItem => _item;
- public override AnalyzerReference AnalyzerReference => _item.AnalyzerReference;
- }
+ public override AnalyzerReference? AnalyzerReference => _item.AnalyzerReference;
}
diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/LegacyDiagnosticItemSourceProvider.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/LegacyDiagnosticItemSourceProvider.cs
index c48962188a1f3..6ef52d112ac9f 100644
--- a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/LegacyDiagnosticItemSourceProvider.cs
+++ b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/LegacyDiagnosticItemSourceProvider.cs
@@ -5,40 +5,33 @@
using System;
using System.ComponentModel.Composition;
using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host.Mef;
+using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.Internal.VisualStudio.PlatformUI;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Utilities;
-namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer
+namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer;
+
+[Export(typeof(IAttachedCollectionSourceProvider))]
+[Name(nameof(LegacyDiagnosticItemSourceProvider))]
+[Order]
+[AppliesToProject("(CSharp | VB) & !CPS")]
+[method: ImportingConstructor]
+[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
+internal sealed class LegacyDiagnosticItemSourceProvider(
+ [Import(typeof(AnalyzersCommandHandler))] IAnalyzersCommandHandler commandHandler,
+ IDiagnosticAnalyzerService diagnosticAnalyzerService) : AttachedCollectionSourceProvider
{
- [Export(typeof(IAttachedCollectionSourceProvider))]
- [Name(nameof(LegacyDiagnosticItemSourceProvider))]
- [Order]
- [AppliesToProject("(CSharp | VB) & !CPS")]
- internal sealed class LegacyDiagnosticItemSourceProvider : AttachedCollectionSourceProvider
+ protected override IAttachedCollectionSource? CreateCollectionSource(AnalyzerItem item, string relationshipName)
{
- private readonly IAnalyzersCommandHandler _commandHandler;
- private readonly IDiagnosticAnalyzerService _diagnosticAnalyzerService;
-
- [ImportingConstructor]
- [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
- public LegacyDiagnosticItemSourceProvider(
- [Import(typeof(AnalyzersCommandHandler))] IAnalyzersCommandHandler commandHandler,
- IDiagnosticAnalyzerService diagnosticAnalyzerService)
+ if (relationshipName == KnownRelationships.Contains)
{
- _commandHandler = commandHandler;
- _diagnosticAnalyzerService = diagnosticAnalyzerService;
+ return new LegacyDiagnosticItemSource(
+ item, commandHandler, diagnosticAnalyzerService);
}
- protected override IAttachedCollectionSource? CreateCollectionSource(AnalyzerItem item, string relationshipName)
- {
- if (relationshipName == KnownRelationships.Contains)
- {
- return new LegacyDiagnosticItemSource(item, _commandHandler, _diagnosticAnalyzerService);
- }
-
- return null;
- }
+ return null;
}
}
diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/SourceGeneratorItem.BrowseObject.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/SourceGeneratorItem.BrowseObject.cs
index 27939c54c48e2..0949019cea990 100644
--- a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/SourceGeneratorItem.BrowseObject.cs
+++ b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/SourceGeneratorItem.BrowseObject.cs
@@ -4,27 +4,19 @@
using Microsoft.VisualStudio.Shell;
-namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer
+namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer;
+
+internal sealed partial class SourceGeneratorItem
{
- internal sealed partial class SourceGeneratorItem
+ internal sealed class BrowseObject(SourceGeneratorItem sourceGeneratorItem) : LocalizableProperties
{
- internal sealed class BrowseObject : LocalizableProperties
- {
- private readonly SourceGeneratorItem _sourceGeneratorItem;
-
- public BrowseObject(SourceGeneratorItem sourceGeneratorItem)
- {
- _sourceGeneratorItem = sourceGeneratorItem;
- }
-
- [BrowseObjectDisplayName(nameof(SolutionExplorerShim.Type_Name))]
- public string TypeName => _sourceGeneratorItem.Identity.TypeName;
+ [BrowseObjectDisplayName(nameof(SolutionExplorerShim.Type_Name))]
+ public string TypeName => sourceGeneratorItem.Identity.TypeName;
- [BrowseObjectDisplayName(nameof(SolutionExplorerShim.Path))]
- public string? Path => _sourceGeneratorItem.AnalyzerReference.FullPath;
+ [BrowseObjectDisplayName(nameof(SolutionExplorerShim.Path))]
+ public string? Path => sourceGeneratorItem._path;
- public override string GetClassName() => SolutionExplorerShim.Source_Generator_Properties;
- public override string GetComponentName() => TypeName;
- }
+ public override string GetClassName() => SolutionExplorerShim.Source_Generator_Properties;
+ public override string GetComponentName() => TypeName;
}
}
diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/SourceGeneratorItem.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/SourceGeneratorItem.cs
index 2728157932efc..d7a8ce4a0d773 100644
--- a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/SourceGeneratorItem.cs
+++ b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/SourceGeneratorItem.cs
@@ -2,33 +2,47 @@
// 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 Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.VisualStudio.Imaging;
using Microsoft.VisualStudio.Imaging.Interop;
+using Roslyn.Utilities;
-namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer
+namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer;
+
+internal sealed partial class SourceGeneratorItem(
+ ProjectId projectId,
+ SourceGeneratorIdentity identity,
+ string? path) : BaseItem(identity.TypeName), IEquatable
{
- internal sealed partial class SourceGeneratorItem : BaseItem
+ public ProjectId ProjectId { get; } = projectId;
+ public SourceGeneratorIdentity Identity { get; } = identity;
+ private readonly string? _path = path;
+
+ // TODO: do we need an icon for our use?
+ public override ImageMoniker IconMoniker
+ => KnownMonikers.Process;
+
+ public override object GetBrowseObject()
+ => new BrowseObject(this);
+
+ public override int GetHashCode()
+ => Hash.Combine(this.Name,
+ Hash.Combine(this.ProjectId,
+ Hash.Combine(_path, this.Identity.GetHashCode())));
+
+ public override bool Equals(object obj)
+ => Equals(obj as SourceGeneratorItem);
+
+ public bool Equals(SourceGeneratorItem? other)
{
- public ProjectId ProjectId { get; }
- public SourceGeneratorIdentity Identity { get; }
- public AnalyzerReference AnalyzerReference { get; }
-
- public SourceGeneratorItem(ProjectId projectId, ISourceGenerator generator, AnalyzerReference analyzerReference)
- : base(name: SourceGeneratorIdentity.GetGeneratorTypeName(generator))
- {
- ProjectId = projectId;
- Identity = SourceGeneratorIdentity.Create(generator, analyzerReference);
- AnalyzerReference = analyzerReference;
- }
-
- // TODO: do we need an icon for our use?
- public override ImageMoniker IconMoniker => KnownMonikers.Process;
-
- public override object GetBrowseObject()
- {
- return new BrowseObject(this);
- }
+ if (this == other)
+ return true;
+
+ return other != null &&
+ this.Name == other.Name &&
+ this.ProjectId == other.ProjectId &&
+ this.Identity == other.Identity &&
+ _path == other._path;
}
}
diff --git a/src/VisualStudio/Core/Test/SolutionExplorer/CpsDiagnosticItemSourceTests.vb b/src/VisualStudio/Core/Test/SolutionExplorer/CpsDiagnosticItemSourceTests.vb
index 4f75fb6c2e803..7c33159685a6e 100644
--- a/src/VisualStudio/Core/Test/SolutionExplorer/CpsDiagnosticItemSourceTests.vb
+++ b/src/VisualStudio/Core/Test/SolutionExplorer/CpsDiagnosticItemSourceTests.vb
@@ -5,18 +5,21 @@
Imports System.Collections.Immutable
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Diagnostics
+Imports Microsoft.CodeAnalysis.Editor.[Shared].Utilities
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
+Imports Microsoft.CodeAnalysis.[Shared].TestHooks
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.Internal.VisualStudio.PlatformUI
Imports Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer
Imports Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim.Framework
Imports Microsoft.VisualStudio.Shell
+Imports Roslyn.Test.Utilities
Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.SolutionExplorer
Public Class CpsDiagnosticItemSourceTests
-
- Public Sub AnalyzerHasDiagnostics()
+
+ Public Async Function AnalyzerHasDiagnostics() As Task
Dim workspaceXml =
@@ -35,6 +38,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.SolutionExplorer
Const analyzerPath = "C:\Analyzer.dll"
workspace.OnAnalyzerReferenceAdded(project.Id, New TestAnalyzerReferenceByLanguage(analyzers, analyzerPath))
+ Dim listenerProvider = workspace.GetService(Of IAsynchronousOperationListenerProvider)
Dim source As IAttachedCollectionSource = New CpsDiagnosticItemSource(
workspace,
project.FilePath,
@@ -43,9 +47,13 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.SolutionExplorer
New FakeAnalyzersCommandHandler, workspace.GetService(Of IDiagnosticAnalyzerService))
Assert.True(source.HasItems)
+
+ Dim waiter = DirectCast(listenerProvider.GetListener(FeatureAttribute.SourceGenerators), IAsynchronousOperationWaiter)
+ Await waiter.ExpeditedWaitAsync()
+
Dim diagnostic = Assert.IsAssignableFrom(Of ITreeDisplayItem)(Assert.Single(source.Items))
Assert.Contains(IDEDiagnosticIds.UseAutoPropertyDiagnosticId, diagnostic.Text)
End Using
- End Sub
+ End Function
End Class
End Namespace
diff --git a/src/VisualStudio/Core/Test/SolutionExplorer/SourceGeneratorItemTests.vb b/src/VisualStudio/Core/Test/SolutionExplorer/SourceGeneratorItemTests.vb
index 74145221a2051..8634c1210b3b5 100644
--- a/src/VisualStudio/Core/Test/SolutionExplorer/SourceGeneratorItemTests.vb
+++ b/src/VisualStudio/Core/Test/SolutionExplorer/SourceGeneratorItemTests.vb
@@ -19,7 +19,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.SolutionExplorer
Public Class SourceGeneratorItemTests
- Public Sub SourceGeneratorsListed()
+ Public Async Function SourceGeneratorsListed() As Task
Dim workspaceXml =
@@ -30,13 +30,14 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.SolutionExplorer
Dim projectId = workspace.Projects.Single().Id
Dim source = CreateItemSourceForAnalyzerReference(workspace, projectId)
+ Await WaitForGeneratorsAndItemSourcesAsync(workspace)
Assert.True(source.HasItems)
Dim generatorItem = Assert.IsAssignableFrom(Of SourceGeneratorItem)(Assert.Single(source.Items))
Assert.Equal(GetType(GenerateFileForEachAdditionalFileWithContentsCommented).FullName, generatorItem.Text)
End Using
- End Sub
+ End Function
Public Async Function PlaceholderItemCreateIfGeneratorProducesNoFiles() As Task
@@ -49,6 +50,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.SolutionExplorer
Using workspace = EditorTestWorkspace.Create(workspaceXml)
Dim projectId = workspace.Projects.Single().Id
Dim source = CreateItemSourceForAnalyzerReference(workspace, projectId)
+ Await WaitForGeneratorsAndItemSourcesAsync(workspace)
Dim generatorItem = Assert.IsAssignableFrom(Of SourceGeneratorItem)(Assert.Single(source.Items))
Dim generatorFilesItemSource = CreateSourceGeneratedFilesItemSource(workspace, generatorItem)
@@ -74,6 +76,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.SolutionExplorer
Using workspace = EditorTestWorkspace.Create(workspaceXml)
Dim projectId = workspace.Projects.Single().Id
Dim source = CreateItemSourceForAnalyzerReference(workspace, projectId)
+ Await WaitForGeneratorsAndItemSourcesAsync(workspace)
Dim generatorItem = Assert.IsAssignableFrom(Of SourceGeneratorItem)(Assert.Single(source.Items))
Dim generatorFilesItemSource = CreateSourceGeneratedFilesItemSource(workspace, generatorItem)
@@ -108,6 +111,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.SolutionExplorer
Using workspace = EditorTestWorkspace.Create(workspaceXml)
Dim projectId = workspace.Projects.Single().Id
Dim source = CreateItemSourceForAnalyzerReference(workspace, projectId)
+ Await WaitForGeneratorsAndItemSourcesAsync(workspace)
Dim generatorItem = Assert.IsAssignableFrom(Of SourceGeneratorItem)(Assert.Single(source.Items))
Dim generatorFilesItemSource = CreateSourceGeneratedFilesItemSource(workspace, generatorItem)
@@ -142,6 +146,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.SolutionExplorer
Dim projectId = workspace.Projects.Single().Id
Dim source = CreateItemSourceForAnalyzerReference(workspace, projectId)
+ Await WaitForGeneratorsAndItemSourcesAsync(workspace)
Dim generatorItem = Assert.IsAssignableFrom(Of SourceGeneratorItem)(Assert.Single(source.Items))
Dim generatorFilesItemSource = CreateSourceGeneratedFilesItemSource(workspace, generatorItem)
@@ -182,6 +187,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.SolutionExplorer
Dim projectId = workspace.Projects.Single().Id
Dim source = CreateItemSourceForAnalyzerReference(workspace, projectId)
+ Await WaitForGeneratorsAndItemSourcesAsync(workspace)
Dim generatorItem = Assert.IsAssignableFrom(Of SourceGeneratorItem)(Assert.Single(source.Items))
Dim generatorFilesItemSource = CreateSourceGeneratedFilesItemSource(workspace, generatorItem)
@@ -234,6 +240,8 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.SolutionExplorer
Using workspace = EditorTestWorkspace.Create(workspaceXml)
Dim projectId = workspace.Projects.Single().Id
Dim source = CreateItemSourceForAnalyzerReference(workspace, projectId)
+ Await WaitForGeneratorsAndItemSourcesAsync(workspace)
+
Dim generatorItem = Assert.IsAssignableFrom(Of SourceGeneratorItem)(Assert.Single(source.Items))
Dim generatorFilesItemSource = CreateSourceGeneratedFilesItemSource(workspace, generatorItem)
diff --git a/src/Workspaces/Core/Portable/SourceGeneration/IRemoteSourceGenerationService.cs b/src/Workspaces/Core/Portable/SourceGeneration/IRemoteSourceGenerationService.cs
index fffa94b324236..ce1a05a2ca1d8 100644
--- a/src/Workspaces/Core/Portable/SourceGeneration/IRemoteSourceGenerationService.cs
+++ b/src/Workspaces/Core/Portable/SourceGeneration/IRemoteSourceGenerationService.cs
@@ -8,12 +8,13 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.SourceGeneration;
[DataContract]
-internal readonly record struct SourceGeneratedDocmentInfo(
+internal readonly record struct SourceGeneratedDocumentInfo(
[property: DataMember(Order = 0)] SourceGeneratedDocumentIdentity DocumentIdentity,
[property: DataMember(Order = 1)] SourceGeneratedDocumentContentIdentity ContentIdentity,
[property: DataMember(Order = 2)] DateTime GenerationDateTime);
@@ -30,7 +31,7 @@ internal interface IRemoteSourceGenerationService
/// Controls if the caller wants frozen source generator documents
/// included in the result, or if only the most underlying generated documents (produced by the real compiler should be included.
- ValueTask> GetSourceGeneratedDocumentInfoAsync(
+ ValueTask> GetSourceGeneratedDocumentInfoAsync(
Checksum solutionChecksum, ProjectId projectId, bool withFrozenSourceGeneratedDocuments, CancellationToken cancellationToken);
///
diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SourceGeneratorIdentity.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SourceGeneratorIdentity.cs
index cf815501c688a..91818767b01f9 100644
--- a/src/Workspaces/Core/Portable/Workspace/Solution/SourceGeneratorIdentity.cs
+++ b/src/Workspaces/Core/Portable/Workspace/Solution/SourceGeneratorIdentity.cs
@@ -32,7 +32,4 @@ public static SourceGeneratorIdentity Create(ISourceGenerator generator, Analyze
return new SourceGeneratorIdentity(
assemblyName.Name!, analyzerReference.FullPath, assemblyName.Version!, generatorType.FullName!);
}
-
- public static string GetGeneratorTypeName(ISourceGenerator generator)
- => generator.GetGeneratorType().FullName!;
}
diff --git a/src/Workspaces/Remote/ServiceHub/Services/SourceGeneration/RemoteSourceGenerationService.cs b/src/Workspaces/Remote/ServiceHub/Services/SourceGeneration/RemoteSourceGenerationService.cs
index f1cd430234c82..cffdf6bca2b0b 100644
--- a/src/Workspaces/Remote/ServiceHub/Services/SourceGeneration/RemoteSourceGenerationService.cs
+++ b/src/Workspaces/Remote/ServiceHub/Services/SourceGeneration/RemoteSourceGenerationService.cs
@@ -29,7 +29,7 @@ protected override IRemoteSourceGenerationService CreateService(in ServiceConstr
=> new RemoteSourceGenerationService(arguments);
}
- public ValueTask> GetSourceGeneratedDocumentInfoAsync(
+ public ValueTask> GetSourceGeneratedDocumentInfoAsync(
Checksum solutionChecksum, ProjectId projectId, bool withFrozenSourceGeneratedDocuments, CancellationToken cancellationToken)
{
return RunServiceAsync(solutionChecksum, async solution =>
@@ -38,7 +38,7 @@ public ValueTask> GetSourceGeneratedD
var documentStates = await solution.CompilationState.GetSourceGeneratedDocumentStatesAsync(
project.State, withFrozenSourceGeneratedDocuments, cancellationToken).ConfigureAwait(false);
- var result = new FixedSizeArrayBuilder(documentStates.States.Count);
+ var result = new FixedSizeArrayBuilder(documentStates.States.Count);
foreach (var (id, state) in documentStates.States)
{
Contract.ThrowIfFalse(id.IsSourceGenerated);