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/SLCoreTestRunner.cs b/src/SLCore.IntegrationTests/SLCoreTestRunner.cs index f1a8198a2e..dff4554381 100644 --- a/src/SLCore.IntegrationTests/SLCoreTestRunner.cs +++ b/src/SLCore.IntegrationTests/SLCoreTestRunner.cs @@ -103,7 +103,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 9f75549601..540f459c1d 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/ValidateConnectionParamsTests.cs b/src/SLCore.UnitTests/Service/Connection/ValidateConnectionParamsTests.cs index f1979e19ba..c23deda614 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" } } """; @@ -114,4 +116,37 @@ public void Ctor_TransientSonarCloudConnectionDtoDtoWithToken_SerializeAsExpecte serializedString.Should().Be(expectedString); } + + + [DataRow(SonarCloudRegion.EU, """ + { + "transientConnection": { + "organization": "myOrg", + "credentials": { + "token": "myToken" + }, + "region": "EU" + } + } + """)] + [DataRow(SonarCloudRegion.US, """ + { + "transientConnection": { + "organization": "myOrg", + "credentials": { + "token": "myToken" + }, + "region": "US" + } + } + """)] + [DataTestMethod] + public void Ctor_TransientSonarCloudConnectionWithRegion_SerializeAsExpected(SonarCloudRegion region, string expectedString) + { + var testSubject = new ValidateConnectionParams(new TransientSonarCloudConnectionDto("myOrg", Either.CreateLeft(new TokenDto("myToken")), region)); + + var serializedString = JsonConvert.SerializeObject(testSubject, Formatting.Indented); + + serializedString.Should().Be(expectedString); + } } diff --git a/src/SLCore.UnitTests/Service/Lifecycle/InitializeParamsTests.cs b/src/SLCore.UnitTests/Service/Lifecycle/InitializeParamsTests.cs index 1c99fa6128..7bea9bda1d 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 { @@ -107,8 +110,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/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)