From e0344b6c7d224698e16a27b9d2d8a35fd106199c Mon Sep 17 00:00:00 2001
From: Georgii Borovinskikh
<117642191+georgii-borovinskikh-sonarsource@users.noreply.github.com>
Date: Fri, 15 Mar 2024 10:36:52 +0100
Subject: [PATCH] Add SLCoreService with SLOOP initialization & shutdown
(#5297)
Part of #5291
---
src/Core/Binding/IConfigScopeUpdater.cs | 29 ++
.../MefServices/ActiveSolutionBoundTracker.cs | 1 -
src/Integration/Service/VersionHelper.cs | 2 +-
.../SLCoreTestProcessRunner.cs | 1 +
src/SLCore.UnitTests/SLCoreHandleTests.cs | 310 ++++++++++++++++++
src/SLCore.UnitTests/SLCoreRpcFactoryTests.cs | 1 +
.../State/ActiveConfigScopeTrackerTests.cs | 4 +-
.../State/AliveConnectionTrackerTests.cs | 2 +-
.../State}/ConfigScopeUpdaterTests.cs | 6 +-
.../ISLCoreConfigurationProvider.cs | 29 ++
.../Configuration/ISLCoreConstantsProvider.cs | 30 ++
.../ISLCoreEmbeddedPluginJarLocator.cs} | 10 +-
.../Configuration/ISLCoreFoldersProvider.cs | 26 ++
.../ISLCoreLocator.cs | 4 +-
src/SLCore/Configuration/SLCoreFolders.cs | 23 ++
.../SLCoreLaunchParameters.cs | 4 +-
src/SLCore/Core/ISLCoreServiceProvider.cs | 2 +-
.../Core/Process/ISLCoreProcessFactory.cs | 2 +
src/SLCore/Core/Process/SLCoreProcess.cs | 1 +
.../Core/Process/SLCoreProcessFactory.cs | 1 +
src/SLCore/ISLCoreRpcFactory.cs | 3 +-
src/SLCore/SLCore.csproj | 10 +-
src/SLCore/SLCoreHandle.cs | 125 +++++++
....Designer.cs => SLCoreStrings.Designer.cs} | 15 +-
.../{Strings.resx => SLCoreStrings.resx} | 0
src/SLCore/State/ActiveConfigScopeTracker.cs | 4 +-
src/SLCore/State/AliveConnectionTracker.cs | 2 +-
.../State}/ConfigScopeUpdater.cs | 22 +-
src/SLCore/State/ServerConnectionsProvider.cs | 2 +-
29 files changed, 619 insertions(+), 52 deletions(-)
create mode 100644 src/Core/Binding/IConfigScopeUpdater.cs
create mode 100644 src/SLCore.UnitTests/SLCoreHandleTests.cs
rename src/{Integration.UnitTests/MefServices => SLCore.UnitTests/State}/ConfigScopeUpdaterTests.cs (97%)
create mode 100644 src/SLCore/Configuration/ISLCoreConfigurationProvider.cs
create mode 100644 src/SLCore/Configuration/ISLCoreConstantsProvider.cs
rename src/{ConnectedMode/Binding/IServerConnectionConfigurationProvider.cs => SLCore/Configuration/ISLCoreEmbeddedPluginJarLocator.cs} (76%)
create mode 100644 src/SLCore/Configuration/ISLCoreFoldersProvider.cs
rename src/SLCore/{Core/Process => Configuration}/ISLCoreLocator.cs (91%)
create mode 100644 src/SLCore/Configuration/SLCoreFolders.cs
rename src/SLCore/{Core/Process => Configuration}/SLCoreLaunchParameters.cs (85%)
create mode 100644 src/SLCore/SLCoreHandle.cs
rename src/SLCore/{Strings.Designer.cs => SLCoreStrings.Designer.cs} (87%)
rename src/SLCore/{Strings.resx => SLCoreStrings.resx} (100%)
rename src/{Integration/MefServices => SLCore/State}/ConfigScopeUpdater.cs (82%)
diff --git a/src/Core/Binding/IConfigScopeUpdater.cs b/src/Core/Binding/IConfigScopeUpdater.cs
new file mode 100644
index 000000000..638f21ff8
--- /dev/null
+++ b/src/Core/Binding/IConfigScopeUpdater.cs
@@ -0,0 +1,29 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+namespace SonarLint.VisualStudio.Core.Binding;
+
+///
+/// Updates current active configuration scope of SLCore
+///
+public interface IConfigScopeUpdater
+{
+ void UpdateConfigScopeForCurrentSolution(BoundSonarQubeProject currentBinding);
+}
diff --git a/src/Integration/MefServices/ActiveSolutionBoundTracker.cs b/src/Integration/MefServices/ActiveSolutionBoundTracker.cs
index 7c303f311..e1349435a 100644
--- a/src/Integration/MefServices/ActiveSolutionBoundTracker.cs
+++ b/src/Integration/MefServices/ActiveSolutionBoundTracker.cs
@@ -27,7 +27,6 @@
using SonarLint.VisualStudio.Core;
using SonarLint.VisualStudio.Core.Binding;
using SonarLint.VisualStudio.Integration.State;
-using SonarLint.VisualStudio.SLCore.Core;
using SonarQube.Client;
using Task = System.Threading.Tasks.Task;
diff --git a/src/Integration/Service/VersionHelper.cs b/src/Integration/Service/VersionHelper.cs
index 828c02d4e..9fb9a8e8f 100644
--- a/src/Integration/Service/VersionHelper.cs
+++ b/src/Integration/Service/VersionHelper.cs
@@ -25,7 +25,7 @@
namespace SonarLint.VisualStudio.Integration.Service
{
- internal static class VersionHelper
+ public static class VersionHelper
{
private const char PrereleaseSeparator = '-';
diff --git a/src/SLCore.IntegrationTests/SLCoreTestProcessRunner.cs b/src/SLCore.IntegrationTests/SLCoreTestProcessRunner.cs
index 5866f3b6d..f72586481 100644
--- a/src/SLCore.IntegrationTests/SLCoreTestProcessRunner.cs
+++ b/src/SLCore.IntegrationTests/SLCoreTestProcessRunner.cs
@@ -23,6 +23,7 @@
using System.IO;
using System.Threading;
using Microsoft.VisualStudio.Threading;
+using SonarLint.VisualStudio.SLCore.Configuration;
using SonarLint.VisualStudio.SLCore.Core;
using SonarLint.VisualStudio.SLCore.Core.Process;
using SonarLint.VisualStudio.SLCore.Protocol;
diff --git a/src/SLCore.UnitTests/SLCoreHandleTests.cs b/src/SLCore.UnitTests/SLCoreHandleTests.cs
new file mode 100644
index 000000000..6ccf33119
--- /dev/null
+++ b/src/SLCore.UnitTests/SLCoreHandleTests.cs
@@ -0,0 +1,310 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using NSubstitute;
+using NSubstitute.ClearExtensions;
+using SonarLint.VisualStudio.Core;
+using SonarLint.VisualStudio.Core.Binding;
+using SonarLint.VisualStudio.SLCore.Configuration;
+using SonarLint.VisualStudio.SLCore.Core;
+using SonarLint.VisualStudio.SLCore.Service.Connection.Models;
+using SonarLint.VisualStudio.SLCore.Service.Lifecycle;
+using SonarLint.VisualStudio.SLCore.Service.Lifecycle.Models;
+using SonarLint.VisualStudio.SLCore.Service.Telemetry;
+using SonarLint.VisualStudio.SLCore.State;
+using Language = SonarLint.VisualStudio.SLCore.Common.Models.Language;
+
+namespace SonarLint.VisualStudio.SLCore.UnitTests;
+
+[TestClass]
+public class SLCoreHandleTests
+{
+ private const string StorageRoot = "storageRootSl";
+ private const string WorkDir = "workDirSl";
+ private const string UserHome = "userHomeSl";
+
+ private static readonly ClientConstantsDto ClientConstants = new(default, default);
+ private static readonly FeatureFlagsDto FeatureFlags = new(default, default, default, default, default, default, default);
+ private static readonly TelemetryClientConstantAttributesDto TelemetryConstants = new(default, default, default, default, default);
+
+ private static readonly SonarQubeConnectionConfigurationDto SonarQubeConnection1 = new("sq1", true, "http://localhost/");
+ private static readonly SonarQubeConnectionConfigurationDto SonarQubeConnection2 = new("sq2", true, "https://next.sonarqube.org/");
+ private static readonly SonarCloudConnectionConfigurationDto SonarCloudConnection = new("sc", true, "https://sonarcloud.io/");
+
+ private static readonly BoundSonarQubeProject Binding = new();
+
+ private static readonly List JarList = new() { "jar1" };
+
+ [TestMethod]
+ public async Task Initialize_ThrowsIfServicesUnavailable()
+ {
+ var testSubject = CreateTestSubject(out var slCoreRpcFactory, out _, out _, out _, out _, out _, out _, out _);
+ SetUpSLCoreRpcFactory(slCoreRpcFactory, out var rpc);
+ SetUpSLCoreRpc(rpc, out var serviceProvider);
+ serviceProvider.TryGetTransientService(out Arg.Any()).ReturnsForAnyArgs(false);
+
+ var act = () => testSubject.InitializeAsync();
+
+ await act.Should().ThrowAsync().WithMessage(SLCoreStrings.ServiceProviderNotInitialized);
+ }
+
+ [TestMethod]
+ public async Task Initialize_SuccessfullyInitializesInCorrectOrder()
+ {
+ var testSubject = CreateTestSubject(out var slCoreRpcFactory,
+ out var constantsProvider,
+ out var foldersProvider,
+ out var connectionsProvider,
+ out var jarLocator,
+ out var activeSolutionBoundTracker,
+ out var configScopeUpdater,
+ out var threadHandling);
+
+ SetUpSuccessfulInitialization(slCoreRpcFactory,
+ constantsProvider,
+ foldersProvider,
+ connectionsProvider,
+ jarLocator,
+ activeSolutionBoundTracker,
+ out var lifecycleManagement,
+ out var telemetryService,
+ out _);
+
+ await testSubject.InitializeAsync();
+
+ Received.InOrder(() =>
+ {
+ threadHandling.ThrowIfOnUIThread();
+ slCoreRpcFactory.StartNewRpcInstance();
+ lifecycleManagement.InitializeAsync(Arg.Is(parameters =>
+ parameters.clientConstantInfo == ClientConstants
+ && parameters.featureFlags == FeatureFlags
+ && parameters.storageRoot == StorageRoot
+ && parameters.workDir == WorkDir
+ && parameters.embeddedPluginPaths == JarList
+ && parameters.connectedModeEmbeddedPluginPathsByKey.Count == 0
+ && parameters.enabledLanguagesInStandaloneMode.SequenceEqual(new[]
+ {
+ Language.C,
+ Language.CPP,
+ Language.CS,
+ Language.VBNET,
+ Language.JS,
+ Language.TS,
+ Language.CSS,
+ Language.SECRETS
+ })
+ && parameters.extraEnabledLanguagesInConnectedMode.Count == 0
+ && parameters.sonarQubeConnections.SequenceEqual(new[] { SonarQubeConnection1, SonarQubeConnection2 })
+ && parameters.sonarCloudConnections.SequenceEqual(new[] { SonarCloudConnection })
+ && parameters.sonarlintUserHome == UserHome
+ && parameters.standaloneRuleConfigByKey.Count == 0
+ && !parameters.isFocusOnNewCode
+ && parameters.telemetryConstantAttributes == TelemetryConstants
+ && parameters.clientNodeJsPath == null));
+ telemetryService.DisableTelemetry();
+ configScopeUpdater.UpdateConfigScopeForCurrentSolution(Binding);
+ });
+ }
+
+ [TestMethod]
+ public async Task Dispose_Initialized_ShutsDownAndDisposesRpc()
+ {
+ var testSubject = CreateTestSubject(out var slCoreRpcFactory,
+ out var constantsProvider,
+ out var foldersProvider,
+ out var connectionsProvider,
+ out var jarLocator,
+ out var activeSolutionBoundTracker,
+ out _,
+ out var threadHandling);
+
+ SetUpSuccessfulInitialization(slCoreRpcFactory,
+ constantsProvider,
+ foldersProvider,
+ connectionsProvider,
+ jarLocator,
+ activeSolutionBoundTracker,
+ out var lifecycleManagement,
+ out _,
+ out var rpc);
+ await testSubject.InitializeAsync();
+
+ var serviceProvider = rpc.ServiceProvider;
+ serviceProvider.ClearReceivedCalls();
+ testSubject.Dispose();
+
+
+ serviceProvider.Received().TryGetTransientService(out Arg.Any());
+ threadHandling.ReceivedWithAnyArgs().Run(() => Task.FromResult(0));
+ lifecycleManagement.Received().ShutdownAsync();
+ rpc.Received().Dispose();
+ }
+
+ [TestMethod]
+ public async Task Dispose_ConnectionDied_DisposesRpc()
+ {
+ var testSubject = CreateTestSubject(out var slCoreRpcFactory,
+ out var constantsProvider,
+ out var foldersProvider,
+ out var connectionsProvider,
+ out var jarLocator,
+ out var activeSolutionBoundTracker,
+ out _,
+ out var threadHandling);
+
+ SetUpSuccessfulInitialization(slCoreRpcFactory,
+ constantsProvider,
+ foldersProvider,
+ connectionsProvider,
+ jarLocator,
+ activeSolutionBoundTracker,
+ out var lifecycleManagement,
+ out _,
+ out var rpc);
+ await testSubject.InitializeAsync();
+
+ var slCoreServiceProvider = rpc.ServiceProvider;
+ slCoreServiceProvider.ClearSubstitute();
+ slCoreServiceProvider.ClearReceivedCalls();
+ slCoreServiceProvider.TryGetTransientService(out Arg.Any()).Returns(false);
+ testSubject.Dispose();
+
+ slCoreServiceProvider.ReceivedWithAnyArgs().TryGetTransientService(out Arg.Any());
+ rpc.Received().Dispose();
+ threadHandling.DidNotReceiveWithAnyArgs().Run(() => Task.FromResult(0));
+ lifecycleManagement.DidNotReceive().ShutdownAsync();
+ }
+
+ [TestMethod]
+ public void Dispose_NotInitialized_DoesNothing()
+ {
+ var testSubject = CreateTestSubject(out _,
+ out _,
+ out _,
+ out _,
+ out _,
+ out _,
+ out _,
+ out var threadHandling);
+
+ var act = () => testSubject.Dispose();
+
+ act.Should().NotThrow();
+ threadHandling.DidNotReceiveWithAnyArgs().Run(() => Task.FromResult(0));
+ }
+
+ private void SetUpSuccessfulInitialization(ISLCoreRpcFactory slCoreRpcFactory,
+ ISLCoreConstantsProvider constantsProvider,
+ ISLCoreFoldersProvider foldersProvider,
+ IServerConnectionsProvider connectionsProvider,
+ ISLCoreEmbeddedPluginJarLocator jarLocator,
+ IActiveSolutionBoundTracker activeSolutionBoundTracker,
+ out ILifecycleManagementSLCoreService lifecycleManagement,
+ out ITelemetrySLCoreService telemetry,
+ out ISLCoreRpc rpc)
+ {
+ SetUpSLCoreRpcFactory(slCoreRpcFactory, out rpc);
+ SetUpSLCoreRpc(rpc, out var serviceProvider);
+ SetUpSLCoreServiceProvider(serviceProvider, out lifecycleManagement, out telemetry);
+ constantsProvider.ClientConstants.Returns(ClientConstants);
+ constantsProvider.FeatureFlags.Returns(FeatureFlags);
+ constantsProvider.TelemetryConstants.Returns(TelemetryConstants);
+ foldersProvider.GetWorkFolders().Returns(new SLCoreFolders(StorageRoot, WorkDir, UserHome));
+ connectionsProvider.GetServerConnections().Returns(new Dictionary
+ {
+ { SonarQubeConnection1.connectionId, SonarQubeConnection1 },
+ { SonarQubeConnection2.connectionId, SonarQubeConnection2 },
+ { SonarCloudConnection.connectionId, SonarCloudConnection }
+ });
+ jarLocator.ListJarFiles().Returns(JarList);
+ activeSolutionBoundTracker.CurrentConfiguration.Returns(new BindingConfiguration(Binding, SonarLintMode.Connected, "dir"));
+ }
+
+ #region RpcSetUp
+
+ private void SetUpSLCoreRpcFactory(ISLCoreRpcFactory slCoreRpcFactory, out ISLCoreRpc slCoreRpc)
+ {
+ slCoreRpc = Substitute.For();
+ slCoreRpcFactory.StartNewRpcInstance().Returns(slCoreRpc);
+ }
+
+ private void SetUpSLCoreRpc(ISLCoreRpc slCoreRpc, out ISLCoreServiceProvider slCoreServiceProvider)
+ {
+ slCoreServiceProvider = Substitute.For();
+ slCoreRpc.ServiceProvider.Returns(slCoreServiceProvider);
+ }
+
+ private void SetUpSLCoreServiceProvider(ISLCoreServiceProvider slCoreServiceProvider,
+ out ILifecycleManagementSLCoreService lifecycleManagementSlCoreService, out ITelemetrySLCoreService telemetrySlCoreService)
+ {
+ var managementService = Substitute.For();
+ lifecycleManagementSlCoreService = managementService;
+ var telemetryService = Substitute.For();
+ telemetrySlCoreService = telemetryService;
+ slCoreServiceProvider.TryGetTransientService(out Arg.Any()).Returns(x =>
+ {
+ x[0] = managementService;
+ return true;
+ });
+ slCoreServiceProvider.TryGetTransientService(out Arg.Any()).Returns(x =>
+ {
+ x[0] = telemetryService;
+ return true;
+ });
+ }
+
+ #endregion
+
+ private SLCoreHandle CreateTestSubject(out ISLCoreRpcFactory slCoreRpcFactory,
+ out ISLCoreConstantsProvider constantsProvider,
+ out ISLCoreFoldersProvider slCoreFoldersProvider,
+ out IServerConnectionsProvider serverConnectionConfigurationProvider,
+ out ISLCoreEmbeddedPluginJarLocator slCoreEmbeddedPluginJarProvider,
+ out IActiveSolutionBoundTracker activeSolutionBoundTracker,
+ out IConfigScopeUpdater configScopeUpdater,
+ out IThreadHandling threadHandling)
+ {
+ slCoreRpcFactory = Substitute.For();
+ constantsProvider = Substitute.For();
+ slCoreFoldersProvider = Substitute.For();
+ serverConnectionConfigurationProvider = Substitute.For();
+ slCoreEmbeddedPluginJarProvider = Substitute.For();
+ activeSolutionBoundTracker = Substitute.For();
+ configScopeUpdater = Substitute.For();
+ threadHandling = Substitute.ForPartsOf();
+
+ return new SLCoreHandle(slCoreRpcFactory,
+ constantsProvider,
+ slCoreFoldersProvider,
+ serverConnectionConfigurationProvider,
+ slCoreEmbeddedPluginJarProvider,
+ activeSolutionBoundTracker,
+ configScopeUpdater,
+ threadHandling);
+ }
+
+ internal class AnySLCoreService : Arg.AnyType, ISLCoreService
+ {
+ }
+}
diff --git a/src/SLCore.UnitTests/SLCoreRpcFactoryTests.cs b/src/SLCore.UnitTests/SLCoreRpcFactoryTests.cs
index 7ac3ef572..e625415ef 100644
--- a/src/SLCore.UnitTests/SLCoreRpcFactoryTests.cs
+++ b/src/SLCore.UnitTests/SLCoreRpcFactoryTests.cs
@@ -19,6 +19,7 @@
*/
using NSubstitute;
+using SonarLint.VisualStudio.SLCore.Configuration;
using SonarLint.VisualStudio.SLCore.Core;
using SonarLint.VisualStudio.SLCore.Core.Process;
diff --git a/src/SLCore.UnitTests/State/ActiveConfigScopeTrackerTests.cs b/src/SLCore.UnitTests/State/ActiveConfigScopeTrackerTests.cs
index 888fc510b..2b7bef6d5 100644
--- a/src/SLCore.UnitTests/State/ActiveConfigScopeTrackerTests.cs
+++ b/src/SLCore.UnitTests/State/ActiveConfigScopeTrackerTests.cs
@@ -116,7 +116,7 @@ public void SetCurrentConfigScope_ServiceUnavailable_Throws()
var act = () => testSubject.SetCurrentConfigScope("id");
- act.Should().ThrowExactly().WithMessage(Strings.ServiceProviderNotInitialized);
+ act.Should().ThrowExactly().WithMessage(SLCoreStrings.ServiceProviderNotInitialized);
VerifyThreadHandling(threadHandling);
}
@@ -147,7 +147,7 @@ public void RemoveCurrentConfigScope_ServiceUnavailable_Throws()
var act = () => testSubject.RemoveCurrentConfigScope();
- act.Should().ThrowExactly().WithMessage(Strings.ServiceProviderNotInitialized);
+ act.Should().ThrowExactly().WithMessage(SLCoreStrings.ServiceProviderNotInitialized);
VerifyThreadHandling(threadHandling);
}
diff --git a/src/SLCore.UnitTests/State/AliveConnectionTrackerTests.cs b/src/SLCore.UnitTests/State/AliveConnectionTrackerTests.cs
index a6017830c..58673494b 100644
--- a/src/SLCore.UnitTests/State/AliveConnectionTrackerTests.cs
+++ b/src/SLCore.UnitTests/State/AliveConnectionTrackerTests.cs
@@ -140,7 +140,7 @@ public void Refresh_ServiceUnavailable_Throws()
var act = () => testSubject.RefreshConnectionList();
- act.Should().ThrowExactly().WithMessage(Strings.ServiceProviderNotInitialized);
+ act.Should().ThrowExactly().WithMessage(SLCoreStrings.ServiceProviderNotInitialized);
}
[TestMethod]
diff --git a/src/Integration.UnitTests/MefServices/ConfigScopeUpdaterTests.cs b/src/SLCore.UnitTests/State/ConfigScopeUpdaterTests.cs
similarity index 97%
rename from src/Integration.UnitTests/MefServices/ConfigScopeUpdaterTests.cs
rename to src/SLCore.UnitTests/State/ConfigScopeUpdaterTests.cs
index 18dacbf48..3c7abbdcb 100644
--- a/src/Integration.UnitTests/MefServices/ConfigScopeUpdaterTests.cs
+++ b/src/SLCore.UnitTests/State/ConfigScopeUpdaterTests.cs
@@ -18,18 +18,14 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-using System;
using System.Threading.Tasks;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;
using SonarLint.VisualStudio.Core;
using SonarLint.VisualStudio.Core.Binding;
using SonarLint.VisualStudio.SLCore.Common.Helpers;
using SonarLint.VisualStudio.SLCore.State;
-using SonarLint.VisualStudio.TestInfrastructure;
using SonarQube.Client.Models;
-namespace SonarLint.VisualStudio.Integration.UnitTests.MefServices;
+namespace SonarLint.VisualStudio.SLCore.UnitTests.State;
[TestClass]
public class ConfigScopeUpdaterTests
diff --git a/src/SLCore/Configuration/ISLCoreConfigurationProvider.cs b/src/SLCore/Configuration/ISLCoreConfigurationProvider.cs
new file mode 100644
index 000000000..d21ff3e66
--- /dev/null
+++ b/src/SLCore/Configuration/ISLCoreConfigurationProvider.cs
@@ -0,0 +1,29 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+namespace SonarLint.VisualStudio.SLCore.Configuration;
+
+internal interface ISLCoreConfigurationProvider : ISLCoreLocator,
+ ISLCoreConstantsProvider,
+ ISLCoreFoldersProvider,
+ ISLCoreEmbeddedPluginJarLocator
+{
+ // placeholder for implementation
+}
diff --git a/src/SLCore/Configuration/ISLCoreConstantsProvider.cs b/src/SLCore/Configuration/ISLCoreConstantsProvider.cs
new file mode 100644
index 000000000..19074a002
--- /dev/null
+++ b/src/SLCore/Configuration/ISLCoreConstantsProvider.cs
@@ -0,0 +1,30 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+using SonarLint.VisualStudio.SLCore.Service.Lifecycle.Models;
+
+namespace SonarLint.VisualStudio.SLCore.Configuration;
+
+internal interface ISLCoreConstantsProvider
+{
+ ClientConstantsDto ClientConstants { get; }
+ FeatureFlagsDto FeatureFlags { get; }
+ TelemetryClientConstantAttributesDto TelemetryConstants { get; }
+}
diff --git a/src/ConnectedMode/Binding/IServerConnectionConfigurationProvider.cs b/src/SLCore/Configuration/ISLCoreEmbeddedPluginJarLocator.cs
similarity index 76%
rename from src/ConnectedMode/Binding/IServerConnectionConfigurationProvider.cs
rename to src/SLCore/Configuration/ISLCoreEmbeddedPluginJarLocator.cs
index 1e021681d..9464b4a35 100644
--- a/src/ConnectedMode/Binding/IServerConnectionConfigurationProvider.cs
+++ b/src/SLCore/Configuration/ISLCoreEmbeddedPluginJarLocator.cs
@@ -19,12 +19,10 @@
*/
using System.Collections.Generic;
-using SonarLint.VisualStudio.SLCore.Service.Connection.Models;
-namespace SonarLint.VisualStudio.ConnectedMode.Binding
+namespace SonarLint.VisualStudio.SLCore.Configuration;
+
+internal interface ISLCoreEmbeddedPluginJarLocator
{
- public interface IServerConnectionConfigurationProvider
- {
- IEnumerable GetServerConnectionConfiguration();
- }
+ List ListJarFiles();
}
diff --git a/src/SLCore/Configuration/ISLCoreFoldersProvider.cs b/src/SLCore/Configuration/ISLCoreFoldersProvider.cs
new file mode 100644
index 000000000..4ef3c4f13
--- /dev/null
+++ b/src/SLCore/Configuration/ISLCoreFoldersProvider.cs
@@ -0,0 +1,26 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+namespace SonarLint.VisualStudio.SLCore.Configuration;
+
+internal interface ISLCoreFoldersProvider
+{
+ SLCoreFolders GetWorkFolders();
+}
diff --git a/src/SLCore/Core/Process/ISLCoreLocator.cs b/src/SLCore/Configuration/ISLCoreLocator.cs
similarity index 91%
rename from src/SLCore/Core/Process/ISLCoreLocator.cs
rename to src/SLCore/Configuration/ISLCoreLocator.cs
index e7642a049..7e60ae278 100644
--- a/src/SLCore/Core/Process/ISLCoreLocator.cs
+++ b/src/SLCore/Configuration/ISLCoreLocator.cs
@@ -18,9 +18,9 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-namespace SonarLint.VisualStudio.SLCore.Core.Process;
+namespace SonarLint.VisualStudio.SLCore.Configuration;
-internal interface ISLCoreLocator
+public interface ISLCoreLocator
{
SLCoreLaunchParameters LocateExecutable();
}
diff --git a/src/SLCore/Configuration/SLCoreFolders.cs b/src/SLCore/Configuration/SLCoreFolders.cs
new file mode 100644
index 000000000..8f01e8551
--- /dev/null
+++ b/src/SLCore/Configuration/SLCoreFolders.cs
@@ -0,0 +1,23 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+namespace SonarLint.VisualStudio.SLCore.Configuration;
+
+internal record SLCoreFolders(string StorageRoot, string WorkDir, string SonarlintUserHome);
diff --git a/src/SLCore/Core/Process/SLCoreLaunchParameters.cs b/src/SLCore/Configuration/SLCoreLaunchParameters.cs
similarity index 85%
rename from src/SLCore/Core/Process/SLCoreLaunchParameters.cs
rename to src/SLCore/Configuration/SLCoreLaunchParameters.cs
index 48d288df8..472793c96 100644
--- a/src/SLCore/Core/Process/SLCoreLaunchParameters.cs
+++ b/src/SLCore/Configuration/SLCoreLaunchParameters.cs
@@ -18,6 +18,6 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-namespace SonarLint.VisualStudio.SLCore.Core.Process;
+namespace SonarLint.VisualStudio.SLCore.Configuration;
-internal record SLCoreLaunchParameters(string PathToExecutable, string LaunchArguments);
+public record SLCoreLaunchParameters(string PathToExecutable, string LaunchArguments);
diff --git a/src/SLCore/Core/ISLCoreServiceProvider.cs b/src/SLCore/Core/ISLCoreServiceProvider.cs
index 915f01185..c8c65496b 100644
--- a/src/SLCore/Core/ISLCoreServiceProvider.cs
+++ b/src/SLCore/Core/ISLCoreServiceProvider.cs
@@ -89,7 +89,7 @@ public bool TryGetTransientService(out TService service) where TServic
}
catch (Exception ex)
{
- logger.WriteLine(Strings.SLCoreServiceProvider_CreateServiceError, ex.Message);
+ logger.WriteLine(SLCoreStrings.SLCoreServiceProvider_CreateServiceError, ex.Message);
return false;
}
cache.Add(serviceType, cachedService);
diff --git a/src/SLCore/Core/Process/ISLCoreProcessFactory.cs b/src/SLCore/Core/Process/ISLCoreProcessFactory.cs
index 0b0513ee7..7bc80feb8 100644
--- a/src/SLCore/Core/Process/ISLCoreProcessFactory.cs
+++ b/src/SLCore/Core/Process/ISLCoreProcessFactory.cs
@@ -18,6 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+using SonarLint.VisualStudio.SLCore.Configuration;
+
namespace SonarLint.VisualStudio.SLCore.Core.Process;
internal interface ISLCoreProcessFactory
diff --git a/src/SLCore/Core/Process/SLCoreProcess.cs b/src/SLCore/Core/Process/SLCoreProcess.cs
index aaa25f031..e566fc1e2 100644
--- a/src/SLCore/Core/Process/SLCoreProcess.cs
+++ b/src/SLCore/Core/Process/SLCoreProcess.cs
@@ -21,6 +21,7 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
+using SonarLint.VisualStudio.SLCore.Configuration;
namespace SonarLint.VisualStudio.SLCore.Core.Process;
diff --git a/src/SLCore/Core/Process/SLCoreProcessFactory.cs b/src/SLCore/Core/Process/SLCoreProcessFactory.cs
index 24c9efb34..46ebec3b6 100644
--- a/src/SLCore/Core/Process/SLCoreProcessFactory.cs
+++ b/src/SLCore/Core/Process/SLCoreProcessFactory.cs
@@ -20,6 +20,7 @@
using System.ComponentModel.Composition;
using System.Diagnostics.CodeAnalysis;
+using SonarLint.VisualStudio.SLCore.Configuration;
namespace SonarLint.VisualStudio.SLCore.Core.Process;
diff --git a/src/SLCore/ISLCoreRpcFactory.cs b/src/SLCore/ISLCoreRpcFactory.cs
index f298515f7..41000d7f3 100644
--- a/src/SLCore/ISLCoreRpcFactory.cs
+++ b/src/SLCore/ISLCoreRpcFactory.cs
@@ -21,12 +21,13 @@
using System;
using System.ComponentModel.Composition;
using System.Threading.Tasks;
+using SonarLint.VisualStudio.SLCore.Configuration;
using SonarLint.VisualStudio.SLCore.Core;
using SonarLint.VisualStudio.SLCore.Core.Process;
namespace SonarLint.VisualStudio.SLCore;
-public interface ISLCoreRpcFactory
+internal interface ISLCoreRpcFactory
{
ISLCoreRpc StartNewRpcInstance();
}
diff --git a/src/SLCore/SLCore.csproj b/src/SLCore/SLCore.csproj
index f2ac21e6b..c6d55f727 100644
--- a/src/SLCore/SLCore.csproj
+++ b/src/SLCore/SLCore.csproj
@@ -21,17 +21,17 @@
-
+
True
True
- Strings.resx
+ SLCoreStrings.resx
-
- ResXFileCodeGenerator
- Strings.Designer.cs
+
+ PublicResXFileCodeGenerator
+ SLCoreStrings.Designer.cs
diff --git a/src/SLCore/SLCoreHandle.cs b/src/SLCore/SLCoreHandle.cs
new file mode 100644
index 000000000..d4d523255
--- /dev/null
+++ b/src/SLCore/SLCoreHandle.cs
@@ -0,0 +1,125 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using SonarLint.VisualStudio.Core;
+using SonarLint.VisualStudio.Core.Binding;
+using SonarLint.VisualStudio.SLCore.Configuration;
+using SonarLint.VisualStudio.SLCore.Service.Connection.Models;
+using SonarLint.VisualStudio.SLCore.Service.Lifecycle;
+using SonarLint.VisualStudio.SLCore.Service.Rules.Models;
+using SonarLint.VisualStudio.SLCore.Service.Telemetry;
+using SonarLint.VisualStudio.SLCore.State;
+using Language = SonarLint.VisualStudio.SLCore.Common.Models.Language;
+
+namespace SonarLint.VisualStudio.SLCore;
+
+internal sealed class SLCoreHandle : IDisposable
+{
+ private readonly IActiveSolutionBoundTracker activeSolutionBoundTracker;
+ private readonly ISLCoreRpcFactory slCoreRpcFactory;
+ private readonly IServerConnectionsProvider serverConnectionConfigurationProvider;
+ private readonly IConfigScopeUpdater configScopeUpdater;
+ private readonly ISLCoreConstantsProvider constantsProvider;
+ private readonly ISLCoreFoldersProvider slCoreFoldersProvider;
+ private readonly ISLCoreEmbeddedPluginJarLocator slCoreEmbeddedPluginJarProvider;
+ private readonly IThreadHandling threadHandling;
+ private ISLCoreRpc slCoreRpc;
+
+
+ public SLCoreHandle(ISLCoreRpcFactory slCoreRpcFactory, ISLCoreConstantsProvider constantsProvider, ISLCoreFoldersProvider slCoreFoldersProvider,
+ IServerConnectionsProvider serverConnectionConfigurationProvider, ISLCoreEmbeddedPluginJarLocator slCoreEmbeddedPluginJarProvider,
+ IActiveSolutionBoundTracker activeSolutionBoundTracker, IConfigScopeUpdater configScopeUpdater, IThreadHandling threadHandling)
+ {
+ this.slCoreRpcFactory = slCoreRpcFactory;
+ this.constantsProvider = constantsProvider;
+ this.slCoreFoldersProvider = slCoreFoldersProvider;
+ this.serverConnectionConfigurationProvider = serverConnectionConfigurationProvider;
+ this.slCoreEmbeddedPluginJarProvider = slCoreEmbeddedPluginJarProvider;
+ this.activeSolutionBoundTracker = activeSolutionBoundTracker;
+ this.configScopeUpdater = configScopeUpdater;
+ this.threadHandling = threadHandling;
+ }
+
+ public async Task InitializeAsync()
+ {
+ threadHandling.ThrowIfOnUIThread();
+
+ slCoreRpc = slCoreRpcFactory.StartNewRpcInstance();
+
+ if (!slCoreRpc.ServiceProvider.TryGetTransientService(out ILifecycleManagementSLCoreService lifecycleManagementSlCoreService) ||
+ !slCoreRpc.ServiceProvider.TryGetTransientService(out ITelemetrySLCoreService telemetrySlCoreService))
+ {
+ throw new InvalidOperationException(SLCoreStrings.ServiceProviderNotInitialized);
+ }
+
+ var serverConnectionConfigurations = serverConnectionConfigurationProvider.GetServerConnections();
+ var (storageRoot, workDir, sonarlintUserHome) = slCoreFoldersProvider.GetWorkFolders();
+
+ await lifecycleManagementSlCoreService.InitializeAsync(new InitializeParams(
+ constantsProvider.ClientConstants,
+ new HttpConfigurationDto(new SslConfigurationDto()),
+ constantsProvider.FeatureFlags,
+ storageRoot,
+ workDir,
+ embeddedPluginPaths: slCoreEmbeddedPluginJarProvider.ListJarFiles(),
+ connectedModeEmbeddedPluginPathsByKey: new Dictionary(),
+ enabledLanguagesInStandaloneMode: new List
+ {
+ Language.C,
+ Language.CPP,
+ Language.CS,
+ Language.VBNET,
+ Language.JS,
+ Language.TS,
+ Language.CSS,
+ Language.SECRETS
+ },
+ extraEnabledLanguagesInConnectedMode: new List(),
+ serverConnectionConfigurations.Values.OfType().ToList(),
+ serverConnectionConfigurations.Values.OfType().ToList(),
+ sonarlintUserHome,
+ standaloneRuleConfigByKey: new Dictionary(),
+ isFocusOnNewCode: false,
+ constantsProvider.TelemetryConstants,
+ null));
+
+ telemetrySlCoreService.DisableTelemetry();
+
+ configScopeUpdater.UpdateConfigScopeForCurrentSolution(activeSolutionBoundTracker.CurrentConfiguration.Project);
+ }
+
+ public void Dispose()
+ {
+ if (slCoreRpc?.ServiceProvider?.TryGetTransientService(out ILifecycleManagementSLCoreService lifecycleManagementSlCoreService) ?? false)
+ {
+ threadHandling.Run(async () =>
+ {
+ await lifecycleManagementSlCoreService.ShutdownAsync();
+ return 0;
+ });
+ }
+
+ slCoreRpc?.Dispose();
+ }
+}
diff --git a/src/SLCore/Strings.Designer.cs b/src/SLCore/SLCoreStrings.Designer.cs
similarity index 87%
rename from src/SLCore/Strings.Designer.cs
rename to src/SLCore/SLCoreStrings.Designer.cs
index 0044437e1..d557f4f87 100644
--- a/src/SLCore/Strings.Designer.cs
+++ b/src/SLCore/SLCoreStrings.Designer.cs
@@ -1,6 +1,7 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -21,24 +22,24 @@ namespace SonarLint.VisualStudio.SLCore {
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- internal class Strings {
+ public class SLCoreStrings {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal Strings() {
+ internal SLCoreStrings() {
}
///
/// Returns the cached ResourceManager instance used by this class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager {
+ public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SonarLint.VisualStudio.SLCore.Strings", typeof(Strings).Assembly);
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SonarLint.VisualStudio.SLCore.SLCoreStrings", typeof(SLCoreStrings).Assembly);
resourceMan = temp;
}
return resourceMan;
@@ -50,7 +51,7 @@ internal Strings() {
/// resource lookups using this strongly typed resource class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture {
+ public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
@@ -62,7 +63,7 @@ internal Strings() {
///
/// Looks up a localized string similar to Service Provider is unavailable.
///
- internal static string ServiceProviderNotInitialized {
+ public static string ServiceProviderNotInitialized {
get {
return ResourceManager.GetString("ServiceProviderNotInitialized", resourceCulture);
}
@@ -71,7 +72,7 @@ internal static string ServiceProviderNotInitialized {
///
/// Looks up a localized string similar to "[SLCoreServiceProvider]Cannot Create Service. Error: {0}".
///
- internal static string SLCoreServiceProvider_CreateServiceError {
+ public static string SLCoreServiceProvider_CreateServiceError {
get {
return ResourceManager.GetString("SLCoreServiceProvider_CreateServiceError", resourceCulture);
}
diff --git a/src/SLCore/Strings.resx b/src/SLCore/SLCoreStrings.resx
similarity index 100%
rename from src/SLCore/Strings.resx
rename to src/SLCore/SLCoreStrings.resx
diff --git a/src/SLCore/State/ActiveConfigScopeTracker.cs b/src/SLCore/State/ActiveConfigScopeTracker.cs
index e283e043f..0be7b7a9f 100644
--- a/src/SLCore/State/ActiveConfigScopeTracker.cs
+++ b/src/SLCore/State/ActiveConfigScopeTracker.cs
@@ -94,7 +94,7 @@ public void SetCurrentConfigScope(string id, string connectionId = null, string
if (!serviceProvider.TryGetTransientService(out IConfigurationScopeSLCoreService configurationScopeService))
{
- throw new InvalidOperationException(Strings.ServiceProviderNotInitialized);
+ throw new InvalidOperationException(SLCoreStrings.ServiceProviderNotInitialized);
}
var configurationScopeDto = new ConfigurationScopeDto(id,
@@ -126,7 +126,7 @@ public void RemoveCurrentConfigScope()
if (!serviceProvider.TryGetTransientService(out IConfigurationScopeSLCoreService configurationScopeService))
{
- throw new InvalidOperationException(Strings.ServiceProviderNotInitialized);
+ throw new InvalidOperationException(SLCoreStrings.ServiceProviderNotInitialized);
}
using (asyncLock.Acquire())
diff --git a/src/SLCore/State/AliveConnectionTracker.cs b/src/SLCore/State/AliveConnectionTracker.cs
index 3a0542513..4749a5cd3 100644
--- a/src/SLCore/State/AliveConnectionTracker.cs
+++ b/src/SLCore/State/AliveConnectionTracker.cs
@@ -73,7 +73,7 @@ public void RefreshConnectionList()
if (!serviceProvider.TryGetTransientService(out IConnectionConfigurationSLCoreService connectionConfigurationService))
{
- throw new InvalidOperationException(Strings.ServiceProviderNotInitialized);
+ throw new InvalidOperationException(SLCoreStrings.ServiceProviderNotInitialized);
}
using (asyncLock.Acquire())
diff --git a/src/Integration/MefServices/ConfigScopeUpdater.cs b/src/SLCore/State/ConfigScopeUpdater.cs
similarity index 82%
rename from src/Integration/MefServices/ConfigScopeUpdater.cs
rename to src/SLCore/State/ConfigScopeUpdater.cs
index 8a51b0f94..eb5c16e76 100644
--- a/src/Integration/MefServices/ConfigScopeUpdater.cs
+++ b/src/SLCore/State/ConfigScopeUpdater.cs
@@ -24,14 +24,8 @@
using SonarLint.VisualStudio.Core;
using SonarLint.VisualStudio.Core.Binding;
using SonarLint.VisualStudio.SLCore.Common.Helpers;
-using SonarLint.VisualStudio.SLCore.State;
-namespace SonarLint.VisualStudio.Integration;
-
-internal interface IConfigScopeUpdater
-{
- void UpdateConfigScopeForCurrentSolution(BoundSonarQubeProject currentBinding);
-}
+namespace SonarLint.VisualStudio.SLCore.State;
[Export(typeof(IConfigScopeUpdater))]
[PartCreationPolicy(CreationPolicy.Shared)]
@@ -56,13 +50,13 @@ public void UpdateConfigScopeForCurrentSolution(BoundSonarQubeProject currentBin
var solutionName = solutionInfoProvider.GetSolutionName();
threadHandling.RunOnBackgroundThread(() =>
- {
- HandleConfigScopeUpdateInternal(solutionName,
- connectionIdHelper.GetConnectionIdFromUri(currentBinding?.ServerUri,
- currentBinding?.Organization?.Key),
- currentBinding?.ProjectKey);
- return Task.FromResult(0);
- }).Forget();
+ {
+ HandleConfigScopeUpdateInternal(solutionName,
+ connectionIdHelper.GetConnectionIdFromUri(currentBinding?.ServerUri,
+ currentBinding?.Organization?.Key),
+ currentBinding?.ProjectKey);
+ return Task.FromResult(0);
+ }).Forget();
}
private void HandleConfigScopeUpdateInternal(string solutionName, string connectionId, string projectKey)
diff --git a/src/SLCore/State/ServerConnectionsProvider.cs b/src/SLCore/State/ServerConnectionsProvider.cs
index 3aae1f1d6..09eaa32e1 100644
--- a/src/SLCore/State/ServerConnectionsProvider.cs
+++ b/src/SLCore/State/ServerConnectionsProvider.cs
@@ -26,7 +26,7 @@
namespace SonarLint.VisualStudio.SLCore.State;
-internal interface IServerConnectionsProvider
+public interface IServerConnectionsProvider
{
Dictionary GetServerConnections();
}