Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SLVS-1598 Use getEffectiveIssueDetails for issues with SLCore id instead of getEffectiveRuleDetails #5830

Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/ConnectedMode.UnitTests/TestFilterableIssue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ namespace SonarLint.VisualStudio.ConnectedMode.UnitTests;

internal class TestFilterableIssue : IFilterableIssue
{
public Guid? IssueId { get; set; }
public string RuleId { get; set; }
public string LineHash { get; set; }
public int? StartLine { get; set; }
Expand Down
5 changes: 4 additions & 1 deletion src/Core/IEducation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

using SonarLint.VisualStudio.Core.Suppressions;

namespace SonarLint.VisualStudio.Core
{
/// <summary>
Expand All @@ -32,6 +34,7 @@ public interface IEducation
/// be displayed in the IDE. Otherwise, the rule help will be displayed in the
/// browser i.e. at rules.sonarsource.com</remarks>
/// <param name="issueContext">Key for the How to fix it Context acquired from a specific issue. Can be null.</param>
void ShowRuleHelp(SonarCompositeRuleId ruleId, string issueContext);
/// <param name="issueId">The SlCore issue ID for which the rule help should be shown.s</param>
void ShowRuleHelp(SonarCompositeRuleId ruleId, Guid? issueId, string issueContext);
}
}
4 changes: 4 additions & 0 deletions src/Core/Suppressions/FilterableRoslynIssue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ public FilterableRoslynIssue(string ruleId, string filePath, int startLine, int
RoslynStartColumn = startColumn;
}

