Skip to content

Commit cdb5032

Browse files
committed
feat: Add provider MicrosoftVisualStudioThreadingAnalyzers
1 parent d6a5657 commit cdb5032

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed

src/Atc.CodingRules.AnalyzerProviders/AnalyzerProviderCollector.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public static string[] GetAllBaseRuleProviderNames()
1919
MicrosoftCodeAnalysisNetAnalyzersProvider.Name,
2020
MicrosoftCompilerErrorsProvider.Name,
2121
MicrosoftCompilerErrorsProviderUndocumented.Name,
22+
MicrosoftVisualStudioThreadingAnalyzersProvider.Name,
2223
SecurityCodeScanVs2019Provider.Name,
2324
StyleCopAnalyzersProvider.Name,
2425
SonarAnalyzerCSharpProvider.Name,
@@ -51,6 +52,9 @@ public async Task<Collection<AnalyzerProviderBaseRuleData>> CollectAllBaseRules(
5152
var microsoftCodeAnalysisNetAnalyzersProviderUndocumented = new MicrosoftCompilerErrorsProviderUndocumented(logger, logWithAnsiConsoleMarkup);
5253
var microsoftCompilerErrorsUndocumentedTask = microsoftCodeAnalysisNetAnalyzersProviderUndocumented.CollectBaseRules(ProviderCollectingMode.ReCollect);
5354

55+
var microsoftVisualStudioThreadingAnalyzersProvider = new MicrosoftVisualStudioThreadingAnalyzersProvider(logger, logWithAnsiConsoleMarkup);
56+
var microsoftVisualStudioThreadingAnalyzersProviderTask = microsoftVisualStudioThreadingAnalyzersProvider.CollectBaseRules(ProviderCollectingMode.ReCollect);
57+
5458
var securityCodeScanVs2019Provider = new SecurityCodeScanVs2019Provider(logger, logWithAnsiConsoleMarkup);
5559
var securityCodeScanVs2019Task = securityCodeScanVs2019Provider.CollectBaseRules(providerCollectingMode);
5660

@@ -67,6 +71,7 @@ await Task.WhenAll(
6771
microsoftCodeAnalysisNetAnalyzersTask,
6872
microsoftCompilerErrorsTask,
6973
microsoftCompilerErrorsUndocumentedTask,
74+
microsoftVisualStudioThreadingAnalyzersProviderTask,
7075
securityCodeScanVs2019Task,
7176
styleCopAnalyzersTask,
7277
sonarAnalyzerCSharpTask);
@@ -77,6 +82,7 @@ await Task.WhenAll(
7782
data.Add(await microsoftCodeAnalysisNetAnalyzersTask);
7883
data.Add(await microsoftCompilerErrorsTask);
7984
data.Add(await microsoftCompilerErrorsUndocumentedTask);
85+
data.Add(await microsoftVisualStudioThreadingAnalyzersProviderTask);
8086
data.Add(await securityCodeScanVs2019Task);
8187
data.Add(await styleCopAnalyzersTask);
8288
data.Add(await sonarAnalyzerCSharpTask);
@@ -104,6 +110,9 @@ public void CacheCleanup()
104110
var microsoftCodeAnalysisNetAnalyzersProviderUndocumented = new MicrosoftCompilerErrorsProviderUndocumented(logger);
105111
microsoftCodeAnalysisNetAnalyzersProviderUndocumented.Cleanup();
106112

113+
var microsoftVisualStudioThreadingAnalyzersProvider = new MicrosoftVisualStudioThreadingAnalyzersProvider(logger);
114+
microsoftVisualStudioThreadingAnalyzersProvider.Cleanup();
115+
107116
var securityCodeScanVs2019Provider = new SecurityCodeScanVs2019Provider(logger);
108117
securityCodeScanVs2019Provider.Cleanup();
109118

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
namespace Atc.CodingRules.AnalyzerProviders.Providers;
2+
3+
public class MicrosoftVisualStudioThreadingAnalyzersProvider : AnalyzerProviderBase
4+
{
5+
private const int TableColumnId = 0;
6+
private const int TableColumnCategory = 2;
7+
private const int TableColumnTitle = 1;
8+
9+
public MicrosoftVisualStudioThreadingAnalyzersProvider(ILogger logger, bool logWithAnsiConsoleMarkup = false)
10+
: base(logger, logWithAnsiConsoleMarkup)
11+
{
12+
}
13+
14+
public static string Name => "Microsoft.VisualStudio.Threading.Analyzers";
15+
16+
public override Uri? DocumentationLink { get; set; } = new ("https://github.com/microsoft/vs-threading/blob/main/doc/analyzers/index.md", UriKind.Absolute);
17+
18+
protected override AnalyzerProviderBaseRuleData CreateData()
19+
=> new (Name);
20+
21+
protected override async Task ReCollect(
22+
AnalyzerProviderBaseRuleData data)
23+
{
24+
ArgumentNullException.ThrowIfNull(data);
25+
26+
var web = new HtmlWeb();
27+
var htmlDoc = await web.LoadFromWebAsync(DocumentationLink!.AbsoluteUri).ConfigureAwait(false);
28+
var articleNode = htmlDoc.DocumentNode.SelectNodes("//article[@class='markdown-body entry-content container-lg']").First();
29+
var articleTableRows = articleNode.SelectNodes("//*//table[1]//tr").ToList();
30+
31+
foreach (var row in articleTableRows)
32+
{
33+
if (row.SelectNodes("td") is null)
34+
{
35+
continue;
36+
}
37+
38+
var cells = row.SelectNodes("td").ToList();
39+
if (cells.Count <= 0)
40+
{
41+
continue;
42+
}
43+
44+
var aHrefNode = cells[TableColumnId].SelectSingleNode("a");
45+
if (aHrefNode is null)
46+
{
47+
continue;
48+
}
49+
50+
var code = aHrefNode.InnerText;
51+
var title = HtmlEntity.DeEntitize(cells[TableColumnTitle].InnerText);
52+
var link = aHrefNode.Attributes["href"].Value;
53+
var category = cells[TableColumnCategory].InnerText;
54+
55+
data.Rules.Add(
56+
new Rule(
57+
code,
58+
title,
59+
link,
60+
category: category));
61+
}
62+
}
63+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
namespace Atc.CodingRules.AnalyzerProviders.Tests.Providers;
2+
3+
[Trait(Traits.Category, Traits.Categories.Integration)]
4+
[Trait(Traits.Category, Traits.Categories.SkipWhenLiveUnitTesting)]
5+
public class MicrosoftVisualStudioThreadingAnalyzersProviderTests
6+
{
7+
[Theory]
8+
[InlineData(ProviderCollectingMode.LocalCache)]
9+
[InlineData(ProviderCollectingMode.GitHub)]
10+
[InlineData(ProviderCollectingMode.ReCollect)]
11+
public async Task CollectBaseRules(ProviderCollectingMode providerCollectingMode)
12+
{
13+
// Arrange
14+
var provider = new MicrosoftVisualStudioThreadingAnalyzersProvider(NullLogger.Instance);
15+
16+
// Act
17+
var actual = await provider.CollectBaseRules(providerCollectingMode);
18+
19+
// Assert
20+
Assert.NotNull(actual);
21+
Assert.NotNull(actual.Name);
22+
Assert.Equal(MicrosoftVisualStudioThreadingAnalyzersProvider.Name, actual.Name);
23+
Assert.NotNull(actual.Rules);
24+
Assert.True(actual.Rules.Count >= 23);
25+
}
26+
}

0 commit comments

Comments
 (0)