Skip to content

Commit

Permalink
Add formatting with grouping option by rules
Browse files Browse the repository at this point in the history
  • Loading branch information
FrediKats committed May 16, 2024
1 parent f5eb2aa commit 9880b2e
Show file tree
Hide file tree
Showing 6 changed files with 689 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Kysect.CommonLib.Collections.Extensions;
using Kysect.CommonLib.BaseTypes.Extensions;
using Kysect.CommonLib.Collections.Extensions;
using Kysect.Configuin.EditorConfig.DocumentModel;
using Kysect.Configuin.EditorConfig.DocumentModel.Nodes;
using Kysect.Configuin.EditorConfig.Settings;
Expand All @@ -18,22 +19,81 @@ public EditorConfigFormatter(DotnetConfigSettingsParser settingsParser)
public EditorConfigDocument Format(EditorConfigDocument value)
{
List<EditorConfigPropertyNode> nodesForRemoving = new List<EditorConfigPropertyNode>();
IReadOnlyCollection<EditorConfigPropertyNode> styleRuleNodesForMoving = SelectIdeNodes(value, RoslynRuleType.StyleRule);
IReadOnlyCollection<EditorConfigPropertyNode> qualityRuleNodesForMoving = SelectIdeNodes(value, RoslynRuleType.QualityRule);
IReadOnlyCollection<EditorConfigPropertyNode> styleRuleNodesForMoving = SelectIdeNodes(value, RoslynRuleType.StyleRule).OrderBy(r => r.Key.Value).ToList();
IReadOnlyCollection<EditorConfigPropertyNode> qualityRuleNodesForMoving = SelectIdeNodes(value, RoslynRuleType.QualityRule).OrderBy(r => r.Key.Value).ToList();
nodesForRemoving.AddRange(styleRuleNodesForMoving);
nodesForRemoving.AddRange(qualityRuleNodesForMoving);

if (nodesForRemoving.IsEmpty())
return value;

value = value.RemoveNodes(nodesForRemoving);
var autoGeneratedSection = new EditorConfigCategoryNode("*.cs", [], ["# Autoformatted values"], null);
EditorConfigCategoryNode autoGeneratedSection = CreateAutoGeneratedCategory(styleRuleNodesForMoving, qualityRuleNodesForMoving);

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

public EditorConfigDocument FormatAccordingToRuleDefinitions(EditorConfigDocument document, RoslynRules rules)
{
rules.ThrowIfNull();

List<EditorConfigPropertyNode> nodesForRemoving = new List<EditorConfigPropertyNode>();

List<EditorConfigPropertyNode> propertyNodes = document
.DescendantNodes()
.OfType<EditorConfigPropertyNode>()
.ToList();

List<EditorConfigPropertyNode> selectedStyleRuleNodes = new List<EditorConfigPropertyNode>();
foreach (RoslynStyleRuleGroup roslynStyleRuleGroup in rules.StyleRuleGroups)
{
foreach (RoslynStyleRule roslynStyleRule in roslynStyleRuleGroup.Rules)
{
EditorConfigPropertyNode? editorConfigPropertyNode = TryFindSeverityNode(propertyNodes, roslynStyleRule.RuleId);
if (editorConfigPropertyNode is null)
continue;

selectedStyleRuleNodes.Add(editorConfigPropertyNode);
}

foreach (RoslynStyleRuleOption roslynStyleRuleOption in roslynStyleRuleGroup.Options)
{
EditorConfigPropertyNode? editorConfigPropertyNode = TryFindOptionNode(propertyNodes, roslynStyleRuleOption);
if (editorConfigPropertyNode is null)
continue;

selectedStyleRuleNodes.Add(editorConfigPropertyNode);
}
}

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);
}

nodesForRemoving.AddRange(selectedStyleRuleNodes);
nodesForRemoving.AddRange(selectedQualityRuleNodes);
EditorConfigCategoryNode autoGeneratedSection = CreateAutoGeneratedCategory(selectedStyleRuleNodes, selectedQualityRuleNodes);

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

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

if (styleRuleNodesForMoving.Any())
{
var styleRuleSection = new EditorConfigDocumentSectionNode("### IDE ###");

styleRuleNodesForMoving = styleRuleNodesForMoving.OrderBy(r => r.Key.Value).ToList();
foreach (EditorConfigPropertyNode styleRule in styleRuleNodesForMoving)
styleRuleSection = styleRuleSection.AddChild(styleRule);

Expand All @@ -43,20 +103,16 @@ public EditorConfigDocument Format(EditorConfigDocument value)
if (qualityRuleNodesForMoving.Any())
{
var qualitySection = new EditorConfigDocumentSectionNode("### CA ###");

qualityRuleNodesForMoving = qualityRuleNodesForMoving.OrderBy(r => r.Key.Value).ToList();
foreach (EditorConfigPropertyNode qualityRule in qualityRuleNodesForMoving)
qualitySection = qualitySection.AddChild(qualityRule);

autoGeneratedSection = autoGeneratedSection.AddChild(qualitySection);
}

value = value.AddChild(autoGeneratedSection);

return value;
return autoGeneratedSection;
}

