Skip to content

Commit

Permalink
Add grouping CA rules by category during formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
FrediKats committed May 18, 2024
1 parent 9f36635 commit b13a199
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 18 deletions.
26 changes: 26 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,29 @@ Some features:
- Options saved near the rule
- Not parsed rules don't change
- Comments are saved and moved with the rule
#### Grouping by category
Command 'format' support flag `--group-ca` that allows to group rules by category. For example:
```
# with --group-ca false
# Autogenerated values
[*.cs]
### CA ###
dotnet_diagnostic.CA1016.severity = none
dotnet_diagnostic.CA1027.severity = none
dotnet_diagnostic.CA1501.severity = none
dotnet_diagnostic.CA1835.severity = none
# with --group-ca true
# Autogenerated values
[*.cs]
### CA Design ###
dotnet_diagnostic.CA1016.severity = none
dotnet_diagnostic.CA1027.severity = none
### CA Maintainability ###
dotnet_diagnostic.CA1501.severity = none
### CA Performance ###
dotnet_diagnostic.CA1835.severity = none
```
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ public sealed class Settings : CommandSettings
[Description("Path to cloned MS Learn repository.")]
[CommandOption("-d|--documentation")]
public string? MsLearnRepositoryPath { get; init; }

[Description("Group CA rules by category")]
[CommandOption("--group-ca")]
[DefaultValue(true)]
public bool GroupQualityRulesByCategory { get; init; }
}

public override int Execute(CommandContext context, Settings settings)
Expand All @@ -38,7 +43,7 @@ public override int Execute(CommandContext context, Settings settings)
MsLearnDocumentationRawInfo msLearnDocumentationRawInfo = repositoryPathReader.Provide(settings.MsLearnRepositoryPath);
RoslynRules roslynRules = msLearnDocumentationParser.Parse(msLearnDocumentationRawInfo);
EditorConfigDocument editorConfigDocument = editorConfigDocumentParser.Parse(editorConfigContentLines);
EditorConfigDocument formattedDocument = editorConfigFormatter.FormatAccordingToRuleDefinitions(editorConfigDocument, roslynRules);
EditorConfigDocument formattedDocument = editorConfigFormatter.FormatAccordingToRuleDefinitions(editorConfigDocument, roslynRules, settings.GroupQualityRulesByCategory);
File.WriteAllText(settings.EditorConfigPath, formattedDocument.ToFullString());

return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ public EditorConfigDocument Format(EditorConfigDocument value)
if (nodesForRemoving.IsEmpty())
return value;

EditorConfigCategoryNode autoGeneratedSection = CreateAutoGeneratedCategory(styleRuleNodesForMoving, qualityRuleNodesForMoving);
EditorConfigCategoryNode autoGeneratedSection = CreateAutoGeneratedCategory(styleRuleNodesForMoving, [new RoslynQualityRuleFormattedSection("CA", qualityRuleNodesForMoving)]);

return value
.RemoveNodes(nodesForRemoving)
.AddChild(autoGeneratedSection);
}

public EditorConfigDocument FormatAccordingToRuleDefinitions(EditorConfigDocument document, RoslynRules rules)
public EditorConfigDocument FormatAccordingToRuleDefinitions(EditorConfigDocument document, RoslynRules rules, bool groupQualityRulesByCategory = false)
{
rules.ThrowIfNull();

Expand Down Expand Up @@ -80,26 +80,54 @@ public EditorConfigDocument FormatAccordingToRuleDefinitions(EditorConfigDocumen
}
}

List<EditorConfigPropertyNode> selectedQualityRuleNodes = new List<EditorConfigPropertyNode>();
foreach (RoslynQualityRule qualityRule in rules.QualityRules)
List<RoslynQualityRuleFormattedSection> formattedSections = new List<RoslynQualityRuleFormattedSection>();
if (groupQualityRulesByCategory)
{
EditorConfigPropertyNode? editorConfigPropertyNode = TryFindSeverityNode(propertyNodes, qualityRule.RuleId);
if (editorConfigPropertyNode is null)
continue;
foreach (IGrouping<string, RoslynQualityRule> categoryRules in rules.QualityRules.GroupBy(r => r.Category).OrderBy(c => c.Key))
{
List<EditorConfigPropertyNode> selectedQualityRuleNodes = new List<EditorConfigPropertyNode>();
foreach (RoslynQualityRule qualityRule in categoryRules.OrderBy(r => r.RuleId))
{
EditorConfigPropertyNode? editorConfigPropertyNode = TryFindSeverityNode(propertyNodes, qualityRule.RuleId);
if (editorConfigPropertyNode is null)
continue;

selectedQualityRuleNodes.Add(editorConfigPropertyNode);
}

if (selectedQualityRuleNodes.Any())
formattedSections.Add(new RoslynQualityRuleFormattedSection($"CA {categoryRules.Key}", selectedQualityRuleNodes));
}
}
else
{
List<EditorConfigPropertyNode> selectedQualityRuleNodes = new List<EditorConfigPropertyNode>();
foreach (RoslynQualityRule qualityRule in rules.QualityRules)
{
EditorConfigPropertyNode? editorConfigPropertyNode = TryFindSeverityNode(propertyNodes, qualityRule.RuleId);
if (editorConfigPropertyNode is null)
continue;

selectedQualityRuleNodes.Add(editorConfigPropertyNode);
selectedQualityRuleNodes.Add(editorConfigPropertyNode);
}
if (selectedQualityRuleNodes.Any())
formattedSections.Add(new RoslynQualityRuleFormattedSection("CA", selectedQualityRuleNodes));
}

