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-1693 Fix: issues set to empty after hotspots event #5886

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion src/CFamily.UnitTests/Subprocess/MessageHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public void HandleMessage_IssuesForAnalyzedFileAreNotIgnored(string fileNameInMe
context.IssueConverter.Invocations.Count.Should().Be(1);
context.IssueConsumer.Invocations.Count.Should().Be(1);

context.IssueConsumer.Verify(x => x.Set(analyzedFile, It.IsAny<IEnumerable<IAnalysisIssue>>()));
context.IssueConsumer.Verify(x => x.SetIssues(analyzedFile, It.IsAny<IEnumerable<IAnalysisIssue>>()));
}

[TestMethod]
Expand Down
2 changes: 1 addition & 1 deletion src/CFamily/Subprocess/MessageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ private void HandleAnalysisIssue(Message message)
// TextBufferIssueTracker when the file was closed, but the TextBufferIssueTracker will
// still exist and handle the call.
// todo https://sonarsource.atlassian.net/browse/SLVS-1661
issueConsumer.Set(request.Context.File, new[] { issue });
issueConsumer.SetIssues(request.Context.File, new[] { issue });
}

internal /* for testing */ static bool IsIssueForActiveRule(Message message, ICFamilyRulesConfig rulesConfiguration)
Expand Down
38 changes: 0 additions & 38 deletions src/Core.UnitTests/Analysis/AnalysisServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,44 +113,6 @@ public void ScheduleAnalysis_NoEnvironmentSettings_DefaultTimeout()
scheduler.Received().Schedule("file/path", Arg.Any<Action<CancellationToken>>(), AnalysisService.DefaultAnalysisTimeoutMs);
}

[TestMethod]
public void PublishIssues_NoConsumerInStorage_DoesNothing()
{
var issueConsumerStorage = CreateIssueConsumerStorageWithStoredItem(Guid.NewGuid(), null, false);
var testSubject = CreateTestSubject(issueConsumerStorage:issueConsumerStorage);

var act = () => testSubject.PublishIssues("file/path", Guid.NewGuid(), Substitute.For<IEnumerable<IAnalysisIssue>>());

act.Should().NotThrow();
}

[TestMethod]
public void PublishIssues_DifferentAnalysisId_DoesNothing()
{
var analysisId = Guid.NewGuid();
var issueConsumer = Substitute.For<IIssueConsumer>();
var issueConsumerStorage = CreateIssueConsumerStorageWithStoredItem(Guid.NewGuid(), issueConsumer, true);
var testSubject = CreateTestSubject(issueConsumerStorage:issueConsumerStorage);

testSubject.PublishIssues("file/path", analysisId, Substitute.For<IEnumerable<IAnalysisIssue>>());

issueConsumer.DidNotReceiveWithAnyArgs().Set(default, default);
}

[TestMethod]
public void PublishIssues_MatchingConsumer_PublishesIssues()
{
var analysisId = Guid.NewGuid();
var issueConsumer = Substitute.For<IIssueConsumer>();
var issueConsumerStorage = CreateIssueConsumerStorageWithStoredItem(analysisId, issueConsumer, true);
var testSubject = CreateTestSubject(issueConsumerStorage:issueConsumerStorage);
var analysisIssues = Substitute.For<IEnumerable<IAnalysisIssue>>();

testSubject.PublishIssues("file/path", analysisId, analysisIssues);

issueConsumer.Received().Set("file/path", analysisIssues);
}

[DataRow(true)]
[DataRow(false)]
[DataTestMethod]
Expand Down
96 changes: 96 additions & 0 deletions src/Core.UnitTests/Analysis/HotspotsPublisherTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* 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.Analysis;
using SonarLint.VisualStudio.TestInfrastructure;

namespace SonarLint.VisualStudio.Core.UnitTests.Analysis;

