diff --git a/src/VisualStudio/Core/Def/ID.RoslynCommands.cs b/src/VisualStudio/Core/Def/ID.RoslynCommands.cs index f07de6e079be2..d3aae7ef33bd3 100644 --- a/src/VisualStudio/Core/Def/ID.RoslynCommands.cs +++ b/src/VisualStudio/Core/Def/ID.RoslynCommands.cs @@ -25,6 +25,7 @@ public static class RoslynCommands public const int SetSeverityHidden = 0x0113; public const int SetSeverityNone = 0x0114; public const int OpenDiagnosticHelpLink = 0x0116; + public const int SetActiveRuleSet = 0x0118; } } } diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/Extensions/IVsHierarchyExtensions.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/Extensions/IVsHierarchyExtensions.cs index 8a0e6d4e56ce1..13c1c0111152a 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/Extensions/IVsHierarchyExtensions.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/Extensions/IVsHierarchyExtensions.cs @@ -7,10 +7,10 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem { internal static class IVsHierarchyExtensions { - public static bool TryGetProperty(this IVsHierarchy hierarchy, int propertyId, out T value) + public static bool TryGetItemProperty(this IVsHierarchy hierarchy, uint itemId, int propertyId, out T value) { object property; - if (ErrorHandler.Failed(hierarchy.GetProperty(VSConstants.VSITEMID_ROOT, propertyId, out property)) || + if (ErrorHandler.Failed(hierarchy.GetProperty(itemId, propertyId, out property)) || !(property is T)) { value = default(T); @@ -22,11 +22,22 @@ public static bool TryGetProperty(this IVsHierarchy hierarchy, int propertyId return true; } + public static bool TryGetProperty(this IVsHierarchy hierarchy, int propertyId, out T value) + { + const uint root = VSConstants.VSITEMID_ROOT; + return hierarchy.TryGetItemProperty(root, propertyId, out value); + } + public static bool TryGetProperty(this IVsHierarchy hierarchy, __VSHPROPID propertyId, out T value) { return hierarchy.TryGetProperty((int)propertyId, out value); } + public static bool TryGetItemProperty(this IVsHierarchy hierarchy, uint itemId, __VSHPROPID propertyId, out T value) + { + return hierarchy.TryGetItemProperty(itemId, (int)propertyId, out value); + } + public static bool TryGetGuidProperty(this IVsHierarchy hierarchy, int propertyId, out Guid guid) { return ErrorHandler.Succeeded(hierarchy.GetGuidProperty(VSConstants.VSITEMID_ROOT, propertyId, out guid)); @@ -47,6 +58,11 @@ public static bool TryGetName(this IVsHierarchy hierarchy, out string name) return hierarchy.TryGetProperty(__VSHPROPID.VSHPROPID_Name, out name); } + public static bool TryGetItemName(this IVsHierarchy hierarchy, uint itemId, out string name) + { + return hierarchy.TryGetItemProperty(itemId, __VSHPROPID.VSHPROPID_Name, out name); + } + public static bool TryGetParentHierarchy(this IVsHierarchy hierarchy, out IVsHierarchy parentHierarchy) { return hierarchy.TryGetProperty(__VSHPROPID.VSHPROPID_ParentHierarchy, out parentHierarchy); diff --git a/src/VisualStudio/Core/SolutionExplorerShim/AnalyzersCommandHandler.cs b/src/VisualStudio/Core/SolutionExplorerShim/AnalyzersCommandHandler.cs index a136aa2218a6b..a0a00491b84c2 100644 --- a/src/VisualStudio/Core/SolutionExplorerShim/AnalyzersCommandHandler.cs +++ b/src/VisualStudio/Core/SolutionExplorerShim/AnalyzersCommandHandler.cs @@ -42,6 +42,7 @@ internal class AnalyzersCommandHandler : IVsUpdateSolutionEvents private MenuCommand _referencesContextAddMenuItem; private MenuCommand _removeMenuItem; private MenuCommand _openRuleSetMenuItem; + private MenuCommand _setActiveRuleSetMenuItem; private MenuCommand _setSeverityErrorMenuItem; private MenuCommand _setSeverityWarningMenuItem; @@ -70,6 +71,7 @@ public void Initialize(IMenuCommandService menuCommandService) _removeMenuItem = AddCommandHandler(menuCommandService, ID.RoslynCommands.RemoveAnalyzer, RemoveAnalyzerHandler); _openRuleSetMenuItem = AddCommandHandler(menuCommandService, ID.RoslynCommands.OpenRuleSet, OpenRuleSetHandler); + _setActiveRuleSetMenuItem = AddCommandHandler(menuCommandService, ID.RoslynCommands.SetActiveRuleSet, SetActiveRuleSetHandler); _setSeverityErrorMenuItem = AddCommandHandler(menuCommandService, ID.RoslynCommands.SetSeverityError, SetSeverityHandler); _setSeverityWarningMenuItem = AddCommandHandler(menuCommandService, ID.RoslynCommands.SetSeverityWarning, SetSeverityHandler); @@ -141,7 +143,7 @@ private void SelectedItemIdChangedHandler(object sender, EventArgs e) private void UpdateMenuItemVisibility() { - bool selectedProjectSupportsAnalyzers = SelectedProjectSupportAnalyzers(); + bool selectedProjectSupportsAnalyzers = SelectedProjectSupportsAnalyzers(); _addMenuItem.Visible = selectedProjectSupportsAnalyzers; _projectAddMenuItem.Visible = selectedProjectSupportsAnalyzers; _projectContextAddMenuItem.Visible = selectedProjectSupportsAnalyzers && _tracker.SelectedItemId == VSConstants.VSITEMID_ROOT; @@ -149,6 +151,12 @@ private void UpdateMenuItemVisibility() _openHelpLinkMenuItem.Visible = _tracker.SelectedDiagnosticItems.Length == 1 && !string.IsNullOrWhiteSpace(_tracker.SelectedDiagnosticItems[0].Descriptor.HelpLinkUri); + + + string itemName; + _setActiveRuleSetMenuItem.Visible = selectedProjectSupportsAnalyzers && + _tracker.SelectedHierarchy.TryGetItemName(_tracker.SelectedItemId, out itemName) && + Path.GetExtension(itemName).Equals(".ruleset", StringComparison.OrdinalIgnoreCase); } private void UpdateMenuItemsChecked() @@ -165,7 +173,7 @@ private bool AnyDiagnosticsWithSeverity(ReportDiagnostic severity) return _selectedDiagnosticItems.Any(item => item.EffectiveSeverity == severity); } - private bool SelectedProjectSupportAnalyzers() + private bool SelectedProjectSupportsAnalyzers() { EnvDTE.Project project; return _tracker != null && @@ -328,6 +336,17 @@ private void OpenDiagnosticHelpLinkHandler(object sender, EventArgs e) } } + private void SetActiveRuleSetHandler(object sender, EventArgs e) + { + EnvDTE.Project project; + string fileName; + if (_tracker.SelectedHierarchy.TryGetProject(out project) && + _tracker.SelectedHierarchy.TryGetItemName(_tracker.SelectedItemId, out fileName)) + { + UpdateProjectConfigurationsToUseRuleSetFile(project, fileName); + } + } + private string CreateCopyOfRuleSetForProject(string pathToRuleSet, EnvDTE.Project envDteProject) { string fileName = GetNewRuleSetFileNameForProject(envDteProject); diff --git a/src/VisualStudio/Setup/Commands.vsct b/src/VisualStudio/Setup/Commands.vsct index 02cddb7c431e2..5a7187560c121 100644 --- a/src/VisualStudio/Setup/Commands.vsct +++ b/src/VisualStudio/Setup/Commands.vsct @@ -53,6 +53,9 @@ + + + @@ -242,7 +245,7 @@ SetSeverityNone - + + + @@ -323,6 +338,15 @@ + + + + + + + + + @@ -372,6 +396,8 @@ + +