nodesForRemoving.AddRange(selectedStyleRuleNodes);
nodesForRemoving.AddRange(selectedQualityRuleNodes);
EditorConfigCategoryNode autoGeneratedSection = CreateAutoGeneratedCategory(selectedStyleRuleNodes, selectedQualityRuleNodes);
nodesForRemoving.AddRange(formattedSections.SelectMany(s => s.SelectedQualityRuleNodes));
EditorConfigCategoryNode autoGeneratedSection = CreateAutoGeneratedCategory(selectedStyleRuleNodes, formattedSections);

return document
.RemoveNodes(nodesForRemoving)
.AddChild(autoGeneratedSection);
}

private EditorConfigCategoryNode CreateAutoGeneratedCategory(IReadOnlyCollection<EditorConfigPropertyNode> styleRuleNodesForMoving, IReadOnlyCollection<EditorConfigPropertyNode> qualityRuleNodesForMoving)
public record RoslynQualityRuleFormattedSection(string Title, IReadOnlyCollection<EditorConfigPropertyNode> SelectedQualityRuleNodes);

private EditorConfigCategoryNode CreateAutoGeneratedCategory(
IReadOnlyCollection<EditorConfigPropertyNode> styleRuleNodesForMoving,
IReadOnlyCollection<RoslynQualityRuleFormattedSection> qualityRuleNodesForMoving)
{
var autoGeneratedSection = new EditorConfigCategoryNode("*.cs", [], ["# Autogenerated values"], null);

Expand All @@ -113,12 +141,14 @@ private EditorConfigCategoryNode CreateAutoGeneratedCategory(IReadOnlyCollection
autoGeneratedSection = autoGeneratedSection.AddChild(styleRuleSection);
}

if (qualityRuleNodesForMoving.Any())
foreach (RoslynQualityRuleFormattedSection roslynQualityRuleFormattedSection in qualityRuleNodesForMoving)
{
var qualitySection = new EditorConfigDocumentSectionNode("### CA ###");
foreach (EditorConfigPropertyNode qualityRule in qualityRuleNodesForMoving)
qualitySection = qualitySection.AddChild(qualityRule);
if (roslynQualityRuleFormattedSection.SelectedQualityRuleNodes.IsEmpty())
continue;

var qualitySection = new EditorConfigDocumentSectionNode($"### {roslynQualityRuleFormattedSection.Title} ###");
foreach (EditorConfigPropertyNode qualityRule in roslynQualityRuleFormattedSection.SelectedQualityRuleNodes)
qualitySection = qualitySection.AddChild(qualityRule);
autoGeneratedSection = autoGeneratedSection.AddChild(qualitySection);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,38 @@ public void Format_NamingRule_ReturnOrderedLinesWithHeader()
RoslynRules roslynRules = _msLearnDocumentationParser.Parse(msLearnDocumentationRawInfo);

EditorConfigDocument editorConfigDocument = _parser.Parse(input);
EditorConfigDocument formattedDocument = _formatter.FormatAccordingToRuleDefinitions(editorConfigDocument, roslynRules);
EditorConfigDocument formattedDocument = _formatter.FormatAccordingToRuleDefinitions(editorConfigDocument, roslynRules, false);

formattedDocument.ToFullString().Should().Be(expected);
}

[Fact]
public void Format_QualityRuleByCategory_ReturnGroupedByCategory()
{
var input = """
dotnet_diagnostic.CA1016.severity = none
dotnet_diagnostic.CA1027.severity = none
dotnet_diagnostic.CA1501.severity = none
dotnet_diagnostic.CA1835.severity = none
""";

var expected = """
# Autogenerated values
[*.cs]
### CA Design ###
dotnet_diagnostic.CA1016.severity = none
dotnet_diagnostic.CA1027.severity = none
### CA Maintainability ###
dotnet_diagnostic.CA1501.severity = none
### CA Performance ###
dotnet_diagnostic.CA1835.severity = none
""";

MsLearnDocumentationRawInfo msLearnDocumentationRawInfo = _repositoryPathReader.Provide(Constants.GetPathToMsDocsRoot());
RoslynRules roslynRules = _msLearnDocumentationParser.Parse(msLearnDocumentationRawInfo);

EditorConfigDocument editorConfigDocument = _parser.Parse(input);
EditorConfigDocument formattedDocument = _formatter.FormatAccordingToRuleDefinitions(editorConfigDocument, roslynRules, true);

formattedDocument.ToFullString().Should().Be(expected);
}
Expand All @@ -119,7 +150,7 @@ public void FormatAccordingToRuleDefinitions_Sample_ReturnExpectedFormatterDocum
RoslynRules roslynRules = _msLearnDocumentationParser.Parse(msLearnDocumentationRawInfo);

EditorConfigDocument editorConfigDocument = _parser.Parse(input);
EditorConfigDocument formattedDocument = _formatter.FormatAccordingToRuleDefinitions(editorConfigDocument, roslynRules);
EditorConfigDocument formattedDocument = _formatter.FormatAccordingToRuleDefinitions(editorConfigDocument, roslynRules, false);
// TODO: Do smth with this =_=

formattedDocument.ToFullString()
Expand Down

0 comments on commit b13a199

Please sign in to comment.