/// <summary>
/// Always null, as this Id is specific to SlCore
/// </summary>
public Guid? IssueId => null;
public string RuleId { get; }
public string FilePath { get; }
public int? StartLine => RoslynStartLine;
Expand Down
5 changes: 5 additions & 0 deletions src/Core/Suppressions/IFilterableIssue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ namespace SonarLint.VisualStudio.Core.Suppressions
/// </summary>
public interface IFilterableIssue
{
/// <summary>
/// The id of the issue that comes from SlCore
/// Nullable due to the fact that some issues do not come from SlCore (e.g. Roslyn)
/// </summary>
Guid? IssueId { get; }
string RuleId { get; }
string FilePath { get; }
string LineHash { get; }
Expand Down
45 changes: 31 additions & 14 deletions src/Education.UnitTests/EducationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,10 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

using System;
using System.Threading;
using System.Windows.Documents;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SonarLint.VisualStudio.Core;
using SonarLint.VisualStudio.Education.Commands;
using SonarLint.VisualStudio.Core.Suppressions;
using SonarLint.VisualStudio.Education.Rule;
using SonarLint.VisualStudio.Education.XamlGenerator;
using SonarLint.VisualStudio.TestInfrastructure;
Expand Down Expand Up @@ -53,7 +49,7 @@ public void ShowRuleHelp_KnownRule_DocumentIsDisplayedInToolWindow()
var ruleId = new SonarCompositeRuleId("repoKey", "ruleKey");

var ruleInfo = Mock.Of<IRuleInfo>();
ruleMetaDataProvider.Setup(x => x.GetRuleInfoAsync(It.IsAny<SonarCompositeRuleId>())).ReturnsAsync(ruleInfo);
ruleMetaDataProvider.Setup(x => x.GetRuleInfoAsync(It.IsAny<SonarCompositeRuleId>(), It.IsAny<Guid?>())).ReturnsAsync(ruleInfo);

var flowDocument = Mock.Of<FlowDocument>();
var ruleHelpXamlBuilder = new Mock<IRuleHelpXamlBuilder>();
Expand All @@ -74,9 +70,9 @@ public void ShowRuleHelp_KnownRule_DocumentIsDisplayedInToolWindow()
toolWindowService.Invocations.Should().HaveCount(0);

// Act
testSubject.ShowRuleHelp(ruleId, null);
testSubject.ShowRuleHelp(ruleId, null, null);

ruleMetaDataProvider.Verify(x => x.GetRuleInfoAsync(ruleId), Times.Once);
ruleMetaDataProvider.Verify(x => x.GetRuleInfoAsync(ruleId, It.IsAny<Guid?>()), Times.Once);
ruleHelpXamlBuilder.Verify(x => x.Create(ruleInfo, /* todo */ null), Times.Once);
ruleDescriptionToolWindow.Verify(x => x.UpdateContent(flowDocument), Times.Once);
toolWindowService.Verify(x => x.Show(RuleHelpToolWindow.ToolWindowId), Times.Once);
Expand All @@ -95,7 +91,7 @@ public void ShowRuleHelp_FailedToDisplayRule_RuleIsShownInBrowser()
var ruleId = new SonarCompositeRuleId("repoKey", "ruleKey");

var ruleInfo = Mock.Of<IRuleInfo>();
ruleMetadataProvider.Setup(x => x.GetRuleInfoAsync(It.IsAny<SonarCompositeRuleId>())).ReturnsAsync(ruleInfo);
ruleMetadataProvider.Setup(x => x.GetRuleInfoAsync(It.IsAny<SonarCompositeRuleId>(), It.IsAny<Guid?>())).ReturnsAsync(ruleInfo);

ruleHelpXamlBuilder.Setup(x => x.Create(ruleInfo, /* todo */ null)).Throws(new Exception("some layout error"));

Expand All @@ -107,9 +103,9 @@ public void ShowRuleHelp_FailedToDisplayRule_RuleIsShownInBrowser()

toolWindowService.Reset(); // Called in the constructor, so need to reset to clear the list of invocations

testSubject.ShowRuleHelp(ruleId, /* todo */ null);
testSubject.ShowRuleHelp(ruleId, /* todo */ null, null);

ruleMetadataProvider.Verify(x => x.GetRuleInfoAsync(ruleId), Times.Once);
ruleMetadataProvider.Verify(x => x.GetRuleInfoAsync(ruleId, It.IsAny<Guid?>()), Times.Once);
showRuleInBrowser.Verify(x => x.ShowRuleDescription(ruleId), Times.Once);

// should have attempted to build the rule, but failed
Expand All @@ -126,7 +122,7 @@ public void ShowRuleHelp_UnknownRule_RuleIsShownInBrowser()
var showRuleInBrowser = new Mock<IShowRuleInBrowser>();

var unknownRule = new SonarCompositeRuleId("known", "xxx");
ruleMetadataProvider.Setup(x => x.GetRuleInfoAsync(unknownRule)).ReturnsAsync((IRuleInfo)null);
ruleMetadataProvider.Setup(x => x.GetRuleInfoAsync(unknownRule, It.IsAny<Guid?>())).ReturnsAsync((IRuleInfo)null);

var testSubject = CreateEducation(
toolWindowService.Object,
Expand All @@ -136,16 +132,37 @@ public void ShowRuleHelp_UnknownRule_RuleIsShownInBrowser()

toolWindowService.Reset(); // Called in the constructor, so need to reset to clear the list of invocations

testSubject.ShowRuleHelp(unknownRule, /* todo */ null);
testSubject.ShowRuleHelp(unknownRule, /* todo */ null, null);

ruleMetadataProvider.Verify(x => x.GetRuleInfoAsync(unknownRule), Times.Once);
ruleMetadataProvider.Verify(x => x.GetRuleInfoAsync(unknownRule, It.IsAny<Guid?>()), Times.Once);
showRuleInBrowser.Verify(x => x.ShowRuleDescription(unknownRule), Times.Once);

// Should not have attempted to build the rule
ruleHelpXamlBuilder.Invocations.Should().HaveCount(0);
toolWindowService.Invocations.Should().HaveCount(0);
}

[TestMethod]
public void ShowRuleHelp_FilterableIssueProvided_CallsGetRuleInfoForIssue()
{
var toolWindowService = new Mock<IToolWindowService>();
var ruleMetadataProvider = new Mock<IRuleMetaDataProvider>();
var ruleHelpXamlBuilder = new Mock<IRuleHelpXamlBuilder>();
var showRuleInBrowser = new Mock<IShowRuleInBrowser>();
var issueId = Guid.NewGuid();
var ruleId = new SonarCompositeRuleId("repoKey", "ruleKey");
ruleMetadataProvider.Setup(x => x.GetRuleInfoAsync(ruleId, issueId)).ReturnsAsync((IRuleInfo)null);
var testSubject = CreateEducation(
toolWindowService.Object,
ruleMetadataProvider.Object,
showRuleInBrowser.Object,
ruleHelpXamlBuilder.Object);

testSubject.ShowRuleHelp(ruleId,issueId, null);

ruleMetadataProvider.Verify(x => x.GetRuleInfoAsync(ruleId, issueId), Times.Once);
}

private Education CreateEducation(IToolWindowService toolWindowService = null,
IRuleMetaDataProvider ruleMetadataProvider = null,
IShowRuleInBrowser showRuleInBrowser = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

using FluentAssertions;
using Microsoft.VisualStudio.Shell.TableControl;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SonarLint.VisualStudio.Core;
using SonarLint.VisualStudio.Core.Suppressions;
using SonarLint.VisualStudio.Education.SonarLint.VisualStudio.Education.ErrorList;
using SonarLint.VisualStudio.Infrastructure.VS;
using SonarLint.VisualStudio.TestInfrastructure;
Expand Down Expand Up @@ -68,10 +67,30 @@ public void PreprocessNavigateToHelp_IsASonarRule_EventIsHandledAndEducationServ

errorListHelper.Verify(x => x.TryGetRuleId(handle, out ruleId));
education.Invocations.Should().HaveCount(1);
education.Verify(x => x.ShowRuleHelp(ruleId, /* todo */ null));
education.Verify(x => x.ShowRuleHelp(ruleId, /* todo */ null, null));
eventArgs.Handled.Should().BeTrue();
}

[TestMethod]
[DataRow(true)]
[DataRow(false)]
public void PreprocessNavigateToHelp_IsASonarRule_EducationServiceIsCalledWithIssueId(bool getFilterableIssueResult)
{
SonarCompositeRuleId ruleId;
IFilterableIssue filterableIssue = new Mock<IFilterableIssue>().Object;
SonarCompositeRuleId.TryParse("cpp:S123", out ruleId);
var handle = Mock.Of<ITableEntryHandle>();
var errorListHelper = CreateErrorListHelper(isSonarRule: true, ruleId);
errorListHelper.Setup(x => x.TryGetFilterableIssue(It.IsAny<ITableEntryHandle>(), out filterableIssue)).Returns(getFilterableIssueResult);
var education = new Mock<IEducation>();
var testSubject = CreateTestSubject(education.Object, errorListHelper.Object);

testSubject.PreprocessNavigateToHelp(handle, new TableEntryEventArgs());

education.Invocations.Should().HaveCount(1);
education.Verify(x => x.ShowRuleHelp(ruleId, filterableIssue.IssueId, null));
}

private static Mock<IErrorListHelper> CreateErrorListHelper(bool isSonarRule, SonarCompositeRuleId ruleId)
{
var mock = new Mock<IErrorListHelper>();
Expand Down
Loading