[TestClass]
public class HotspotPublisherTests
{
private IIssueConsumerStorage issueConsumerStorage;
private IIssueConsumer issueConsumer;
private HotspotPublisher testSubject;

[TestMethod]
public void MefCtor_CheckIsExported() =>
MefTestHelpers.CheckTypeCanBeImported<HotspotPublisher, IHotspotPublisher>(MefTestHelpers.CreateExport<IIssueConsumerStorage>());

[TestMethod]
public void MefCtor_CheckIsSingleton() =>
MefTestHelpers.CheckIsSingletonMefComponent<HotspotPublisher>();

[TestInitialize]
public void TestInitialize()
{
issueConsumerStorage = Substitute.For<IIssueConsumerStorage>();
issueConsumer = Substitute.For<IIssueConsumer>();
testSubject = new HotspotPublisher(issueConsumerStorage);
}

[TestMethod]
public void PublishHotspots_NoConsumerInStorage_DoesNothing()
{
issueConsumerStorage.TryGet(default, out _, out _).ReturnsForAnyArgs(false);

var act = () => testSubject.Publish("file/path", Guid.NewGuid(), Substitute.For<IEnumerable<IAnalysisIssue>>());

act.Should().NotThrow();
issueConsumer.DidNotReceiveWithAnyArgs().SetIssues(default, default);
issueConsumer.DidNotReceiveWithAnyArgs().SetHotspots(default, default);
}

[TestMethod]
public void PublishHotspots_DifferentAnalysisId_DoesNothing()
{
issueConsumerStorage.TryGet("file/path", out Arg.Any<Guid>(), out Arg.Any<IIssueConsumer>())
.Returns(info =>
{
info[1] = Guid.NewGuid();
info[2] = issueConsumer;
return true;
});

testSubject.Publish("file/path", Guid.NewGuid(), Substitute.For<IEnumerable<IAnalysisIssue>>());

issueConsumer.DidNotReceiveWithAnyArgs().SetIssues(default, default);
issueConsumer.DidNotReceiveWithAnyArgs().SetHotspots(default, default);
}

[TestMethod]
public void PublishHotspots_MatchingConsumer_PublishesHotspots()
{
var analysisId = Guid.NewGuid();
var analysisIssues = Substitute.For<IEnumerable<IAnalysisIssue>>();
issueConsumerStorage.TryGet("file/path", out Arg.Any<Guid>(), out Arg.Any<IIssueConsumer>())
.Returns(info =>
{
info[1] = analysisId;
info[2] = issueConsumer;
return true;
});

testSubject.Publish("file/path", analysisId, analysisIssues);

issueConsumer.Received().SetHotspots("file/path", analysisIssues);
issueConsumer.DidNotReceiveWithAnyArgs().SetIssues(default, default);
}
}
96 changes: 96 additions & 0 deletions src/Core.UnitTests/Analysis/IssuePublisherTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* 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.Analysis;
using SonarLint.VisualStudio.TestInfrastructure;

namespace SonarLint.VisualStudio.Core.UnitTests.Analysis;

[TestClass]
public class IssuePublisherTests
{
private IIssueConsumerStorage issueConsumerStorage;
private IIssueConsumer issueConsumer;
private IssuePublisher testSubject;

[TestMethod]
public void MefCtor_CheckIsExported() =>
MefTestHelpers.CheckTypeCanBeImported<IssuePublisher, IIssuePublisher>(MefTestHelpers.CreateExport<IIssueConsumerStorage>());

[TestMethod]
public void MefCtor_CheckIsSingleton() =>
MefTestHelpers.CheckIsSingletonMefComponent<IssuePublisher>();

[TestInitialize]
public void TestInitialize()
{
issueConsumerStorage = Substitute.For<IIssueConsumerStorage>();
issueConsumer = Substitute.For<IIssueConsumer>();
testSubject = new IssuePublisher(issueConsumerStorage);
}

[TestMethod]
public void PublishIssues_NoConsumerInStorage_DoesNothing()
{
issueConsumerStorage.TryGet(default, out _, out _).ReturnsForAnyArgs(false);

var act = () => testSubject.Publish("file/path", Guid.NewGuid(), Substitute.For<IEnumerable<IAnalysisIssue>>());

act.Should().NotThrow();
issueConsumer.DidNotReceiveWithAnyArgs().SetIssues(default, default);
issueConsumer.DidNotReceiveWithAnyArgs().SetHotspots(default, default);
}

[TestMethod]
public void PublishIssues_DifferentAnalysisId_DoesNothing()
{
issueConsumerStorage.TryGet("file/path", out Arg.Any<Guid>(), out Arg.Any<IIssueConsumer>())
.Returns(info =>
{
info[1] = Guid.NewGuid();
info[2] = issueConsumer;
return true;
});

testSubject.Publish("file/path", Guid.NewGuid(), Substitute.For<IEnumerable<IAnalysisIssue>>());

issueConsumer.DidNotReceiveWithAnyArgs().SetIssues(default, default);
issueConsumer.DidNotReceiveWithAnyArgs().SetHotspots(default, default);
}

[TestMethod]
public void PublishIssues_MatchingConsumer_PublishesIssues()
{
var analysisId = Guid.NewGuid();
var analysisIssues = Substitute.For<IEnumerable<IAnalysisIssue>>();
issueConsumerStorage.TryGet("file/path", out Arg.Any<Guid>(), out Arg.Any<IIssueConsumer>())
.Returns(info =>
{
info[1] = analysisId;
info[2] = issueConsumer;
return true;
});

testSubject.Publish("file/path", analysisId, analysisIssues);

issueConsumer.Received().SetIssues("file/path", analysisIssues);
issueConsumer.DidNotReceiveWithAnyArgs().SetHotspots(default, default);
}
}
9 changes: 0 additions & 9 deletions src/Core/Analysis/AnalysisService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,6 @@ public bool IsAnalysisSupported(IEnumerable<AnalysisLanguage> languages)
return analyzerController.IsAnalysisSupported(languages);
}

