diff --git a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestTests.cs b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestTests.cs index 5515d4a663..b0203f0141 100644 --- a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestTests.cs +++ b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestTests.cs @@ -444,11 +444,11 @@ public async Task InvokeAsync_ComponentKeyNotSpecified_ComponentsAreNotIncludedI _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); var actualQueryString = GetSingleActualQueryString(handlerMock); - actualQueryString.Contains("components").Should().BeFalse(); + actualQueryString.Should().NotContain("component"); } [TestMethod] - public async Task InvokeAsync_ComponentKeySpecified_ComponentsAreIncludedInQueryString() + public async Task InvokeAsync_ComponentKeySpecified_ComponentsAreNotIncludedInQueryString() { var testSubject = CreateTestSubject("any", "any", componentKey: "project1"); @@ -462,7 +462,7 @@ public async Task InvokeAsync_ComponentKeySpecified_ComponentsAreIncludedInQuery _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); var actualQueryString = GetSingleActualQueryString(handlerMock); - actualQueryString.Contains("components=project1").Should().BeTrue(); + actualQueryString.Should().NotContain("component"); } private static GetIssuesRequest CreateTestSubject(string projectKey, string statusesToRequest, string branch = null, string[] issueKeys = null, string ruleId = null, string componentKey = null) @@ -475,7 +475,6 @@ private static GetIssuesRequest CreateTestSubject(string projectKey, string stat Branch = branch, IssueKeys = issueKeys, RuleId = ruleId, - ComponentKey = componentKey }; return testSubject; diff --git a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestWrapperTests.cs b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestWrapperTests.cs index 6ebdece57b..fb3465b55f 100644 --- a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestWrapperTests.cs +++ b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesRequestWrapperTests.cs @@ -25,6 +25,7 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; +using SonarQube.Client.Api; using SonarQube.Client.Api.V7_20; using SonarQube.Client.Tests.Infra; using static SonarQube.Client.Tests.Infra.MocksHelper; @@ -34,10 +35,15 @@ namespace SonarQube.Client.Tests.Requests.Api.V7_20 [TestClass] public class GetIssuesRequestWrapperTests { - [TestMethod] - public async Task InvokeAsync_NoIssueKeys_ExpectedPropertiesArePassedInMultipleRequests() + private const string ComponentPropertyNameSonarQube = "components"; + private const string ComponentPropertyNameSonarCloud = "componentKeys"; + + [DataTestMethod] + [DataRow(ComponentPropertyNameSonarQube, DisplayName = "SonarQube")] + [DataRow(ComponentPropertyNameSonarCloud, DisplayName = "SonarCloud")] + public async Task InvokeAsync_NoIssueKeys_ExpectedPropertiesArePassedInMultipleRequests(string componentPropertyName) { - var testSubject = CreateTestSubject("aaaProject", "xStatus", "yBranch", null, "rule1", "project1"); + var testSubject = CreateTestSubject(componentPropertyName, "aaaProject", "xStatus", "yBranch", null, "rule1", "component1"); var handlerMock = new Mock(MockBehavior.Strict); var httpClient = new HttpClient(handlerMock.Object) @@ -51,15 +57,18 @@ public async Task InvokeAsync_NoIssueKeys_ExpectedPropertiesArePassedInMultipleR // The wrapper is expected to make three calls, for code smells, bugs, then vulnerabilities handlerMock.Invocations.Count.Should().Be(3); - CheckExpectedQueryStringsParameters(handlerMock, 0, "aaaProject", "xStatus", "yBranch", "CODE_SMELL", "rule1", "project1"); - CheckExpectedQueryStringsParameters(handlerMock, 1, "aaaProject", "xStatus", "yBranch", "BUG", "rule1", "project1"); - CheckExpectedQueryStringsParameters(handlerMock, 2, "aaaProject", "xStatus", "yBranch", "VULNERABILITY", "rule1", "project1"); + CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 0, expectedTypes: "CODE_SMELL"); + CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 1, expectedTypes: "BUG"); + CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 2, expectedTypes: "VULNERABILITY"); } - [TestMethod] - public async Task InvokeAsync_HasIssueKeys_ExpectedPropertiesArePassedInASingleRequest() + [DataTestMethod] + [DataRow(ComponentPropertyNameSonarQube, DisplayName = "SonarQube")] + [DataRow(ComponentPropertyNameSonarCloud, DisplayName = "SonarCloud")] + public async Task InvokeAsync_HasIssueKeys_ExpectedPropertiesArePassedInASingleRequest(string componentPropertyName) { - var testSubject = CreateTestSubject("aaaProject", "xStatus", "yBranch", new[] { "issue1", "issue2" }, "rule1", "project1"); + var issueKeys = new[] { "issue1", "issue2" }; + var testSubject = CreateTestSubject(componentPropertyName,"aaaProject", "xStatus", "yBranch", issueKeys, "rule1", "component1"); var handlerMock = new Mock(MockBehavior.Strict); var httpClient = new HttpClient(handlerMock.Object) @@ -74,44 +83,71 @@ public async Task InvokeAsync_HasIssueKeys_ExpectedPropertiesArePassedInASingleR // The wrapper is expected to make one call with the given issueKeys handlerMock.Invocations.Count.Should().Be(1); - var actualQueryString = GetActualQueryStringForInvocation(handlerMock, 0); - actualQueryString.Contains("?projects=aaaProject").Should().BeTrue(); - actualQueryString.Contains("&statuses=xStatus&").Should().BeTrue(); - actualQueryString.Contains("&branch=yBranch&").Should().BeTrue(); - actualQueryString.Contains("&issues=issue1%2Cissue2&").Should().BeTrue(); - actualQueryString.Contains("&rules=rule1").Should().BeTrue(); - actualQueryString.Contains("&components=project1").Should().BeTrue(); - actualQueryString.Contains("types").Should().BeFalse(); + CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 0, expectedKeys: issueKeys); } - private static GetIssuesRequestWrapper CreateTestSubject(string projectKey, string statusesToRequest, string branch, string[] issueKeys, string ruleId, string componentKey) + private static IGetIssuesRequest CreateTestSubject(string componentPropertyName, string projectKey, string statusesToRequest, string branch, string[] issueKeys, string ruleId, string componentKey) { - var testSubject = new GetIssuesRequestWrapper + return componentPropertyName switch { - Logger = new TestLogger(), - ProjectKey = projectKey, - Statuses = statusesToRequest, - Branch = branch, - IssueKeys = issueKeys, - RuleId = ruleId, - ComponentKey = componentKey + ComponentPropertyNameSonarQube => new GetIssuesRequestWrapper + { + Logger = new TestLogger(), + ProjectKey = projectKey, + Statuses = statusesToRequest, + Branch = branch, + IssueKeys = issueKeys, + RuleId = ruleId, + ComponentKey = componentKey + }, + ComponentPropertyNameSonarCloud => new GetIssuesRequestWrapper + { + Logger = new TestLogger(), + ProjectKey = projectKey, + Statuses = statusesToRequest, + Branch = branch, + IssueKeys = issueKeys, + RuleId = ruleId, + ComponentKey = componentKey + }, + _ => throw new ArgumentOutOfRangeException() }; - - return testSubject; } - private static void CheckExpectedQueryStringsParameters(Mock handlerMock, int invocationIndex, - string expectedProject, string expectedStatues, string expectedBranch, string expectedTypes, string expectedRule, string expectedComponent) + private static void CheckExpectedQueryStringsParameters(string componentKeyName, + Mock handlerMock, + int invocationIndex, + string expectedTypes = null, + string[] expectedKeys = null) { var actualQueryString = GetActualQueryStringForInvocation(handlerMock, invocationIndex); Console.WriteLine($"Invocation [{invocationIndex}]: {actualQueryString}"); - actualQueryString.Contains($"?projects={expectedProject}").Should().BeTrue(); - actualQueryString.Contains($"&statuses={expectedStatues}&").Should().BeTrue(); - actualQueryString.Contains($"&branch={expectedBranch}&").Should().BeTrue(); - actualQueryString.Contains($"&types={expectedTypes}&").Should().BeTrue(); - actualQueryString.Contains($"&rules={expectedRule}&").Should().BeTrue(); - actualQueryString.Contains($"&components={expectedComponent}&").Should().BeTrue(); + actualQueryString.Contains($"?{componentKeyName}=component1").Should().BeTrue(); + actualQueryString.Contains("&projects=aaaProject").Should().BeTrue(); + actualQueryString.Contains("&statuses=xStatus").Should().BeTrue(); + actualQueryString.Contains("&branch=yBranch").Should().BeTrue(); + actualQueryString.Contains("&rules=rule1").Should().BeTrue(); + + if (expectedTypes != null) + { + actualQueryString.Contains($"&types={expectedTypes}").Should().BeTrue(); + } + else + { + actualQueryString.Contains("types").Should().BeFalse(); + } + + if (expectedKeys != null) + { + var keys = string.Join("%2C", expectedKeys); + actualQueryString.Contains($"&issues={keys}").Should().BeTrue(); + } + else + { + actualQueryString.Contains("issues").Should().BeFalse(); + } + } private static string GetActualQueryStringForInvocation(Mock handlerMock, int invocationIndex) diff --git a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarCloudRequestTests.cs b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarCloudRequestTests.cs new file mode 100644 index 0000000000..ed25c5fe0f --- /dev/null +++ b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarCloudRequestTests.cs @@ -0,0 +1,92 @@ +/* + * 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.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SonarQube.Client.Api.V7_20; +using SonarQube.Client.Tests.Infra; +using static SonarQube.Client.Tests.Infra.MocksHelper; + +namespace SonarQube.Client.Tests.Requests.Api.V7_20; + +[TestClass] +public class GetIssuesWithComponentSonarCloudRequestTests +{ + [TestMethod] + public async Task InvokeAsync_ComponentKeyNotSpecified_ComponentsAreNotIncludedInQueryString() + { + var testSubject = CreateTestSubject("any", "any", componentKey: null); + + var handlerMock = new Mock(); + var httpClient = new HttpClient(handlerMock.Object) + { + BaseAddress = new Uri(ValidBaseAddress) + }; + + SetupHttpRequest(handlerMock, EmptyGetIssuesResponse); + _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); + + var actualQueryString = GetSingleActualQueryString(handlerMock); + actualQueryString.Should().NotContain("component"); + } + + [TestMethod] + public async Task InvokeAsync_ComponentKeySpecified_ComponentsAreIncludedInQueryString() + { + var testSubject = CreateTestSubject("any", "any", componentKey: "project1"); + + var handlerMock = new Mock(); + var httpClient = new HttpClient(handlerMock.Object) + { + BaseAddress = new Uri(ValidBaseAddress) + }; + + SetupHttpRequest(handlerMock, EmptyGetIssuesResponse); + _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); + + var actualQueryString = GetSingleActualQueryString(handlerMock); + actualQueryString.Should().Contain("componentKeys=project1"); + } + + private static GetIssuesWithComponentSonarCloudRequest CreateTestSubject(string projectKey, string statusesToRequest, string componentKey = null) + { + var testSubject = new GetIssuesWithComponentSonarCloudRequest + { + Logger = new TestLogger(), + ProjectKey = projectKey, + Statuses = statusesToRequest, + ComponentKey = componentKey + }; + + return testSubject; + } + + private static string GetSingleActualQueryString(Mock handlerMock) + { + handlerMock.Invocations.Count.Should().Be(1); + var requestMessage = (HttpRequestMessage)handlerMock.Invocations[0].Arguments[0]; + return requestMessage.RequestUri.Query; + } +} diff --git a/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarQubeRequestTests.cs b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarQubeRequestTests.cs new file mode 100644 index 0000000000..4c8620c582 --- /dev/null +++ b/src/SonarQube.Client.Tests/Requests/Api/V7_20/GetIssuesWithComponentSonarQubeRequestTests.cs @@ -0,0 +1,92 @@ +/* + * 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.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SonarQube.Client.Api.V7_20; +using SonarQube.Client.Tests.Infra; +using static SonarQube.Client.Tests.Infra.MocksHelper; + +namespace SonarQube.Client.Tests.Requests.Api.V7_20; + +[TestClass] +public class GetIssuesWithComponentSonarQubeRequestTests +{ + [TestMethod] + public async Task InvokeAsync_ComponentKeyNotSpecified_ComponentsAreNotIncludedInQueryString() + { + var testSubject = CreateTestSubject("any", "any", componentKey: null); + + var handlerMock = new Mock(); + var httpClient = new HttpClient(handlerMock.Object) + { + BaseAddress = new Uri(ValidBaseAddress) + }; + + SetupHttpRequest(handlerMock, EmptyGetIssuesResponse); + _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); + + var actualQueryString = GetSingleActualQueryString(handlerMock); + actualQueryString.Should().NotContain("component"); + } + + [TestMethod] + public async Task InvokeAsync_ComponentKeySpecified_ComponentsAreIncludedInQueryString() + { + var testSubject = CreateTestSubject("any", "any", componentKey: "project1"); + + var handlerMock = new Mock(); + var httpClient = new HttpClient(handlerMock.Object) + { + BaseAddress = new Uri(ValidBaseAddress) + }; + + SetupHttpRequest(handlerMock, EmptyGetIssuesResponse); + _ = await testSubject.InvokeAsync(httpClient, CancellationToken.None); + + var actualQueryString = GetSingleActualQueryString(handlerMock); + actualQueryString.Should().Contain("components=project1"); + } + + private static GetIssuesWithComponentSonarQubeRequest CreateTestSubject(string projectKey, string statusesToRequest, string componentKey = null) + { + var testSubject = new GetIssuesWithComponentSonarQubeRequest + { + Logger = new TestLogger(), + ProjectKey = projectKey, + Statuses = statusesToRequest, + ComponentKey = componentKey + }; + + return testSubject; + } + + private static string GetSingleActualQueryString(Mock handlerMock) + { + handlerMock.Invocations.Count.Should().Be(1); + var requestMessage = (HttpRequestMessage)handlerMock.Invocations[0].Arguments[0]; + return requestMessage.RequestUri.Query; + } +} diff --git a/src/SonarQube.Client.Tests/Requests/DefaultConfiguration_Configure.cs b/src/SonarQube.Client.Tests/Requests/DefaultConfiguration_Configure_Tests.cs similarity index 98% rename from src/SonarQube.Client.Tests/Requests/DefaultConfiguration_Configure.cs rename to src/SonarQube.Client.Tests/Requests/DefaultConfiguration_Configure_Tests.cs index 85244a231d..2405cbe246 100644 --- a/src/SonarQube.Client.Tests/Requests/DefaultConfiguration_Configure.cs +++ b/src/SonarQube.Client.Tests/Requests/DefaultConfiguration_Configure_Tests.cs @@ -29,7 +29,7 @@ namespace SonarQube.Client.Tests.Requests { [TestClass] - public class DefaultConfiguration_Configure + public class DefaultConfiguration_Configure_Tests { [TestMethod] public void ConfigureSonarQube_Writes_Debug_Messages() @@ -62,7 +62,7 @@ public void ConfigureSonarQube_Writes_Debug_Messages() "Registered SonarQube.Client.Api.V6_60.GetRoslynExportProfileRequest for 6.6", "Registered SonarQube.Client.Api.V6_60.GetProjectBranchesRequest for 6.6", "Registered SonarQube.Client.Api.V7_00.GetOrganizationsRequest for 7.0", - "Registered SonarQube.Client.Api.V7_20.GetIssuesRequestWrapper for 7.2", + "Registered SonarQube.Client.Api.V7_20.GetIssuesRequestWrapper`1[SonarQube.Client.Api.V7_20.GetIssuesWithComponentSonarQubeRequest] for 7.2", "Registered SonarQube.Client.Api.V8_6.GetHotspotRequest for 8.6", "Registered SonarQube.Client.Api.V8_6.GetTaintVulnerabilitiesRequest for 8.6", "Registered SonarQube.Client.Api.V7_20.GetExclusionsRequest for 7.2", @@ -111,7 +111,7 @@ public void ConfigureSonarCloud_Writes_Debug_Messages() "Registered SonarQube.Client.Api.V6_60.GetRoslynExportProfileRequest", "Registered SonarQube.Client.Api.V6_60.GetProjectBranchesRequest", "Registered SonarQube.Client.Api.V7_00.GetOrganizationsRequest", - "Registered SonarQube.Client.Api.V7_20.GetIssuesRequestWrapper", + "Registered SonarQube.Client.Api.V7_20.GetIssuesRequestWrapper`1[SonarQube.Client.Api.V7_20.GetIssuesWithComponentSonarCloudRequest]", "Registered SonarQube.Client.Api.V8_6.GetHotspotRequest", "Registered SonarQube.Client.Api.V10_2.GetTaintVulnerabilitiesWithCCTRequest", "Registered SonarQube.Client.Api.V7_20.GetExclusionsRequest", diff --git a/src/SonarQube.Client.Tests/SonarQubeService_GetIssuesBase.cs b/src/SonarQube.Client.Tests/SonarQubeService_GetIssuesBase.cs index 85509d84c6..31963575c6 100644 --- a/src/SonarQube.Client.Tests/SonarQubeService_GetIssuesBase.cs +++ b/src/SonarQube.Client.Tests/SonarQubeService_GetIssuesBase.cs @@ -77,7 +77,7 @@ protected void SetupPageOfResponses(string projectName, string ruleId, string co componentJson = CreateComponentJson(); } - SetupRequest($"api/issues/search?projects={projectName}&rules={ruleId}&components={componentKey}&branch={branch}&types={issueType}&p={pageNumber}&ps={PageSize}", $@" + SetupRequest($"api/issues/search?components={componentKey}&projects={projectName}&rules={ruleId}&branch={branch}&types={issueType}&p={pageNumber}&ps={PageSize}", $@" {{ ""paging"": {{ ""pageIndex"": {pageNumber}, diff --git a/src/SonarQube.Client/Api/DefaultConfiguration.cs b/src/SonarQube.Client/Api/DefaultConfiguration.cs index 100c150204..638088b768 100644 --- a/src/SonarQube.Client/Api/DefaultConfiguration.cs +++ b/src/SonarQube.Client/Api/DefaultConfiguration.cs @@ -51,7 +51,7 @@ public static RequestFactory ConfigureSonarQube(RequestFactory requestFactory) .RegisterRequest("6.6") .RegisterRequest("6.6") .RegisterRequest("7.0") - .RegisterRequest("7.2") + .RegisterRequest>("7.2") .RegisterRequest("8.6") .RegisterRequest("8.6") .RegisterRequest("7.2") @@ -90,7 +90,7 @@ public static UnversionedRequestFactory ConfigureSonarCloud(UnversionedRequestFa .RegisterRequest() .RegisterRequest() .RegisterRequest() - .RegisterRequest() + .RegisterRequest>() .RegisterRequest() .RegisterRequest() .RegisterRequest() diff --git a/src/SonarQube.Client/Api/V10_2/GetIssuesWithCCTRequest.cs b/src/SonarQube.Client/Api/V10_2/GetIssuesWithCCTRequest.cs index 6c3e03769d..0b7ceee283 100644 --- a/src/SonarQube.Client/Api/V10_2/GetIssuesWithCCTRequest.cs +++ b/src/SonarQube.Client/Api/V10_2/GetIssuesWithCCTRequest.cs @@ -22,13 +22,17 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using SonarQube.Client.Api.Common; +using SonarQube.Client.Api.V7_20; using SonarQube.Client.Api.V9_6; using SonarQube.Client.Helpers; using SonarQube.Client.Models; namespace SonarQube.Client.Api.V10_2 { - public class GetIssuesWithCCTRequest : GetIssuesWithContextRequest + /// + /// This class does not support component-based search. See for more information + /// + internal class GetIssuesWithCCTRequest : GetIssuesWithContextRequest { protected override SonarQubeIssue[] ParseResponse(string response) { diff --git a/src/SonarQube.Client/Api/V5_10/GetIssuesRequest.cs b/src/SonarQube.Client/Api/V5_10/GetIssuesRequest.cs index 4451538f48..699e7064a5 100644 --- a/src/SonarQube.Client/Api/V5_10/GetIssuesRequest.cs +++ b/src/SonarQube.Client/Api/V5_10/GetIssuesRequest.cs @@ -56,8 +56,10 @@ public string Statuses protected override string Path => "batch/issues"; + [JsonIgnore] // We decided not to support it for API calls older than v7.20 public string RuleId { get; set; } + [JsonIgnore] // We decided not to support it for API calls older than v7.20 public string ComponentKey { get; set; } [JsonIgnore] diff --git a/src/SonarQube.Client/Api/V7_20/GetIssuesRequest.cs b/src/SonarQube.Client/Api/V7_20/GetIssuesRequest.cs index 0c53815a64..f6b0d57c5e 100644 --- a/src/SonarQube.Client/Api/V7_20/GetIssuesRequest.cs +++ b/src/SonarQube.Client/Api/V7_20/GetIssuesRequest.cs @@ -31,7 +31,11 @@ namespace SonarQube.Client.Api.V7_20 { - public class GetIssuesRequest : PagedRequestBase, IGetIssuesRequest + /// + /// Generic get issues class. It does not support as it is server-type-specific. + /// See and for more details. + /// + internal class GetIssuesRequest : PagedRequestBase { [JsonProperty("projects")] public virtual string ProjectKey { get; set; } @@ -50,9 +54,6 @@ public class GetIssuesRequest : PagedRequestBase, IGetIssuesRequ [JsonProperty("rules")] public string RuleId { get; set; } - [JsonProperty("components")] - public string ComponentKey { get; set; } - [JsonIgnore] public bool IncludeTaint { get; set; } = true; diff --git a/src/SonarQube.Client/Api/V7_20/GetIssuesRequestWrapper.cs b/src/SonarQube.Client/Api/V7_20/GetIssuesRequestWrapper.cs index b66f3451f2..8c44b38718 100644 --- a/src/SonarQube.Client/Api/V7_20/GetIssuesRequestWrapper.cs +++ b/src/SonarQube.Client/Api/V7_20/GetIssuesRequestWrapper.cs @@ -39,9 +39,10 @@ namespace SonarQube.Client.Api.V7_20 /// /// This class should be removed if/when SonarQube removes the 10k API result limitation. /// - public class GetIssuesRequestWrapper : IGetIssuesRequest + internal class GetIssuesRequestWrapper : IGetIssuesRequest + where T : GetIssuesWithComponentRequest, new() { - private readonly GetIssuesRequest innerRequest = new GetIssuesRequest(); + private readonly T innerRequest = new T(); public string ProjectKey { get; set; } diff --git a/src/SonarQube.Client/Api/V7_20/GetIssuesWithComponentRequest.cs b/src/SonarQube.Client/Api/V7_20/GetIssuesWithComponentRequest.cs new file mode 100644 index 0000000000..e4faf7ec5b --- /dev/null +++ b/src/SonarQube.Client/Api/V7_20/GetIssuesWithComponentRequest.cs @@ -0,0 +1,54 @@ +/* + * 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 Newtonsoft.Json; + +namespace SonarQube.Client.Api.V7_20 +{ + // This class should not be used on it's own + internal abstract class GetIssuesWithComponentRequest : GetIssuesRequest + { + public abstract string ComponentKey { get; set; } + } + + /// + /// This class is used to override the query string property name for for + /// + /// + /// Reason to create this class https://github.com/SonarSource/sonarlint-visualstudio/issues/5181 + /// + internal class GetIssuesWithComponentSonarCloudRequest : GetIssuesWithComponentRequest, IGetIssuesRequest + { + [JsonProperty("componentKeys")] + public override string ComponentKey { get; set; } + } + + /// + /// This class is used to override the query string property name for for + /// + /// + /// Reason to create this class https://github.com/SonarSource/sonarlint-visualstudio/issues/5181 + /// + internal class GetIssuesWithComponentSonarQubeRequest : GetIssuesWithComponentRequest, IGetIssuesRequest + { + [JsonProperty("components")] + public override string ComponentKey { get; set; } + } +} diff --git a/src/SonarQube.Client/Api/V8_6/GetTaintVulnerabilitiesRequest.cs b/src/SonarQube.Client/Api/V8_6/GetTaintVulnerabilitiesRequest.cs index cd6cd513e7..30b0b41fac 100644 --- a/src/SonarQube.Client/Api/V8_6/GetTaintVulnerabilitiesRequest.cs +++ b/src/SonarQube.Client/Api/V8_6/GetTaintVulnerabilitiesRequest.cs @@ -28,7 +28,7 @@ namespace SonarQube.Client.Api.V8_6 { - public class GetTaintVulnerabilitiesRequest : IGetTaintVulnerabilitiesRequest + internal class GetTaintVulnerabilitiesRequest : IGetTaintVulnerabilitiesRequest { protected GetIssuesRequest getIssuesRequest = new GetIssuesRequest(); diff --git a/src/SonarQube.Client/Api/V9_6/GetIssuesWithContextRequest.cs b/src/SonarQube.Client/Api/V9_6/GetIssuesWithContextRequest.cs index def7e33298..e66c094eb0 100644 --- a/src/SonarQube.Client/Api/V9_6/GetIssuesWithContextRequest.cs +++ b/src/SonarQube.Client/Api/V9_6/GetIssuesWithContextRequest.cs @@ -23,7 +23,10 @@ namespace SonarQube.Client.Api.V9_6 { - public class GetIssuesWithContextRequest : GetIssuesRequest + /// + /// This class does not support component-based search. See for more information + /// + internal class GetIssuesWithContextRequest : GetIssuesRequest { [JsonProperty("additionalFields")] public string AdditionalFields => "ruleDescriptionContextKey"; diff --git a/src/SonarQube.Client/Api/V9_6/GetTaintVulnerabilitiesWithContextRequest.cs b/src/SonarQube.Client/Api/V9_6/GetTaintVulnerabilitiesWithContextRequest.cs index 85114035aa..ebecb3993d 100644 --- a/src/SonarQube.Client/Api/V9_6/GetTaintVulnerabilitiesWithContextRequest.cs +++ b/src/SonarQube.Client/Api/V9_6/GetTaintVulnerabilitiesWithContextRequest.cs @@ -26,7 +26,7 @@ namespace SonarQube.Client.Api.V9_6 { - public class GetTaintVulnerabilitiesWithContextRequest : GetTaintVulnerabilitiesRequest + internal class GetTaintVulnerabilitiesWithContextRequest : GetTaintVulnerabilitiesRequest { public override async Task InvokeAsync(HttpClient httpClient, CancellationToken token) { diff --git a/src/SonarQube.Client/Requests/RequestFactory.cs b/src/SonarQube.Client/Requests/RequestFactory.cs index 8a816eb8f0..611d838263 100644 --- a/src/SonarQube.Client/Requests/RequestFactory.cs +++ b/src/SonarQube.Client/Requests/RequestFactory.cs @@ -85,7 +85,7 @@ private RequestFactory RegisterRequest(string version, F } versionRequestMap[parsedVersion] = () => factory(); - logger.Debug($"Registered {typeof(TRequestImpl).FullName} for {parsedVersion}"); + logger.Debug($"Registered {typeof(TRequestImpl)} for {parsedVersion}"); return this; } @@ -117,7 +117,7 @@ public TRequest Create(ServerInfo serverInfo) var request = (TRequest)factory(); request.Logger = logger; - logger.Debug($"Created request of type '{request.GetType().FullName}'."); + logger.Debug($"Created request of type '{request.GetType()}'."); return request; } diff --git a/src/SonarQube.Client/Requests/UnversionedRequestFactory.cs b/src/SonarQube.Client/Requests/UnversionedRequestFactory.cs index ea8cf38b6a..001f7ea94b 100644 --- a/src/SonarQube.Client/Requests/UnversionedRequestFactory.cs +++ b/src/SonarQube.Client/Requests/UnversionedRequestFactory.cs @@ -58,7 +58,7 @@ public UnversionedRequestFactory RegisterRequest() } requestToFactoryMap[typeof(TRequest)] = () => new TRequestImpl(); - logger.Debug($"Registered {typeof(TRequestImpl).FullName}"); + logger.Debug($"Registered {typeof(TRequestImpl)}"); return this; } @@ -72,7 +72,7 @@ public TRequest Create(ServerInfo serverInfo) where TRequest : IReques var request = (TRequest)factory(); request.Logger = logger; - logger.Debug($"Created request of type '{request.GetType().FullName}'."); + logger.Debug($"Created request of type '{request.GetType()}'."); return request; }