Skip to content

Commit 11a6c94

Browse files
Implement a workaround for roslyn issues broken rule descriptions since VS 17.10 (#5461)
Fixes #5455
1 parent 9609e61 commit 11a6c94

File tree

2 files changed

+56
-45
lines changed

2 files changed

+56
-45
lines changed

src/Infrastructure.VS.UnitTests/ErrorListHelperTests.cs

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
using Microsoft.VisualStudio.Shell.TableManager;
2525
using Moq;
2626
using SonarLint.VisualStudio.IssueVisualization.Models;
27-
using SonarLint.VisualStudio.TestInfrastructure;
2827

2928
namespace SonarLint.VisualStudio.Infrastructure.VS.UnitTests
3029
{
@@ -232,21 +231,25 @@ public void TryGetRoslynIssueFromSelectedRow_NoStartColumn_NothingReturned()
232231
}
233232

234233
[TestMethod]
235-
[DataRow("S666", "csharpsquid", "S666", "SonarAnalyzer.CSharp")]
236-
[DataRow("S666", "vbnet", "S666", "SonarAnalyzer.VisualBasic")]
237-
[DataRow("S234", "vbnet", "S234", "SonarAnalyzer.VisualBasic")]
238-
[DataRow("c:S111", "c", "S111", "SonarLint")]
239-
[DataRow("cpp:S222", "cpp", "S222", "SonarLint")]
240-
[DataRow("javascript:S333", "javascript", "S333", "SonarLint")]
241-
[DataRow("typescript:S444", "typescript", "S444", "SonarLint")]
242-
[DataRow("secrets:S555", "secrets", "S555", "SonarLint")]
243-
[DataRow("foo:bar", "foo", "bar", "SonarLint")]
244-
public void TryGetRuleIdFromSelectedRow_SingleSonarIssue_ErrorCodeReturned(string fullRuleKey, string expectedRepo, string expectedRule, string buildTool)
234+
[DataRow("S666", "csharpsquid", "S666", "SonarAnalyzer.CSharp", null)]
235+
[DataRow("S666", "vbnet", "S666", "SonarAnalyzer.VisualBasic", null)]
236+
[DataRow("S234", "vbnet", "S234", "SonarAnalyzer.VisualBasic", null)]
237+
[DataRow("c:S111", "c", "S111", "SonarLint", null)]
238+
[DataRow("cpp:S222", "cpp", "S222", "SonarLint", null)]
239+
[DataRow("javascript:S333", "javascript", "S333", "SonarLint", null)]
240+
[DataRow("typescript:S444", "typescript", "S444", "SonarLint", null)]
241+
[DataRow("secrets:S555", "secrets", "S555", "SonarLint", null)]
242+
[DataRow("foo:bar", "foo", "bar", "SonarLint", null)]
243+
[DataRow("S666", "csharpsquid", "S666", null, "https://rules.sonarsource.com/csharp/RSPEC-666/")]
244+
[DataRow("S666", "vbnet", "S666", null, "https://rules.sonarsource.com/vbnet/RSPEC-666/")]
245+
[DataRow("S234", "vbnet", "S234", null, "https://rules.sonarsource.com/vbnet/RSPEC-234/")]
246+
public void TryGetRuleIdFromSelectedRow_SingleSonarIssue_ErrorCodeReturned(string fullRuleKey, string expectedRepo, string expectedRule, string buildTool, string helpLink)
245247
{
246248
// Arrange
247249
var issueHandle = CreateIssueHandle(111, new Dictionary<string, object>
248250
{
249251
{ StandardTableKeyNames.BuildTool, buildTool },
252+
{ StandardTableKeyNames.HelpLink, helpLink },
250253
{ StandardTableKeyNames.ErrorCode, fullRuleKey }
251254
});
252255

@@ -264,16 +267,19 @@ public void TryGetRuleIdFromSelectedRow_SingleSonarIssue_ErrorCodeReturned(strin
264267
}
265268

266269
[TestMethod]
267-
[DataRow("S666", "csharpsquid", "S666", "SonarAnalyzer.CSharp")]
268-
[DataRow("S666", "vbnet", "S666", "SonarAnalyzer.VisualBasic")]
269-
[DataRow("S234", "vbnet", "S234", "SonarAnalyzer.VisualBasic")]
270-
[DataRow("c:S111", "c", "S111", "SonarLint")]
271-
[DataRow("cpp:S222", "cpp", "S222", "SonarLint")]
272-
[DataRow("javascript:S333", "javascript", "S333", "SonarLint")]
273-
[DataRow("typescript:S444", "typescript", "S444", "SonarLint")]
274-
[DataRow("secrets:S555", "secrets", "S555", "SonarLint")]
275-
[DataRow("foo:bar", "foo", "bar", "SonarLint")]
276-
public void TryGetRuleId_FromHandle_ErrorCodeReturned(string fullRuleKey, string expectedRepo, string expectedRule, string buildTool)
270+
[DataRow("S666", "csharpsquid", "S666", "SonarAnalyzer.CSharp", null)]
271+
[DataRow("S666", "vbnet", "S666", "SonarAnalyzer.VisualBasic", null)]
272+
[DataRow("S234", "vbnet", "S234", "SonarAnalyzer.VisualBasic", null)]
273+
[DataRow("c:S111", "c", "S111", "SonarLint", null)]
274+
[DataRow("cpp:S222", "cpp", "S222", "SonarLint", null)]
275+
[DataRow("javascript:S333", "javascript", "S333", "SonarLint", null)]
276+
[DataRow("typescript:S444", "typescript", "S444", "SonarLint", null)]
277+
[DataRow("secrets:S555", "secrets", "S555", "SonarLint", null)]
278+
[DataRow("foo:bar", "foo", "bar", "SonarLint", null)]
279+
[DataRow("S666", "csharpsquid", "S666", null, "https://rules.sonarsource.com/csharp/RSPEC-666/")]
280+
[DataRow("S666", "vbnet", "S666", null, "https://rules.sonarsource.com/vbnet/RSPEC-666/")]
281+
[DataRow("S234", "vbnet", "S234", null, "https://rules.sonarsource.com/vbnet/RSPEC-234/")]
282+
public void TryGetRuleId_FromHandle_ErrorCodeReturned(string fullRuleKey, string expectedRepo, string expectedRule, string buildTool, string helpLink)
277283
{
278284
// Note: this is a copy of TryGetRuleIdFromSelectedRow_SingleSonarIssue_ErrorCodeReturned,
279285
// but without the serviceProvider and IErrorList setup
@@ -282,6 +288,7 @@ public void TryGetRuleId_FromHandle_ErrorCodeReturned(string fullRuleKey, string
282288
var issueHandle = CreateIssueHandle(111, new Dictionary<string, object>
283289
{
284290
{ StandardTableKeyNames.BuildTool, buildTool },
291+
{ StandardTableKeyNames.HelpLink, helpLink },
285292
{ StandardTableKeyNames.ErrorCode, fullRuleKey }
286293
});
287294

@@ -366,16 +373,20 @@ public void TryGetRuleIdFromSelectedRow_NotSonarLintIssue()
366373
}
367374

368375
[TestMethod]
369-
public void TryGetRuleId_FromHandle_NotSonarLintIssue()
376+
[DataRow("cpp:S333", "AnotherAnalyzer", null)]
377+
[DataRow("S666", "AnotherAnalyzerWithSonarHelpLink", "https://rules.sonarsource.com/csharp/RSPEC-666/")]
378+
[DataRow("S234", "SomeOtherAnalyzer", "https://rules.sonarsource.com/vbnet/RSPEC-234/")]
379+
public void TryGetRuleId_FromHandle_NotSonarLintIssue(string fullRuleKey, object buildTool, string helpLink)
370380
{
371381
// Note: this is a copy of TryGetRuleIdFromSelectedRow_SingleSonarIssue_ErrorCodeReturned,
372382
// but without the serviceProvider and IErrorList setup
373383

374384
// Arrange
375385
var issueHandle = CreateIssueHandle(111, new Dictionary<string, object>
376386
{
377-
{ StandardTableKeyNames.BuildTool, new object() },
378-
{ StandardTableKeyNames.ErrorCode, "cpp:S333" }
387+
{ StandardTableKeyNames.BuildTool, buildTool },
388+
{ StandardTableKeyNames.HelpLink, helpLink },
389+
{ StandardTableKeyNames.ErrorCode, fullRuleKey }
379390
});
380391

381392
// Act

src/Infrastructure.VS/ErrorListHelper.cs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -130,35 +130,35 @@ private static bool IsSuppressed(ITableEntryHandle handle)
130130

131131
private static string FindErrorCodeForEntry(ITableEntriesSnapshot snapshot, int index)
132132
{
133-
if (TryGetValue(snapshot, index, StandardTableKeyNames.BuildTool, out string buildTool))
133+
if (!TryGetValue(snapshot, index, StandardTableKeyNames.ErrorCode, out string errorCode))
134134
{
135-
var prefixErrorCode = "";
135+
return null;
136+
}
136137

138+
if (TryGetValue(snapshot, index, StandardTableKeyNames.BuildTool, out string buildTool))
139+
{
137140
// For CSharp and VisualBasic the buildTool returns the name of the analyzer package.
138141
// The prefix is required for roslyn languages as the error code is in style "S111" meaning
139142
// unlike other languages it has no repository prefix.
140-
switch (buildTool)
143+
return buildTool switch
141144
{
142-
case "SonarAnalyzer.CSharp":
143-
{
144-
prefixErrorCode = $"{SonarRuleRepoKeys.CSharpRules}:";
145-
break;
146-
}
147-
case "SonarAnalyzer.VisualBasic":
148-
{
149-
prefixErrorCode = $"{SonarRuleRepoKeys.VBNetRules}:";
150-
break;
151-
}
152-
case "SonarLint":
153-
break;
154-
155-
default:
156-
return null;
157-
}
145+
"SonarAnalyzer.CSharp" => $"{SonarRuleRepoKeys.CSharpRules}:{errorCode}",
146+
"SonarAnalyzer.VisualBasic" => $"{SonarRuleRepoKeys.VBNetRules}:{errorCode}",
147+
"SonarLint" => errorCode,
148+
_ => null
149+
};
150+
}
158151

159-
if (TryGetValue(snapshot, index, StandardTableKeyNames.ErrorCode, out string errorCode))
152+
if (TryGetValue(snapshot, index, StandardTableKeyNames.HelpLink, out string helpLink))
153+
{
154+
if (helpLink.Contains("rules.sonarsource.com/csharp/"))
155+
{
156+
return $"{SonarRuleRepoKeys.CSharpRules}:{errorCode}";
157+
}
158+
159+
if (helpLink.Contains("rules.sonarsource.com/vbnet/"))
160160
{
161-
return prefixErrorCode + errorCode;
161+
return $"{SonarRuleRepoKeys.VBNetRules}:{errorCode}";
162162
}
163163
}
164164

0 commit comments

Comments
 (0)