public void PublishIssues(string filePath, Guid analysisId, IEnumerable<IAnalysisIssue> issues)
{
if (issueConsumerStorage.TryGet(filePath, out var currentAnalysisId, out var issueConsumer)
&& analysisId == currentAnalysisId)
{
issueConsumer.Set(filePath, issues);
}
}

public void ScheduleAnalysis(string filePath,
Guid analysisId,
IEnumerable<AnalysisLanguage> detectedLanguages,
Expand Down
38 changes: 38 additions & 0 deletions src/Core/Analysis/HotspotPublisher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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;

namespace SonarLint.VisualStudio.Core.Analysis;

[Export(typeof(IHotspotPublisher))]
[PartCreationPolicy(CreationPolicy.Shared)]
[method:ImportingConstructor]
internal class HotspotPublisher(IIssueConsumerStorage issueConsumerStorage) : IHotspotPublisher
{
public void Publish(string filePath, Guid analysisId, IEnumerable<IAnalysisIssue> findings)
{
if (issueConsumerStorage.TryGet(filePath, out var currentAnalysisId, out var issueConsumer)
&& analysisId == currentAnalysisId)
{
issueConsumer.SetHotspots(filePath, findings);
}
}
}
5 changes: 0 additions & 5 deletions src/Core/Analysis/IAnalysisService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@ public interface IAnalysisService
/// </summary>
bool IsAnalysisSupported(IEnumerable<AnalysisLanguage> languages);

/// <summary>
/// Handles analysis results
/// </summary>
void PublishIssues(string filePath, Guid analysisId, IEnumerable<IAnalysisIssue> issues);

/// <summary>
/// Starts analysis for <paramref name="filePath"/>
/// </summary>
Expand Down
33 changes: 33 additions & 0 deletions src/Core/Analysis/IFindingsPublisher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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.
*/

namespace SonarLint.VisualStudio.Core.Analysis;

public interface IFindingsPublisher
{
/// <summary>
/// Handles analysis results
/// </summary>
void Publish(string filePath, Guid analysisId, IEnumerable<IAnalysisIssue> findings);
}

public interface IIssuePublisher : IFindingsPublisher;

public interface IHotspotPublisher : IFindingsPublisher;
3 changes: 2 additions & 1 deletion src/Core/Analysis/IIssueConsumer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ namespace SonarLint.VisualStudio.Core.Analysis;
/// </summary>
public interface IIssueConsumer
{
void Set(string path, IEnumerable<IAnalysisIssue> issues);
void SetIssues(string path, IEnumerable<IAnalysisIssue> issues);
void SetHotspots(string path, IEnumerable<IAnalysisIssue> hotspots);
}
Loading
Loading