提交 189e9828 编写于 作者: C Charles Stoner

Merge pull request #11693 from cston/225790-m2

Remove SolutionExplorer ProjectItem base classes added in 56136680
......@@ -2,41 +2,83 @@
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Shell;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer
{
internal sealed class AnalyzerItemSource : ProjectItemSource
internal class AnalyzerItemSource : IAttachedCollectionSource, INotifyPropertyChanged
{
private readonly AnalyzersFolderItem _analyzersFolder;
private readonly IAnalyzersCommandHandler _commandHandler;
private IReadOnlyCollection<AnalyzerReference> _analyzerReferences;
private BulkObservableCollection<AnalyzerItem> _analyzerItems;
public AnalyzerItemSource(AnalyzersFolderItem analyzersFolder, IAnalyzersCommandHandler commandHandler) :
base(analyzersFolder, analyzersFolder.Workspace, analyzersFolder.ProjectId)
public event PropertyChangedEventHandler PropertyChanged;
public AnalyzerItemSource(AnalyzersFolderItem analyzersFolder, IAnalyzersCommandHandler commandHandler)
{
_analyzersFolder = analyzersFolder;
_commandHandler = commandHandler;
_analyzersFolder.Workspace.WorkspaceChanged += Workspace_WorkspaceChanged;
}
private void Workspace_WorkspaceChanged(object sender, WorkspaceChangeEventArgs e)
{
switch (e.Kind)
{
case WorkspaceChangeKind.SolutionAdded:
case WorkspaceChangeKind.SolutionChanged:
case WorkspaceChangeKind.SolutionReloaded:
UpdateAnalyzers();
break;
case WorkspaceChangeKind.SolutionRemoved:
case WorkspaceChangeKind.SolutionCleared:
_analyzersFolder.Workspace.WorkspaceChanged -= Workspace_WorkspaceChanged;
break;
case WorkspaceChangeKind.ProjectAdded:
case WorkspaceChangeKind.ProjectReloaded:
case WorkspaceChangeKind.ProjectChanged:
if (e.ProjectId == _analyzersFolder.ProjectId)
{
UpdateAnalyzers();
}
break;
case WorkspaceChangeKind.ProjectRemoved:
if (e.ProjectId == _analyzersFolder.ProjectId)
{
_analyzersFolder.Workspace.WorkspaceChanged -= Workspace_WorkspaceChanged;
}
break;
}
}
protected override void Update()
private void UpdateAnalyzers()
{
if (_analyzerItems == null)
{
// The set of AnalyzerItems hasn't been realized yet. Just signal that HasItems
// may have changed.
NotifyPropertyChanged(nameof(HasItems));
NotifyPropertyChanged("HasItems");
return;
}
var project = _analyzersFolder.GetProject();
var project = _analyzersFolder.Workspace
.CurrentSolution
.GetProject(_analyzersFolder.ProjectId);
if (project != null &&
project.AnalyzerReferences != _analyzerReferences)
{
......@@ -70,11 +112,16 @@ protected override void Update()
_analyzerItems.EndBulkOperation();
NotifyPropertyChanged(nameof(HasItems));
NotifyPropertyChanged("HasItems");
}
}
public override bool HasItems
private void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public bool HasItems
{
get
{
......@@ -83,7 +130,10 @@ public override bool HasItems
return _analyzerItems.Count > 0;
}
var project = _analyzersFolder.GetProject();
var project = _analyzersFolder.Workspace
.CurrentSolution
.GetProject(_analyzersFolder.ProjectId);
if (project != null)
{
return project.AnalyzerReferences.Count > 0;
......@@ -93,7 +143,7 @@ public override bool HasItems
}
}
public override IEnumerable Items
public IEnumerable Items
{
get
{
......@@ -101,7 +151,10 @@ public override IEnumerable Items
{
_analyzerItems = new BulkObservableCollection<AnalyzerItem>();
var project = _analyzersFolder.GetProject();
var project = _analyzersFolder.Workspace
.CurrentSolution
.GetProject(_analyzersFolder.ProjectId);
if (project != null)
{
_analyzerReferences = project.AnalyzerReferences;
......@@ -119,5 +172,13 @@ public override IEnumerable Items
return _analyzerItems;
}
}
public object SourceItem
{
get
{
return _analyzersFolder;
}
}
}
}
// 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.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.Internal.VisualStudio.PlatformUI;
using Microsoft.VisualStudio.Imaging;
......@@ -18,6 +19,7 @@ internal partial class AnalyzersFolderItem : BaseItem
private readonly IVsHierarchyItem _parentItem;
private readonly IContextMenuController _contextMenuController;
public AnalyzersFolderItem(
Workspace workspace,
ProjectId projectId,
......@@ -72,11 +74,6 @@ public override IContextMenuController ContextMenuController
get { return _contextMenuController; }
}
internal Project GetProject()
{
return _workspace.CurrentSolution.GetProject(_projectId);
}
/// <summary>
/// Get the DTE object for the Project.
/// </summary>
......
......@@ -4,8 +4,10 @@
using System.Collections.Immutable;
using System.ComponentModel.Composition;
using System.Linq;
using System.Runtime.CompilerServices;
using Microsoft.CodeAnalysis;
using Microsoft.Internal.VisualStudio.PlatformUI;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Utilities;
......@@ -15,25 +17,29 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplore
[Export(typeof(IAttachedCollectionSourceProvider))]
[Name("AnalyzersFolderProvider")]
[Order(Before = HierarchyItemsProviderNames.Contains)]
internal sealed class AnalyzersFolderItemProvider : ProjectFolderItemProvider
internal class AnalyzersFolderItemProvider : AttachedCollectionSourceProvider<IVsHierarchyItem>
{
private readonly IComponentModel _componentModel;
private readonly IAnalyzersCommandHandler _commandHandler;
private IHierarchyItemToProjectIdMap _projectMap;
private Workspace _workspace;
[ImportingConstructor]
public AnalyzersFolderItemProvider(
[Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider,
[Import(typeof(AnalyzersCommandHandler))] IAnalyzersCommandHandler commandHandler) :
base(serviceProvider)
[Import(typeof(AnalyzersCommandHandler))] IAnalyzersCommandHandler commandHandler)
{
_componentModel = (IComponentModel)serviceProvider.GetService(typeof(SComponentModel));
_commandHandler = commandHandler;
}
/// <summary>
/// Constructor for use only in unit tests. Bypasses MEF to set the project mapper, workspace and glyph service.
/// </summary>
internal AnalyzersFolderItemProvider(IHierarchyItemToProjectIdMap projectMap, Workspace workspace, IAnalyzersCommandHandler commandHandler) :
base(projectMap, workspace)
internal AnalyzersFolderItemProvider(IHierarchyItemToProjectIdMap projectMap, Workspace workspace, IAnalyzersCommandHandler commandHandler)
{
_projectMap = projectMap;
_workspace = workspace;
_commandHandler = commandHandler;
}
......@@ -50,18 +56,43 @@ protected override IAttachedCollectionSource CreateCollectionSource(IVsHierarchy
var projectTreeCapabilities = GetProjectTreeCapabilities(hierarchy, itemId);
if (projectTreeCapabilities.Any(c => c.Equals("References")))
{
var projectId = TryGetProject(item.Parent);
if (projectId != null)
{
var workspace = TryGetWorkspace();
return new AnalyzersFolderItemSource(workspace, projectId, item, _commandHandler);
}
return CreateCollectionSourceCore(item.Parent, item);
}
}
return null;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private IAttachedCollectionSource CreateCollectionSourceCore(IVsHierarchyItem parentItem, IVsHierarchyItem item)
{
var hierarchyMapper = TryGetProjectMap();
ProjectId projectId;
if (hierarchyMapper != null &&
hierarchyMapper.TryGetProjectId(parentItem, out projectId))
{
var workspace = TryGetWorkspace();
return new AnalyzersFolderItemSource(workspace, projectId, item, _commandHandler);
}
return null;
}
private static ImmutableArray<string> GetProjectCapabilities(IVsHierarchy hierarchy)
{
object capabilitiesObj;
if (hierarchy.GetProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID5.VSHPROPID_ProjectCapabilities, out capabilitiesObj) == VSConstants.S_OK)
{
var capabilitiesString = (string)capabilitiesObj;
return ImmutableArray.Create(capabilitiesString.Split(' '));
}
else
{
return ImmutableArray<string>.Empty;
}
}
private static ImmutableArray<string> GetProjectTreeCapabilities(IVsHierarchy hierarchy, uint itemId)
{
object capabilitiesObj;
......@@ -75,5 +106,35 @@ private static ImmutableArray<string> GetProjectTreeCapabilities(IVsHierarchy hi
return ImmutableArray<string>.Empty;
}
}
private Workspace TryGetWorkspace()
{
if (_workspace == null)
{
var provider = _componentModel.DefaultExportProvider.GetExportedValueOrDefault<ISolutionExplorerWorkspaceProvider>();
if (provider != null)
{
_workspace = provider.GetWorkspace();
}
}
return _workspace;
}
private IHierarchyItemToProjectIdMap TryGetProjectMap()
{
var workspace = TryGetWorkspace();
if (workspace == null)
{
return null;
}
if (_projectMap == null)
{
_projectMap = workspace.Services.GetService<IHierarchyItemToProjectIdMap>();
}
return _projectMap;
}
}
}
......@@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.VisualStudio.Shell;
......@@ -23,12 +24,8 @@ public AnalyzersFolderItemSource(Workspace workspace, ProjectId projectId, IVsHi
_commandHandler = commandHandler;
_folderItems = new ObservableCollection<AnalyzersFolderItem>();
_folderItems.Add(
new AnalyzersFolderItem(
_workspace,
_projectId,
_projectHierarchyItem,
_commandHandler.AnalyzerFolderContextMenuController));
Update();
}
public bool HasItems
......@@ -54,5 +51,21 @@ public object SourceItem
return _projectHierarchyItem;
}
}
internal void Update()
{
// Don't create the item a 2nd time.
if (_folderItems.Any())
{
return;
}
_folderItems.Add(
new AnalyzersFolderItem(
_workspace,
_projectId,
_projectHierarchyItem,
_commandHandler.AnalyzerFolderContextMenuController));
}
}
}
// 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 Microsoft.CodeAnalysis;
using Microsoft.Internal.VisualStudio.PlatformUI;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Shell;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer
{
internal abstract class ProjectFolderItemProvider : AttachedCollectionSourceProvider<IVsHierarchyItem>
{
private readonly IComponentModel _componentModel;
private IHierarchyItemToProjectIdMap _projectMap;
private Workspace _workspace;
internal ProjectFolderItemProvider(IServiceProvider serviceProvider)
{
_componentModel = (IComponentModel)serviceProvider.GetService(typeof(SComponentModel));
}
/// <summary>
/// Constructor for use only in unit tests. Bypasses MEF.
/// </summary>
internal ProjectFolderItemProvider(IHierarchyItemToProjectIdMap projectMap, Workspace workspace)
{
_projectMap = projectMap;
_workspace = workspace;
}
protected Workspace TryGetWorkspace()
{
if (_workspace == null)
{
var provider = _componentModel.DefaultExportProvider.GetExportedValueOrDefault<ISolutionExplorerWorkspaceProvider>();
if (provider != null)
{
_workspace = provider.GetWorkspace();
}
}
return _workspace;
}
protected ProjectId TryGetProject(IVsHierarchyItem item)
{
var hierarchyMapper = TryGetProjectMap();
if (hierarchyMapper == null)
{
return null;
}
ProjectId projectId;
hierarchyMapper.TryGetProjectId(item, out projectId);
return projectId;
}
private IHierarchyItemToProjectIdMap TryGetProjectMap()
{
var workspace = TryGetWorkspace();
if (workspace == null)
{
return null;
}
if (_projectMap == null)
{
_projectMap = workspace.Services.GetService<IHierarchyItemToProjectIdMap>();
}
return _projectMap;
}
}
}
// 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.Collections;
using System.ComponentModel;
using Microsoft.CodeAnalysis;
using Microsoft.VisualStudio.Shell;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer
{
internal abstract class ProjectItemSource : IAttachedCollectionSource, INotifyPropertyChanged
{
private readonly BaseItem _folder;
private readonly Workspace _workspace;
private readonly ProjectId _projectId;
public event PropertyChangedEventHandler PropertyChanged;
protected ProjectItemSource(BaseItem folder, Workspace workspace, ProjectId projectId)
{
_folder = folder;
_workspace = workspace;
_projectId = projectId;
_workspace.WorkspaceChanged += Workspace_WorkspaceChanged;
}
private void Workspace_WorkspaceChanged(object sender, WorkspaceChangeEventArgs e)
{
switch (e.Kind)
{
case WorkspaceChangeKind.SolutionAdded:
case WorkspaceChangeKind.SolutionChanged:
case WorkspaceChangeKind.SolutionReloaded:
Update();
break;
case WorkspaceChangeKind.SolutionRemoved:
case WorkspaceChangeKind.SolutionCleared:
_workspace.WorkspaceChanged -= Workspace_WorkspaceChanged;
break;
case WorkspaceChangeKind.ProjectAdded:
case WorkspaceChangeKind.ProjectReloaded:
case WorkspaceChangeKind.ProjectChanged:
if (e.ProjectId == _projectId)
{
Update();
}
break;
case WorkspaceChangeKind.ProjectRemoved:
if (e.ProjectId == _projectId)
{
_workspace.WorkspaceChanged -= Workspace_WorkspaceChanged;
}
break;
}
}
protected abstract void Update();
protected void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public abstract bool HasItems { get; }
public abstract IEnumerable Items { get; }
public object SourceItem
{
get { return _folder; }
}
}
}
......@@ -285,15 +285,6 @@ internal class SolutionExplorerShim {
}
}
/// <summary>
/// Looks up a localized string similar to Generated Source.
/// </summary>
internal static string GeneratedSourceFolderItem_Name {
get {
return ResourceManager.GetString("GeneratedSourceFolderItem_Name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Default.
/// </summary>
......
......@@ -105,8 +105,6 @@
<Compile Include="LocalizableProperties.cs" />
<Compile Include="DiagnosticItem\DiagnosticItemSource.cs" />
<Compile Include="DiagnosticItem\DiagnosticItem.cs" />
<Compile Include="ProjectItem\ProjectFolderItemProvider.cs" />
<Compile Include="ProjectItem\ProjectItemSource.cs" />
<Compile Include="RuleSetDocumentExtensions.cs" />
<Compile Include="SolutionExplorerShim.Designer.cs">
<AutoGen>True</AutoGen>
......
......@@ -210,7 +210,4 @@
<data name="DiagnosticItemTitleDisplayName" xml:space="preserve">
<value>Title</value>
</data>
<data name="GeneratedSourceFolderItem_Name" xml:space="preserve">
<value>Generated Source</value>
</data>
</root>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册