public IReadOnlyCollection<EditorConfigPropertyNode> SelectIdeNodes(EditorConfigDocument document, RoslynRuleType roslynRuleType)
private IReadOnlyCollection<EditorConfigPropertyNode> SelectIdeNodes(EditorConfigDocument document, RoslynRuleType roslynRuleType)
{
List<EditorConfigPropertyNode> propertyNodes = document
.DescendantNodes()
Expand All @@ -76,4 +132,34 @@ public IReadOnlyCollection<EditorConfigPropertyNode> SelectIdeNodes(EditorConfig

return styleRuleNodes;
}

private EditorConfigPropertyNode? TryFindSeverityNode(IReadOnlyCollection<EditorConfigPropertyNode> propertyNodes, RoslynRuleId id)
{
foreach (EditorConfigPropertyNode editorConfigPropertyNode in propertyNodes)
{
IEditorConfigSetting editorConfigSetting = _settingsParser.ParseSetting(editorConfigPropertyNode);
if (editorConfigSetting is not RoslynSeverityEditorConfigSetting severitySettings)
continue;

if (severitySettings.RuleId == id)
return editorConfigPropertyNode;
}

return null;
}

private EditorConfigPropertyNode? TryFindOptionNode(IReadOnlyCollection<EditorConfigPropertyNode> propertyNodes, RoslynStyleRuleOption roslynStyleRuleOption)
{
foreach (EditorConfigPropertyNode editorConfigPropertyNode in propertyNodes)
{
IEditorConfigSetting editorConfigSetting = _settingsParser.ParseSetting(editorConfigPropertyNode);
if (editorConfigSetting is not RoslynOptionEditorConfigSetting option)
continue;

if (option.Key == roslynStyleRuleOption.Name)
return editorConfigPropertyNode;
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,6 @@ public void Parse_EditorConfigFile_ReturnWithoutErrors()

// TODO: add more asserts
dotnetConfigSettings.Settings
.Should().HaveCount(393);
.Should().HaveCount(392);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
using Kysect.Configuin.EditorConfig.DocumentModel;
using Kysect.Configuin.EditorConfig.DocumentModel.Nodes;
using Kysect.Configuin.EditorConfig.Formatter;
using Kysect.Configuin.MsLearn;
using Kysect.Configuin.MsLearn.Models;
using Kysect.Configuin.RoslynModels;
using Kysect.Configuin.Tests.Tools;

namespace Kysect.Configuin.Tests.EditorConfig;
Expand All @@ -10,6 +13,8 @@ public class EditorConfigFormatterTests
{
private readonly EditorConfigFormatter _formatter;
private readonly EditorConfigDocumentParser _parser;
private readonly MsLearnDocumentationInfoLocalReader _repositoryPathReader = TestImplementations.CreateDocumentationInfoLocalProvider();
private readonly MsLearnDocumentationParser _msLearnDocumentationParser = new MsLearnDocumentationParser(TestImplementations.GetTextExtractor(), TestLogger.ProviderForTests());

public EditorConfigFormatterTests()
{
Expand All @@ -31,7 +36,7 @@ public void Format_OrderedIdeRulesWithoutHeader_HeaderAdded()
var expected = """
first = value
second = value
# Autoformatted values
# Autogenerated values
[*.cs]
### IDE ###
dotnet_diagnostic.IDE0080.severity = none
Expand All @@ -57,7 +62,7 @@ public void Format_QualityAndStyleRulesMashed_ReturnOrderedLinesWithHeader()
var expected = """
first = value
second = value
# Autoformatted values
# Autogenerated values
[*.cs]
### IDE ###
dotnet_diagnostic.IDE0080.severity = none
Expand All @@ -70,6 +75,19 @@ public void Format_QualityAndStyleRulesMashed_ReturnOrderedLinesWithHeader()
FormatAndCompare(input, expected);
}

[Fact]
public void FormatAccordingToRuleDefinitions_Sample_ReturnExpectedFormatterDocument()
{
string input = File.ReadAllText(Path.Combine("Resources", "Editor-config-sample.ini"));
string expected = File.ReadAllText(Path.Combine("Resources", "Editor-config-sample-formatted.ini"));
MsLearnDocumentationRawInfo msLearnDocumentationRawInfo = _repositoryPathReader.Provide(Constants.GetPathToMsDocsRoot());
RoslynRules roslynRules = _msLearnDocumentationParser.Parse(msLearnDocumentationRawInfo);

EditorConfigDocument editorConfigDocument = _parser.Parse(input);
EditorConfigDocument formattedDocument = _formatter.FormatAccordingToRuleDefinitions(editorConfigDocument, roslynRules);
formattedDocument.ToFullString().Should().Be(expected);
}

private void FormatAndCompare(string input, string expected)
{
EditorConfigDocument editorConfigDocument = _parser.Parse(input);
Expand Down
3 changes: 3 additions & 0 deletions Sources/Kysect.Configuin.Tests/Kysect.Configuin.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
<None Update="Resources\DotnetFormatOutput-two-report.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Resources\Editor-config-sample-formatted.ini">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Resources\Editor-config-sample.ini">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
Loading

0 comments on commit 9880b2e

Please sign in to comment.