diff --git a/src/ConnectedMode.UnitTests/UI/ManageBinding/ManageBindingViewModelTests.cs b/src/ConnectedMode.UnitTests/UI/ManageBinding/ManageBindingViewModelTests.cs index 51fd618ad..eb524d86a 100644 --- a/src/ConnectedMode.UnitTests/UI/ManageBinding/ManageBindingViewModelTests.cs +++ b/src/ConnectedMode.UnitTests/UI/ManageBinding/ManageBindingViewModelTests.cs @@ -40,11 +40,11 @@ namespace SonarLint.VisualStudio.ConnectedMode.UnitTests.UI.ManageBinding; public class ManageBindingViewModelTests { private const string ALocalProjectKey = "local-project-key"; - - private readonly ServerProject serverProject = new ("a-project", "A Project"); - private readonly ConnectionInfo sonarQubeConnectionInfo = new ("http://localhost:9000", ConnectionServerType.SonarQube); - private readonly ConnectionInfo sonarCloudConnectionInfo = new ("organization", ConnectionServerType.SonarCloud); - private readonly BasicAuthCredentials validCredentials = new ("TOKEN", new SecureString()); + + private readonly ServerProject serverProject = new("a-project", "A Project"); + private readonly ConnectionInfo sonarQubeConnectionInfo = new("http://localhost:9000", ConnectionServerType.SonarQube); + private readonly ConnectionInfo sonarCloudConnectionInfo = new("organization", ConnectionServerType.SonarCloud); + private readonly BasicAuthCredentials validCredentials = new("TOKEN", new SecureString()); private readonly SharedBindingConfigModel sonarQubeSharedBindingConfigModel = new() { Uri = new Uri("http://localhost:9000"), ProjectKey = "myProj" }; private readonly SharedBindingConfigModel sonarCloudSharedBindingConfigModel = new() { Organization = "myOrg", ProjectKey = "myProj" }; @@ -210,16 +210,7 @@ await progressReporterViewModel.Received(1) x.TaskToPerform == testSubject.UnbindAsync && x.ProgressStatus == UiResources.UnbindingInProgressText && x.WarningText == UiResources.UnbindingFailedText && - x.AfterProgressUpdated == testSubject.OnProgressUpdated && - x.AfterSuccess == testSubject.AfterUnbind)); - } - - [TestMethod] - public async Task UnbindAsync_UnbindsOnUIThread() - { - await testSubject.UnbindAsync(); - - await threadHandling.Received(1).RunOnUIThreadAsync(Arg.Any()); + x.AfterProgressUpdated == testSubject.OnProgressUpdated)); } [TestMethod] @@ -239,7 +230,6 @@ public async Task UnbindAsync_UnbindsCurrentSolution() public async Task UnbindAsync_ReturnsResponseOfUnbinding(bool expectedResponse) { await InitializeBoundProject(); - connectedModeServices.ThreadHandling.Returns(new NoOpThreadHandler()); connectedModeBindingServices.BindingController.Unbind(Arg.Any()).Returns(expectedResponse); var adapterResponse = await testSubject.UnbindAsync(); @@ -250,10 +240,9 @@ public async Task UnbindAsync_ReturnsResponseOfUnbinding(bool expectedResponse) [TestMethod] public async Task UnbindAsync_UnbindingThrows_ReturnsFalse() { + await InitializeBoundProject(); var exceptionMsg = "Failed to load connections"; - var mockedThreadHandling = Substitute.For(); - connectedModeServices.ThreadHandling.Returns(mockedThreadHandling); - mockedThreadHandling.When(x => x.RunOnUIThreadAsync(Arg.Any())).Do(_ => throw new Exception(exceptionMsg)); + connectedModeBindingServices.BindingController.When(x => x.Unbind(Arg.Any())).Do(_ => throw new Exception(exceptionMsg)); var adapterResponse = await testSubject.UnbindAsync(); @@ -262,23 +251,14 @@ public async Task UnbindAsync_UnbindingThrows_ReturnsFalse() } [TestMethod] - public void AfterUnbind_SetsBoundProjectToNull() + public async Task UnbindAsync_ClearsBindingProperties() { - testSubject.BoundProject = serverProject; + await InitializeBoundProject(); + SetupConfigurationProvider(new BindingConfiguration(null, SonarLintMode.Standalone, null)); - testSubject.AfterUnbind(new AdapterResponse(true)); + await testSubject.UnbindAsync(); testSubject.BoundProject.Should().BeNull(); - } - - [TestMethod] - public void AfterUnbind_SetsConnectionInfoToNull() - { - testSubject.SelectedConnectionInfo = sonarQubeConnectionInfo; - testSubject.SelectedProject = serverProject; - - testSubject.AfterUnbind(new AdapterResponse(true)); - testSubject.SelectedConnectionInfo.Should().BeNull(); testSubject.SelectedProject.Should().BeNull(); } @@ -552,7 +532,7 @@ await progressReporterViewModel.Received(1) x.WarningText == UiResources.LoadingConnectionsFailedText && x.AfterProgressUpdated == testSubject.OnProgressUpdated)); } - + [TestMethod] public async Task InitializeDataAsync_DisplaysBindStatusAndReportsProgress() { @@ -566,12 +546,12 @@ await progressReporterViewModel.Received(1) x.WarningText == UiResources.FetchingBindingStatusFailedText && x.AfterProgressUpdated == testSubject.OnProgressUpdated)); } - + [TestMethod] public async Task InitializeDataAsync_WhenStandalone_ChecksForSharedBindingAndReportsProgress() { SetupUnboundProject(); - + await testSubject.InitializeDataAsync(); await progressReporterViewModel.Received(1) @@ -582,12 +562,12 @@ await progressReporterViewModel.Received(1) x.WarningText == UiResources.CheckingForSharedBindingFailedText && x.AfterProgressUpdated == testSubject.OnProgressUpdated)); } - + [TestMethod] public async Task InitializeDataAsync_WhenBound_DoesNotChecksForSharedBindingAndReportsProgress() { testSubject.BoundProject = serverProject; - + await testSubject.InitializeDataAsync(); await progressReporterViewModel.DidNotReceive() @@ -603,20 +583,20 @@ await progressReporterViewModel.DidNotReceive() public async Task DisplayBindStatusAsync_WhenProjectIsNotBound_Succeeds() { SetupUnboundProject(); - + var response = await testSubject.DisplayBindStatusAsync(); - + response.Should().BeEquivalentTo(new AdapterResponse(true)); } - + [TestMethod] public async Task DisplayBindStatusAsync_WhenProjectIsBoundAndBindingStatusIsFetched_Succeeds() { var sonarCloudConnection = new ServerConnection.SonarCloud("organization", credentials: validCredentials); SetupBoundProject(sonarCloudConnection, serverProject); - + var response = await testSubject.DisplayBindStatusAsync(); - + testSubject.BoundProject.Should().NotBeNull(); response.Should().BeEquivalentTo(new AdapterResponse(true)); } @@ -626,9 +606,9 @@ public async Task DisplayBindStatusAsync_WhenProjectIsBoundButBindingStatusIsNot { var sonarCloudConnection = new ServerConnection.SonarCloud("organization", credentials: validCredentials); SetupBoundProjectThatDoesNotExistOnServer(sonarCloudConnection); - + var response = await testSubject.DisplayBindStatusAsync(); - + testSubject.BoundProject.Should().BeNull(); response.Should().BeEquivalentTo(new AdapterResponse(false)); } @@ -638,23 +618,23 @@ public async Task DisplayBindStatusAsync_WhenSolutionIsOpen_FetchesSolutionInfo( { solutionInfoProvider.GetSolutionNameAsync().Returns("Local solution name"); solutionInfoProvider.IsFolderWorkspaceAsync().Returns(false); - + await testSubject.DisplayBindStatusAsync(); - + testSubject.SolutionInfo.Should().BeEquivalentTo(new SolutionInfoModel("Local solution name", SolutionType.Solution)); } - + [TestMethod] public async Task DisplayBindStatusAsync_WhenFolderIsOpen_FetchesSolutionInfo() { solutionInfoProvider.GetSolutionNameAsync().Returns("Local folder name"); solutionInfoProvider.IsFolderWorkspaceAsync().Returns(true); - + await testSubject.DisplayBindStatusAsync(); - + testSubject.SolutionInfo.Should().BeEquivalentTo(new SolutionInfoModel("Local folder name", SolutionType.Folder)); } - + [TestMethod] public async Task DisplayBindStatusAsync_WhenProjectIsBoundToSonarCloud_SelectsBoundSonarCloudConnection() { @@ -662,7 +642,7 @@ public async Task DisplayBindStatusAsync_WhenProjectIsBoundToSonarCloud_SelectsB SetupBoundProject(sonarCloudConnection); await testSubject.DisplayBindStatusAsync(); - + testSubject.SelectedConnectionInfo.Should().BeEquivalentTo(new ConnectionInfo("organization", ConnectionServerType.SonarCloud)); } @@ -671,17 +651,17 @@ public async Task DisplayBindStatusAsync_WhenProjectIsBoundToSonarQube_SelectsBo { var sonarQubeConnection = new ServerConnection.SonarQube(new Uri("http://localhost:9000/"), credentials: validCredentials); SetupBoundProject(sonarQubeConnection); - + await testSubject.DisplayBindStatusAsync(); - + testSubject.SelectedConnectionInfo.Should().BeEquivalentTo(new ConnectionInfo("http://localhost:9000/", ConnectionServerType.SonarQube)); } - + [TestMethod] public async Task DisplayBindStatusAsync_WhenProjectIsNotBound_SelectedConnectionShouldBeEmpty() { SetupUnboundProject(); - + await testSubject.DisplayBindStatusAsync(); testSubject.SelectedConnectionInfo.Should().BeNull(); @@ -693,9 +673,9 @@ public async Task DisplayBindStatusAsync_WhenProjectIsBound_SelectsServerProject var expectedServerProject = new ServerProject("server-project-key", "server-project-name"); var sonarCloudConnection = new ServerConnection.SonarCloud("organization", credentials: validCredentials); SetupBoundProject(sonarCloudConnection, expectedServerProject); - + await testSubject.DisplayBindStatusAsync(); - + testSubject.SelectedProject.Should().BeEquivalentTo(expectedServerProject); testSubject.BoundProject.Should().BeEquivalentTo(testSubject.SelectedProject); } @@ -705,13 +685,26 @@ public async Task DisplayBindStatusAsync_WhenProjectIsBoundButProjectNotFoundOnS { var sonarCloudConnection = new ServerConnection.SonarCloud("organization", credentials: validCredentials); SetupBoundProjectThatDoesNotExistOnServer(sonarCloudConnection); - + await testSubject.DisplayBindStatusAsync(); - + testSubject.SelectedProject.Should().BeNull(); testSubject.BoundProject.Should().BeNull(); } - + + [TestMethod] + public async Task DisplayBindStatusAsync_WhenProjectWasBoundAndBecomesUnbound_UpdatesCurrentProjectAndBindingInfoToNull() + { + await InitializeBoundProject(); + SetupUnboundProject(); + + await testSubject.DisplayBindStatusAsync(); + + testSubject.BoundProject.Should().BeNull(); + testSubject.SelectedConnectionInfo.Should().BeNull(); + testSubject.SelectedProject.Should().BeNull(); + } + [TestMethod] public async Task LoadDataAsync_LoadsConnectionsOnUIThread() { @@ -774,21 +767,21 @@ public async Task BindAsync_WhenConnectionNotFound_Fails() callInfo[1] = null; return false; }); - + var response = await testSubject.BindAsync(); - + response.Success.Should().BeFalse(); } - + [TestMethod] public async Task BindAsync_WhenBindingFailsUnexpectedly_FailsAndLogs() { var sonarCloudConnection = new ServerConnection.SonarCloud("organization", credentials: validCredentials); SetupConnectionAndProjectToBind(sonarCloudConnection, serverProject); bindingController.BindAsync(Arg.Any(), Arg.Any()).ThrowsAsync(new Exception("Failed unexpectedly")); - + var response = await testSubject.BindAsync(); - + response.Success.Should().BeFalse(); logger.Received(1).WriteLine(Resources.Binding_Fails, "Failed unexpectedly"); } @@ -800,7 +793,7 @@ public async Task BindAsync_WhenBindingCompletesSuccessfully_Succeeds() SetupConnectionAndProjectToBind(sonarCloudConnection, serverProject); var response = await testSubject.BindAsync(); - + response.Success.Should().BeTrue(); } @@ -809,9 +802,9 @@ public async Task BindAsync_WhenBindingCompletesSuccessfully_SetsBoundProjectToS { var sonarCloudConnection = new ServerConnection.SonarCloud("organization", credentials: validCredentials); SetupConnectionAndProjectToBind(sonarCloudConnection, serverProject); - + await testSubject.BindAsync(); - + testSubject.BoundProject.Should().BeEquivalentTo(serverProject); } @@ -826,7 +819,7 @@ public async Task CheckForSharedBindingAsync_WhenSharedBindingExists_SetsSharedB sharedBindingConfigProvider.Received(1).GetSharedBinding(); testSubject.SharedBindingConfigModel.Should().Be(sharedBindingModel); } - + [TestMethod] public async Task CheckForSharedBindingAsync_WhenSharedBindingDoesNotExist_SetsNullSharedBindingConfigModel() { @@ -866,7 +859,7 @@ public async Task UseSharedBindingAsync_SharedBindingForSonarQubeConnection_Bind response.Success.Should().BeTrue(); await bindingController.Received(1) .BindAsync(Arg.Is(proj => - proj.ServerProjectKey == testSubject.SharedBindingConfigModel.ProjectKey), Arg.Any()); + proj.ServerProjectKey == testSubject.SharedBindingConfigModel.ProjectKey), Arg.Any()); } [TestMethod] @@ -905,7 +898,7 @@ public async Task UseSharedBindingAsync_SharedBindingForExistingSonarCloudConnec { testSubject.SelectedProject = serverProject; // this is to make sure the SelectedProject is ignored and the shared config is used instead testSubject.SharedBindingConfigModel = sonarCloudSharedBindingConfigModel; - var expectedServerConnection = new ServerConnection.SonarCloud(testSubject.SharedBindingConfigModel.Organization); + var expectedServerConnection = new ServerConnection.SonarCloud(testSubject.SharedBindingConfigModel.Organization); SetupBoundProject(expectedServerConnection); var response = await testSubject.UseSharedBindingAsync(); @@ -925,7 +918,8 @@ public async Task UseSharedBindingAsync_SharedBindingForNonExistingSonarQubeConn var response = await testSubject.UseSharedBindingAsync(); response.Success.Should().BeFalse(); - messageBox.Received(1).Show(UiResources.NotFoundConnectionForSharedBindingMessageBoxText, UiResources.NotFoundConnectionForSharedBindingMessageBoxCaption, MessageBoxButton.OK, MessageBoxImage.Warning); + messageBox.Received(1).Show(UiResources.NotFoundConnectionForSharedBindingMessageBoxText, UiResources.NotFoundConnectionForSharedBindingMessageBoxCaption, MessageBoxButton.OK, + MessageBoxImage.Warning); logger.WriteLine(Resources.UseSharedBinding_ConnectionNotFound, testSubject.SharedBindingConfigModel.Uri); await bindingController.DidNotReceive() .BindAsync(Arg.Is(proj => @@ -942,7 +936,8 @@ public async Task UseSharedBindingAsync_SharedBindingForNonExistingSonarCloudCon response.Success.Should().BeFalse(); logger.WriteLine(Resources.UseSharedBinding_ConnectionNotFound, testSubject.SharedBindingConfigModel.Organization); - messageBox.Received(1).Show(UiResources.NotFoundConnectionForSharedBindingMessageBoxText, UiResources.NotFoundConnectionForSharedBindingMessageBoxCaption, MessageBoxButton.OK, MessageBoxImage.Warning); + messageBox.Received(1).Show(UiResources.NotFoundConnectionForSharedBindingMessageBoxText, UiResources.NotFoundConnectionForSharedBindingMessageBoxCaption, MessageBoxButton.OK, + MessageBoxImage.Warning); await bindingController.DidNotReceive() .BindAsync(Arg.Is(proj => proj.ServerProjectKey == testSubject.SharedBindingConfigModel.ProjectKey), Arg.Any()); @@ -960,13 +955,13 @@ public async Task UseSharedBindingAsync_SharedBindingSonarCloudConnectionWithMis response.Success.Should().BeFalse(); logger.WriteLine(Resources.UseSharedBinding_CredentiasNotFound, testSubject.SharedBindingConfigModel.Organization); - messageBox.Received(1).Show(UiResources.NotFoundCredentialsForSharedBindingMessageBoxText, UiResources.NotFoundCredentialsForSharedBindingMessageBoxCaption, MessageBoxButton.OK, MessageBoxImage.Warning); + messageBox.Received(1).Show(UiResources.NotFoundCredentialsForSharedBindingMessageBoxText, UiResources.NotFoundCredentialsForSharedBindingMessageBoxCaption, MessageBoxButton.OK, + MessageBoxImage.Warning); await bindingController.DidNotReceive() .BindAsync(Arg.Is(proj => proj.ServerProjectKey == testSubject.SharedBindingConfigModel.ProjectKey), Arg.Any()); } - [TestMethod] public async Task UseSharedBindingAsync_SharedBindingSonarQubeConnectionWithMissingCredentials_ReturnsFalseAndLogsAndInformsUser() { @@ -979,7 +974,8 @@ public async Task UseSharedBindingAsync_SharedBindingSonarQubeConnectionWithMiss response.Success.Should().BeFalse(); logger.WriteLine(Resources.UseSharedBinding_CredentiasNotFound, testSubject.SharedBindingConfigModel.Uri); - messageBox.Received(1).Show(UiResources.NotFoundCredentialsForSharedBindingMessageBoxText, UiResources.NotFoundCredentialsForSharedBindingMessageBoxCaption, MessageBoxButton.OK, MessageBoxImage.Warning); + messageBox.Received(1).Show(UiResources.NotFoundCredentialsForSharedBindingMessageBoxText, UiResources.NotFoundCredentialsForSharedBindingMessageBoxCaption, MessageBoxButton.OK, + MessageBoxImage.Warning); await bindingController.DidNotReceive() .BindAsync(Arg.Is(proj => proj.ServerProjectKey == testSubject.SharedBindingConfigModel.ProjectKey), Arg.Any()); @@ -999,7 +995,6 @@ public async Task UseSharedBindingAsync_BindingFails_ReturnsFalse() response.Success.Should().BeFalse(); } - private void MockServices() { serverConnectionsRepositoryAdapter = Substitute.For(); @@ -1030,18 +1025,18 @@ private void MockTryGetAllConnectionsInfo(List connectionInfos) return true; }); } - + private void SetupConnectionAndProjectToBind(ServerConnection selectedServerConnection, ServerProject selectedServerProject) { SetupBoundProject(selectedServerConnection, selectedServerProject); testSubject.SelectedConnectionInfo = sonarCloudConnectionInfo; testSubject.SelectedProject = selectedServerProject; } - + private void SetupBoundProject(ServerConnection serverConnection, ServerProject expectedServerProject = null) { expectedServerProject ??= serverProject; - + serverConnection.Credentials = validCredentials; var boundServerProject = new BoundServerProject(ALocalProjectKey, expectedServerProject.Key, serverConnection); var configurationProvider = Substitute.For(); @@ -1049,7 +1044,7 @@ private void SetupBoundProject(ServerConnection serverConnection, ServerProject connectedModeServices.ConfigurationProvider.Returns(configurationProvider); MockTryGetServerConnection(serverConnection); solutionInfoProvider.GetSolutionNameAsync().Returns(ALocalProjectKey); - + MockGetServerProjectByKey(true, expectedServerProject); } @@ -1063,28 +1058,31 @@ private void MockTryGetServerConnection(ServerConnection expectedServerConnectio } private void SetupUnboundProject() + { + SetupConfigurationProvider(new BindingConfiguration(null, SonarLintMode.Standalone, null)); + + MockGetServerProjectByKey(false, null); + } + + private void SetupConfigurationProvider(BindingConfiguration bindingConfiguration) { var configurationProvider = Substitute.For(); - configurationProvider.GetConfiguration().Returns(new BindingConfiguration(null, SonarLintMode.Standalone, null)); + configurationProvider.GetConfiguration().Returns(bindingConfiguration); connectedModeServices.ConfigurationProvider.Returns(configurationProvider); - - MockGetServerProjectByKey(false, null); } - + private void SetupBoundProjectThatDoesNotExistOnServer(ServerConnection serverConnection) { var boundServerProject = new BoundServerProject(ALocalProjectKey, "a-server-project", serverConnection); - var configurationProvider = Substitute.For(); - configurationProvider.GetConfiguration().Returns(new BindingConfiguration(boundServerProject, SonarLintMode.Connected, "binding-dir")); - connectedModeServices.ConfigurationProvider.Returns(configurationProvider); - + SetupConfigurationProvider(new BindingConfiguration(boundServerProject, SonarLintMode.Connected, "binding-dir")); + MockGetServerProjectByKey(false, null); } private void MockGetServerProjectByKey(bool success, ServerProject responseData) { var slCoreConnectionAdapter = Substitute.For(); - slCoreConnectionAdapter.GetServerProjectByKeyAsync(Arg.Any(),Arg.Any()) + slCoreConnectionAdapter.GetServerProjectByKeyAsync(Arg.Any(), Arg.Any()) .Returns(Task.FromResult(new AdapterResponseWithData(success, responseData))); connectedModeServices.SlCoreConnectionAdapter.Returns(slCoreConnectionAdapter); } diff --git a/src/ConnectedMode/UI/ManageBinding/ManageBindingViewModel.cs b/src/ConnectedMode/UI/ManageBinding/ManageBindingViewModel.cs index 67eb8ca1b..34870826e 100644 --- a/src/ConnectedMode/UI/ManageBinding/ManageBindingViewModel.cs +++ b/src/ConnectedMode/UI/ManageBinding/ManageBindingViewModel.cs @@ -21,7 +21,6 @@ using System.Collections.ObjectModel; using System.Windows; using SonarLint.VisualStudio.ConnectedMode.Shared; -using SonarLint.VisualStudio.ConnectedMode.UI.ManageConnections; using SonarLint.VisualStudio.ConnectedMode.UI.ProjectSelection; using SonarLint.VisualStudio.ConnectedMode.UI.Resources; using SonarLint.VisualStudio.Core.Binding; @@ -31,14 +30,14 @@ namespace SonarLint.VisualStudio.ConnectedMode.UI.ManageBinding; public sealed class ManageBindingViewModel : ViewModelBase, IDisposable { - private SolutionInfoModel solutionInfo; + private readonly CancellationTokenSource cancellationTokenSource = new(); + private readonly IConnectedModeBindingServices connectedModeBindingServices; + private readonly IConnectedModeServices connectedModeServices; private ServerProject boundProject; private ConnectionInfo selectedConnectionInfo; private ServerProject selectedProject; private SharedBindingConfigModel sharedBindingConfigModel; - private readonly IConnectedModeServices connectedModeServices; - private readonly IConnectedModeBindingServices connectedModeBindingServices; - private readonly CancellationTokenSource cancellationTokenSource = new(); + private SolutionInfoModel solutionInfo; public SolutionInfoModel SolutionInfo { @@ -131,6 +130,8 @@ public ManageBindingViewModel( ProgressReporter = progressReporterViewModel; } + public void Dispose() => cancellationTokenSource?.Dispose(); + public async Task InitializeDataAsync() { var loadData = new TaskToPerformParams(LoadDataAsync, UiResources.LoadingConnectionsText, @@ -163,12 +164,8 @@ public async Task UseSharedBindingWithProgressAsync() public async Task UnbindWithProgressAsync() { - var bind = new TaskToPerformParams(UnbindAsync, UiResources.UnbindingInProgressText, UiResources.UnbindingFailedText) - { - AfterSuccess = AfterUnbind, - AfterProgressUpdated = OnProgressUpdated - }; - await ProgressReporter.ExecuteTaskWithProgressAsync(bind); + var unbind = new TaskToPerformParams(UnbindAsync, UiResources.UnbindingInProgressText, UiResources.UnbindingFailedText) { AfterProgressUpdated = OnProgressUpdated }; + await ProgressReporter.ExecuteTaskWithProgressAsync(unbind); } public async Task ExportBindingConfigurationAsync() @@ -185,11 +182,6 @@ public async Task ExportBindingConfigurationAsync() } } - public void Dispose() - { - cancellationTokenSource?.Dispose(); - } - internal Task CheckForSharedBindingAsync() { SharedBindingConfigModel = connectedModeBindingServices.SharedBindingConfigProvider.GetSharedBinding(); @@ -254,17 +246,17 @@ internal bool LoadConnections() internal /* for testing */ async Task DisplayBindStatusAsync() { - var solutionName = await connectedModeBindingServices.SolutionInfoProvider.GetSolutionNameAsync(); - var isFolderWorkspace = await connectedModeBindingServices.SolutionInfoProvider.IsFolderWorkspaceAsync(); - SolutionInfo = new SolutionInfoModel(solutionName, isFolderWorkspace ? SolutionType.Folder : SolutionType.Solution); + SolutionInfo = await GetSolutionInfoModelAsync(); var bindingConfiguration = connectedModeServices.ConfigurationProvider.GetConfiguration(); if (bindingConfiguration == null || bindingConfiguration.Mode == SonarLintMode.Standalone) { - return new AdapterResponse(true); + var successResponse = new AdapterResponse(true); + UpdateBoundProjectProperties(null, null); + return successResponse; } - var boundServerProject = connectedModeServices.ConfigurationProvider.GetConfiguration()?.Project; + var boundServerProject = bindingConfiguration.Project; var serverConnection = boundServerProject?.ServerConnection; if (serverConnection == null) { @@ -272,10 +264,8 @@ internal bool LoadConnections() } var response = await connectedModeServices.SlCoreConnectionAdapter.GetServerProjectByKeyAsync(serverConnection, boundServerProject.ServerProjectKey); + UpdateBoundProjectProperties(serverConnection, response.ResponseData); - SelectedConnectionInfo = ConnectionInfo.From(serverConnection); - SelectedProject = response.ResponseData; - BoundProject = SelectedProject; return new AdapterResponse(BoundProject != null); } @@ -290,10 +280,11 @@ internal bool LoadConnections() internal async Task UnbindAsync() { - var succeeded = false; + bool succeeded; try { - await connectedModeServices.ThreadHandling.RunOnUIThreadAsync(() => succeeded = connectedModeBindingServices.BindingController.Unbind(SolutionInfo.Name)); + succeeded = connectedModeBindingServices.BindingController.Unbind(SolutionInfo.Name); + await DisplayBindStatusAsync(); } catch (Exception ex) { @@ -304,13 +295,6 @@ internal async Task UnbindAsync() return new AdapterResponse(succeeded); } - internal void AfterUnbind(AdapterResponse obj) - { - BoundProject = null; - SelectedConnectionInfo = null; - SelectedProject = null; - } - private async Task BindAsync(ServerConnection serverConnection, string serverProjectKey) { try @@ -352,10 +336,22 @@ private bool CredentialsExists(ConnectionInfo connectionInfo, ServerConnection s return false; } - private ConnectionInfo CreateConnectionInfoFromSharedBinding() - { - return SharedBindingConfigModel.IsSonarCloud() + private ConnectionInfo CreateConnectionInfoFromSharedBinding() => + SharedBindingConfigModel.IsSonarCloud() ? new ConnectionInfo(SharedBindingConfigModel.Organization, ConnectionServerType.SonarCloud) : new ConnectionInfo(SharedBindingConfigModel.Uri.ToString(), ConnectionServerType.SonarQube); + + private void UpdateBoundProjectProperties(ServerConnection serverConnection, ServerProject serverProject) + { + SelectedConnectionInfo = serverConnection == null ? null : ConnectionInfo.From(serverConnection); + SelectedProject = serverProject; + BoundProject = SelectedProject; + } + + private async Task GetSolutionInfoModelAsync() + { + var solutionName = await connectedModeBindingServices.SolutionInfoProvider.GetSolutionNameAsync(); + var isFolderWorkspace = await connectedModeBindingServices.SolutionInfoProvider.IsFolderWorkspaceAsync(); + return new SolutionInfoModel(solutionName, isFolderWorkspace ? SolutionType.Folder : SolutionType.Solution); } }