|
// 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;
using System.ComponentModel.Composition;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using VSLangProj140;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer;
/// <summary>
/// This class is responsible for showing an add analyzer dialog to the user and adding the analyzer
/// that is selected by the user in the dialog.
/// </summary>
[Export]
internal sealed class AnalyzerReferenceManager : IVsReferenceManagerUser
{
private readonly IServiceProvider _serviceProvider;
private IVsReferenceManager? _referenceManager;
private readonly AnalyzerItemsTracker _tracker;
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public AnalyzerReferenceManager(
[Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider,
AnalyzerItemsTracker analyzerItemsTracker)
{
_serviceProvider = serviceProvider;
_tracker = analyzerItemsTracker;
}
/// <summary>
/// Show the add analyzer dialog.
/// </summary>
public void ShowDialog()
{
var referenceManager = GetReferenceManager();
if (referenceManager != null &&
_tracker.SelectedHierarchy != null)
{
referenceManager.ShowReferenceManager(this,
SolutionExplorerShim.Add_Analyzer,
null,
VSConstants.FileReferenceProvider_Guid,
fForceShowDefaultProvider: false);
}
}
/// <summary>
/// Called by the ReferenceManagerDialog to apply the user selection of references.
/// </summary>
public void ChangeReferences(uint operation, IVsReferenceProviderContext changedContext)
{
var referenceOperation = (__VSREFERENCECHANGEOPERATION)operation;
// The items selected in Solution Explorer should correspond to exactly one
// IVsHierarchy, otherwise we shouldn't have even tried to show the dialog.
Contract.ThrowIfNull(_tracker.SelectedHierarchy);
if (_tracker.SelectedHierarchy.TryGetProject(out var project))
{
if (project.Object is VSProject3 vsproject)
{
foreach (IVsReference reference in changedContext.References)
{
var path = reference.FullPath;
switch (referenceOperation)
{
case __VSREFERENCECHANGEOPERATION.VSREFERENCECHANGEOPERATION_ADD:
vsproject.AnalyzerReferences.Add(path);
break;
case __VSREFERENCECHANGEOPERATION.VSREFERENCECHANGEOPERATION_REMOVE:
vsproject.AnalyzerReferences.Remove(path);
break;
default:
break;
}
}
}
}
}
/// <summary>
/// Called by the ReferenceManagerDialog to determine what contexts to show in the UI.
/// </summary>
public Array GetProviderContexts()
{
// Return just the File provider context so that just the browse tab shows up.
var context = (IVsFileReferenceProviderContext)GetReferenceManager().CreateProviderContext(VSConstants.FileReferenceProvider_Guid);
context.BrowseFilter = string.Format("{0} (*.dll)\0*.dll\0", SolutionExplorerShim.Analyzer_Files);
return new[] { context };
}
private IVsReferenceManager GetReferenceManager()
{
if (_referenceManager == null)
{
_referenceManager = _serviceProvider.GetService(typeof(SVsReferenceManager)) as IVsReferenceManager;
Assumes.Present(_referenceManager);
}
return _referenceManager;
}
}
|