From 3edccfaee9c33fedaee6d3b46867f0912810498c Mon Sep 17 00:00:00 2001 From: Georgii Borovinskikh <117642191+georgii-borovinskikh-sonarsource@users.noreply.github.com> Date: Wed, 5 Feb 2025 12:47:22 +0100 Subject: [PATCH] SLVS-1818 Upgrade SLCore to 10.14.0.80189 and adapt RPC changes for SQC multi-region (#5985) [SLVS-1818](https://sonarsource.atlassian.net/browse/SLVS-1818) [SLVS-1818]: https://sonarsource.atlassian.net/browse/SLVS-1818?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --- .../SlCoreConnectionAdapterTests.cs | 14 ++-- src/EmbeddedSonarAnalyzer.props | 2 +- .../InitializationTests.cs | 3 +- .../SLCoreTestRunner.cs | 2 +- .../SLCoreInstanceHandleTests.cs | 2 +- .../Connection/GetAllProjectsParamsTests.cs | 6 +- .../GetProjectNamesByKeyParamsTests.cs | 6 +- .../ListUserOrganizationsParamsTests.cs | 63 ++++++++++------ ...narCloudConnectionConfigurationDtoTests.cs | 73 ++++++++++++++++++ .../TransientSonarCloudConnectionDtoTests.cs | 75 +++++++++++++++++++ .../ValidateConnectionParamsTests.cs | 6 +- .../Lifecycle/InitializeParamsTests.cs | 12 ++- .../State/AliveConnectionTrackerTests.cs | 2 +- .../State/ServerConnectionsProviderTests.cs | 4 +- .../Connection/ListUserOrganizationsParams.cs | 4 +- ...> ServerConnectionConfigurationDtoBase.cs} | 7 +- .../SonarCloudConnectionConfigurationDto.cs | 9 +-- .../Connection/Models/SonarCloudRegion.cs | 29 +++++++ .../SonarQubeConnectionConfigurationDto.cs | 9 +-- .../TransientSonarCloudConnectionDto.cs | 3 +- src/SLCore/State/ServerConnectionsProvider.cs | 8 +- 21 files changed, 278 insertions(+), 61 deletions(-) create mode 100644 src/SLCore.UnitTests/Service/Connection/Models/SonarCloudConnectionConfigurationDtoTests.cs create mode 100644 src/SLCore.UnitTests/Service/Connection/Models/TransientSonarCloudConnectionDtoTests.cs rename src/SLCore/Service/Connection/Models/{ServerConnectionConfiguration.cs => ServerConnectionConfigurationDtoBase.cs} (90%) create mode 100644 src/SLCore/Service/Connection/Models/SonarCloudRegion.cs diff --git a/src/ConnectedMode.UnitTests/SlCoreConnectionAdapterTests.cs b/src/ConnectedMode.UnitTests/SlCoreConnectionAdapterTests.cs index 8ce28e7557..8417b84e6d 100644 --- a/src/ConnectedMode.UnitTests/SlCoreConnectionAdapterTests.cs +++ b/src/ConnectedMode.UnitTests/SlCoreConnectionAdapterTests.cs @@ -38,6 +38,7 @@ namespace SonarLint.VisualStudio.ConnectedMode.UnitTests; [TestClass] public class SlCoreConnectionAdapterTests { + private const string Token = "token123"; private static readonly TokenAuthCredentials ValidTokenAuth = new ("I_AM_JUST_A_TOKEN".ToSecureString()); private readonly ServerConnection.SonarQube sonarQubeConnection = new(new Uri("http://localhost:9000/"), new ServerConnectionSettings(true), ValidTokenAuth); private readonly ServerConnection.SonarCloud sonarCloudConnection = new("myOrg", new ServerConnectionSettings(true), ValidTokenAuth); @@ -176,7 +177,7 @@ public async Task GetOrganizationsAsync_TokenIsProvided_CallsSlCoreListUserOrgan await testSubject.GetOrganizationsAsync(new TokenCredentialsModel(token.CreateSecureString())); - await connectionConfigurationSlCoreService.Received(1).ListUserOrganizationsAsync(Arg.Is(x=> IsExpectedCredentials(x.credentials, token))); + await connectionConfigurationSlCoreService.Received(1).ListUserOrganizationsAsync(Arg.Is(x=> IsExpectedCredentials(x.credentials, token) && IsEuRegion(x))); } [TestMethod] @@ -192,10 +193,10 @@ public async Task GetOrganizationsAsync_CredentialsIsNull_ReturnsFailedResponseA [TestMethod] public async Task GetOrganizationsAsync_NoOrganizationExists_ReturnsSuccessResponseAndEmptyOrganizations() { - connectionConfigurationSlCoreService.ListUserOrganizationsAsync(Arg.Any()) + connectionConfigurationSlCoreService.ListUserOrganizationsAsync(Arg.Is(x => IsExpectedCredentials(x.credentials, Token) && IsEuRegion(x))) .Returns(new ListUserOrganizationsResponse([])); - var response = await testSubject.GetOrganizationsAsync(new TokenCredentialsModel("token".CreateSecureString())); + var response = await testSubject.GetOrganizationsAsync(new TokenCredentialsModel(Token.CreateSecureString())); response.Success.Should().BeTrue(); response.ResponseData.Should().BeEmpty(); @@ -205,10 +206,11 @@ public async Task GetOrganizationsAsync_NoOrganizationExists_ReturnsSuccessRespo public async Task GetOrganizationsAsync_OrganizationExists_ReturnsSuccessResponseAndMappedOrganizations() { List serverOrganizations = [new OrganizationDto("key", "name", "desc"), new OrganizationDto("key2", "name2", "desc2")]; - connectionConfigurationSlCoreService.ListUserOrganizationsAsync(Arg.Any()) + + connectionConfigurationSlCoreService.ListUserOrganizationsAsync(Arg.Is(x => IsExpectedCredentials(x.credentials, Token) && IsEuRegion(x))) .Returns(new ListUserOrganizationsResponse(serverOrganizations)); - var response = await testSubject.GetOrganizationsAsync(new TokenCredentialsModel("token".CreateSecureString())); + var response = await testSubject.GetOrganizationsAsync(new TokenCredentialsModel(Token.CreateSecureString())); response.Success.Should().BeTrue(); response.ResponseData.Should().BeEquivalentTo([ @@ -466,6 +468,8 @@ private bool IsExpectedSonarQubeConnectionParams(Either x.region == SonarCloudRegion.EU; + private static bool IsExpectedCredentials(Either credentials, string token) { return credentials.Left.token == token; diff --git a/src/EmbeddedSonarAnalyzer.props b/src/EmbeddedSonarAnalyzer.props index 665fed2785..23cf3b393c 100644 --- a/src/EmbeddedSonarAnalyzer.props +++ b/src/EmbeddedSonarAnalyzer.props @@ -10,6 +10,6 @@ 3.18.0.5605 2.20.0.5038 - 10.13.0.79996 + 10.14.0.80189 \ No newline at end of file diff --git a/src/SLCore.IntegrationTests/InitializationTests.cs b/src/SLCore.IntegrationTests/InitializationTests.cs index 10880a171e..8ca55c66f5 100644 --- a/src/SLCore.IntegrationTests/InitializationTests.cs +++ b/src/SLCore.IntegrationTests/InitializationTests.cs @@ -46,7 +46,8 @@ public async Task Sloop_StartedAndStoppedWithoutErrors() VerifyNoErrorsInLogs(testLogger); VerifyNoErrorsInLogs(slCoreErrorLogger); VerifyLogMessagesReceived(slCoreLogger); - slCoreLogger.AssertPartialOutputStringExists("SonarLint backend started"); + slCoreLogger.AssertPartialOutputStringExists("Telemetry disabled on server startup"); + slCoreLogger.AssertPartialOutputStringDoesNotExist("Internal error"); } [TestMethod] diff --git a/src/SLCore.IntegrationTests/SLCoreTestRunner.cs b/src/SLCore.IntegrationTests/SLCoreTestRunner.cs index 92bf61b102..e4e5f858ac 100644 --- a/src/SLCore.IntegrationTests/SLCoreTestRunner.cs +++ b/src/SLCore.IntegrationTests/SLCoreTestRunner.cs @@ -102,7 +102,7 @@ public void Start() foldersProvider.GetWorkFolders().Returns(new SLCoreFolders(storageRoot, workDir, userHome)); var connectionProvider = Substitute.For(); - connectionProvider.GetServerConnections().Returns(new Dictionary()); + connectionProvider.GetServerConnections().Returns(new Dictionary()); var jarProvider = Substitute.For(); jarProvider.ListJarFiles().Returns(DependencyLocator.AnalyzerPlugins); diff --git a/src/SLCore.UnitTests/SLCoreInstanceHandleTests.cs b/src/SLCore.UnitTests/SLCoreInstanceHandleTests.cs index 0eef716992..de778a4943 100644 --- a/src/SLCore.UnitTests/SLCoreInstanceHandleTests.cs +++ b/src/SLCore.UnitTests/SLCoreInstanceHandleTests.cs @@ -279,7 +279,7 @@ private void SetUpSuccessfulInitialization(out ILifecycleManagementSLCoreService constantsProvider.TelemetryConstants.Returns(TelemetryConstants); foldersProvider.GetWorkFolders().Returns(new SLCoreFolders(StorageRoot, WorkDir, UserHome)); - connectionsProvider.GetServerConnections().Returns(new Dictionary + connectionsProvider.GetServerConnections().Returns(new Dictionary { { SonarQubeConnection1.connectionId, SonarQubeConnection1 }, { SonarQubeConnection2.connectionId, SonarQubeConnection2 }, diff --git a/src/SLCore.UnitTests/Service/Connection/GetAllProjectsParamsTests.cs b/src/SLCore.UnitTests/Service/Connection/GetAllProjectsParamsTests.cs index dfadb7cd7b..bf6a46020d 100644 --- a/src/SLCore.UnitTests/Service/Connection/GetAllProjectsParamsTests.cs +++ b/src/SLCore.UnitTests/Service/Connection/GetAllProjectsParamsTests.cs @@ -102,7 +102,8 @@ public void Serialize_WithSonarCloudToken_AsExpected() "organization": "my-org", "credentials": { "token": "super-secret-token" - } + }, + "region": "EU" } } """; @@ -131,7 +132,8 @@ public void Serialize_WithSonarCloudUsernamePassword_AsExpected() "credentials": { "username": "jeff@thiscompany.com", "password": "betwEEn-me-and-U" - } + }, + "region": "EU" } } """; diff --git a/src/SLCore.UnitTests/Service/Connection/GetProjectNamesByKeyParamsTests.cs b/src/SLCore.UnitTests/Service/Connection/GetProjectNamesByKeyParamsTests.cs index 8c1ccc02d6..75c83196d7 100644 --- a/src/SLCore.UnitTests/Service/Connection/GetProjectNamesByKeyParamsTests.cs +++ b/src/SLCore.UnitTests/Service/Connection/GetProjectNamesByKeyParamsTests.cs @@ -115,7 +115,8 @@ public void Serialize_WithSonarCloudToken_AsExpected() "organization": "my-org", "credentials": { "token": "super-secret-token" - } + }, + "region": "EU" }, "projectKeys": [ "project-key-1", @@ -149,7 +150,8 @@ public void Serialize_WithSonarCloudUsernamePassword_AsExpected() "credentials": { "username": "jeff@thiscompany.com", "password": "betwEEn-me-and-U" - } + }, + "region": "EU" }, "projectKeys": [ "project-key-1", diff --git a/src/SLCore.UnitTests/Service/Connection/ListUserOrganizationsParamsTests.cs b/src/SLCore.UnitTests/Service/Connection/ListUserOrganizationsParamsTests.cs index 54233b36ca..ead2869425 100644 --- a/src/SLCore.UnitTests/Service/Connection/ListUserOrganizationsParamsTests.cs +++ b/src/SLCore.UnitTests/Service/Connection/ListUserOrganizationsParamsTests.cs @@ -22,43 +22,62 @@ using SonarLint.VisualStudio.SLCore.Common.Models; using SonarLint.VisualStudio.SLCore.Protocol; using SonarLint.VisualStudio.SLCore.Service.Connection; +using SonarLint.VisualStudio.SLCore.Service.Connection.Models; namespace SonarLint.VisualStudio.SLCore.UnitTests.Service.Connection; [TestClass] public class ListUserOrganizationsParamsTests { + + [DataRow(SonarCloudRegion.EU, """ + { + "credentials": { + "username": "myUser", + "password": "password" + }, + "region": "EU" + } + """)] + [DataRow(SonarCloudRegion.US, """ + { + "credentials": { + "username": "myUser", + "password": "password" + }, + "region": "US" + } + """)] [TestMethod] - public void Ctor_UsernamePasswordIsUsed_SerializeAsExpected() + public void Ctor_UsernamePasswordIsUsed_SerializeAsExpected(SonarCloudRegion region, string expectedString) { - var testSubject = new ListUserOrganizationsParams(Either.CreateRight(new UsernamePasswordDto("myUser", "password"))); - - const string expectedString = """ - { - "credentials": { - "username": "myUser", - "password": "password" - } - } - """; + var testSubject = new ListUserOrganizationsParams(new UsernamePasswordDto("myUser", "password"), region); var serializedString = JsonConvert.SerializeObject(testSubject, Formatting.Indented); serializedString.Should().Be(expectedString); } - [TestMethod] - public void Ctor_TokenIsUsed_SerializeAsExpected() + [DataRow(SonarCloudRegion.EU, """ + { + "credentials": { + "token": "mytoken" + }, + "region": "EU" + } + """)] + [DataRow(SonarCloudRegion.US, """ + { + "credentials": { + "token": "mytoken" + }, + "region": "US" + } + """)] + [DataTestMethod] + public void Ctor_TokenIsUsed_SerializeAsExpected(SonarCloudRegion region, string expectedString) { - var testSubject = new ListUserOrganizationsParams(Either.CreateLeft(new TokenDto("mytoken"))); - - const string expectedString = """ - { - "credentials": { - "token": "mytoken" - } - } - """; + var testSubject = new ListUserOrganizationsParams(new TokenDto("mytoken"), region); var serializedString = JsonConvert.SerializeObject(testSubject, Formatting.Indented); diff --git a/src/SLCore.UnitTests/Service/Connection/Models/SonarCloudConnectionConfigurationDtoTests.cs b/src/SLCore.UnitTests/Service/Connection/Models/SonarCloudConnectionConfigurationDtoTests.cs new file mode 100644 index 0000000000..c7860f10f7 --- /dev/null +++ b/src/SLCore.UnitTests/Service/Connection/Models/SonarCloudConnectionConfigurationDtoTests.cs @@ -0,0 +1,73 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2025 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 Newtonsoft.Json; +using SonarLint.VisualStudio.SLCore.Service.Connection.Models; + +namespace SonarLint.VisualStudio.SLCore.UnitTests.Service.Connection.Models; + +[TestClass] +public class SonarCloudConnectionConfigurationDtoTests +{ + + [DataRow("id", true, "org", SonarCloudRegion.EU, """ + { + "organization": "org", + "region": "EU", + "connectionId": "id", + "disableNotification": true + } + """)] + [DataRow("id id id", true, "org", SonarCloudRegion.EU, """ + { + "organization": "org", + "region": "EU", + "connectionId": "id id id", + "disableNotification": true + } + """)] + [DataRow("id", false, "org", SonarCloudRegion.EU, """ + { + "organization": "org", + "region": "EU", + "connectionId": "id", + "disableNotification": false + } + """)] + [DataRow("id", true, "org org org", SonarCloudRegion.EU, """ + { + "organization": "org org org", + "region": "EU", + "connectionId": "id", + "disableNotification": true + } + """)] + [DataRow("id", true, "org", SonarCloudRegion.US, """ + { + "organization": "org", + "region": "US", + "connectionId": "id", + "disableNotification": true + } + """)] + [DataTestMethod] + public void Serialize_AsExpected(string id, bool notificationEnabled, string organization, SonarCloudRegion region, string expected) => + JsonConvert.SerializeObject(new SonarCloudConnectionConfigurationDto(id, notificationEnabled, organization, region), Formatting.Indented).Should().Be(expected); +} diff --git a/src/SLCore.UnitTests/Service/Connection/Models/TransientSonarCloudConnectionDtoTests.cs b/src/SLCore.UnitTests/Service/Connection/Models/TransientSonarCloudConnectionDtoTests.cs new file mode 100644 index 0000000000..91662f4e9c --- /dev/null +++ b/src/SLCore.UnitTests/Service/Connection/Models/TransientSonarCloudConnectionDtoTests.cs @@ -0,0 +1,75 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2025 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 Newtonsoft.Json; +using SonarLint.VisualStudio.SLCore.Common.Models; +using SonarLint.VisualStudio.SLCore.Service.Connection.Models; + +namespace SonarLint.VisualStudio.SLCore.UnitTests.Service.Connection.Models; + +[TestClass] +public class TransientSonarCloudConnectionDtoTests +{ + [DataRow("my org", SonarCloudRegion.US, """ + { + "organization": "my org", + "credentials": { + "token": "abctoken" + }, + "region": "US" + } + """)] + [DataRow("my org two", SonarCloudRegion.EU, """ + { + "organization": "my org two", + "credentials": { + "token": "abctoken" + }, + "region": "EU" + } + """)] + [DataTestMethod] + public void Serialized_Token_AsExpected(string organization, SonarCloudRegion region, string expected) => + JsonConvert.SerializeObject(new TransientSonarCloudConnectionDto(organization, new TokenDto("abctoken"), region), Formatting.Indented).Should().Be(expected); + + [DataRow("my org", SonarCloudRegion.US, """ + { + "organization": "my org", + "credentials": { + "username": "usr", + "password": "pwd" + }, + "region": "US" + } + """)] + [DataRow("my org two", SonarCloudRegion.EU, """ + { + "organization": "my org two", + "credentials": { + "username": "usr", + "password": "pwd" + }, + "region": "EU" + } + """)] + [DataTestMethod] + public void Serialized_UsernameAndPassword_AsExpected(string organization, SonarCloudRegion region, string expected) => + JsonConvert.SerializeObject(new TransientSonarCloudConnectionDto(organization, new UsernamePasswordDto("usr", "pwd"), region), Formatting.Indented).Should().Be(expected); +} diff --git a/src/SLCore.UnitTests/Service/Connection/ValidateConnectionParamsTests.cs b/src/SLCore.UnitTests/Service/Connection/ValidateConnectionParamsTests.cs index f1979e19ba..bdb657ffcb 100644 --- a/src/SLCore.UnitTests/Service/Connection/ValidateConnectionParamsTests.cs +++ b/src/SLCore.UnitTests/Service/Connection/ValidateConnectionParamsTests.cs @@ -84,7 +84,8 @@ public void Ctor_TransientSonarCloudConnectionDtoWithCredentials_SerializeAsExpe "credentials": { "username": "myUser", "password": "password" - } + }, + "region": "EU" } } """; @@ -105,7 +106,8 @@ public void Ctor_TransientSonarCloudConnectionDtoDtoWithToken_SerializeAsExpecte "organization": "myOrg", "credentials": { "token": "myToken" - } + }, + "region": "EU" } } """; diff --git a/src/SLCore.UnitTests/Service/Lifecycle/InitializeParamsTests.cs b/src/SLCore.UnitTests/Service/Lifecycle/InitializeParamsTests.cs index 6a3b7439c3..63e496394b 100644 --- a/src/SLCore.UnitTests/Service/Lifecycle/InitializeParamsTests.cs +++ b/src/SLCore.UnitTests/Service/Lifecycle/InitializeParamsTests.cs @@ -45,7 +45,10 @@ public void Serialize_AsExpected() [Language.CPP], ["csharp"], [new SonarQubeConnectionConfigurationDto("con1", true, "localhost")], - [new SonarCloudConnectionConfigurationDto("con2", false, "organization1")], + [ + new SonarCloudConnectionConfigurationDto("con2", false, "organization1"), + new SonarCloudConnectionConfigurationDto("con3", true, "organization2", SonarCloudRegion.US) + ], "userHome", new Dictionary { @@ -106,8 +109,15 @@ [new SonarCloudConnectionConfigurationDto("con2", false, "organization1")], "sonarCloudConnections": [ { "organization": "organization1", + "region": "EU", "connectionId": "con2", "disableNotification": false + }, + { + "organization": "organization2", + "region": "US", + "connectionId": "con3", + "disableNotification": true } ], "sonarlintUserHome": "userHome", diff --git a/src/SLCore.UnitTests/State/AliveConnectionTrackerTests.cs b/src/SLCore.UnitTests/State/AliveConnectionTrackerTests.cs index cb984b52c7..0cb2647616 100644 --- a/src/SLCore.UnitTests/State/AliveConnectionTrackerTests.cs +++ b/src/SLCore.UnitTests/State/AliveConnectionTrackerTests.cs @@ -258,7 +258,7 @@ private static void VerifyLockTakenAndReleased(Mock asyncLock, Mock< } private static void ConfigureConnectionProvider(out Mock connectionProvider, - params ServerConnectionConfiguration[] connections) + params ServerConnectionConfigurationDtoBase[] connections) { connectionProvider = new Mock(); connectionProvider.Setup(x => x.GetServerConnections()).Returns(connections.ToDictionary(x => x.connectionId, x => x)); diff --git a/src/SLCore.UnitTests/State/ServerConnectionsProviderTests.cs b/src/SLCore.UnitTests/State/ServerConnectionsProviderTests.cs index 249865c039..78fc75f130 100644 --- a/src/SLCore.UnitTests/State/ServerConnectionsProviderTests.cs +++ b/src/SLCore.UnitTests/State/ServerConnectionsProviderTests.cs @@ -83,7 +83,7 @@ public void GetServerConnections_CorrectlyReturnsSonarCloudConnection() var serverConnections = testSubject.GetServerConnections(); serverConnections.Should().HaveCount(1); - serverConnections[connection.Id].Should().BeOfType().Which.organization.Should().Be(organizationKey); + serverConnections[connection.Id].Should().BeEquivalentTo(new SonarCloudConnectionConfigurationDto("https://sonarcloud.io/organizations/org", false, "org", SonarCloudRegion.EU)); } [TestMethod] @@ -99,7 +99,7 @@ public void GetServerConnections_CorrectlyReturnsSonarCloudNotifications(bool is var serverConnections = testSubject.GetServerConnections(); serverConnections.Should().HaveCount(1); - serverConnections[connection.Id].Should().BeOfType().Which.disableNotification.Should().Be(!isSmartNotificationsEnabled); + serverConnections[connection.Id].Should().BeEquivalentTo(new SonarCloudConnectionConfigurationDto("https://sonarcloud.io/organizations/org", !isSmartNotificationsEnabled, "org", SonarCloudRegion.EU)); } [TestMethod] diff --git a/src/SLCore/Service/Connection/ListUserOrganizationsParams.cs b/src/SLCore/Service/Connection/ListUserOrganizationsParams.cs index f1db9657d1..6e85ed9a50 100644 --- a/src/SLCore/Service/Connection/ListUserOrganizationsParams.cs +++ b/src/SLCore/Service/Connection/ListUserOrganizationsParams.cs @@ -21,9 +21,11 @@ using Newtonsoft.Json; using SonarLint.VisualStudio.SLCore.Common.Models; using SonarLint.VisualStudio.SLCore.Protocol; +using SonarLint.VisualStudio.SLCore.Service.Connection.Models; namespace SonarLint.VisualStudio.SLCore.Service.Connection; public record ListUserOrganizationsParams( [property: JsonConverter(typeof(EitherJsonConverter))] - Either credentials); + Either credentials, + SonarCloudRegion region = SonarCloudRegion.EU); diff --git a/src/SLCore/Service/Connection/Models/ServerConnectionConfiguration.cs b/src/SLCore/Service/Connection/Models/ServerConnectionConfigurationDtoBase.cs similarity index 90% rename from src/SLCore/Service/Connection/Models/ServerConnectionConfiguration.cs rename to src/SLCore/Service/Connection/Models/ServerConnectionConfigurationDtoBase.cs index 3c8457a98c..752791153d 100644 --- a/src/SLCore/Service/Connection/Models/ServerConnectionConfiguration.cs +++ b/src/SLCore/Service/Connection/Models/ServerConnectionConfigurationDtoBase.cs @@ -18,7 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -namespace SonarLint.VisualStudio.SLCore.Service.Connection.Models -{ - public record ServerConnectionConfiguration(string connectionId, bool disableNotification); -} +namespace SonarLint.VisualStudio.SLCore.Service.Connection.Models; + +public record ServerConnectionConfigurationDtoBase(string connectionId, bool disableNotification); diff --git a/src/SLCore/Service/Connection/Models/SonarCloudConnectionConfigurationDto.cs b/src/SLCore/Service/Connection/Models/SonarCloudConnectionConfigurationDto.cs index 86a7d1025d..b65ff9a056 100644 --- a/src/SLCore/Service/Connection/Models/SonarCloudConnectionConfigurationDto.cs +++ b/src/SLCore/Service/Connection/Models/SonarCloudConnectionConfigurationDto.cs @@ -18,8 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -namespace SonarLint.VisualStudio.SLCore.Service.Connection.Models -{ - public record SonarCloudConnectionConfigurationDto(string connectionId, bool disableNotification, string organization) - : ServerConnectionConfiguration(connectionId, disableNotification); -} +namespace SonarLint.VisualStudio.SLCore.Service.Connection.Models; + +public record SonarCloudConnectionConfigurationDto(string connectionId, bool disableNotification, string organization, SonarCloudRegion region = SonarCloudRegion.EU) + : ServerConnectionConfigurationDtoBase(connectionId, disableNotification); diff --git a/src/SLCore/Service/Connection/Models/SonarCloudRegion.cs b/src/SLCore/Service/Connection/Models/SonarCloudRegion.cs new file mode 100644 index 0000000000..9894ab1d7b --- /dev/null +++ b/src/SLCore/Service/Connection/Models/SonarCloudRegion.cs @@ -0,0 +1,29 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2025 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 Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace SonarLint.VisualStudio.SLCore.Service.Connection.Models; + +[JsonConverter(typeof(StringEnumConverter))] +public enum SonarCloudRegion { + EU, US +} diff --git a/src/SLCore/Service/Connection/Models/SonarQubeConnectionConfigurationDto.cs b/src/SLCore/Service/Connection/Models/SonarQubeConnectionConfigurationDto.cs index 67e228fe5c..ce3e207a00 100644 --- a/src/SLCore/Service/Connection/Models/SonarQubeConnectionConfigurationDto.cs +++ b/src/SLCore/Service/Connection/Models/SonarQubeConnectionConfigurationDto.cs @@ -18,8 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -namespace SonarLint.VisualStudio.SLCore.Service.Connection.Models -{ - public record SonarQubeConnectionConfigurationDto(string connectionId, bool disableNotification, string serverUrl) - : ServerConnectionConfiguration(connectionId, disableNotification); -} +namespace SonarLint.VisualStudio.SLCore.Service.Connection.Models; + +public record SonarQubeConnectionConfigurationDto(string connectionId, bool disableNotification, string serverUrl) + : ServerConnectionConfigurationDtoBase(connectionId, disableNotification); diff --git a/src/SLCore/Service/Connection/Models/TransientSonarCloudConnectionDto.cs b/src/SLCore/Service/Connection/Models/TransientSonarCloudConnectionDto.cs index 0bb20013af..b5ece3be29 100644 --- a/src/SLCore/Service/Connection/Models/TransientSonarCloudConnectionDto.cs +++ b/src/SLCore/Service/Connection/Models/TransientSonarCloudConnectionDto.cs @@ -27,4 +27,5 @@ namespace SonarLint.VisualStudio.SLCore.Service.Connection.Models; public record TransientSonarCloudConnectionDto( string organization, [property: JsonConverter(typeof(EitherJsonConverter))] - Either credentials); + Either credentials, + SonarCloudRegion region = SonarCloudRegion.EU); diff --git a/src/SLCore/State/ServerConnectionsProvider.cs b/src/SLCore/State/ServerConnectionsProvider.cs index 95f3cecb1d..96e81ca360 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 { - Dictionary GetServerConnections(); + Dictionary GetServerConnections(); } [Export(typeof(IServerConnectionsProvider))] @@ -41,15 +41,15 @@ public ServerConnectionsProvider(IServerConnectionsRepository serverConnectionsR this.serverConnectionsRepository = serverConnectionsRepository; } - public Dictionary GetServerConnections() + public Dictionary GetServerConnections() { var succeeded = serverConnectionsRepository.TryGetAll(out var serverConnections); return succeeded ? GetServerConnectionConfigurations(serverConnections).ToDictionary(conf => conf.connectionId) : []; } - private static List GetServerConnectionConfigurations(IReadOnlyList serverConnections) + private static List GetServerConnectionConfigurations(IReadOnlyList serverConnections) { - var serverConnectionConfigurations = new List(); + var serverConnectionConfigurations = new List(); foreach (var serverConnection in serverConnections) { switch (serverConnection)