diff --git a/src/ConnectedMode.UnitTests/IssueMatcherTests.cs b/src/ConnectedMode.UnitTests/IssueMatcherTests.cs index efd953366c..d927e4c1c8 100644 --- a/src/ConnectedMode.UnitTests/IssueMatcherTests.cs +++ b/src/ConnectedMode.UnitTests/IssueMatcherTests.cs @@ -55,7 +55,7 @@ public void IsMatch_MatchesBasedOnAllParameters(string serverRuleId, int? server var issueToMatch = CreateIssueToMatch("CorrectRuleId", 1, "CorrectHash"); var serverIssue = CreateServerIssue(serverRuleId, serverIssueLine, serverHash); - CreateTestSubject().IsGoodMatch(issueToMatch, serverIssue).Should().Be(expectedResult); + CreateTestSubject().IsLikelyMatch(issueToMatch, serverIssue).Should().Be(expectedResult); } [DataTestMethod] @@ -71,7 +71,7 @@ public void IsMatch_FileLevelIssue(string serverRuleId, int? serverIssueLine, var issueToMatch = CreateIssueToMatch("CorrectRuleId", null, null); var serverIssue = CreateServerIssue(serverRuleId, serverIssueLine, serverHash); - CreateTestSubject().IsGoodMatch(issueToMatch, serverIssue); + CreateTestSubject().IsLikelyMatch(issueToMatch, serverIssue).Should().Be(expectedResult); } [TestMethod] @@ -103,7 +103,7 @@ public void IsMatch_CheckFileComparisons(string serverFilePath, string localFile var serverIssue = CreateServerIssue("111", 0, "hash", filePath: serverFilePath); - CreateTestSubject().IsGoodMatch(issueToMatch, serverIssue).Should().Be(expected); + CreateTestSubject().IsLikelyMatch(issueToMatch, serverIssue).Should().Be(expected); } [TestMethod] @@ -116,7 +116,7 @@ public void FindMatchOrDefault_FindsFirstMatch() var correctServerIssue = CreateServerIssue(ruleId, startLine, null, serverPath); - CreateTestSubject().GetFirstMatchFromSameFileOrNull(issueToMatch, new[] + CreateTestSubject().GetFirstLikelyMatchFromSameFileOrNull(issueToMatch, new[] { CreateServerIssue("222", startLine, null, serverPath), CreateServerIssue(ruleId, 111, null, serverPath), @@ -130,7 +130,7 @@ public void FindMatchOrDefault_NoServerIssues_ReturnsNull() { var issueToMatch = CreateIssueToMatch("1", 1, "1"); - CreateTestSubject().GetFirstMatchFromSameFileOrNull(issueToMatch, Array.Empty()).Should().BeNull(); + CreateTestSubject().GetFirstLikelyMatchFromSameFileOrNull(issueToMatch, Array.Empty()).Should().BeNull(); } private IssueMatcher CreateTestSubject() diff --git a/src/ConnectedMode.UnitTests/Suppressions/SuppressedIssueMatcherTests.cs b/src/ConnectedMode.UnitTests/Suppressions/SuppressedIssueMatcherTests.cs index 751c7845e6..e8f87ac38d 100644 --- a/src/ConnectedMode.UnitTests/Suppressions/SuppressedIssueMatcherTests.cs +++ b/src/ConnectedMode.UnitTests/Suppressions/SuppressedIssueMatcherTests.cs @@ -87,7 +87,7 @@ public void MatchExists_MultipleServerIssues(int indexOfServerIssue) var hasMatch = indexOfServerIssue != -1; if (hasMatch) { - issueMatcherMock.Setup(x => x.IsGoodMatch(issueToMatch, sonarQubeIssues[indexOfServerIssue])).Returns(true); + issueMatcherMock.Setup(x => x.IsLikelyMatch(issueToMatch, sonarQubeIssues[indexOfServerIssue])).Returns(true); } ConfigureServerIssues(sonarQubeIssues); @@ -106,7 +106,7 @@ public void MatchExists_ResultDependsOnSuppressionState(string serverRuleId, int var issueToMatch = CreateIssueToMatch(); ConfigureServerIssues(CreateServerIssue(isSuppressed)); issueMatcherMock - .Setup(x => x.IsGoodMatch(It.IsAny(), It.IsAny())) + .Setup(x => x.IsLikelyMatch(It.IsAny(), It.IsAny())) .Returns(true); // Act and assert diff --git a/src/ConnectedMode/IssueMatcher.cs b/src/ConnectedMode/IssueMatcher.cs index ac924c51d6..40ec3a569d 100644 --- a/src/ConnectedMode/IssueMatcher.cs +++ b/src/ConnectedMode/IssueMatcher.cs @@ -30,27 +30,35 @@ namespace SonarLint.VisualStudio.ConnectedMode { internal interface IIssueMatcher { - bool IsGoodMatch(IFilterableIssue issue, SonarQubeIssue serverIssue); + /// + /// This method attempts to match with . + /// There's a possibility of False Positive matches: in case false tail-match of file paths, as the project root is not taken into account, + /// or when line number matches but line hash doesn't. + /// + /// Local issue + /// Server issue + /// The best possible match based on rule id, file name (tail matched to the server path), line number and line hash (not checked when line numbers match) + bool IsLikelyMatch(IFilterableIssue issue, SonarQubeIssue serverIssue); - SonarQubeIssue GetFirstMatchFromSameFileOrNull(IFilterableIssue issue, IEnumerable serverIssuesFromSameFile); + /// + /// Returns the first matching issue. Note: for this method to work correctly, all need to be from the same server file + /// + /// Local issue + /// List of server issues from the same file + /// A matching server issue, if present in the list, or null + SonarQubeIssue GetFirstLikelyMatchFromSameFileOrNull(IFilterableIssue issue, IEnumerable serverIssuesFromSameFile); } [Export(typeof(IIssueMatcher))] [PartCreationPolicy(CreationPolicy.Shared)] internal class IssueMatcher : IIssueMatcher { - public bool IsGoodMatch(IFilterableIssue issue, SonarQubeIssue serverIssue) + public bool IsLikelyMatch(IFilterableIssue issue, SonarQubeIssue serverIssue) { return IsMatch(issue, serverIssue, true); } - /// - /// Returns the first matching issue. Note: for this method to work correctly, all need to be from the same server file - /// - /// Local issue - /// List of server issues from the same file - /// A matching server issue, if present in the list, or null - public SonarQubeIssue GetFirstMatchFromSameFileOrNull(IFilterableIssue issue, IEnumerable serverIssuesFromSameFile) + public SonarQubeIssue GetFirstLikelyMatchFromSameFileOrNull(IFilterableIssue issue, IEnumerable serverIssuesFromSameFile) { return serverIssuesFromSameFile?.FirstOrDefault(serverIssue => IsMatch(issue, serverIssue, false)); } diff --git a/src/ConnectedMode/Suppressions/SuppressedIssueMatcher.cs b/src/ConnectedMode/Suppressions/SuppressedIssueMatcher.cs index 2028d6e91b..f7806198b7 100644 --- a/src/ConnectedMode/Suppressions/SuppressedIssueMatcher.cs +++ b/src/ConnectedMode/Suppressions/SuppressedIssueMatcher.cs @@ -54,7 +54,7 @@ public bool SuppressionExists(IFilterableIssue issue) var serverIssues = serverIssuesStore.Get(); // Try to find an issue with the same ID and either the same line number or same line hash - return serverIssues.Any(s => s.IsResolved && issueMatcher.IsGoodMatch(issue, s)); + return serverIssues.Any(s => s.IsResolved && issueMatcher.IsLikelyMatch(issue, s)); } } }