提交 7ae5d359 编写于 作者: H Heejae Chang

expose a way to enable compiler diagnostics to custom workspace

上级 c7de25cf
......@@ -12,9 +12,11 @@
namespace Microsoft.CodeAnalysis.Editor.Implementation.TodoComments
{
[Export(typeof(ITodoListProvider))]
[Shared]
[ExportIncrementalAnalyzerProvider(WorkspaceKind.Host, WorkspaceKind.Interactive, WorkspaceKind.MiscellaneousFiles)]
[Export(typeof(ITodoListProvider))]
[ExportIncrementalAnalyzerProvider(
name: nameof(TodoCommentIncrementalAnalyzerProvider),
workspaceKinds: new[] { WorkspaceKind.Host, WorkspaceKind.Interactive, WorkspaceKind.MiscellaneousFiles })]
internal class TodoCommentIncrementalAnalyzerProvider : IIncrementalAnalyzerProvider, ITodoListProvider
{
private static readonly ConditionalWeakTable<Workspace, TodoCommentIncrementalAnalyzer> s_analyzers = new ConditionalWeakTable<Workspace, TodoCommentIncrementalAnalyzer>();
......
......@@ -9,24 +9,26 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Options;
using Microsoft.CodeAnalysis.SolutionCrawler;
using Roslyn.Utilities;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.Diagnostics
{
[ExportIncrementalAnalyzerProvider(WorkspaceKind.MiscellaneousFiles)]
[Shared]
internal partial class MiscellaneousDiagnosticAnalyzerService : IIncrementalAnalyzerProvider, IDiagnosticUpdateSource
[ExportIncrementalAnalyzerProvider(WellKnownSolutionCrawlerAnalyzers.Diagnostic, workspaceKinds: null)]
internal partial class DefaultDiagnosticAnalyzerService : IIncrementalAnalyzerProvider, IDiagnosticUpdateSource
{
private const int Syntax = 1;
private const int Semantic = 2;
private readonly IDiagnosticAnalyzerService _analyzerService;
[ImportingConstructor]
public MiscellaneousDiagnosticAnalyzerService(IDiagnosticAnalyzerService analyzerService, IDiagnosticUpdateSourceRegistrationService registrationService)
public DefaultDiagnosticAnalyzerService(
IDiagnosticAnalyzerService analyzerService, IDiagnosticUpdateSourceRegistrationService registrationService)
{
_analyzerService = analyzerService;
registrationService.Register(this);
}
......@@ -37,7 +39,7 @@ public IIncrementalAnalyzer CreateIncrementalAnalyzer(Workspace workspace)
return null;
}
return new SyntaxOnlyDiagnosticAnalyzer(this, workspace);
return new CompilerDiagnosticAnalyzer(this, workspace);
}
public event EventHandler<DiagnosticsUpdatedArgs> DiagnosticsUpdated;
......@@ -62,21 +64,33 @@ internal void RaiseDiagnosticsUpdated(DiagnosticsUpdatedArgs state)
this.DiagnosticsUpdated?.Invoke(this, state);
}
private class SyntaxOnlyDiagnosticAnalyzer : IIncrementalAnalyzer
private class CompilerDiagnosticAnalyzer : IIncrementalAnalyzer
{
private readonly MiscellaneousDiagnosticAnalyzerService _service;
private readonly DefaultDiagnosticAnalyzerService _service;
private readonly Workspace _workspace;
public SyntaxOnlyDiagnosticAnalyzer(MiscellaneousDiagnosticAnalyzerService service, Workspace workspace)
public CompilerDiagnosticAnalyzer(DefaultDiagnosticAnalyzerService service, Workspace workspace)
{
_service = service;
_workspace = workspace;
}
public bool NeedsReanalysisOnOptionChanged(object sender, OptionChangedEventArgs e)
{
if (e.Option == InternalRuntimeDiagnosticOptions.Syntax ||
e.Option == InternalRuntimeDiagnosticOptions.Semantic)
{
return true;
}
return false;
}
public async Task AnalyzeSyntaxAsync(Document document, CancellationToken cancellationToken)
{
// if closed file diagnostic is off and document is not opened, then don't do anything
if (!CheckOptions(document))
// right now, there is no way to observe diagnostics for closed file.
if (!_workspace.IsDocumentOpen(document.Id) ||
!_workspace.Options.GetOption(InternalRuntimeDiagnosticOptions.Syntax))
{
return;
}
......@@ -87,25 +101,45 @@ public async Task AnalyzeSyntaxAsync(Document document, CancellationToken cancel
Contract.Requires(document.Project.Solution.Workspace == _workspace);
var diagnosticData = diagnostics == null ? ImmutableArray<DiagnosticData>.Empty : diagnostics.Select(d => DiagnosticData.Create(document, d)).ToImmutableArrayOrEmpty();
_service.RaiseDiagnosticsUpdated(
DiagnosticsUpdatedArgs.DiagnosticsCreated(new DefaultUpdateArgsId(_workspace.Kind, Syntax, document.Id),
_workspace, document.Project.Solution, document.Project.Id, document.Id, diagnosticData));
}
public async Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, CancellationToken cancellationToken)
{
// right now, there is no way to observe diagnostics for closed file.
if (!_workspace.IsDocumentOpen(document.Id) ||
!_workspace.Options.GetOption(InternalRuntimeDiagnosticOptions.Semantic))
{
return;
}
var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var diagnostics = model.GetMethodBodyDiagnostics(span: null, cancellationToken: cancellationToken).Concat(
model.GetDeclarationDiagnostics(span: null, cancellationToken: cancellationToken));
Contract.Requires(document.Project.Solution.Workspace == _workspace);
var diagnosticData = diagnostics == null ? ImmutableArray<DiagnosticData>.Empty : diagnostics.Select(d => DiagnosticData.Create(document, d)).ToImmutableArrayOrEmpty();
_service.RaiseDiagnosticsUpdated(
DiagnosticsUpdatedArgs.DiagnosticsCreated(new MiscUpdateArgsId(document.Id),
DiagnosticsUpdatedArgs.DiagnosticsCreated(new DefaultUpdateArgsId(_workspace.Kind, Semantic, document.Id),
_workspace, document.Project.Solution, document.Project.Id, document.Id, diagnosticData));
}
public void RemoveDocument(DocumentId documentId)
{
// a file is removed from misc project
RaiseEmptyDiagnosticUpdated(documentId);
RaiseEmptyDiagnosticUpdated(Syntax, documentId);
RaiseEmptyDiagnosticUpdated(Semantic, documentId);
}
public Task DocumentResetAsync(Document document, CancellationToken cancellationToken)
{
// no closed file diagnostic and file is not opened, remove any existing diagnostics
if (!CheckOptions(document))
{
RaiseEmptyDiagnosticUpdated(document.Id);
}
RemoveDocument(document.Id);
return SpecializedTasks.EmptyTask;
}
......@@ -114,16 +148,10 @@ public Task DocumentCloseAsync(Document document, CancellationToken cancellation
return DocumentResetAsync(document, cancellationToken);
}
private void RaiseEmptyDiagnosticUpdated(DocumentId documentId)
private void RaiseEmptyDiagnosticUpdated(int kind, DocumentId documentId)
{
_service.RaiseDiagnosticsUpdated(DiagnosticsUpdatedArgs.DiagnosticsRemoved(
ValueTuple.Create(this, documentId), _workspace, null, documentId.ProjectId, documentId));
}
// method we don't care. misc project only supports syntax errors
public Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, CancellationToken cancellationToken)
{
return SpecializedTasks.EmptyTask;
new DefaultUpdateArgsId(_workspace.Kind, kind, documentId), _workspace, null, documentId.ProjectId, documentId));
}
public Task AnalyzeProjectAsync(Project project, bool semanticsChanged, CancellationToken cancellationToken)
......@@ -136,11 +164,6 @@ public Task DocumentOpenAsync(Document document, CancellationToken cancellationT
return SpecializedTasks.EmptyTask;
}
public bool NeedsReanalysisOnOptionChanged(object sender, OptionChangedEventArgs e)
{
return false;
}
public Task NewSolutionSnapshotAsync(Solution solution, CancellationToken cancellationToken)
{
return SpecializedTasks.EmptyTask;
......@@ -150,45 +173,31 @@ public void RemoveProject(ProjectId projectId)
{
}
private bool CheckOptions(Document document)
private class DefaultUpdateArgsId : BuildToolId.Base<int, DocumentId>, ISupportLiveUpdate
{
if (ServiceFeatureOnOffOptions.IsClosedFileDiagnosticsEnabled(_workspace, document.Project.Language) &&
_workspace.Options.GetOption(RuntimeOptions.FullSolutionAnalysis))
{
return true;
}
return document.IsOpen();
}
private readonly string _workspaceKind;
private class MiscUpdateArgsId : BuildToolId.Base<DocumentId>, ISupportLiveUpdate
{
public MiscUpdateArgsId(DocumentId documentId) : base(documentId)
public DefaultUpdateArgsId(string workspaceKind, int type, DocumentId documentId) : base(type, documentId)
{
_workspaceKind = workspaceKind;
}
public override string BuildTool
{
get
{
return PredefinedBuildTools.Live;
}
}
public override string BuildTool => PredefinedBuildTools.Live;
public override bool Equals(object obj)
{
var other = obj as MiscUpdateArgsId;
var other = obj as DefaultUpdateArgsId;
if (other == null)
{
return false;
}
return base.Equals(obj);
return _workspaceKind == other._workspaceKind && base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
return Hash.Combine(_workspaceKind.GetHashCode(), base.GetHashCode());
}
}
}
......
......@@ -15,7 +15,9 @@
namespace Microsoft.CodeAnalysis.Diagnostics
{
[ExportIncrementalAnalyzerProvider(highPriorityForActiveFile: true, workspaceKinds: new string[] { WorkspaceKind.Host, WorkspaceKind.Interactive })]
[ExportIncrementalAnalyzerProvider(
highPriorityForActiveFile: true, name: WellKnownSolutionCrawlerAnalyzers.Diagnostic,
workspaceKinds: new string[] { WorkspaceKind.Host, WorkspaceKind.Interactive })]
internal partial class DiagnosticAnalyzerService : IIncrementalAnalyzerProvider
{
private readonly ConditionalWeakTable<Workspace, BaseDiagnosticIncrementalAnalyzer> _map;
......
......@@ -221,6 +221,7 @@
<Compile Include="Diagnostics\HostDiagnosticAnalyzerPackage.cs" />
<Compile Include="Diagnostics\IDiagnosticUpdateSourceRegistrationService.cs" />
<Compile Include="Diagnostics\InternalDiagnosticsOptionsProvider.cs" />
<Compile Include="Diagnostics\DefaultDiagnosticAnalyzerService.cs" />
<Compile Include="Diagnostics\PredefinedBuildTools.cs" />
<Compile Include="Diagnostics\DiagnosticAnalyzerService_BuildSynchronization.cs" />
<Compile Include="Diagnostics\BuildToolId.cs" />
......@@ -529,17 +530,13 @@
<Compile Include="Snippets\SnippetInfo.cs" />
<Compile Include="SolutionCrawler\AbstractDocumentDifferenceService.cs" />
<Compile Include="SolutionCrawler\AggregateIncrementalAnalyzer.cs" />
<Compile Include="SolutionCrawler\Extensibility\ExportIncrementalAnalyzerProviderAttribute.cs" />
<Compile Include="SolutionCrawler\Extensibility\ExportPerLanguageIncrementalAnalyzerProviderAttribute.cs" />
<Compile Include="SolutionCrawler\Extensibility\IIncrementalAnalyzerProvider.cs" />
<Compile Include="SolutionCrawler\Extensibility\IncrementalAnalyzerProviderMetadata.cs" />
<Compile Include="SolutionCrawler\Extensibility\IPerLanguageIncrementalAnalyzerProvider.cs" />
<Compile Include="SolutionCrawler\Extensibility\PerLanguageIncrementalAnalyzerProviderMetadata.cs" />
<Compile Include="SolutionCrawler\Extensions.cs" />
<Compile Include="SolutionCrawler\IdleProcessor.cs" />
<Compile Include="SolutionCrawler\IDocumentDifferenceService.cs" />
<Compile Include="SolutionCrawler\IDocumentTrackingService.cs" />
<Compile Include="SolutionCrawler\IIncrementalAnalyzer.cs" />
<Compile Include="SolutionCrawler\IncrementalAnalyzerBase.cs" />
<Compile Include="SolutionCrawler\IncrementalAnalyzerProviderBase.cs" />
<Compile Include="SolutionCrawler\InternalSolutionCrawlerOptionsProvider.cs" />
......@@ -548,7 +545,6 @@
<Compile Include="SolutionCrawler\ISolutionCrawlerProgressReporter.cs" />
<Compile Include="SolutionCrawler\ISolutionCrawlerService.cs" />
<Compile Include="SolutionCrawler\IWorkCoordinatorPriorityService.cs" />
<Compile Include="SolutionCrawler\ISolutionCrawlerRegistrationService.cs" />
<Compile Include="SolutionCrawler\PredefinedInvocationReasons.cs" />
<Compile Include="SolutionCrawler\SolutionCrawlerLogger.cs" />
<Compile Include="SolutionCrawler\InternalSolutionCrawlerOptions.cs" />
......
......@@ -33,7 +33,7 @@ namespace Microsoft.CodeAnalysis.IncrementalCaches
/// once it is fully indexed, then total results will be returned.
/// </summary>
[Shared]
[ExportIncrementalAnalyzerProvider(WorkspaceKind.Host)]
[ExportIncrementalAnalyzerProvider(nameof(SymbolTreeInfoIncrementalAnalyzerProvider), new[] { WorkspaceKind.Host })]
[ExportWorkspaceServiceFactory(typeof(ISymbolTreeInfoCacheService))]
internal class SymbolTreeInfoIncrementalAnalyzerProvider : IIncrementalAnalyzerProvider, IWorkspaceServiceFactory
{
......
......@@ -8,7 +8,7 @@
namespace Microsoft.CodeAnalysis.IncrementalCaches
{
[ExportIncrementalAnalyzerProvider(WorkspaceKind.Host), Shared]
[ExportIncrementalAnalyzerProvider(nameof(SyntaxTreeInfoIncrementalAnalyzerProvider), new[] { WorkspaceKind.Host }), Shared]
internal class SyntaxTreeInfoIncrementalAnalyzerProvider : IIncrementalAnalyzerProvider
{
public IIncrementalAnalyzer CreateIncrementalAnalyzer(Workspace workspace)
......
......@@ -3,6 +3,7 @@
using System;
using System.Collections.Concurrent;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Options;
......@@ -13,7 +14,7 @@
namespace Microsoft.CodeAnalysis.Notification
{
[Export(typeof(ISemanticChangeNotificationService)), Shared]
[ExportIncrementalAnalyzerProvider(WorkspaceKind.Host, WorkspaceKind.Interactive, WorkspaceKind.MiscellaneousFiles)]
[ExportIncrementalAnalyzerProvider(nameof(SemanticChangeNotificationService), workspaceKinds: null)]
internal class SemanticChangeNotificationService : ISemanticChangeNotificationService, IIncrementalAnalyzerProvider
{
public event EventHandler<Document> OpenedDocumentSemanticChanged;
......@@ -38,17 +39,36 @@ public NotificationService(SemanticChangeNotificationService owner)
_owner = owner;
}
public Task DocumentResetAsync(Document document, CancellationToken cancellationToken)
public void RemoveDocument(DocumentId documentId)
{
// now it runs for all workspace, make sure we get rid of entry from the map
// as soon as it is not needed.
// this whole thing will go away when workspace disable itself from solution crawler.
VersionStamp unused;
_map.TryRemove(document.Id, out unused);
_map.TryRemove(documentId, out unused);
}
public void RemoveProject(ProjectId projectId)
{
foreach (var documentId in _map.Keys.Where(id => id.ProjectId == projectId).ToArray())
{
RemoveDocument(documentId);
}
}
public Task DocumentCloseAsync(Document document, CancellationToken cancellationToken)
{
return DocumentResetAsync(document, cancellationToken);
}
public Task DocumentResetAsync(Document document, CancellationToken cancellationToken)
{
RemoveDocument(document.Id);
return SpecializedTasks.EmptyTask;
}
public bool NeedsReanalysisOnOptionChanged(object sender, OptionChangedEventArgs e)
{
// TODO: Is this correct?
return false;
}
......@@ -81,11 +101,6 @@ public Task DocumentOpenAsync(Document document, CancellationToken cancellationT
return SpecializedTasks.EmptyTask;
}
public Task DocumentCloseAsync(Document document, CancellationToken cancellationToken)
{
return SpecializedTasks.EmptyTask;
}
public Task NewSolutionSnapshotAsync(Solution solution, CancellationToken cancellationToken)
{
return SpecializedTasks.EmptyTask;
......@@ -101,13 +116,6 @@ public Task AnalyzeProjectAsync(Project project, bool semanticsChanged, Cancella
return SpecializedTasks.EmptyTask;
}
public void RemoveDocument(DocumentId documentId)
{
}
public void RemoveProject(ProjectId projectId)
{
}
#endregion
}
}
......
......@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
......@@ -16,11 +17,13 @@ namespace Microsoft.CodeAnalysis.SolutionCrawler
[ExportWorkspaceService(typeof(ISolutionCrawlerRegistrationService), ServiceLayer.Host), Shared]
internal partial class SolutionCrawlerRegistrationService : ISolutionCrawlerRegistrationService
{
private const string Default = "*";
private readonly object _gate;
private readonly SolutionCrawlerProgressReporter _progressReporter;
private readonly IAsynchronousOperationListener _listener;
private readonly ImmutableArray<Lazy<IIncrementalAnalyzerProvider, IncrementalAnalyzerProviderMetadata>> _analyzerProviders;
private readonly ImmutableDictionary<string, ImmutableArray<Lazy<IIncrementalAnalyzerProvider, IncrementalAnalyzerProviderMetadata>>> _analyzerProviders;
private readonly Dictionary<Workspace, WorkCoordinator> _documentWorkCoordinatorMap;
[ImportingConstructor]
......@@ -30,7 +33,9 @@ internal partial class SolutionCrawlerRegistrationService : ISolutionCrawlerRegi
{
_gate = new object();
_analyzerProviders = analyzerProviders.ToImmutableArray();
_analyzerProviders = analyzerProviders.GroupBy(kv => kv.Metadata.Name).ToImmutableDictionary(g => g.Key, g => g.ToImmutableArray());
AssertAnalyzerProviders(_analyzerProviders);
_documentWorkCoordinatorMap = new Dictionary<Workspace, WorkCoordinator>(ReferenceEqualityComparer.Instance);
_listener = new AggregateAsynchronousOperationListener(asyncListeners, FeatureAttribute.SolutionCrawler);
......@@ -51,7 +56,7 @@ public void Register(Workspace workspace)
var coordinator = new WorkCoordinator(
_listener,
_analyzerProviders.Where(l => l.Metadata.WorkspaceKinds.Any(wk => wk == workspace.Kind)),
GetAnalyzerProviders(workspace),
new Registration(correlationId, workspace, _progressReporter));
_documentWorkCoordinatorMap.Add(workspace, coordinator);
......@@ -127,6 +132,99 @@ internal void WaitUntilCompletion_ForTestingPurposesOnly(Workspace workspace)
}
}
private IEnumerable<Lazy<IIncrementalAnalyzerProvider, IncrementalAnalyzerProviderMetadata>> GetAnalyzerProviders(Workspace workspace)
{
Lazy<IIncrementalAnalyzerProvider, IncrementalAnalyzerProviderMetadata> lazyProvider;
foreach (var kv in _analyzerProviders)
{
var lazyProviders = kv.Value;
// try get provider for the specific workspace kind
if (TryGetProvider(workspace.Kind, lazyProviders, out lazyProvider))
{
yield return lazyProvider;
continue;
}
// try get default provider
if (TryGetProvider(Default, lazyProviders, out lazyProvider))
{
yield return lazyProvider;
}
}
}
private bool TryGetProvider(
string kind,
ImmutableArray<Lazy<IIncrementalAnalyzerProvider, IncrementalAnalyzerProviderMetadata>> lazyProviders,
out Lazy<IIncrementalAnalyzerProvider, IncrementalAnalyzerProviderMetadata> lazyProvider)
{
// set out param
lazyProvider = null;
// try find provider for specific workspace kind
if (kind != Default)
{
foreach (var provider in lazyProviders)
{
if (provider.Metadata.WorkspaceKinds?.Any(wk => wk == kind) == true)
{
lazyProvider = provider;
return true;
}
}
return false;
}
// try find default provider
foreach (var provider in lazyProviders)
{
if (IsDefaultProvider(provider.Metadata))
{
lazyProvider = provider;
return true;
}
return false;
}
return false;
}
[Conditional("DEBUG")]
private static void AssertAnalyzerProviders(
ImmutableDictionary<string, ImmutableArray<Lazy<IIncrementalAnalyzerProvider, IncrementalAnalyzerProviderMetadata>>> analyzerProviders)
{
#if DEBUG
// make sure there is duplicated provider defined for same workspace.
var set = new HashSet<string>();
foreach (var kv in analyzerProviders)
{
foreach (var lazyProvider in kv.Value)
{
if (IsDefaultProvider(lazyProvider.Metadata))
{
Contract.Requires(set.Add(Default));
continue;
}
foreach (var kind in lazyProvider.Metadata.WorkspaceKinds)
{
Contract.Requires(set.Add(kind));
}
}
set.Clear();
}
#endif
}
private static bool IsDefaultProvider(IncrementalAnalyzerProviderMetadata providerMetadata)
{
return providerMetadata.WorkspaceKinds == null || providerMetadata.WorkspaceKinds.Length == 0;
}
private class Registration
{
public readonly int CorrelationId;
......
......@@ -75,9 +75,7 @@ private IDiagnosticAnalyzerService GetDiagnosticAnalyzerService(IEnumerable<Lazy
private static ImmutableArray<IIncrementalAnalyzer> GetActiveFileIncrementalAnalyzers(
Registration registration, IEnumerable<Lazy<IIncrementalAnalyzerProvider, IncrementalAnalyzerProviderMetadata>> providers)
{
var matchingProviders = providers.Where(p => p.Metadata.HighPriorityForActiveFile && p.Metadata.WorkspaceKinds.Contains(registration.Workspace.Kind));
var orderedAnalyzers = GetOrderedAnalyzers(registration, matchingProviders);
var orderedAnalyzers = GetOrderedAnalyzers(registration, providers.Where(p => p.Metadata.HighPriorityForActiveFile));
SolutionCrawlerLogger.LogActiveFileAnalyzers(registration.CorrelationId, registration.Workspace, orderedAnalyzers);
return orderedAnalyzers;
......@@ -86,9 +84,7 @@ private IDiagnosticAnalyzerService GetDiagnosticAnalyzerService(IEnumerable<Lazy
private static ImmutableArray<IIncrementalAnalyzer> GetIncrementalAnalyzers(
Registration registration, IEnumerable<Lazy<IIncrementalAnalyzerProvider, IncrementalAnalyzerProviderMetadata>> providers)
{
var matchingProviders = providers.Where(p => p.Metadata.WorkspaceKinds.Contains(registration.Workspace.Kind));
var orderedAnalyzers = GetOrderedAnalyzers(registration, matchingProviders);
var orderedAnalyzers = GetOrderedAnalyzers(registration, providers);
SolutionCrawlerLogger.LogAnalyzers(registration.CorrelationId, registration.Workspace, orderedAnalyzers);
return orderedAnalyzers;
......
......@@ -8,7 +8,9 @@
namespace Microsoft.VisualStudio.LanguageServices.Implementation.CompilationErrorTelemetry
{
[ExportIncrementalAnalyzerProvider(WorkspaceKind.Host), Shared]
// Disabled compilation error telemetry per discussion with .net team.
// tracking bug - https://github.com/dotnet/roslyn/issues/11133
// [ExportIncrementalAnalyzerProvider(WorkspaceKind.Host), Shared]
internal class CompilationErrorTelemetryIncrementalAnalyzer : IncrementalAnalyzerProviderBase
{
public const string Name = "CompilationErrorTelemetryIncrementalAnalyzer";
......
......@@ -8,7 +8,7 @@
namespace Microsoft.VisualStudio.LanguageServices.Implementation.DesignerAttribute
{
[ExportIncrementalAnalyzerProvider(WorkspaceKind.Host), Shared]
[ExportIncrementalAnalyzerProvider(Name, new[] { WorkspaceKind.Host }), Shared]
internal class DesignerAttributeIncrementalAnalyzerProvider : IncrementalAnalyzerProviderBase
{
public const string Name = "DesignerAttributeIncrementalAnalyzerProvider";
......
......@@ -43,9 +43,6 @@ internal sealed partial class MiscellaneousFilesWorkspace : Workspace, IVsRunnin
private readonly ImmutableArray<MetadataReference> _metadataReferences;
private uint _runningDocumentTableEventsCookie;
// document worker coordinator
private ISolutionCrawlerRegistrationService _registrationService;
[ImportingConstructor]
public MiscellaneousFilesWorkspace(
IVsEditorAdaptersFactoryService editorAdaptersFactoryService,
......@@ -53,7 +50,7 @@ internal sealed partial class MiscellaneousFilesWorkspace : Workspace, IVsRunnin
SaveEventsService saveEventsService,
VisualStudioWorkspace visualStudioWorkspace,
SVsServiceProvider serviceProvider) :
base(visualStudioWorkspace.Services.HostServices, "MiscellaneousFiles")
base(visualStudioWorkspace.Services.HostServices, WorkspaceKind.MiscellaneousFiles)
{
_editorAdaptersFactoryService = editorAdaptersFactoryService;
_fileTrackingMetadataAsSourceService = fileTrackingMetadataAsSourceService;
......@@ -74,32 +71,12 @@ public void RegisterLanguage(Guid languageGuid, string languageName, string scri
internal void StartSolutionCrawler()
{
if (_registrationService == null)
{
lock (this)
{
if (_registrationService == null)
{
_registrationService = this.Services.GetService<ISolutionCrawlerRegistrationService>();
_registrationService.Register(this);
}
}
}
DiagnosticProvider.Enable(this, DiagnosticProvider.Options.Syntax);
}
internal void StopSolutionCrawler()
{
if (_registrationService != null)
{
lock (this)
{
if (_registrationService != null)
{
_registrationService.Unregister(this, blockingShutdown: true);
_registrationService = null;
}
}
}
DiagnosticProvider.Disable(this);
}
private LanguageInformation TryGetLanguageInformation(string filename)
......@@ -255,7 +232,7 @@ private void Registration_WorkspaceChanged(object sender, EventArgs e)
}
}
else
{
{
// We should now claim this
AttachToDocument(docCookie, moniker);
}
......
......@@ -16,7 +16,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionSize
/// Track approximate solution size.
/// </summary>
[Export]
[ExportIncrementalAnalyzerProvider(WorkspaceKind.Host), Shared]
[ExportIncrementalAnalyzerProvider(nameof(SolutionSizeTracker), new[] { WorkspaceKind.Host }), Shared]
internal class SolutionSizeTracker : IIncrementalAnalyzerProvider
{
private readonly IncrementalAnalyzer _tracker = new IncrementalAnalyzer();
......
......@@ -95,7 +95,6 @@
<Compile Include="Implementation\ProjectSystem\MetadataReferences\VisualStudioFrameworkAssemblyPathResolverFactory.cs" />
<Compile Include="Implementation\ProjectSystem\RuleSets\RuleSetEventHandler.cs" />
<Compile Include="Implementation\ProjectSystem\VisualStudioProjectTracker_IVsSolutionWorkingFoldersEvents.cs" />
<Compile Include="Implementation\Diagnostics\MiscellaneousDiagnosticAnalyzerService.cs" />
<Compile Include="Implementation\Extensions\VisualStudioWorkspaceImplExtensions.cs" />
<Compile Include="Implementation\Options\AbstractLanguageSettingsSerializer.cs" />
<Compile Include="Implementation\Options\ExportLanguageSpecificOptionSerializerAttribute.cs" />
......
......@@ -16,7 +16,7 @@
namespace Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel
{
[ExportIncrementalAnalyzerProvider(WorkspaceKind.Host), Shared]
[ExportIncrementalAnalyzerProvider(nameof(CodeModelIncrementalAnalyzerProvider), new[] { WorkspaceKind.Host }), Shared]
internal class CodeModelIncrementalAnalyzerProvider : IIncrementalAnalyzerProvider
{
private readonly IAsynchronousOperationListener _listener;
......
......@@ -18,14 +18,14 @@ Imports Roslyn.Test.Utilities
Imports Roslyn.Utilities
Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.Diagnostics
Public Class MiscDiagnosticUpdateSourceTests
Public Class DefaultDiagnosticUpdateSourceTests
<WpfFact>
Public Async Function TestMiscSquiggles() As Task
Dim code = <code>
class 123 { }
</code>
Using workspace = Await TestWorkspace.CreateCSharpAsync(code.ToString())
Dim miscService = New MiscellaneousDiagnosticAnalyzerService(
Dim miscService = New DefaultDiagnosticAnalyzerService(
New TestDiagnosticAnalyzerService(DiagnosticExtensions.GetCompilerDiagnosticAnalyzersMap()),
New MockDiagnosticUpdateSourceRegistrationService())
......@@ -68,7 +68,7 @@ class 123 { }
class 123 { }
</code>
Using workspace = Await TestWorkspace.CreateCSharpAsync(code.ToString())
Dim miscService = New MiscellaneousDiagnosticAnalyzerService(
Dim miscService = New DefaultDiagnosticAnalyzerService(
New TestDiagnosticAnalyzerService(DiagnosticExtensions.GetCompilerDiagnosticAnalyzersMap()),
New MockDiagnosticUpdateSourceRegistrationService())
......@@ -93,7 +93,7 @@ Class 123
End Class
</code>
Using workspace = Await TestWorkspace.CreateVisualBasicAsync(code.ToString())
Dim miscService = New MiscellaneousDiagnosticAnalyzerService(
Dim miscService = New DefaultDiagnosticAnalyzerService(
New TestDiagnosticAnalyzerService(DiagnosticExtensions.GetCompilerDiagnosticAnalyzersMap()),
New MockDiagnosticUpdateSourceRegistrationService())
......
......@@ -295,7 +295,7 @@
<Compile Include="Debugging\VisualBasicBreakpointResolutionServiceTests.vb" />
<Compile Include="Diagnostics\DiagnosticTableDataSourceTests.vb" />
<Compile Include="Diagnostics\ExternalDiagnosticUpdateSourceTests.vb" />
<Compile Include="Diagnostics\MiscDiagnosticUpdateSourceTests.vb" />
<Compile Include="Diagnostics\DefaultDiagnosticUpdateSourceTests.vb" />
<Compile Include="Diagnostics\MockExtensionManager.vb" />
<Compile Include="Diagnostics\TestTableManagerProvider.vb" />
<Compile Include="Diagnostics\TodoListTableDataSourceTests.vb" />
......
// 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.Diagnostics;
using Microsoft.CodeAnalysis.SolutionCrawler;
namespace Microsoft.CodeAnalysis
{
/// <summary>
/// Provide a way for users to turn on and off analyzing workspace for compiler diagnostics
/// </summary>
public static class DiagnosticProvider
{
public static void Enable(Workspace workspace, Options options)
{
var service = workspace.Services.GetService<ISolutionCrawlerRegistrationService>();
workspace.Options = GetOptions(workspace, options);
service.Register(workspace);
}
public static void Disable(Workspace workspace)
{
var service = workspace.Services.GetService<ISolutionCrawlerRegistrationService>();
service.Unregister(workspace);
}
private static CodeAnalysis.Options.OptionSet GetOptions(Workspace workspace, Options options)
{
return workspace.Options
.WithChangedOption(InternalRuntimeDiagnosticOptions.Syntax, (options & Options.Syntax) == Options.Syntax)
.WithChangedOption(InternalRuntimeDiagnosticOptions.Semantic, (options & Options.Semantic) == Options.Semantic);
}
[Flags]
public enum Options
{
/// <summary>
/// Include syntax errors
/// </summary>
Syntax = 0x01,
/// <summary>
/// Include semantic errors
/// </summary>
Semantic = 0x02,
}
}
}
// 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 Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.Diagnostics
{
internal static class InternalRuntimeDiagnosticOptions
{
public const string OptionName = "RuntimeDiagnostic";
public static readonly Option<bool> Syntax = new Option<bool>(OptionName, "Syntax", defaultValue: true);
public static readonly Option<bool> Semantic = new Option<bool>(OptionName, "Semantic", defaultValue: true);
}
}
abstract Microsoft.CodeAnalysis.Editing.SyntaxGenerator.NameOfExpression(Microsoft.CodeAnalysis.SyntaxNode expression) -> Microsoft.CodeAnalysis.SyntaxNode
\ No newline at end of file
Microsoft.CodeAnalysis.DiagnosticProvider
Microsoft.CodeAnalysis.DiagnosticProvider.Options
Microsoft.CodeAnalysis.DiagnosticProvider.Options.Semantic = 2 -> Microsoft.CodeAnalysis.DiagnosticProvider.Options
Microsoft.CodeAnalysis.DiagnosticProvider.Options.Syntax = 1 -> Microsoft.CodeAnalysis.DiagnosticProvider.Options
abstract Microsoft.CodeAnalysis.Editing.SyntaxGenerator.NameOfExpression(Microsoft.CodeAnalysis.SyntaxNode expression) -> Microsoft.CodeAnalysis.SyntaxNode
static Microsoft.CodeAnalysis.DiagnosticProvider.Disable(Microsoft.CodeAnalysis.Workspace workspace) -> void
static Microsoft.CodeAnalysis.DiagnosticProvider.Enable(Microsoft.CodeAnalysis.Workspace workspace, Microsoft.CodeAnalysis.DiagnosticProvider.Options options) -> void
\ No newline at end of file
......@@ -10,22 +10,24 @@ namespace Microsoft.CodeAnalysis.SolutionCrawler
internal class ExportIncrementalAnalyzerProviderAttribute : ExportAttribute
{
public bool HighPriorityForActiveFile { get; }
public string Name { get; }
public string[] WorkspaceKinds { get; }
public ExportIncrementalAnalyzerProviderAttribute(params string[] workspaceKinds)
public ExportIncrementalAnalyzerProviderAttribute(string name, string[] workspaceKinds)
: base(typeof(IIncrementalAnalyzerProvider))
{
if (workspaceKinds == null)
if (name == null)
{
throw new ArgumentNullException(nameof(workspaceKinds));
throw new ArgumentNullException(nameof(name));
}
this.WorkspaceKinds = workspaceKinds;
this.Name = name;
this.HighPriorityForActiveFile = false;
}
public ExportIncrementalAnalyzerProviderAttribute(bool highPriorityForActiveFile, params string[] workspaceKinds)
: this(workspaceKinds)
public ExportIncrementalAnalyzerProviderAttribute(bool highPriorityForActiveFile, string name, string[] workspaceKinds)
: this(name, workspaceKinds)
{
this.HighPriorityForActiveFile = highPriorityForActiveFile;
}
......
......@@ -8,11 +8,13 @@ namespace Microsoft.CodeAnalysis.SolutionCrawler
internal class IncrementalAnalyzerProviderMetadata
{
public bool HighPriorityForActiveFile { get; }
public string Name { get; }
public string[] WorkspaceKinds { get; }
public IncrementalAnalyzerProviderMetadata(IDictionary<string, object> data)
{
this.HighPriorityForActiveFile = (bool)data.GetValueOrDefault("HighPriorityForActiveFile");
this.Name = (string)data.GetValueOrDefault("Name");
this.WorkspaceKinds = (string[])data.GetValueOrDefault("WorkspaceKinds");
}
}
......
// 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.Composition;
using Microsoft.CodeAnalysis.Host.Mef;
namespace Microsoft.CodeAnalysis.SolutionCrawler
{
/// <summary>
/// null implementation of the service. it doesn't do anything since there is no way to observe
/// its impact in this layer.
/// </summary>
[ExportWorkspaceService(typeof(ISolutionCrawlerRegistrationService), ServiceLayer.Default), Shared]
internal partial class NullSolutionCrawlerRegistrationService : ISolutionCrawlerRegistrationService
{
public void Register(Workspace workspace)
{
// base implementation do nothing.
}
public void Unregister(Workspace workspace, bool blockingShutdown = false)
{
// base implementation do nothing.
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.CodeAnalysis.SolutionCrawler
{
internal static class WellKnownSolutionCrawlerAnalyzers
{
public const string Diagnostic = nameof(Diagnostic);
}
}
......@@ -334,8 +334,15 @@
<Compile Include="CodeGeneration\CodeGenerationSymbolFactory.cs" />
<Compile Include="CodeGeneration\CodeGenerator.cs" />
<Compile Include="Diagnostics\DiagnosticData.cs" />
<Compile Include="Diagnostics\DiagnosticProvider.cs" />
<Compile Include="Diagnostics\Extensions.cs" />
<Compile Include="Diagnostics\InternalDiagnosticsOptions.cs" />
<Compile Include="Diagnostics\InternalRuntimeDiagnosticOptions.cs" />
<Compile Include="SolutionCrawler\ExportIncrementalAnalyzerProviderAttribute.cs" />
<Compile Include="SolutionCrawler\IIncrementalAnalyzer.cs" />
<Compile Include="SolutionCrawler\IIncrementalAnalyzerProvider.cs" />
<Compile Include="SolutionCrawler\IncrementalAnalyzerProviderMetadata.cs" />
<Compile Include="SolutionCrawler\ISolutionCrawlerRegistrationService.cs" />
<Compile Include="Diagnostics\IWorkspaceVenusSpanMappingService.cs" />
<Compile Include="Diagnostics\WellKnownDiagnosticPropertyNames.cs" />
<Compile Include="Editing\DeclarationKind.cs" />
......@@ -398,6 +405,8 @@
<Compile Include="Packaging\IPackageSearchService.cs" />
<Compile Include="FindSymbols\SymbolTree\ISymbolTreeInfoCacheService.cs" />
<Compile Include="FindSymbols\FindReferences\MetadataUnifyingEquivalenceComparer.cs" />
<Compile Include="SolutionCrawler\NullSolutionCrawlerRegisterationService.cs" />
<Compile Include="SolutionCrawler\WellKnownSolutionCrawlerAnalyzers.cs" />
<Compile Include="Utilities\ArraySlice.cs" />
<Compile Include="Utilities\BKTree.cs" />
<Compile Include="FindSymbols\SyntaxTree\AbstractSyntaxTreeInfo.cs" />
......@@ -978,4 +987,4 @@
<ImportGroup Label="Targets">
<Import Project="..\..\..\..\build\Targets\VSL.Imports.targets" />
</ImportGroup>
</Project>
</Project>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册