From 9ccf3960b44d06f726628fe0805506662ab05b5e Mon Sep 17 00:00:00 2001 From: Georgii Borovinskikh <117642191+georgii-borovinskikh-sonarsource@users.noreply.github.com> Date: Thu, 22 Feb 2024 16:14:03 +0100 Subject: [PATCH] Add ThrowIfOnUIThread to SLCoreServiceProvider (#5243) --- .../Core/SLCoreServiceProviderTests.cs | 20 ++++++++++++++++--- .../Integration/SLCoreIntegrationSmokeTest.cs | 3 ++- src/SLCore/Core/ISLCoreServiceProvider.cs | 7 ++++++- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/SLCore.UnitTests/Core/SLCoreServiceProviderTests.cs b/src/SLCore.UnitTests/Core/SLCoreServiceProviderTests.cs index f987316d23..9fd1e09b00 100644 --- a/src/SLCore.UnitTests/Core/SLCoreServiceProviderTests.cs +++ b/src/SLCore.UnitTests/Core/SLCoreServiceProviderTests.cs @@ -32,6 +32,7 @@ public class SLCoreServiceProviderTests public void MefCtor_CheckIsExported() { MefTestHelpers.CheckTypeCanBeImported( + MefTestHelpers.CreateExport(), MefTestHelpers.CreateExport()); } @@ -39,6 +40,7 @@ public void MefCtor_CheckIsExported() public void MefCtor_WriterInterface_CheckIsExported() { MefTestHelpers.CheckTypeCanBeImported( + MefTestHelpers.CreateExport(), MefTestHelpers.CreateExport()); } @@ -57,6 +59,17 @@ public void TryGetTransientService_TypeNotInterface_Throws() act.Should().Throw().WithMessage($"The type argument {typeof(TestSLCoreService).FullName} is not an interface"); } + + [TestMethod] + public void TryGetTransientService_NotUIThread_Checked() + { + var threadHandling = new Mock(); + var testSubject = CreateTestSubject(threadHandling:threadHandling.Object); + + testSubject.TryGetTransientService(out ITestSLcoreService1 _); + + threadHandling.Verify(x => x.ThrowIfOnUIThread()); + } [TestMethod] public void TryGetTransientService_NotInitialized_ReturnsFalse() @@ -86,7 +99,7 @@ public void TryGetTransientService_RpcThrows_LoggedAndReturnsFalse() var logger = new TestLogger(); - var testSubject = CreateTestSubject(rpcMock.Object, logger); + var testSubject = CreateTestSubject(rpcMock.Object, logger:logger); var result = testSubject.TryGetTransientService(out ISLCoreService service); @@ -196,10 +209,11 @@ private static void SetUpConnectionState(Mock rpcMock, bool isAl rpcMock.SetupGet(x => x.IsAlive).Returns(isAlive); } - private SLCoreServiceProvider CreateTestSubject(ISLCoreJsonRpc jsonRpc = null, ILogger logger = null) + private SLCoreServiceProvider CreateTestSubject(ISLCoreJsonRpc jsonRpc = null, IThreadHandling threadHandling = null, ILogger logger = null) { + threadHandling ??= new NoOpThreadHandler(); logger ??= new TestLogger(); - var testSubject = new SLCoreServiceProvider(logger); + var testSubject = new SLCoreServiceProvider(threadHandling, logger); if (jsonRpc != null) { testSubject.SetCurrentConnection(jsonRpc); diff --git a/src/SLCore.UnitTests/Integration/SLCoreIntegrationSmokeTest.cs b/src/SLCore.UnitTests/Integration/SLCoreIntegrationSmokeTest.cs index 05816b2d5c..45434190ab 100644 --- a/src/SLCore.UnitTests/Integration/SLCoreIntegrationSmokeTest.cs +++ b/src/SLCore.UnitTests/Integration/SLCoreIntegrationSmokeTest.cs @@ -21,6 +21,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using SonarLint.VisualStudio.Infrastructure.VS; using SonarLint.VisualStudio.SLCore.Common.Models; using SonarLint.VisualStudio.SLCore.Core; using SonarLint.VisualStudio.SLCore.Listener; @@ -52,7 +53,7 @@ public async Task SLCore_InitializeStandaloneAndShutdown() var slCoreRunner = new SLCoreRunner(slcoreBat, enableVerboseLogs: true); var logger = new TestLogger(); - var slCoreServiceProvider = new SLCoreServiceProvider(logger); + var slCoreServiceProvider = new SLCoreServiceProvider(new NoOpThreadHandler(), logger); slCoreServiceProvider.SetCurrentConnection(slCoreRunner.Rpc); var slCoreListenerSetUp = new SLCoreListenerSetUp(new[] { new LoggerListener(new TestLogger(logToConsole: true)) }); slCoreListenerSetUp.Setup(slCoreRunner.Rpc); diff --git a/src/SLCore/Core/ISLCoreServiceProvider.cs b/src/SLCore/Core/ISLCoreServiceProvider.cs index 49cbf08849..6b2cc06690 100644 --- a/src/SLCore/Core/ISLCoreServiceProvider.cs +++ b/src/SLCore/Core/ISLCoreServiceProvider.cs @@ -49,19 +49,24 @@ public interface ISLCoreServiceProviderWriter [PartCreationPolicy(CreationPolicy.Shared)] public class SLCoreServiceProvider : ISLCoreServiceProvider, ISLCoreServiceProviderWriter { + private readonly Dictionary cache = new Dictionary(); private readonly object cacheLock = new object(); private ISLCoreJsonRpc jsonRpc; + private readonly IThreadHandling threadHandling; private readonly ILogger logger; [ImportingConstructor] - public SLCoreServiceProvider(ILogger logger) + public SLCoreServiceProvider(IThreadHandling threadHandling, ILogger logger) { + this.threadHandling = threadHandling; this.logger = logger; } public bool TryGetTransientService(out TService service) where TService : class, ISLCoreService { + threadHandling.ThrowIfOnUIThread(); + service = default; var serviceType = typeof(TService);