diff --git a/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs b/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs index ef27a6b5cf86751eeace202521abaf555eceb38a..31ab76e1655c69169e5fb4af9f429609414e8b28 100644 --- a/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs +++ b/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs @@ -805,10 +805,19 @@ public async Task ProgressReporterTest() // set up events bool started = false; - reporter.Started += (o, a) => { started = true; }; - bool stopped = false; - reporter.Stopped += (o, a) => { stopped = true; }; + + reporter.ProgressChanged += (o, s) => + { + if (s) + { + started = true; + } + else + { + stopped = true; + } + }; var registrationService = workspace.Services.GetService(); registrationService.Register(workspace); diff --git a/src/Features/Core/Portable/Diagnostics/IDiagnosticService.cs b/src/Features/Core/Portable/Diagnostics/IDiagnosticService.cs index 46b811b106f53c0a5cff769c10a874de4a240c89..5bf9bb0b6210dbd46b7a657da0a0bd3f08dc629f 100644 --- a/src/Features/Core/Portable/Diagnostics/IDiagnosticService.cs +++ b/src/Features/Core/Portable/Diagnostics/IDiagnosticService.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Threading; using Microsoft.CodeAnalysis.Common; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Diagnostics { @@ -11,6 +12,9 @@ internal interface IDiagnosticService { /// /// Event to get notified as new diagnostics are discovered by IDiagnosticUpdateSource + /// + /// Notifications for this event are serialized to preserve order. + /// However, individual event notifications may occur on any thread. /// event EventHandler DiagnosticsUpdated; diff --git a/src/Features/Core/Portable/SolutionCrawler/ISolutionCrawlerProgressReporter.cs b/src/Features/Core/Portable/SolutionCrawler/ISolutionCrawlerProgressReporter.cs index 226b5d84c7f438ebab5b249aa282af6f6a5fc0f4..873535811f3e4012fb1ab066b5774c6147740784 100644 --- a/src/Features/Core/Portable/SolutionCrawler/ISolutionCrawlerProgressReporter.cs +++ b/src/Features/Core/Portable/SolutionCrawler/ISolutionCrawlerProgressReporter.cs @@ -1,6 +1,7 @@ // 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 Roslyn.Utilities; namespace Microsoft.CodeAnalysis.SolutionCrawler { @@ -15,13 +16,13 @@ internal interface ISolutionCrawlerProgressReporter bool InProgress { get; } /// - /// Raised when there is pending work in solution crawler. + /// Raised when solution crawler progress changed + /// + /// bool indicates whether progress is started or stopped + /// + /// Notifications for this event are serialized to preserve order. + /// However, individual event notifications may occur on any thread. /// - event EventHandler Started; - - /// - /// Raised when there is no more pending work in solution crawler. - /// - event EventHandler Stopped; + event EventHandler ProgressChanged; } } diff --git a/src/Features/Core/Portable/SolutionCrawler/SolutionCrawlerProgressReporter.cs b/src/Features/Core/Portable/SolutionCrawler/SolutionCrawlerProgressReporter.cs index 11740d2cf4ece7a469c44f269144b8502b110aa1..a13ff92aca5fff5d146333b82da02242eb3b8ade 100644 --- a/src/Features/Core/Portable/SolutionCrawler/SolutionCrawlerProgressReporter.cs +++ b/src/Features/Core/Portable/SolutionCrawler/SolutionCrawlerProgressReporter.cs @@ -45,29 +45,16 @@ public bool InProgress } } - public event EventHandler Started + public event EventHandler ProgressChanged { add { - _eventMap.AddEventHandler(nameof(Started), value); + _eventMap.AddEventHandler(nameof(ProgressChanged), value); } remove { - _eventMap.RemoveEventHandler(nameof(Started), value); - } - } - - public event EventHandler Stopped - { - add - { - _eventMap.AddEventHandler(nameof(Stopped), value); - } - - remove - { - _eventMap.RemoveEventHandler(nameof(Stopped), value); + _eventMap.RemoveEventHandler(nameof(ProgressChanged), value); } } @@ -95,23 +82,23 @@ public Task Stop() private Task RaiseStarted() { - return RaiseEvent(nameof(Started)); + return RaiseEvent(nameof(ProgressChanged), running: true); } private Task RaiseStopped() { - return RaiseEvent(nameof(Stopped)); + return RaiseEvent(nameof(ProgressChanged), running: false); } - private Task RaiseEvent(string eventName) + private Task RaiseEvent(string eventName, bool running) { // this method name doesn't have Async since it should work as async void. - var ev = _eventMap.GetEventHandlers(eventName); + var ev = _eventMap.GetEventHandlers>(eventName); if (ev.HasHandlers) { return _eventQueue.ScheduleTask(() => { - ev.RaiseEvent(handler => handler(this, EventArgs.Empty)); + ev.RaiseEvent(handler => handler(this, running)); }); } @@ -128,13 +115,7 @@ private class NullReporter : ISolutionCrawlerProgressReporter public bool InProgress => false; - public event EventHandler Started - { - add { } - remove { } - } - - public event EventHandler Stopped + public event EventHandler ProgressChanged { add { } remove { } diff --git a/src/VisualStudio/Core/Def/Implementation/Diagnostics/DiagnosticProgressReporter.cs b/src/VisualStudio/Core/Def/Implementation/Diagnostics/DiagnosticProgressReporter.cs new file mode 100644 index 0000000000000000000000000000000000000000..6219d7e60cbe0666941476f4ffbfcae9fc75b5a4 --- /dev/null +++ b/src/VisualStudio/Core/Def/Implementation/Diagnostics/DiagnosticProgressReporter.cs @@ -0,0 +1,161 @@ +// 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 System.ComponentModel.Composition; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.SolutionCrawler; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.TaskStatusCenter; +using Roslyn.Utilities; + +namespace Microsoft.VisualStudio.LanguageServices.Implementation.Diagnostics +{ + [Export(typeof(DiagnosticProgressReporter))] + internal sealed class DiagnosticProgressReporter + { + private static readonly TimeSpan s_minimumInterval = TimeSpan.FromMilliseconds(200); + + private readonly IVsTaskStatusCenterService _taskCenterService; + private readonly IDiagnosticService _diagnosticService; + private readonly TaskHandlerOptions _options; + + // these fields are never accessed concurrently + private TaskCompletionSource _currentTask; + private object _lastReportedDocumentOrProject; + private DateTimeOffset _lastTimeReported; + + // this is only field that is shared between 2 events streams (IDiagnosticService and ISolutionCrawlerProgressReporter) + // and can be called concurrently. + private volatile ITaskHandler _taskHandler; + + [ImportingConstructor] + public DiagnosticProgressReporter( + SVsServiceProvider serviceProvider, + IDiagnosticService diagnosticService, + VisualStudioWorkspace workspace) + { + _lastTimeReported = DateTimeOffset.UtcNow; + + _taskCenterService = (IVsTaskStatusCenterService)serviceProvider.GetService(typeof(SVsTaskStatusCenterService)); + _diagnosticService = diagnosticService; + + var crawlerService = workspace.Services.GetService(); + var reporter = crawlerService.GetProgressReporter(workspace); + + Started(reporter.InProgress); + + // no event unsubscription since it will remain alive until VS shutdown + reporter.ProgressChanged += OnSolutionCrawlerProgressChanged; + _diagnosticService.DiagnosticsUpdated += OnDiagnosticsUpdated; + + _options = new TaskHandlerOptions() + { + Title = ServicesVSResources.Live_code_analysis, + ActionsAfterCompletion = CompletionActions.None + }; + } + + private void OnDiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs e) + { + // there is no concurrent call to this method since IDiagnosticService will serialize all + // events to preserve event ordering + var solution = e.Solution; + if (solution == null) + { + return; + } + + // we ignore report for same document/project as last time + // even if they are from different analyzers + // since, for the progress report, they all show up same + var documentOrProject = (object)e.DocumentId ?? e.ProjectId; + if (_lastReportedDocumentOrProject == documentOrProject) + { + return; + } + + var current = DateTimeOffset.UtcNow; + if (current - _lastTimeReported < s_minimumInterval) + { + // make sure we are not flooding UI. + // this is just presentation, fine to not updating UI especially since + // at the end, this notification will go away automatically + return; + } + + // only update when we actually change message + _lastReportedDocumentOrProject = documentOrProject; + _lastTimeReported = current; + + var document = solution.GetDocument(e.DocumentId); + if (document != null) + { + ChangeProgress(string.Format(ServicesVSResources.Analyzing_0, document.Name ?? document.FilePath ?? "...")); + return; + } + + var project = solution.GetProject(e.ProjectId); + if (project != null) + { + ChangeProgress(string.Format(ServicesVSResources.Analyzing_0, project.Name ?? project.FilePath ?? "...")); + return; + } + } + + private void OnSolutionCrawlerProgressChanged(object sender, bool running) + { + // there is no concurrent call to this method since ISolutionCrawlerProgressReporter will serialize all + // events to preserve event ordering + Started(running); + } + + private void Started(bool running) + { + if (running) + { + // if there is any pending one. make sure it is finished. + _currentTask?.TrySetResult(default); + + var taskHandler = _taskCenterService.PreRegister(_options, data: default); + + _currentTask = new TaskCompletionSource(); + taskHandler.RegisterTask(_currentTask.Task); + + var data = new TaskProgressData + { + ProgressText = null, + CanBeCanceled = false, + PercentComplete = null, + }; + + // report initial progress + taskHandler.Progress.Report(data); + + // set handler + _taskHandler = taskHandler; + } + else + { + // stop progress + _currentTask?.TrySetResult(default); + _currentTask = null; + + _taskHandler = null; + } + } + + private void ChangeProgress(string message) + { + var data = new TaskProgressData + { + ProgressText = message, + CanBeCanceled = false, + PercentComplete = null, + }; + + _taskHandler?.Progress.Report(data); + } + } +} + diff --git a/src/VisualStudio/Core/Def/Implementation/TableDataSource/AbstractRoslynTableDataSource.cs b/src/VisualStudio/Core/Def/Implementation/TableDataSource/AbstractRoslynTableDataSource.cs index f1a189b2d2fc26df4a9cca7c0b3dc6c0887c42c4..4cd2c895b0e569e654aff92f8155b3256fbc2e90 100644 --- a/src/VisualStudio/Core/Def/Implementation/TableDataSource/AbstractRoslynTableDataSource.cs +++ b/src/VisualStudio/Core/Def/Implementation/TableDataSource/AbstractRoslynTableDataSource.cs @@ -40,25 +40,20 @@ private void ConnectToSolutionCrawlerService(Workspace workspace) } var reporter = crawlerService.GetProgressReporter(workspace); + reporter.ProgressChanged += OnSolutionCrawlerProgressChanged; // set initial value - IsStable = !reporter.InProgress; - - ChangeStableState(stable: IsStable); - - reporter.Started += OnSolutionCrawlerStarted; - reporter.Stopped += OnSolutionCrawlerStopped; + SolutionCrawlerProgressChanged(reporter.InProgress); } - private void OnSolutionCrawlerStarted(object sender, EventArgs e) + private void OnSolutionCrawlerProgressChanged(object sender, bool running) { - IsStable = false; - ChangeStableState(IsStable); + SolutionCrawlerProgressChanged(running); } - private void OnSolutionCrawlerStopped(object sender, EventArgs e) + private void SolutionCrawlerProgressChanged(bool running) { - IsStable = true; + IsStable = !running; ChangeStableState(IsStable); } } diff --git a/src/VisualStudio/Core/Def/Implementation/TableDataSource/MiscellaneousDiagnosticListTable.cs b/src/VisualStudio/Core/Def/Implementation/TableDataSource/MiscellaneousDiagnosticListTable.cs index 3dd3943643a8cf6c075f13626112a344519da15e..edb372a277c68ac06201cfd77a123d9400b17b9c 100644 --- a/src/VisualStudio/Core/Def/Implementation/TableDataSource/MiscellaneousDiagnosticListTable.cs +++ b/src/VisualStudio/Core/Def/Implementation/TableDataSource/MiscellaneousDiagnosticListTable.cs @@ -20,24 +20,17 @@ internal class MiscellaneousDiagnosticListTable : VisualStudioBaseDiagnosticList private readonly LiveTableDataSource _source; [ImportingConstructor] - public MiscellaneousDiagnosticListTable( - SVsServiceProvider serviceProvider, MiscellaneousFilesWorkspace workspace, IDiagnosticService diagnosticService, ITableManagerProvider provider) : - this(serviceProvider, (Workspace)workspace, diagnosticService, provider) + public MiscellaneousDiagnosticListTable(MiscellaneousFilesWorkspace workspace, IDiagnosticService diagnosticService, ITableManagerProvider provider) : + this((Workspace)workspace, diagnosticService, provider) { ConnectWorkspaceEvents(); } /// this is for test only internal MiscellaneousDiagnosticListTable(Workspace workspace, IDiagnosticService diagnosticService, ITableManagerProvider provider) : - this(null, workspace, diagnosticService, provider) + base(workspace, diagnosticService, provider) { - } - - private MiscellaneousDiagnosticListTable( - SVsServiceProvider serviceProvider, Workspace workspace, IDiagnosticService diagnosticService, ITableManagerProvider provider) : - base(serviceProvider, workspace, diagnosticService, provider) - { - _source = new LiveTableDataSource(serviceProvider, workspace, diagnosticService, IdentifierString); + _source = new LiveTableDataSource(workspace, diagnosticService, IdentifierString); AddInitialTableSource(workspace.CurrentSolution, _source); } diff --git a/src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioBaseDiagnosticListTable.LiveTableDataSource.cs b/src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioBaseDiagnosticListTable.LiveTableDataSource.cs index 214ba534dff5fa9b68e66e26b165f03bb7ca9cb4..6ba3043bebd9f66708c8c5d47b9f154973e48ea4 100644 --- a/src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioBaseDiagnosticListTable.LiveTableDataSource.cs +++ b/src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioBaseDiagnosticListTable.LiveTableDataSource.cs @@ -28,23 +28,20 @@ protected class LiveTableDataSource : AbstractRoslynTableDataSource _tracker; - public LiveTableDataSource(IServiceProvider serviceProvider, Workspace workspace, IDiagnosticService diagnosticService, string identifier) : + public LiveTableDataSource(Workspace workspace, IDiagnosticService diagnosticService, string identifier) : base(workspace) { _workspace = workspace; - _serviceProvider = serviceProvider; _identifier = identifier; _tracker = new OpenDocumentTracker(_workspace); _diagnosticService = diagnosticService; - _diagnosticService.DiagnosticsUpdated += OnDiagnosticsUpdated; - PopulateInitialData(workspace, diagnosticService); + ConnectToDiagnosticService(workspace, diagnosticService); } public override string DisplayName => ServicesVSResources.CSharp_VB_Diagnostics_Table_Data_Source; @@ -175,6 +172,19 @@ public override AbstractTableEntriesSource CreateTableEntriesSou return new TableEntriesSource(this, item.Workspace, item.ProjectId, item.DocumentId, item.Id); } + private void ConnectToDiagnosticService(Workspace workspace, IDiagnosticService diagnosticService) + { + if (diagnosticService == null) + { + // it can be null in unit test + return; + } + + _diagnosticService.DiagnosticsUpdated += OnDiagnosticsUpdated; + + PopulateInitialData(workspace, diagnosticService); + } + private static bool ShouldInclude(DiagnosticData diagnostic) { if (diagnostic == null) diff --git a/src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioBaseDiagnosticListTable.cs b/src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioBaseDiagnosticListTable.cs index c7f3205ed6b4d8db4160b613ec2e9df99316b395..33b3c883367d9dfcb7c14d018f9c4eead9dd8aac 100644 --- a/src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioBaseDiagnosticListTable.cs +++ b/src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioBaseDiagnosticListTable.cs @@ -1,12 +1,10 @@ // 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 System.Collections.Generic; using System.Collections.Immutable; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.VisualStudio.LanguageServices.Implementation.Utilities; -using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.Shell.TableControl; using Microsoft.VisualStudio.Shell.TableManager; @@ -32,8 +30,7 @@ internal abstract partial class VisualStudioBaseDiagnosticListTable : AbstractTa SuppressionStateColumnDefinition.ColumnName }; - protected VisualStudioBaseDiagnosticListTable( - SVsServiceProvider serviceProvider, Microsoft.CodeAnalysis.Workspace workspace, IDiagnosticService diagnosticService, ITableManagerProvider provider) : + protected VisualStudioBaseDiagnosticListTable(Workspace workspace, IDiagnosticService diagnosticService, ITableManagerProvider provider) : base(workspace, provider, StandardTables.ErrorsTable) { } diff --git a/src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioDiagnosticListTable.BuildTableDataSource.cs b/src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioDiagnosticListTable.BuildTableDataSource.cs index 2cbcb510e31e951f79778df423375222034d728e..25b3465c10896ec853dcb04bdbb6f85cd36f39af 100644 --- a/src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioDiagnosticListTable.BuildTableDataSource.cs +++ b/src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioDiagnosticListTable.BuildTableDataSource.cs @@ -37,6 +37,7 @@ private void ConnectToBuildUpdateSource(ExternalErrorDiagnosticUpdateSource erro { if (errorSource == null) { + // it can be null in unit test return; } diff --git a/src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioDiagnosticListTable.cs b/src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioDiagnosticListTable.cs index d9f48d51161a35c5b48ae8388d0e4aea4a248568..0f05a4e1f1da8c7ee483e2d64470c765e9161313 100644 --- a/src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioDiagnosticListTable.cs +++ b/src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioDiagnosticListTable.cs @@ -1,20 +1,15 @@ // 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 System.ComponentModel; using System.ComponentModel.Composition; using System.Linq; -using System.Runtime.CompilerServices; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.Shared.Options; -using Microsoft.Internal.VisualStudio.Shell; using Microsoft.VisualStudio.LanguageServices.Implementation.TaskList; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.Shell.TableManager; -using Roslyn.Utilities; +using Microsoft.VisualStudio.TaskStatusCenter; namespace Microsoft.VisualStudio.LanguageServices.Implementation.TableDataSource { @@ -29,8 +24,6 @@ internal partial class VisualStudioDiagnosticListTable : VisualStudioBaseDiagnos private readonly LiveTableDataSource _liveTableSource; private readonly BuildTableDataSource _buildTableSource; - private const string TypeScriptLanguageName = "TypeScript"; - [ImportingConstructor] public VisualStudioDiagnosticListTable( SVsServiceProvider serviceProvider, @@ -38,7 +31,7 @@ internal partial class VisualStudioDiagnosticListTable : VisualStudioBaseDiagnos IDiagnosticService diagnosticService, ExternalErrorDiagnosticUpdateSource errorSource, ITableManagerProvider provider) : - this(serviceProvider, (Workspace)workspace, diagnosticService, errorSource, provider) + this(workspace, diagnosticService, errorSource, provider) { ConnectWorkspaceEvents(); @@ -66,27 +59,26 @@ private ITableDataSource GetCurrentDataSource() /// this is for test only internal VisualStudioDiagnosticListTable(Workspace workspace, IDiagnosticService diagnosticService, ITableManagerProvider provider) : - this(null, workspace, diagnosticService, null, provider) + this(workspace, diagnosticService, errorSource: null, provider) { AddInitialTableSource(workspace.CurrentSolution, _liveTableSource); } /// this is for test only - internal VisualStudioDiagnosticListTable(Workspace workspace, IDiagnosticService diagnosticService, ExternalErrorDiagnosticUpdateSource errorSource, ITableManagerProvider provider) : - this(null, workspace, diagnosticService, errorSource, provider) + internal VisualStudioDiagnosticListTable(Workspace workspace, ExternalErrorDiagnosticUpdateSource errorSource, ITableManagerProvider provider) : + this(workspace, diagnosticService: null, errorSource, provider) { AddInitialTableSource(workspace.CurrentSolution, _buildTableSource); } private VisualStudioDiagnosticListTable( - SVsServiceProvider serviceProvider, Workspace workspace, IDiagnosticService diagnosticService, ExternalErrorDiagnosticUpdateSource errorSource, ITableManagerProvider provider) : - base(serviceProvider, workspace, diagnosticService, provider) + base(workspace, diagnosticService, provider) { - _liveTableSource = new LiveTableDataSource(serviceProvider, workspace, diagnosticService, IdentifierString); + _liveTableSource = new LiveTableDataSource(workspace, diagnosticService, IdentifierString); _buildTableSource = new BuildTableDataSource(workspace, errorSource); } diff --git a/src/VisualStudio/Core/Def/RoslynPackage.cs b/src/VisualStudio/Core/Def/RoslynPackage.cs index 326a076eaea31eda36107849cb1b84b707817528..009356227c2069a7f455ed29ae98e3642d6b492c 100644 --- a/src/VisualStudio/Core/Def/RoslynPackage.cs +++ b/src/VisualStudio/Core/Def/RoslynPackage.cs @@ -26,6 +26,7 @@ using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using Task = System.Threading.Tasks.Task; +using Microsoft.VisualStudio.LanguageServices.Implementation.Diagnostics; namespace Microsoft.VisualStudio.LanguageServices.Setup { @@ -94,6 +95,7 @@ protected override void LoadComponentsInUIContext() { // we need to load it as early as possible since we can have errors from // package from each language very early + this.ComponentModel.GetService(); this.ComponentModel.GetService(); this.ComponentModel.GetService(); this.ComponentModel.GetService().Initialize(this); @@ -108,7 +110,7 @@ protected override void LoadComponentsInUIContext() this.ComponentModel.GetService(); LoadAnalyzerNodeComponents(); - + Task.Run(() => LoadComponentsBackgroundAsync()); } diff --git a/src/VisualStudio/Core/Def/ServicesVSResources.Designer.cs b/src/VisualStudio/Core/Def/ServicesVSResources.Designer.cs index a598ce44b10b1608bb2b9d4c75515a30bb9b8950..45e5b8a3ba7a3e9a66575e21fcd4393529200e40 100644 --- a/src/VisualStudio/Core/Def/ServicesVSResources.Designer.cs +++ b/src/VisualStudio/Core/Def/ServicesVSResources.Designer.cs @@ -262,6 +262,15 @@ internal class ServicesVSResources { } } + /// + /// Looks up a localized string similar to Analyzing '{0}'. + /// + internal static string Analyzing_0 { + get { + return ResourceManager.GetString("Analyzing_0", resourceCulture); + } + } + /// /// Looks up a localized string similar to Applying remove suppressions fix.... /// @@ -1226,6 +1235,15 @@ internal class ServicesVSResources { } } + /// + /// Looks up a localized string similar to Live code analysis. + /// + internal static string Live_code_analysis { + get { + return ResourceManager.GetString("Live_code_analysis", resourceCulture); + } + } + /// /// Looks up a localized string similar to Location:. /// diff --git a/src/VisualStudio/Core/Def/ServicesVSResources.resx b/src/VisualStudio/Core/Def/ServicesVSResources.resx index c9ef322e5b20ccd7290883dd62bd245e90ee489f..382e6e3cbd2f421f8f0095561aecffc071e97af2 100644 --- a/src/VisualStudio/Core/Def/ServicesVSResources.resx +++ b/src/VisualStudio/Core/Def/ServicesVSResources.resx @@ -1016,4 +1016,10 @@ I agree to all of the foregoing: The settings configured here only apply to your machine. To configure these settings to travel with your solution, use .editorconfig files. - + + Analyzing '{0}' + + + Live code analysis + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf index efc5b6d3d0b0c9e327948b3ee85e43096035f713..924a2afc95eac79cd56982902e59680196720063 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf @@ -1498,6 +1498,16 @@ Souhlasím se všemi výše uvedenými podmínkami: The settings configured here only apply to your machine. To configure these settings to travel with your solution, use .editorconfig files. + + Live code analysis + Live code analysis + + + + Analyzing '{0}' + Analyzing '{0}' + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf index 91de68bdb0d74db4c7e7998a3eaa6af4ef1a4b17..18141106d7c35c315940aada23369bca7a9ae20f 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf @@ -1498,6 +1498,16 @@ Ich stimme allen vorstehenden Bedingungen zu: The settings configured here only apply to your machine. To configure these settings to travel with your solution, use .editorconfig files. + + Live code analysis + Live code analysis + + + + Analyzing '{0}' + Analyzing '{0}' + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf index 6fc271d507c6953a8e0ac062c57c5d7d34ee40e0..9739787b776cc55f2aada8b8299444f6ec9f2155 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf @@ -1498,6 +1498,16 @@ Estoy de acuerdo con todo lo anterior: The settings configured here only apply to your machine. To configure these settings to travel with your solution, use .editorconfig files. + + Live code analysis + Live code analysis + + + + Analyzing '{0}' + Analyzing '{0}' + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf index d4c7085d019edc30a8e5e1ee41b8c9b6f75886a5..6ebf3932c5cf58a683276a94c94c3285a87e6374 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf @@ -1498,6 +1498,16 @@ Je suis d'accord avec tout ce qui précède : The settings configured here only apply to your machine. To configure these settings to travel with your solution, use .editorconfig files. + + Live code analysis + Live code analysis + + + + Analyzing '{0}' + Analyzing '{0}' + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf index 974c5351a767fb75906da44de2949cc27ae6fd79..e044c00dcfde2e559516b90d6e5347f39ec84e9d 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf @@ -1498,6 +1498,16 @@ L'utente accetta le condizioni sopra riportate: The settings configured here only apply to your machine. To configure these settings to travel with your solution, use .editorconfig files. + + Live code analysis + Live code analysis + + + + Analyzing '{0}' + Analyzing '{0}' + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf index 8b92cd51a20a4534d903f9cd98dbe213988a79f8..c93b288fc25db207e2516181cda778f4703bfd86 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf @@ -1498,6 +1498,16 @@ I agree to all of the foregoing: The settings configured here only apply to your machine. To configure these settings to travel with your solution, use .editorconfig files. + + Live code analysis + Live code analysis + + + + Analyzing '{0}' + Analyzing '{0}' + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf index 053385395505ecb63ae69da5f31526f4dfde7396..b3beb527a8ec37d440d8a5619ea532da6e9004b8 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf @@ -1498,6 +1498,16 @@ I agree to all of the foregoing: The settings configured here only apply to your machine. To configure these settings to travel with your solution, use .editorconfig files. + + Live code analysis + Live code analysis + + + + Analyzing '{0}' + Analyzing '{0}' + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf index e95e297499bc4f45f7adedca37106406fb29725a..a7054f3a9157132ec39ed65124be6fa062ebc9cc 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf @@ -1498,6 +1498,16 @@ Wyrażam zgodę na wszystkie następujące postanowienia: The settings configured here only apply to your machine. To configure these settings to travel with your solution, use .editorconfig files. + + Live code analysis + Live code analysis + + + + Analyzing '{0}' + Analyzing '{0}' + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf index 9e0acace5f64132635991e70a97adca09ca5b1e5..5f1651dcb0ea16928e56edb2a66549489e3e5e21 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf @@ -1498,6 +1498,16 @@ Eu concordo com todo o conteúdo supracitado: The settings configured here only apply to your machine. To configure these settings to travel with your solution, use .editorconfig files. + + Live code analysis + Live code analysis + + + + Analyzing '{0}' + Analyzing '{0}' + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf index d2de627fbaac886ab7df56a86e5e4639ba7ff0ba..a3e1a44ddab3f1119ecc4a3bbb9d8d6899c6144b 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf @@ -1498,6 +1498,16 @@ I agree to all of the foregoing: The settings configured here only apply to your machine. To configure these settings to travel with your solution, use .editorconfig files. + + Live code analysis + Live code analysis + + + + Analyzing '{0}' + Analyzing '{0}' + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf index 1199d029ebc6555a1125a9c8f5fdf8359832aabf..d914483464a5f1bfc5023f8721fd159dedb7cdfc 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf @@ -1498,6 +1498,16 @@ Aşağıdakilerin tümünü onaylıyorum: The settings configured here only apply to your machine. To configure these settings to travel with your solution, use .editorconfig files. + + Live code analysis + Live code analysis + + + + Analyzing '{0}' + Analyzing '{0}' + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf index fdbd74c216c113a7f07e12e4afa4a1638caf31b7..14381a5bab12b80b0d9ac43f36f0400e471b27e9 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf @@ -1498,6 +1498,16 @@ I agree to all of the foregoing: The settings configured here only apply to your machine. To configure these settings to travel with your solution, use .editorconfig files. + + Live code analysis + Live code analysis + + + + Analyzing '{0}' + Analyzing '{0}' + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf index d0d37cd10141e43b93d1179a2e7efdec591d7913..6e7cf237bb0b7c5e3aa232ecc765d1abe9ae9e66 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf @@ -1498,6 +1498,16 @@ I agree to all of the foregoing: The settings configured here only apply to your machine. To configure these settings to travel with your solution, use .editorconfig files. + + Live code analysis + Live code analysis + + + + Analyzing '{0}' + Analyzing '{0}' + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Test/Diagnostics/DiagnosticTableDataSourceTests.vb b/src/VisualStudio/Core/Test/Diagnostics/DiagnosticTableDataSourceTests.vb index ea70557f999629a51d36ca77a459baca773cb7e9..166a92c79ac1becf29748f43d726abde51cbcbc0 100644 --- a/src/VisualStudio/Core/Test/Diagnostics/DiagnosticTableDataSourceTests.vb +++ b/src/VisualStudio/Core/Test/Diagnostics/DiagnosticTableDataSourceTests.vb @@ -674,7 +674,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.Diagnostics Dim updateSource = New ExternalErrorDiagnosticUpdateSource(workspace, analyzerService, registration, listener) Dim tableManagerProvider = New TestTableManagerProvider() - Dim table = New VisualStudioDiagnosticListTable(workspace, service, updateSource, tableManagerProvider) + Dim table = New VisualStudioDiagnosticListTable(workspace, updateSource, tableManagerProvider) Dim document1 = workspace.CurrentSolution.Projects.First(Function(p) p.Name = "Proj1").Documents.First() Dim document2 = workspace.CurrentSolution.Projects.First(Function(p) p.Name = "Proj2").Documents.First() diff --git a/src/Workspaces/Core/Portable/Utilities/VoidResult.cs b/src/Workspaces/Core/Portable/Utilities/VoidResult.cs new file mode 100644 index 0000000000000000000000000000000000000000..cb7b05f5dd4824e224c005de342a538f8acdd01e --- /dev/null +++ b/src/Workspaces/Core/Portable/Utilities/VoidResult.cs @@ -0,0 +1,9 @@ +// 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 Roslyn.Utilities +{ + /// + /// Explicitly indicates result is void + /// + internal struct VoidResult { } +} diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/Solution.cs b/src/Workspaces/Core/Portable/Workspace/Solution/Solution.cs index dc886e7ad5a2904a64a5580acc99588735313534..e826098dedd0641c720c5577d4c12744657c5861 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/Solution.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/Solution.cs @@ -94,11 +94,7 @@ internal Solution(Workspace workspace, SolutionInfo info) /// public Project GetProject(ProjectId projectId) { - if (projectId == null) - { - throw new ArgumentNullException(nameof(projectId)); - } - + // ContainsProject checks projectId being null if (this.ContainsProject(projectId)) { return ImmutableHashMapExtensions.GetOrAdd(ref _projectIdToProjectMap, projectId, s_createProjectFunction, this); @@ -165,7 +161,8 @@ public DocumentId GetDocumentId(SyntaxTree syntaxTree, ProjectId projectId) /// public Document GetDocument(DocumentId documentId) { - if (documentId != null && this.ContainsDocument(documentId)) + // ContainsDocument checks documentId being null + if (this.ContainsDocument(documentId)) { return this.GetProject(documentId.ProjectId).GetDocument(documentId); }