未验证 提交 3765a2f2 编写于 作者: H Heejae Chang 提交者: GitHub

make diagnostic analyzer service lazy and not require UI thread. (#25982)

* make diagnostic analyzer service lazy and not require UI thread.

require ExtensionManager change that got checked into 15.8

* change location where we log number of workspace analyzer references due to it being lazy now.

* PR feedback
上级 ea1339f3
...@@ -64,7 +64,8 @@ internal sealed class TestDiagnosticAnalyzerService : DiagnosticAnalyzerService ...@@ -64,7 +64,8 @@ internal sealed class TestDiagnosticAnalyzerService : DiagnosticAnalyzerService
AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource,
PrimaryWorkspace primaryWorkspace, PrimaryWorkspace primaryWorkspace,
Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null) Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null)
: base(SpecializedCollections.EmptyEnumerable<HostDiagnosticAnalyzerPackage>(), null, hostDiagnosticUpdateSource, primaryWorkspace, new MockDiagnosticUpdateSourceRegistrationService()) : base(new Lazy<ImmutableArray<HostDiagnosticAnalyzerPackage>>(() => ImmutableArray<HostDiagnosticAnalyzerPackage>.Empty),
hostAnalyzerAssemblyLoader: null, hostDiagnosticUpdateSource, primaryWorkspace, new MockDiagnosticUpdateSourceRegistrationService())
{ {
_onAnalyzerException = onAnalyzerException; _onAnalyzerException = onAnalyzerException;
} }
......
...@@ -29,7 +29,7 @@ internal partial class DiagnosticAnalyzerService : IDiagnosticAnalyzerService ...@@ -29,7 +29,7 @@ internal partial class DiagnosticAnalyzerService : IDiagnosticAnalyzerService
PrimaryWorkspace primaryWorkspace, PrimaryWorkspace primaryWorkspace,
[Import(AllowDefault = true)]IWorkspaceDiagnosticAnalyzerProviderService diagnosticAnalyzerProviderService = null, [Import(AllowDefault = true)]IWorkspaceDiagnosticAnalyzerProviderService diagnosticAnalyzerProviderService = null,
[Import(AllowDefault = true)]AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource = null) [Import(AllowDefault = true)]AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource = null)
: this(diagnosticAnalyzerProviderService != null ? diagnosticAnalyzerProviderService.GetHostDiagnosticAnalyzerPackages() : SpecializedCollections.EmptyEnumerable<HostDiagnosticAnalyzerPackage>(), : this(new Lazy<ImmutableArray<HostDiagnosticAnalyzerPackage>>(() => GetHostDiagnosticAnalyzerPackage(diagnosticAnalyzerProviderService), isThreadSafe: true),
diagnosticAnalyzerProviderService?.GetAnalyzerAssemblyLoader(), diagnosticAnalyzerProviderService?.GetAnalyzerAssemblyLoader(),
hostDiagnosticUpdateSource, hostDiagnosticUpdateSource,
primaryWorkspace, primaryWorkspace,
...@@ -39,11 +39,9 @@ internal partial class DiagnosticAnalyzerService : IDiagnosticAnalyzerService ...@@ -39,11 +39,9 @@ internal partial class DiagnosticAnalyzerService : IDiagnosticAnalyzerService
// never be null // never be null
} }
public IAsynchronousOperationListener Listener => _listener;
// protected for testing purposes. // protected for testing purposes.
protected DiagnosticAnalyzerService( protected DiagnosticAnalyzerService(
IEnumerable<HostDiagnosticAnalyzerPackage> workspaceAnalyzerPackages, Lazy<ImmutableArray<HostDiagnosticAnalyzerPackage>> workspaceAnalyzerPackages,
IAnalyzerAssemblyLoader hostAnalyzerAssemblyLoader, IAnalyzerAssemblyLoader hostAnalyzerAssemblyLoader,
AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource,
PrimaryWorkspace primaryWorkspace, PrimaryWorkspace primaryWorkspace,
...@@ -53,6 +51,8 @@ internal partial class DiagnosticAnalyzerService : IDiagnosticAnalyzerService ...@@ -53,6 +51,8 @@ internal partial class DiagnosticAnalyzerService : IDiagnosticAnalyzerService
{ {
} }
public IAsynchronousOperationListener Listener => _listener;
// protected for testing purposes. // protected for testing purposes.
protected DiagnosticAnalyzerService( protected DiagnosticAnalyzerService(
HostAnalyzerManager hostAnalyzerManager, HostAnalyzerManager hostAnalyzerManager,
...@@ -255,5 +255,10 @@ public bool ContainsDiagnostics(Workspace workspace, ProjectId projectId) ...@@ -255,5 +255,10 @@ public bool ContainsDiagnostics(Workspace workspace, ProjectId projectId)
AnalyzerHelper.OnAnalyzerException_NoTelemetryLogging(ex, analyzer, diagnostic, _hostDiagnosticUpdateSource, projectId); AnalyzerHelper.OnAnalyzerException_NoTelemetryLogging(ex, analyzer, diagnostic, _hostDiagnosticUpdateSource, projectId);
}; };
} }
private static ImmutableArray<HostDiagnosticAnalyzerPackage> GetHostDiagnosticAnalyzerPackage(IWorkspaceDiagnosticAnalyzerProviderService diagnosticAnalyzerProviderService)
{
return (diagnosticAnalyzerProviderService?.GetHostDiagnosticAnalyzerPackages()).ToImmutableArrayOrEmpty();
}
} }
} }
...@@ -25,7 +25,7 @@ internal sealed partial class HostAnalyzerManager ...@@ -25,7 +25,7 @@ internal sealed partial class HostAnalyzerManager
/// <summary> /// <summary>
/// This contains vsix info on where <see cref="HostDiagnosticAnalyzerPackage"/> comes from. /// This contains vsix info on where <see cref="HostDiagnosticAnalyzerPackage"/> comes from.
/// </summary> /// </summary>
private readonly ImmutableArray<HostDiagnosticAnalyzerPackage> _hostDiagnosticAnalyzerPackages; private readonly Lazy<ImmutableArray<HostDiagnosticAnalyzerPackage>> _hostDiagnosticAnalyzerPackages;
/// <summary> /// <summary>
/// Key is analyzer reference identity <see cref="GetAnalyzerReferenceIdentity(AnalyzerReference)"/>. /// Key is analyzer reference identity <see cref="GetAnalyzerReferenceIdentity(AnalyzerReference)"/>.
...@@ -76,24 +76,19 @@ internal sealed partial class HostAnalyzerManager ...@@ -76,24 +76,19 @@ internal sealed partial class HostAnalyzerManager
/// </summary> /// </summary>
private readonly ConditionalWeakTable<DiagnosticAnalyzer, IReadOnlyCollection<DiagnosticDescriptor>> _descriptorCache; private readonly ConditionalWeakTable<DiagnosticAnalyzer, IReadOnlyCollection<DiagnosticDescriptor>> _descriptorCache;
public HostAnalyzerManager(IEnumerable<HostDiagnosticAnalyzerPackage> hostAnalyzerPackages, IAnalyzerAssemblyLoader hostAnalyzerAssemblyLoader, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource, PrimaryWorkspace primaryWorkspace) : public HostAnalyzerManager(Lazy<ImmutableArray<HostDiagnosticAnalyzerPackage>> hostAnalyzerPackages, IAnalyzerAssemblyLoader hostAnalyzerAssemblyLoader, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource, PrimaryWorkspace primaryWorkspace) :
this(CreateAnalyzerReferencesFromPackages(hostAnalyzerPackages, new HostAnalyzerReferenceDiagnosticReporter(hostDiagnosticUpdateSource, primaryWorkspace), hostAnalyzerAssemblyLoader), this(new Lazy<ImmutableArray<AnalyzerReference>>(() => CreateAnalyzerReferencesFromPackages(hostAnalyzerPackages.Value, new HostAnalyzerReferenceDiagnosticReporter(hostDiagnosticUpdateSource, primaryWorkspace), hostAnalyzerAssemblyLoader), isThreadSafe: true),
hostAnalyzerPackages.ToImmutableArrayOrEmpty(), hostDiagnosticUpdateSource) hostAnalyzerPackages, hostDiagnosticUpdateSource)
{
}
public HostAnalyzerManager(ImmutableArray<AnalyzerReference> hostAnalyzerReferences, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) :
this(hostAnalyzerReferences, ImmutableArray<HostDiagnosticAnalyzerPackage>.Empty, hostDiagnosticUpdateSource)
{ {
} }
private HostAnalyzerManager( private HostAnalyzerManager(
ImmutableArray<AnalyzerReference> hostAnalyzerReferences, ImmutableArray<HostDiagnosticAnalyzerPackage> hostAnalyzerPackages, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) Lazy<ImmutableArray<AnalyzerReference>> hostAnalyzerReferences, Lazy<ImmutableArray<HostDiagnosticAnalyzerPackage>> hostAnalyzerPackages, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource)
{ {
_hostDiagnosticAnalyzerPackages = hostAnalyzerPackages; _hostDiagnosticAnalyzerPackages = hostAnalyzerPackages;
_hostDiagnosticUpdateSource = hostDiagnosticUpdateSource; _hostDiagnosticUpdateSource = hostDiagnosticUpdateSource;
_hostAnalyzerReferencesMap = new Lazy<ImmutableDictionary<object, AnalyzerReference>>(() => hostAnalyzerReferences.IsDefault ? ImmutableDictionary<object, AnalyzerReference>.Empty : CreateAnalyzerReferencesMap(hostAnalyzerReferences)); _hostAnalyzerReferencesMap = new Lazy<ImmutableDictionary<object, AnalyzerReference>>(() => hostAnalyzerReferences.Value.IsDefaultOrEmpty ? ImmutableDictionary<object, AnalyzerReference>.Empty : CreateAnalyzerReferencesMap(hostAnalyzerReferences.Value), isThreadSafe: true);
_hostDiagnosticAnalyzersPerLanguageMap = new ConcurrentDictionary<string, ImmutableDictionary<object, ImmutableArray<DiagnosticAnalyzer>>>(concurrencyLevel: 2, capacity: 2); _hostDiagnosticAnalyzersPerLanguageMap = new ConcurrentDictionary<string, ImmutableDictionary<object, ImmutableArray<DiagnosticAnalyzer>>>(concurrencyLevel: 2, capacity: 2);
_lazyHostDiagnosticAnalyzersPerReferenceMap = new Lazy<ImmutableDictionary<object, ImmutableArray<DiagnosticAnalyzer>>>(() => CreateDiagnosticAnalyzersPerReferenceMap(_hostAnalyzerReferencesMap.Value), isThreadSafe: true); _lazyHostDiagnosticAnalyzersPerReferenceMap = new Lazy<ImmutableDictionary<object, ImmutableArray<DiagnosticAnalyzer>>>(() => CreateDiagnosticAnalyzersPerReferenceMap(_hostAnalyzerReferencesMap.Value), isThreadSafe: true);
...@@ -101,8 +96,12 @@ internal sealed partial class HostAnalyzerManager ...@@ -101,8 +96,12 @@ internal sealed partial class HostAnalyzerManager
_compilerDiagnosticAnalyzerDescriptorMap = ImmutableDictionary<DiagnosticAnalyzer, HashSet<string>>.Empty; _compilerDiagnosticAnalyzerDescriptorMap = ImmutableDictionary<DiagnosticAnalyzer, HashSet<string>>.Empty;
_hostDiagnosticAnalyzerPackageNameMap = ImmutableDictionary<DiagnosticAnalyzer, string>.Empty; _hostDiagnosticAnalyzerPackageNameMap = ImmutableDictionary<DiagnosticAnalyzer, string>.Empty;
_descriptorCache = new ConditionalWeakTable<DiagnosticAnalyzer, IReadOnlyCollection<DiagnosticDescriptor>>(); _descriptorCache = new ConditionalWeakTable<DiagnosticAnalyzer, IReadOnlyCollection<DiagnosticDescriptor>>();
}
DiagnosticAnalyzerLogger.LogWorkspaceAnalyzers(hostAnalyzerReferences); // this is for testing
internal HostAnalyzerManager(ImmutableArray<AnalyzerReference> hostAnalyzerReferences, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) :
this(new Lazy<ImmutableArray<AnalyzerReference>>(() => hostAnalyzerReferences), new Lazy<ImmutableArray<HostDiagnosticAnalyzerPackage>>(() => ImmutableArray<HostDiagnosticAnalyzerPackage>.Empty), hostDiagnosticUpdateSource)
{
} }
/// <summary> /// <summary>
...@@ -357,7 +356,7 @@ public string GetDiagnosticAnalyzerPackageName(string language, DiagnosticAnalyz ...@@ -357,7 +356,7 @@ public string GetDiagnosticAnalyzerPackageName(string language, DiagnosticAnalyz
private ImmutableDictionary<string, string> CreateAnalyzerPathToPackageNameMap() private ImmutableDictionary<string, string> CreateAnalyzerPathToPackageNameMap()
{ {
var builder = ImmutableDictionary.CreateBuilder<string, string>(StringComparer.OrdinalIgnoreCase); var builder = ImmutableDictionary.CreateBuilder<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (var package in _hostDiagnosticAnalyzerPackages) foreach (var package in _hostDiagnosticAnalyzerPackages.Value)
{ {
if (string.IsNullOrEmpty(package.Name)) if (string.IsNullOrEmpty(package.Name))
{ {
...@@ -444,11 +443,11 @@ private bool CheckAnalyzerReferenceIdentity(AnalyzerReference reference) ...@@ -444,11 +443,11 @@ private bool CheckAnalyzerReferenceIdentity(AnalyzerReference reference)
} }
private static ImmutableArray<AnalyzerReference> CreateAnalyzerReferencesFromPackages( private static ImmutableArray<AnalyzerReference> CreateAnalyzerReferencesFromPackages(
IEnumerable<HostDiagnosticAnalyzerPackage> analyzerPackages, ImmutableArray<HostDiagnosticAnalyzerPackage> analyzerPackages,
HostAnalyzerReferenceDiagnosticReporter reporter, HostAnalyzerReferenceDiagnosticReporter reporter,
IAnalyzerAssemblyLoader hostAnalyzerAssemblyLoader) IAnalyzerAssemblyLoader hostAnalyzerAssemblyLoader)
{ {
if (analyzerPackages == null || analyzerPackages.IsEmpty()) if (analyzerPackages.IsEmpty)
{ {
return ImmutableArray<AnalyzerReference>.Empty; return ImmutableArray<AnalyzerReference>.Empty;
} }
...@@ -466,7 +465,10 @@ private bool CheckAnalyzerReferenceIdentity(AnalyzerReference reference) ...@@ -466,7 +465,10 @@ private bool CheckAnalyzerReferenceIdentity(AnalyzerReference reference)
builder.Add(reference); builder.Add(reference);
} }
return builder.ToImmutable(); var references = builder.ToImmutable();
DiagnosticAnalyzerLogger.LogWorkspaceAnalyzers(references);
return references;
} }
private static ImmutableDictionary<object, ImmutableArray<DiagnosticAnalyzer>> MergeDiagnosticAnalyzerMap( private static ImmutableDictionary<object, ImmutableArray<DiagnosticAnalyzer>> MergeDiagnosticAnalyzerMap(
......
...@@ -27,7 +27,7 @@ internal partial class VisualStudioWorkspaceDiagnosticAnalyzerProviderService : ...@@ -27,7 +27,7 @@ internal partial class VisualStudioWorkspaceDiagnosticAnalyzerProviderService :
private const string AnalyzerContentTypeName = "Microsoft.VisualStudio.Analyzer"; private const string AnalyzerContentTypeName = "Microsoft.VisualStudio.Analyzer";
private readonly ImmutableArray<HostDiagnosticAnalyzerPackage> _hostDiagnosticAnalyzerInfo; private readonly Lazy<ImmutableArray<HostDiagnosticAnalyzerPackage>> _hostDiagnosticAnalyzerInfo;
/// <summary> /// <summary>
/// Loader for VSIX-based analyzers. /// Loader for VSIX-based analyzers.
...@@ -54,12 +54,13 @@ internal partial class VisualStudioWorkspaceDiagnosticAnalyzerProviderService : ...@@ -54,12 +54,13 @@ internal partial class VisualStudioWorkspaceDiagnosticAnalyzerProviderService :
FailFast.OnFatalException(new Exception("extension manager can't be null")); FailFast.OnFatalException(new Exception("extension manager can't be null"));
} }
_hostDiagnosticAnalyzerInfo = GetHostAnalyzerPackagesWithName(extensionManager, assembly.GetType("Microsoft.VisualStudio.ExtensionManager.IExtensionContent")); _hostDiagnosticAnalyzerInfo = new Lazy<ImmutableArray<HostDiagnosticAnalyzerPackage>>(
() => GetHostAnalyzerPackagesWithName(extensionManager, assembly.GetType("Microsoft.VisualStudio.ExtensionManager.IExtensionContent")), isThreadSafe: true);
} }
public IEnumerable<HostDiagnosticAnalyzerPackage> GetHostDiagnosticAnalyzerPackages() public IEnumerable<HostDiagnosticAnalyzerPackage> GetHostDiagnosticAnalyzerPackages()
{ {
return _hostDiagnosticAnalyzerInfo; return _hostDiagnosticAnalyzerInfo.Value;
} }
public IAnalyzerAssemblyLoader GetAnalyzerAssemblyLoader() public IAnalyzerAssemblyLoader GetAnalyzerAssemblyLoader()
......
...@@ -50,9 +50,12 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.Diagnostics ...@@ -50,9 +50,12 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.Diagnostics
Dim dir = tempRoot.CreateDirectory Dim dir = tempRoot.CreateDirectory
Dim analyzerFile = DesktopTestHelpers.CreateCSharpAnalyzerAssemblyWithTestAnalyzer(dir, "TestAnalyzer") Dim analyzerFile = DesktopTestHelpers.CreateCSharpAnalyzerAssemblyWithTestAnalyzer(dir, "TestAnalyzer")
Dim analyzerPackage = New HostDiagnosticAnalyzerPackage("MyPackage", ImmutableArray.Create(analyzerFile.Path)) Dim analyzerPackage = New HostDiagnosticAnalyzerPackage("MyPackage", ImmutableArray.Create(analyzerFile.Path))
Dim analyzerPackages = SpecializedCollections.SingletonEnumerable(analyzerPackage) Dim analyzerPackages = ImmutableArray.Create(analyzerPackage)
Dim analyzerLoader = VisualStudioWorkspaceDiagnosticAnalyzerProviderService.GetLoader() Dim analyzerLoader = VisualStudioWorkspaceDiagnosticAnalyzerProviderService.GetLoader()
Dim hostAnalyzerManager = New HostAnalyzerManager(analyzerPackages, analyzerLoader, hostDiagnosticUpdateSource:=Nothing, primaryWorkspace:=Nothing) Dim hostAnalyzerManager = New HostAnalyzerManager(New Lazy(Of ImmutableArray(Of HostDiagnosticAnalyzerPackage))(
Function() analyzerPackages), analyzerLoader,
hostDiagnosticUpdateSource:=Nothing,
primaryWorkspace:=Nothing)
Dim analyzerReferenceMap = hostAnalyzerManager.GetHostDiagnosticAnalyzersPerReference(LanguageNames.CSharp) Dim analyzerReferenceMap = hostAnalyzerManager.GetHostDiagnosticAnalyzersPerReference(LanguageNames.CSharp)
Assert.Single(analyzerReferenceMap) Assert.Single(analyzerReferenceMap)
Dim analyzers = analyzerReferenceMap.Single().Value Dim analyzers = analyzerReferenceMap.Single().Value
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册