Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moved ISolutionCrawlerService down to workspace layer and made misc to use common default diagnostic analyzer service #11158

Merged
merged 5 commits into from
May 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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>();
Expand Down
2 changes: 1 addition & 1 deletion src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public void TestPreviewCreationDefault()
[Fact, Trait(Traits.Editor, Traits.Editors.Preview)]
public void TestPreviewCreationWithExplicitHostServices()
{
var assembly = typeof(ISolutionCrawlerRegistrationService).Assembly;
var assembly = typeof(ISolutionCrawlerService).Assembly;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ISolutionCrawlerRegisterationService moved down to workspace layer

using (var previewWorkspace = new PreviewWorkspace(MefHostServices.Create(MefHostServices.DefaultAssemblies.Concat(assembly))))
{
Assert.NotNull(previewWorkspace.CurrentSolution);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,22 @@
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)]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null indicates default

internal partial class DefaultDiagnosticAnalyzerService : IIncrementalAnalyzerProvider, IDiagnosticUpdateSource
{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defalut diagnostic analyzer service

private readonly IDiagnosticAnalyzerService _analyzerService;
private const int Syntax = 1;
private const int Semantic = 2;

[ImportingConstructor]
public MiscellaneousDiagnosticAnalyzerService(IDiagnosticAnalyzerService analyzerService, IDiagnosticUpdateSourceRegistrationService registrationService)
public DefaultDiagnosticAnalyzerService(IDiagnosticUpdateSourceRegistrationService registrationService)
{
_analyzerService = analyzerService;

registrationService.Register(this);
}

Expand All @@ -37,7 +35,7 @@ public IIncrementalAnalyzer CreateIncrementalAnalyzer(Workspace workspace)
return null;
}

return new SyntaxOnlyDiagnosticAnalyzer(this, workspace);
return new CompilerDiagnosticAnalyzer(this, workspace);
}

public event EventHandler<DiagnosticsUpdatedArgs> DiagnosticsUpdated;
Expand All @@ -62,21 +60,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;
}
Expand All @@ -87,25 +97,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 MiscUpdateArgsId(document.Id),
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 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;
}

Expand All @@ -114,16 +144,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)
Expand All @@ -136,11 +160,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;
Expand All @@ -150,45 +169,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());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 1 addition & 5 deletions src/Features/Core/Portable/Features.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,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" />
Expand Down Expand Up @@ -555,17 +556,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" />
Expand All @@ -574,7 +571,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" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -13,7 +14,7 @@
namespace Microsoft.CodeAnalysis.Notification
{
[Export(typeof(ISemanticChangeNotificationService)), Shared]
[ExportIncrementalAnalyzerProvider(WorkspaceKind.Host, WorkspaceKind.Interactive, WorkspaceKind.MiscellaneousFiles)]
[ExportIncrementalAnalyzerProvider(nameof(SemanticChangeNotificationService), workspaceKinds: null)]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made this analyzer to run for all workspaces.

internal class SemanticChangeNotificationService : ISemanticChangeNotificationService, IIncrementalAnalyzerProvider
{
public event EventHandler<Document> OpenedDocumentSemanticChanged;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -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
}
}
Expand Down
Loading