diff --git a/src/ConnectedMode.UnitTests/ServerSentEvents/SSESessionFactoryTests.cs b/src/ConnectedMode.UnitTests/ServerSentEvents/SSESessionFactoryTests.cs index d129bd54e9..cdd3e32cf3 100644 --- a/src/ConnectedMode.UnitTests/ServerSentEvents/SSESessionFactoryTests.cs +++ b/src/ConnectedMode.UnitTests/ServerSentEvents/SSESessionFactoryTests.cs @@ -18,81 +18,70 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -using System; using SonarLint.VisualStudio.ConnectedMode.ServerSentEvents; using SonarLint.VisualStudio.Core; using SonarLint.VisualStudio.TestInfrastructure; using SonarQube.Client; -using SonarLint.VisualStudio.ConnectedMode.ServerSentEvents.Taint; using SonarLint.VisualStudio.ConnectedMode.ServerSentEvents.Issue; using SonarLint.VisualStudio.ConnectedMode.ServerSentEvents.QualityProfile; -namespace SonarLint.VisualStudio.ConnectedMode.UnitTests.ServerSentEvents +namespace SonarLint.VisualStudio.ConnectedMode.UnitTests.ServerSentEvents; + +[TestClass] +public class SSESessionFactoryTests { - [TestClass] - public class SSESessionFactoryTests + [TestMethod] + public void MefCtor_CheckIsExported() { - [TestMethod] - public void MefCtor_CheckIsExported() - { - MefTestHelpers.CheckTypeCanBeImported( - MefTestHelpers.CreateExport(), - MefTestHelpers.CreateExport(), - MefTestHelpers.CreateExport(), - MefTestHelpers.CreateExport(), - MefTestHelpers.CreateExport(), - MefTestHelpers.CreateExport()); - } + MefTestHelpers.CheckTypeCanBeImported( + MefTestHelpers.CreateExport(), + MefTestHelpers.CreateExport(), + MefTestHelpers.CreateExport(), + MefTestHelpers.CreateExport(), + MefTestHelpers.CreateExport()); + } - [TestMethod] - public void Create_ReturnsCorrectType() - { - var testSubject = CreateTestSubject(); + [TestMethod] + public void Create_ReturnsCorrectType() + { + var testSubject = CreateTestSubject(); - var sseSession = testSubject.Create("MyProjectName", null); + var sseSession = testSubject.Create("MyProjectName", null); - sseSession.Should().NotBeNull().And.BeOfType(); - } + sseSession.Should().NotBeNull().And.BeOfType(); + } - [TestMethod] - public void Create_AfterDispose_Throws() - { - var testSubject = CreateTestSubject(); + [TestMethod] + public void Create_AfterDispose_Throws() + { + var testSubject = CreateTestSubject(); - testSubject.Dispose(); - Action act = () => testSubject.Create("MyProjectName", null); + testSubject.Dispose(); + Action act = () => testSubject.Create("MyProjectName", null); - act.Should().Throw(); - } + act.Should().Throw(); + } - [TestMethod] - public void Dispose_IdempotentAndDisposesPublishers() - { - var taintPublisherMock = new Mock(); - var issuesPublisherMock = new Mock(); - var qualityProfilePublisherMock = new Mock(); - var testSubject = CreateTestSubject(taintPublisherMock, issuesPublisherMock, qualityProfilePublisherMock); + [TestMethod] + public void Dispose_IdempotentAndDisposesPublishers() + { + var issuesPublisherMock = new Mock(); + var qualityProfilePublisherMock = new Mock(); + var testSubject = CreateTestSubject(issuesPublisherMock, qualityProfilePublisherMock); - testSubject.Dispose(); - testSubject.Dispose(); - testSubject.Dispose(); + testSubject.Dispose(); + testSubject.Dispose(); + testSubject.Dispose(); - taintPublisherMock.Verify(p => p.Dispose(), Times.Once); - issuesPublisherMock.Verify(p => p.Dispose(), Times.Once); - qualityProfilePublisherMock.Verify(p => p.Dispose(), Times.Once); - } + issuesPublisherMock.Verify(p => p.Dispose(), Times.Once); + qualityProfilePublisherMock.Verify(p => p.Dispose(), Times.Once); + } - private SSESessionFactory CreateTestSubject(Mock taintPublisher = null, - Mock issuePublisher = null, - Mock qualityProfileServerEventSourcePublisher = null) - { - return new SSESessionFactory(Mock.Of(), - taintPublisher?.Object ?? Mock.Of(), - issuePublisher?.Object ?? Mock.Of(), - qualityProfileServerEventSourcePublisher?.Object ?? Mock.Of(), + private SSESessionFactory CreateTestSubject(Mock issuePublisher = null, + Mock qualityProfileServerEventSourcePublisher = null) => + new(Mock.Of(), + issuePublisher?.Object ?? Mock.Of(), + qualityProfileServerEventSourcePublisher?.Object ?? Mock.Of(), Mock.Of(), - Mock.Of()); - } - } + Mock.Of()); } diff --git a/src/ConnectedMode.UnitTests/ServerSentEvents/SSESessionTests.cs b/src/ConnectedMode.UnitTests/ServerSentEvents/SSESessionTests.cs index d65364da23..7c148a5510 100644 --- a/src/ConnectedMode.UnitTests/ServerSentEvents/SSESessionTests.cs +++ b/src/ConnectedMode.UnitTests/ServerSentEvents/SSESessionTests.cs @@ -18,19 +18,12 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; using SonarLint.VisualStudio.ConnectedMode.ServerSentEvents; using SonarLint.VisualStudio.Core; using SonarLint.VisualStudio.TestInfrastructure; using SonarQube.Client; using SonarQube.Client.Models.ServerSentEvents; using SonarQube.Client.Models.ServerSentEvents.ClientContract; -using SonarLint.VisualStudio.ConnectedMode.ServerSentEvents.Taint; using SonarLint.VisualStudio.ConnectedMode.ServerSentEvents.Issue; using SonarLint.VisualStudio.ConnectedMode.ServerSentEvents.QualityProfile; @@ -62,14 +55,10 @@ public async Task PumpAllAsync_SelectsPublisherCorrectlyAndPreservesOrderWithinT var inputSequence = new IServerEvent[] { Mock.Of(), - Mock.Of(), Mock.Of(), Mock.Of(), - Mock.Of(), - Mock.Of(), Mock.Of(), Mock.Of(), - Mock.Of() }; testScope.SetUpSwitchToBackgroundThread(); var sseStreamMock = testScope.SetUpSQServiceToSuccessfullyReturnSSEStreamReader(); @@ -77,7 +66,6 @@ public async Task PumpAllAsync_SelectsPublisherCorrectlyAndPreservesOrderWithinT await testScope.TestSubject.PumpAllAsync(); - CheckEventsSequence(testScope.TaintPublisherMock.Invocations); CheckEventsSequence(testScope.IssuePublisherMock.Invocations); CheckEventsSequence(testScope.QualityProfilePublisherMock.Invocations); @@ -100,10 +88,8 @@ public async Task PumpAllAsync_WhenNullEvent_Ignores() testScope.SetUpSSEStreamReaderToReturnEventsSequenceAndExit(sseStreamMock, new IServerEvent[] { - Mock.Of(), Mock.Of(), null, - Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of() @@ -111,7 +97,6 @@ public async Task PumpAllAsync_WhenNullEvent_Ignores() await testScope.TestSubject.PumpAllAsync(); - testScope.TaintPublisherMock.Verify(publisher => publisher.Publish(It.IsAny()), Times.Exactly(2)); testScope.IssuePublisherMock.Verify(publisher => publisher.Publish(It.IsAny()), Times.Exactly(2)); testScope.QualityProfilePublisherMock.Verify(publisher => publisher.Publish(It.IsAny()), Times.Exactly(2)); } @@ -126,16 +111,13 @@ public async Task PumpAllAsync_WhenUnsupportedEvent_Ignores() testScope.SetUpSSEStreamReaderToReturnEventsSequenceAndExit(sseStreamMock, new IServerEvent[] { - Mock.Of(), Mock.Of(), Mock.Of(), - Mock.Of(), Mock.Of() }); await testScope.TestSubject.PumpAllAsync(); - testScope.TaintPublisherMock.Verify(publisher => publisher.Publish(It.IsAny()), Times.Exactly(2)); testScope.IssuePublisherMock.Verify(publisher => publisher.Publish(It.IsAny()), Times.Exactly(1)); testScope.QualityProfilePublisherMock.Verify(publisher => publisher.Publish(It.IsAny()), Times.Exactly(1)); } @@ -232,7 +214,6 @@ public TestScope() { mockRepository = new MockRepository(MockBehavior.Strict); SonarQubeServiceMock = mockRepository.Create(); - TaintPublisherMock = mockRepository.Create(MockBehavior.Loose); IssuePublisherMock = mockRepository.Create(MockBehavior.Loose); QualityProfilePublisherMock = mockRepository.Create(MockBehavior.Loose); ThreadHandlingMock = mockRepository.Create(); @@ -241,7 +222,6 @@ public TestScope() var factory = new SSESessionFactory( SonarQubeServiceMock.Object, - TaintPublisherMock.Object, IssuePublisherMock.Object, QualityProfilePublisherMock.Object, ThreadHandlingMock.Object, @@ -249,10 +229,9 @@ public TestScope() TestSubject = factory.Create("blalala", OnSessionFailedAsyncMock.Object); } - + private Mock ThreadHandlingMock { get; } public Mock SonarQubeServiceMock { get; } - public Mock TaintPublisherMock { get; } public Mock IssuePublisherMock { get; } public Mock QualityProfilePublisherMock { get; } public Mock LoggerMock { get; } diff --git a/src/ConnectedMode/ServerSentEvents/SSESessionFactory.cs b/src/ConnectedMode/ServerSentEvents/SSESessionFactory.cs index 88659ad8b3..464c4371d8 100644 --- a/src/ConnectedMode/ServerSentEvents/SSESessionFactory.cs +++ b/src/ConnectedMode/ServerSentEvents/SSESessionFactory.cs @@ -18,213 +18,195 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -using System; using System.ComponentModel.Composition; -using System.Threading; -using System.Threading.Tasks; using Microsoft.VisualStudio.Threading; using SonarLint.VisualStudio.ConnectedMode.ServerSentEvents.Issue; using SonarLint.VisualStudio.ConnectedMode.ServerSentEvents.QualityProfile; -using SonarLint.VisualStudio.ConnectedMode.ServerSentEvents.Taint; using SonarLint.VisualStudio.Core; using SonarLint.VisualStudio.Core.ServerSentEvents; using SonarQube.Client; using SonarQube.Client.Models.ServerSentEvents; using SonarQube.Client.Models.ServerSentEvents.ClientContract; -namespace SonarLint.VisualStudio.ConnectedMode.ServerSentEvents +namespace SonarLint.VisualStudio.ConnectedMode.ServerSentEvents; + +internal delegate Task OnSessionFailedAsync(ISSESession failedSession); + +/// +/// Factory for . Responsible for disposing EventSourcePublishers +/// +internal interface ISSESessionFactory : IDisposable +{ + ISSESession Create(string projectKey, OnSessionFailedAsync onSessionFailedCallback); +} + +/// +/// Represents the session entity, that is responsible for dealing with reader +/// and propagating events to correct topic event publishers +/// +internal interface ISSESession : IDisposable +{ + Task PumpAllAsync(); +} + +[Export(typeof(ISSESessionFactory))] +[PartCreationPolicy(CreationPolicy.Shared)] +internal sealed class SSESessionFactory : ISSESessionFactory { - internal delegate Task OnSessionFailedAsync(ISSESession failedSession); + private readonly ISonarQubeService sonarQubeClient; + private readonly IIssueServerEventSourcePublisher issueServerEventSourcePublisher; + private readonly IQualityProfileServerEventSourcePublisher qualityProfileServerEventSourcePublisher; + private readonly IThreadHandling threadHandling; + + private bool disposed; + private readonly ILogger logger; + + [ImportingConstructor] + public SSESessionFactory(ISonarQubeService sonarQubeClient, + IIssueServerEventSourcePublisher issueServerEventSourcePublisher, + IQualityProfileServerEventSourcePublisher qualityProfileServerEventSourcePublisher, + IThreadHandling threadHandling, + ILogger logger) + { + this.sonarQubeClient = sonarQubeClient; + this.issueServerEventSourcePublisher = issueServerEventSourcePublisher; + this.qualityProfileServerEventSourcePublisher = qualityProfileServerEventSourcePublisher; + this.threadHandling = threadHandling; + this.logger = logger; + } - /// - /// Factory for . Responsible for disposing EventSourcePublishers - /// - internal interface ISSESessionFactory : IDisposable + public ISSESession Create(string projectKey, OnSessionFailedAsync onSessionFailedCallback) { - ISSESession Create(string projectKey, OnSessionFailedAsync onSessionFailedCallback); + if (disposed) + { + throw new ObjectDisposedException(nameof(SSESessionFactory)); + } + + var session = new SSESession( + issueServerEventSourcePublisher, + qualityProfileServerEventSourcePublisher, + projectKey, + threadHandling, + sonarQubeClient, + onSessionFailedCallback, + logger); + + return session; } - /// - /// Represents the session entity, that is responsible for dealing with reader - /// and propagating events to correct topic event publishers - /// - internal interface ISSESession : IDisposable + public void Dispose() { - Task PumpAllAsync(); + if (disposed) + { + return; + } + + issueServerEventSourcePublisher.Dispose(); + qualityProfileServerEventSourcePublisher.Dispose(); + disposed = true; } - [Export(typeof(ISSESessionFactory))] - [PartCreationPolicy(CreationPolicy.Shared)] - internal sealed class SSESessionFactory : ISSESessionFactory + internal sealed class SSESession : ISSESession { - private readonly ISonarQubeService sonarQubeClient; - private readonly ITaintServerEventSourcePublisher taintServerEventSourcePublisher; private readonly IIssueServerEventSourcePublisher issueServerEventSourcePublisher; private readonly IQualityProfileServerEventSourcePublisher qualityProfileServerEventSourcePublisher; + private readonly string projectKey; private readonly IThreadHandling threadHandling; + private readonly ISonarQubeService sonarQubeService; + private readonly OnSessionFailedAsync onSessionFailedCallback; + private readonly ILogger logger; + private readonly CancellationTokenSource sessionTokenSource; private bool disposed; - private readonly ILogger logger; - [ImportingConstructor] - public SSESessionFactory(ISonarQubeService sonarQubeClient, - ITaintServerEventSourcePublisher taintServerEventSourcePublisher, - IIssueServerEventSourcePublisher issueServerEventSourcePublisher, - IQualityProfileServerEventSourcePublisher qualityProfileServerEventSourcePublisher, - IThreadHandling threadHandling, + internal SSESession(IIssueServerEventSourcePublisher issueServerEventSourcePublisher, + IQualityProfileServerEventSourcePublisher qualityProfileServerEventSourcePublisher, + string projectKey, + IThreadHandling threadHandling, + ISonarQubeService sonarQubeService, + OnSessionFailedAsync onSessionFailedCallback, ILogger logger) { - this.sonarQubeClient = sonarQubeClient; - this.taintServerEventSourcePublisher = taintServerEventSourcePublisher; this.issueServerEventSourcePublisher = issueServerEventSourcePublisher; this.qualityProfileServerEventSourcePublisher = qualityProfileServerEventSourcePublisher; + this.projectKey = projectKey; this.threadHandling = threadHandling; + this.sonarQubeService = sonarQubeService; + this.onSessionFailedCallback = onSessionFailedCallback; this.logger = logger; + this.sessionTokenSource = new CancellationTokenSource(); } - public ISSESession Create(string projectKey, OnSessionFailedAsync onSessionFailedCallback) + public async Task PumpAllAsync() { if (disposed) { - throw new ObjectDisposedException(nameof(SSESessionFactory)); + logger.LogVerbose("[SSESession] Session {0} is disposed", GetHashCode()); + throw new ObjectDisposedException(nameof(SSESession)); } - var session = new SSESession(taintServerEventSourcePublisher, - issueServerEventSourcePublisher, - qualityProfileServerEventSourcePublisher, - projectKey, - threadHandling, - sonarQubeClient, - onSessionFailedCallback, - logger); - - return session; - } - - public void Dispose() - { - if (disposed) - { - return; - } + await threadHandling.SwitchToBackgroundThread(); - taintServerEventSourcePublisher.Dispose(); - issueServerEventSourcePublisher.Dispose(); - qualityProfileServerEventSourcePublisher.Dispose(); - disposed = true; - } + var sseStreamReader = await sonarQubeService.CreateSSEStreamReader(projectKey, sessionTokenSource.Token); - internal sealed class SSESession : ISSESession - { - private readonly ITaintServerEventSourcePublisher taintServerEventSourcePublisher; - private readonly IIssueServerEventSourcePublisher issueServerEventSourcePublisher; - private readonly IQualityProfileServerEventSourcePublisher qualityProfileServerEventSourcePublisher; - private readonly string projectKey; - private readonly IThreadHandling threadHandling; - private readonly ISonarQubeService sonarQubeService; - private readonly OnSessionFailedAsync onSessionFailedCallback; - private readonly ILogger logger; - private readonly CancellationTokenSource sessionTokenSource; - - private bool disposed; - - internal SSESession(ITaintServerEventSourcePublisher taintServerEventSourcePublisher, - IIssueServerEventSourcePublisher issueServerEventSourcePublisher, - IQualityProfileServerEventSourcePublisher qualityProfileServerEventSourcePublisher, - string projectKey, - IThreadHandling threadHandling, - ISonarQubeService sonarQubeService, - OnSessionFailedAsync onSessionFailedCallback, - ILogger logger) + if (sseStreamReader == null) { - this.taintServerEventSourcePublisher = taintServerEventSourcePublisher; - this.issueServerEventSourcePublisher = issueServerEventSourcePublisher; - this.qualityProfileServerEventSourcePublisher = qualityProfileServerEventSourcePublisher; - this.projectKey = projectKey; - this.threadHandling = threadHandling; - this.sonarQubeService = sonarQubeService; - this.onSessionFailedCallback = onSessionFailedCallback; - this.logger = logger; - this.sessionTokenSource = new CancellationTokenSource(); + logger.LogVerbose("[SSESession] Failed to create CreateSSEStreamReader"); + return; } - public async Task PumpAllAsync() + while (!sessionTokenSource.IsCancellationRequested) { - if (disposed) + try { - logger.LogVerbose("[SSESession] Session {0} is disposed", GetHashCode()); - throw new ObjectDisposedException(nameof(SSESession)); - } + var serverEvent = await sseStreamReader.ReadAsync(); - await threadHandling.SwitchToBackgroundThread(); - - var sseStreamReader = await sonarQubeService.CreateSSEStreamReader(projectKey, sessionTokenSource.Token); - - if (sseStreamReader == null) - { - logger.LogVerbose("[SSESession] Failed to create CreateSSEStreamReader"); - return; - } - - while (!sessionTokenSource.IsCancellationRequested) - { - try + if (serverEvent == null) { - var serverEvent = await sseStreamReader.ReadAsync(); - - if (serverEvent == null) - { - continue; - } + continue; + } - logger.LogVerbose("[SSESession] Received server event: {0}", serverEvent.GetType()); + logger.LogVerbose("[SSESession] Received server event: {0}", serverEvent.GetType()); - switch (serverEvent) - { - case ITaintServerEvent taintServerEvent: - { - logger.LogVerbose("[SSESession] Publishing taint event..."); - taintServerEventSourcePublisher.Publish(taintServerEvent); - break; - } - case IIssueChangedServerEvent issueChangedServerEvent: + switch (serverEvent) + { + case IIssueChangedServerEvent issueChangedServerEvent: { logger.LogVerbose("[SSESession] Publishing issue changed event..."); issueServerEventSourcePublisher.Publish(issueChangedServerEvent); break; } - case IQualityProfileEvent qualityProfileEvent: + case IQualityProfileEvent qualityProfileEvent: { logger.LogVerbose("[SSESession] Publishing quality profile event..."); qualityProfileServerEventSourcePublisher.Publish(qualityProfileEvent); break; } - } - } - catch (Exception ex) when (!ErrorHandler.IsCriticalException(ex)) - { - logger.LogVerbose($"[SSESession] Failed to handle events: {ex}"); - onSessionFailedCallback(this).Forget(); - Dispose(); - return; } } - - logger.LogVerbose("[SSESession] Session stopped, session token was canceled"); - } - - public void Dispose() - { - logger.LogVerbose("[SSESession] Disposing session: {0}", GetHashCode()); - - if (disposed) + catch (Exception ex) when (!ErrorHandler.IsCriticalException(ex)) { + logger.LogVerbose($"[SSESession] Failed to handle events: {ex}"); + onSessionFailedCallback(this).Forget(); + Dispose(); return; } + } + + logger.LogVerbose("[SSESession] Session stopped, session token was canceled"); + } - disposed = true; - sessionTokenSource.Cancel(); + public void Dispose() + { + logger.LogVerbose("[SSESession] Disposing session: {0}", GetHashCode()); + + if (disposed) + { + return; } + + disposed = true; + sessionTokenSource.Cancel(); } } } diff --git a/src/ConnectedMode/ServerSentEvents/Taint/ITaintServerEventSourcePublisher.cs b/src/ConnectedMode/ServerSentEvents/Taint/ITaintServerEventSourcePublisher.cs deleted file mode 100644 index 474eba4bbb..0000000000 --- a/src/ConnectedMode/ServerSentEvents/Taint/ITaintServerEventSourcePublisher.cs +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.Core.ServerSentEvents; -using SonarQube.Client.Models.ServerSentEvents.ClientContract; - -namespace SonarLint.VisualStudio.ConnectedMode.ServerSentEvents.Taint -{ - /// - public interface ITaintServerEventSourcePublisher : IServerSentEventSourcePublisher { } -} diff --git a/src/IssueViz.Security/Taint/ServerSentEvents/ITaintServerEventSource.cs b/src/IssueViz.Security/Taint/ServerSentEvents/ITaintServerEventSource.cs deleted file mode 100644 index af869cb5eb..0000000000 --- a/src/IssueViz.Security/Taint/ServerSentEvents/ITaintServerEventSource.cs +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.Core.ServerSentEvents; -using SonarQube.Client.Models.ServerSentEvents.ClientContract; - -namespace SonarLint.VisualStudio.IssueVisualization.Security.Taint.ServerSentEvents -{ - /// - internal interface ITaintServerEventSource : IServerSentEventSource { } -} diff --git a/src/IssueViz.Security/Taint/ServerSentEvents/TaintServerEventChannel.cs b/src/IssueViz.Security/Taint/ServerSentEvents/TaintServerEventChannel.cs deleted file mode 100644 index 76ce20c5e9..0000000000 --- a/src/IssueViz.Security/Taint/ServerSentEvents/TaintServerEventChannel.cs +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.ComponentModel.Composition; -using SonarLint.VisualStudio.ConnectedMode.ServerSentEvents.Taint; -using SonarLint.VisualStudio.Core.ServerSentEvents; -using SonarQube.Client.Models.ServerSentEvents.ClientContract; - -namespace SonarLint.VisualStudio.IssueVisualization.Security.Taint.ServerSentEvents -{ - [Export(typeof(ITaintServerEventSource))] - [Export(typeof(ITaintServerEventSourcePublisher))] - [PartCreationPolicy(CreationPolicy.Shared)] - internal class TaintServerEventChannel : ServerEventChannel, ITaintServerEventSource, ITaintServerEventSourcePublisher - { - } -} diff --git a/src/IssueViz.Security/Taint/ServerSentEvents/TaintServerEventsListener.cs b/src/IssueViz.Security/Taint/ServerSentEvents/TaintServerEventsListener.cs deleted file mode 100644 index 9e409a27d6..0000000000 --- a/src/IssueViz.Security/Taint/ServerSentEvents/TaintServerEventsListener.cs +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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.Threading.Tasks; -using SonarLint.VisualStudio.Core; -using System.Threading; -using System.ComponentModel.Composition; -using SonarQube.Client.Models.ServerSentEvents.ClientContract; -using System; - -namespace SonarLint.VisualStudio.IssueVisualization.Security.Taint.ServerSentEvents -{ - /// - /// Consumes and handles coming from the server. - /// - internal interface ITaintServerEventsListener : IDisposable - { - Task ListenAsync(); - } - - [Export(typeof(ITaintServerEventsListener))] - [PartCreationPolicy(CreationPolicy.Shared)] - internal sealed class TaintServerEventsListener : ITaintServerEventsListener - { - private readonly IStatefulServerBranchProvider serverBranchProvider; - private readonly ITaintServerEventSource taintServerEventSource; - private readonly ITaintStore taintStore; - private readonly IThreadHandling threadHandling; - private readonly ITaintIssueToIssueVisualizationConverter taintToIssueVizConverter; - private readonly ILogger logger; - private readonly CancellationTokenSource cancellationTokenSource; - - [ImportingConstructor] - public TaintServerEventsListener( - IStatefulServerBranchProvider serverBranchProvider, - ITaintServerEventSource taintServerEventSource, - ITaintStore taintStore, - IThreadHandling threadHandling, - ITaintIssueToIssueVisualizationConverter taintToIssueVizConverter, - ILogger logger) - { - this.serverBranchProvider = serverBranchProvider; - this.taintServerEventSource = taintServerEventSource; - this.taintStore = taintStore; - this.threadHandling = threadHandling; - this.taintToIssueVizConverter = taintToIssueVizConverter; - this.logger = logger; - - cancellationTokenSource = new CancellationTokenSource(); - } - - public async Task ListenAsync() - { - await threadHandling.SwitchToBackgroundThread(); - - while (!cancellationTokenSource.IsCancellationRequested) - { - try - { - var taintServerEvent = await taintServerEventSource.GetNextEventOrNullAsync(); - - switch (taintServerEvent) - { - case null: - { - // Will return null when taintServerEventSource is disposed - return; - } - case ITaintVulnerabilityClosedServerEvent taintClosedEvent: - { - taintStore.Remove(taintClosedEvent.Key); - break; - } - case ITaintVulnerabilityRaisedServerEvent taintRaisedEvent: - { - await AddToStoreIfOnTheRightBranchAsync(taintRaisedEvent); - break; - } - default: - { - logger.LogVerbose($"[TaintServerEventsListener] Unrecognized taint event type: {taintServerEvent.GetType()}"); - break; - } - } - } - catch (Exception ex) when (!ErrorHandler.IsCriticalException(ex)) - { - logger.LogVerbose($"[TaintServerEventsListener] Failed to handle taint event: {ex}"); - } - } - } - - private async Task AddToStoreIfOnTheRightBranchAsync(ITaintVulnerabilityRaisedServerEvent taintRaisedEvent) - { - // todo https://sonarsource.atlassian.net/browse/SLVS-1593 - - // var serverBranch = await serverBranchProvider.GetServerBranchNameAsync(cancellationTokenSource.Token); - // - // if (taintRaisedEvent.Branch.Equals(serverBranch)) - // { - // var taintIssue = taintToIssueVizConverter.Convert(taintRaisedEvent.Issue); - // taintStore.Add(taintIssue); - // } - } - - private bool disposed; - - public void Dispose() - { - if (disposed) - { - return; - } - - cancellationTokenSource.Cancel(); - cancellationTokenSource.Dispose(); - disposed = true; - } - } -} diff --git a/src/IssueViz.Security/Taint/TaintSyncPackage.cs b/src/IssueViz.Security/Taint/TaintSyncPackage.cs index c58e673612..7c940e73b5 100644 --- a/src/IssueViz.Security/Taint/TaintSyncPackage.cs +++ b/src/IssueViz.Security/Taint/TaintSyncPackage.cs @@ -18,17 +18,13 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -using System; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; -using System.Threading; using Microsoft.VisualStudio.ComponentModelHost; using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Threading; using SonarLint.VisualStudio.Core; using SonarLint.VisualStudio.Core.Binding; using SonarLint.VisualStudio.Infrastructure.VS; -using SonarLint.VisualStudio.IssueVisualization.Security.Taint.ServerSentEvents; using Task = System.Threading.Tasks.Task; namespace SonarLint.VisualStudio.IssueVisualization.Security.Taint @@ -52,7 +48,6 @@ to avoid threading issues on package initialization (if the sync process and tai public sealed class TaintSyncPackage : AsyncPackage { private ITaintIssuesBindingMonitor bindingMonitor; - private ITaintServerEventsListener taintServerEventsListener; protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress progress) { @@ -64,13 +59,11 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke logger.WriteLine(TaintResources.SyncPackage_Initializing); bindingMonitor = componentModel.GetService(); - taintServerEventsListener = componentModel.GetService(); var taintIssuesSynchronizer = componentModel.GetService(); await ThreadHandling.Instance.SwitchToBackgroundThread(); await taintIssuesSynchronizer.SynchronizeWithServer(); - taintServerEventsListener.ListenAsync().Forget(); logger.WriteLine(TaintResources.SyncPackage_Initialized); } @@ -80,7 +73,6 @@ protected override void Dispose(bool disposing) if (disposing) { bindingMonitor?.Dispose(); - taintServerEventsListener?.Dispose(); } base.Dispose(disposing); diff --git a/src/SonarQube.Client.Tests/Models/ServerSentEvents/SSEStreamReaderTests.cs b/src/SonarQube.Client.Tests/Models/ServerSentEvents/SSEStreamReaderTests.cs index 1950095dbb..5f0377f179 100644 --- a/src/SonarQube.Client.Tests/Models/ServerSentEvents/SSEStreamReaderTests.cs +++ b/src/SonarQube.Client.Tests/Models/ServerSentEvents/SSEStreamReaderTests.cs @@ -18,15 +18,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -using System; -using System.Threading.Tasks; -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using Newtonsoft.Json; -using SonarQube.Client.Api.Common; using SonarQube.Client.Logging; -using SonarQube.Client.Models; using SonarQube.Client.Models.ServerSentEvents; using SonarQube.Client.Models.ServerSentEvents.ClientContract; using SonarQube.Client.Models.ServerSentEvents.ServerContract; @@ -138,99 +132,6 @@ public async Task ReadAsync_IssueChangedEventType_DeserializedEvent() issues: new[] { new BranchAndIssueKey("key1", "master") })); } - [TestMethod] - public async Task ReadAsync_TaintVulnerabilityClosedEventType_DeserializedEvent() - { - const string serializedTaintVulnerabilityClosedEvent = - "{\"projectKey\": \"projectKey1\",\"key\": \"taintKey\"}"; - - var sqSSEStreamReader = CreateSqStreamReader(new SqServerEvent("TaintVulnerabilityClosed", serializedTaintVulnerabilityClosedEvent)); - - var testSubject = CreateTestSubject(sqSSEStreamReader); - - var result = await testSubject.ReadAsync(); - - result.Should().NotBeNull(); - result.Should().BeOfType(); - result.Should().BeEquivalentTo( - new TaintVulnerabilityClosedServerEvent( - projectKey: "projectKey1", - key: "taintKey")); - } - - [TestMethod] - public async Task ReadAsync_TaintVulnerabilityRaisedEventType_DeserializedEvent() - { - const string serializedTaintVulnerabilityRaisedEvent = @"{ - ""key"": ""taintKey"", - ""projectKey"": ""projectKey1"", - ""creationDate"": 1676390804000, - ""branch"": ""master"", - ""ruleKey"": ""javasecurity:S123"", - ""severity"": ""MAJOR"", - ""type"": ""VULNERABILITY"", - ""mainLocation"": { - ""filePath"": ""functions/taint.js"", - ""message"": ""blah blah"", - ""textRange"": { - ""startLine"": 17, - ""startLineOffset"": 10, - ""endLine"": 3, - ""endLineOffset"": 2, - ""hash"": ""hash"" - } - }, - ""flows"": [ - { - ""locations"": [ - { - ""filePath"": ""functions/taint.js"", - ""message"": ""sink"" - } - ] - } - ], - ""impacts"": [ - { - ""softwareQuality"": ""SECURITY"", - ""severity"": ""HIGH"" - } - ], - ""ruleDescriptionContextKey"": ""ContextKey"" -}"; - var sqSSEStreamReader = CreateSqStreamReader(new SqServerEvent("TaintVulnerabilityRaised", serializedTaintVulnerabilityRaisedEvent)); - - var testSubject = CreateTestSubject(sqSSEStreamReader); - - var result = await testSubject.ReadAsync(); - - result.Should().NotBeNull(); - result.Should().BeOfType(); - result.Should().BeEquivalentTo( - new TaintVulnerabilityRaisedServerEvent( - projectKey: "projectKey1", - key: "taintKey", - creationDate: DateTimeOffset.Parse("2023-02-14T16:06:44+00:00"), - branch: "master", - ruleKey: "javasecurity:S123", - severity: SonarQubeIssueSeverity.Major, - type: SonarQubeIssueType.Vulnerability, - impacts: new []{new ServerImpact{SoftwareQuality = "SECURITY", Severity = "HIGH"}}, - mainLocation: - new Location( - filePath: "functions/taint.js", - message: "blah blah", - textRange: new TextRange(17, 10, 3, 2, "hash")), - flows: new[] - { - new Flow(new[] - { - new Location(filePath: "functions/taint.js", message: "sink", textRange: null) - }) - }, - ruleDescriptionContextKey: "ContextKey")); - } - [TestMethod] public async Task ReadAsync_QualityProfileEventType_DeserializedEvent() { @@ -250,7 +151,7 @@ public async Task ReadAsync_QualityProfileEventType_DeserializedEvent() "deactivatedRules": [] } """; - + var sqSSEStreamReader = CreateSqStreamReader(new SqServerEvent("RuleSetChanged", serializedQualityProfileEvent)); var testSubject = CreateTestSubject(sqSSEStreamReader); diff --git a/src/SonarQube.Client.Tests/Models/ServerSentEvents/TaintVulnerabilityClosedServerEventTests.cs b/src/SonarQube.Client.Tests/Models/ServerSentEvents/TaintVulnerabilityClosedServerEventTests.cs deleted file mode 100644 index 7a8ac9b857..0000000000 --- a/src/SonarQube.Client.Tests/Models/ServerSentEvents/TaintVulnerabilityClosedServerEventTests.cs +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SonarQube.Client.Models.ServerSentEvents.ClientContract; - -namespace SonarQube.Client.Tests.Models.ServerSentEvents -{ - [TestClass] - public class TaintVulnerabilityClosedServerEventTests - { - [TestMethod] - public void Ctor_InvalidProjectKey_Throws() - { - Action act = () => { new TaintVulnerabilityClosedServerEvent(null, "id1"); }; - - act.Should().ThrowExactly().And.ParamName.Should().Be("projectKey"); - } - - [TestMethod] - public void Ctor_InvalidKey_Throws() - { - Action act = () => { new TaintVulnerabilityClosedServerEvent("MyProject", null); }; - - act.Should().ThrowExactly().And.ParamName.Should().Be("key"); - } - } -} diff --git a/src/SonarQube.Client.Tests/Models/ServerSentEvents/TaintVulnerabilityRaisedServerEventTests.cs b/src/SonarQube.Client.Tests/Models/ServerSentEvents/TaintVulnerabilityRaisedServerEventTests.cs deleted file mode 100644 index 68a26a752a..0000000000 --- a/src/SonarQube.Client.Tests/Models/ServerSentEvents/TaintVulnerabilityRaisedServerEventTests.cs +++ /dev/null @@ -1,179 +0,0 @@ -/* - * 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 FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using Newtonsoft.Json; -using SonarQube.Client.Models; -using SonarQube.Client.Models.ServerSentEvents.ClientContract; - -namespace SonarQube.Client.Tests.Models.ServerSentEvents -{ - [TestClass] - public class TaintVulnerabilityRaisedServerEventTests - { - [TestMethod] - public void Ctor_InvalidProjectKey_Throws() - { - Action act = () => { new TaintVulnerabilityRaisedServerEvent(null, "id1", "main", Mock.Of()); }; - - act.Should().ThrowExactly().And.ParamName.Should().Be("projectKey"); - } - - [TestMethod] - public void Ctor_InvalidKey_Throws() - { - Action act = () => { new TaintVulnerabilityRaisedServerEvent("MyProject", null, "main", Mock.Of()); }; - - act.Should().ThrowExactly().And.ParamName.Should().Be("key"); - } - - [TestMethod] - public void Ctor_InvalidBranch_Throws() - { - Action act = () => { new TaintVulnerabilityRaisedServerEvent("MyProject", "id1", null, Mock.Of()); }; - - act.Should().ThrowExactly().And.ParamName.Should().Be("branch"); - } - - [TestMethod] - public void Ctor_InvalidIssue_Throws() - { - Action act = () => { new TaintVulnerabilityRaisedServerEvent("MyProject", "id1", "branch", null); }; - - act.Should().ThrowExactly().And.ParamName.Should().Be("issue"); - } - - [TestMethod] - public void Deserialize_ServerEventDeserializedCorrectly() - { - const string serializedTaintVulnerabilityRaisedEvent = @"{ - ""key"": ""taintKey"", - ""projectKey"": ""projectKey1"", - ""branch"": ""master"", - ""creationDate"": 1676390804000, - ""ruleKey"": ""javasecurity:S123"", - ""severity"": ""MAJOR"", - ""type"": ""VULNERABILITY"", - ""mainLocation"": { - ""filePath"": ""functions/taint.js"", - ""message"": ""blah blah"", - ""textRange"": { - ""startLine"": 17, - ""startLineOffset"": 10, - ""endLine"": 3, - ""endLineOffset"": 2, - ""hash"": ""hash"" - } - }, - ""flows"": [ - { - ""locations"": [ - { - ""filePath"": ""functions/taint.js"", - ""message"": ""sink: tainted value is used to perform a security-sensitive operation"", - ""textRange"": { - ""startLine"": 15, - ""startLineOffset"": 14, - ""endLine"": 6, - ""endLineOffset"": 7, - ""hash"": ""hash1"" - } - }, - { - ""filePath"": ""functions/taint2.js"", - ""message"": ""sink: tainted value is used to perform a security-sensitive operation"", - ""textRange"": { - ""startLine"": 18, - ""startLineOffset"": 11, - ""endLine"": 4, - ""endLineOffset"": 3, - ""hash"": ""hash2"" - } - } - ] - } - ], - ""impacts"": [ - { - ""softwareQuality"": ""SECURITY"", - ""severity"": ""HIGH"" - } - ] -}"; - - var expectedDeserializedEvent = new TaintVulnerabilityRaisedServerEvent( - - projectKey: "projectKey1", - key: "taintKey", - branch: "master", - issue: new TaintIssue( - key: "taintKey", - ruleKey: "javasecurity:S123", - creationDate: DateTimeOffset.Parse("2023-02-14T16:06:44+00:00"), - severity: SonarQubeIssueSeverity.Major, - type: SonarQubeIssueType.Vulnerability, - defaultImpacts: new Dictionary{ - { SonarQubeSoftwareQuality.Security, SonarQubeSoftwareQualitySeverity.High}}, - flows: new[] - { - new Flow(locations: new[] - { - new Location( - message: "sink: tainted value is used to perform a security-sensitive operation", - filePath: "functions/taint.js", - textRange: new TextRange( - startLine: 15, - startLineOffset: 14, - endLine: 6, - endLineOffset: 7, - hash: "hash1")), - new Location( - message: "sink: tainted value is used to perform a security-sensitive operation", - filePath: "functions/taint2.js", - textRange: new TextRange( - startLine: 18, - startLineOffset: 11, - endLine: 4, - endLineOffset: 3, - hash: "hash2")) - }) - }, - mainLocation: new Location( - message: "blah blah", - filePath: "functions/taint.js", - textRange: new TextRange( - startLine: 17, - startLineOffset: 10, - endLine: 3, - endLineOffset: 2, - hash: "hash")), - context: null - )); - - var result = JsonConvert.DeserializeObject(serializedTaintVulnerabilityRaisedEvent); - - result.Should().BeEquivalentTo(expectedDeserializedEvent); - } - } -} diff --git a/src/SonarQube.Client/Models/ServerSentEvents/ClientContract/ITaintIssue.cs b/src/SonarQube.Client/Models/ServerSentEvents/ClientContract/ITaintIssue.cs deleted file mode 100644 index 0b1fb7c7d8..0000000000 --- a/src/SonarQube.Client/Models/ServerSentEvents/ClientContract/ITaintIssue.cs +++ /dev/null @@ -1,136 +0,0 @@ -/* - * 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; - -namespace SonarQube.Client.Models.ServerSentEvents.ClientContract -{ - public interface ITaintIssue - { - string Key { get; } - string RuleKey { get; } - DateTimeOffset CreationDate { get; } - SonarQubeIssueSeverity Severity { get; } - SonarQubeIssueType Type { get; } - ILocation MainLocation { get; } - IFlow[] Flows { get; } - string Context { get; } - Dictionary DefaultImpacts { get; } - } - - public interface IFlow - { - ILocation[] Locations { get; } - } - - public interface ILocation - { - string FilePath { get; } - string Message { get; } - ITextRange TextRange { get; } - } - - public interface ITextRange - { - int StartLine { get; } - int StartLineOffset { get; } - int EndLine { get; } - int EndLineOffset { get; } - string Hash { get; } - } - - internal class TaintIssue : ITaintIssue - { - public TaintIssue( - string key, - string ruleKey, - DateTimeOffset creationDate, - SonarQubeIssueSeverity severity, - SonarQubeIssueType type, - Dictionary defaultImpacts, - Location mainLocation, - Flow[] flows, - string context) - { - Key = key ?? throw new ArgumentNullException(nameof(key)); - RuleKey = ruleKey ?? throw new ArgumentNullException(nameof(ruleKey)); - CreationDate = creationDate; - Severity = severity; - Type = type; - DefaultImpacts = defaultImpacts; - MainLocation = mainLocation ?? throw new ArgumentNullException(nameof(mainLocation)); - Flows = flows ?? throw new ArgumentNullException(nameof(flows)); - Context = context; - } - - public string Key { get; } - public string RuleKey { get; } - public DateTimeOffset CreationDate { get; } - public SonarQubeIssueSeverity Severity { get; } - public SonarQubeIssueType Type { get; } - public Dictionary DefaultImpacts { get; } - public ILocation MainLocation { get; } - public IFlow[] Flows { get; } - public string Context { get; } - } - - internal class Flow : IFlow - { - public Flow(Location[] locations) - { - Locations = locations ?? throw new ArgumentNullException(nameof(locations)); - } - - public ILocation[] Locations { get; } - } - - internal class Location : ILocation - { - public Location(string filePath, string message, TextRange textRange) - { - FilePath = filePath ?? throw new ArgumentNullException(nameof(filePath)); - Message = message ?? throw new ArgumentNullException(nameof(message)); - TextRange = textRange; - } - - public string FilePath { get; } - public string Message { get; } - public ITextRange TextRange { get; } - } - - internal class TextRange : ITextRange - { - public TextRange(int startLine, int startLineOffset, int endLine, int endLineOffset, string hash) - { - StartLine = startLine; - StartLineOffset = startLineOffset; - EndLine = endLine; - EndLineOffset = endLineOffset; - Hash = hash; - } - - public int StartLine { get; } - public int StartLineOffset { get; } - public int EndLine { get; } - public int EndLineOffset { get; } - public string Hash { get; } - } -} diff --git a/src/SonarQube.Client/Models/ServerSentEvents/ClientContract/ITaintServerEvent.cs b/src/SonarQube.Client/Models/ServerSentEvents/ClientContract/ITaintServerEvent.cs deleted file mode 100644 index 4b0bc8ea36..0000000000 --- a/src/SonarQube.Client/Models/ServerSentEvents/ClientContract/ITaintServerEvent.cs +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 Newtonsoft.Json; -using SonarQube.Client.Api.Common; -using SonarQube.Client.Helpers; - -namespace SonarQube.Client.Models.ServerSentEvents.ClientContract -{ - public interface ITaintServerEvent : IServerEvent - { - string ProjectKey { get; } - string Key { get; } - } - - /// - /// Represents TaintVulnerabilityRaised server event information - /// - public interface ITaintVulnerabilityRaisedServerEvent : ITaintServerEvent - { - string Branch { get; } - ITaintIssue Issue { get; } - } - - internal class TaintVulnerabilityRaisedServerEvent : ITaintVulnerabilityRaisedServerEvent - { - [JsonConstructor] - public TaintVulnerabilityRaisedServerEvent(string projectKey, - string key, - string branch, - string ruleKey, - [JsonConverter(typeof(MillisecondUnixTimestampDateTimeOffsetConverter))] DateTimeOffset creationDate, - SonarQubeIssueSeverity severity, - SonarQubeIssueType type, - ServerImpact[] impacts, - Location mainLocation, - Flow[] flows, - string ruleDescriptionContextKey) - : this(projectKey, - key, - branch, - new TaintIssue(key, - ruleKey, - creationDate, - severity, - type, - CleanCodeTaxonomyHelpers.ToDefaultImpacts(impacts), - mainLocation, - flows, - ruleDescriptionContextKey)) - { - } - - public TaintVulnerabilityRaisedServerEvent(string projectKey, string key, string branch, ITaintIssue issue) - { - ProjectKey = projectKey ?? throw new ArgumentNullException(nameof(projectKey)); - Key = key ?? throw new ArgumentNullException(nameof(key)); - Branch = branch ?? throw new ArgumentNullException(nameof(branch)); - Issue = issue ?? throw new ArgumentNullException(nameof(issue)); - } - - public string ProjectKey { get; } - public string Key { get; } - public string Branch { get; } - public ITaintIssue Issue { get; } - } - - /// - /// Represents TaintVulnerabilityClosed server event information - /// - public interface ITaintVulnerabilityClosedServerEvent : ITaintServerEvent - { - } - - internal class TaintVulnerabilityClosedServerEvent : ITaintVulnerabilityClosedServerEvent - { - public TaintVulnerabilityClosedServerEvent(string projectKey, string key) - { - ProjectKey = projectKey ?? throw new ArgumentNullException(nameof(projectKey)); - Key = key ?? throw new ArgumentNullException(nameof(key)); - } - - public string ProjectKey { get; } - public string Key { get; } - } -} diff --git a/src/SonarQube.Client/Models/ServerSentEvents/SSEStreamReader.cs b/src/SonarQube.Client/Models/ServerSentEvents/SSEStreamReader.cs index 6429e3ec8b..9c63da80fa 100644 --- a/src/SonarQube.Client/Models/ServerSentEvents/SSEStreamReader.cs +++ b/src/SonarQube.Client/Models/ServerSentEvents/SSEStreamReader.cs @@ -52,8 +52,6 @@ internal class SSEStreamReader : ISSEStreamReader private readonly IDictionary eventTypeToDataTypeMap = new Dictionary { {"IssueChanged", typeof(IssueChangedServerEvent)}, - {"TaintVulnerabilityClosed", typeof(TaintVulnerabilityClosedServerEvent)}, - {"TaintVulnerabilityRaised", typeof(TaintVulnerabilityRaisedServerEvent)}, {"RuleSetChanged", typeof(QualityProfileEvent)}, };