Skip to content

Commit

Permalink
Merge pull request #77 from kysect/feat/analyze-invalid-option-values
Browse files Browse the repository at this point in the history
Analyze invalid option values
  • Loading branch information
FrediKats committed Sep 14, 2023
2 parents 88588d5 + 2781b94 commit 086b8a4
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Kysect.CommonLib.BaseTypes.Extensions;
using Kysect.CommonLib.Logging;
using Kysect.Configuin.EditorConfig;
using Kysect.Configuin.MsLearn;
using Kysect.Configuin.MsLearn.Models;
Expand Down Expand Up @@ -45,33 +44,18 @@ public override int Execute([NotNull] CommandContext context, [NotNull] Settings
settings.MsLearnRepositoryPath.ThrowIfNull();

var editorConfigAnalyzer = new EditorConfigAnalyzer();
IEditorConfigAnalyzeReporter reporter = new EditorConfigAnalyzeLogReporter(_logger);

string editorConfigContent = _editorConfigContentProvider.Provide(settings.EditorConfigPath);
EditorConfigSettings editorConfigSettings = _editorConfigSettingsParser.Parse(editorConfigContent);
MsLearnDocumentationRawInfo msLearnDocumentationRawInfo = _msLearnDocumentationInfoReader.Provide(settings.MsLearnRepositoryPath);
RoslynRules roslynRules = _msLearnDocumentationParser.Parse(msLearnDocumentationRawInfo);
EditorConfigMissedConfiguration editorConfigMissedConfiguration = editorConfigAnalyzer.GetMissedConfigurations(editorConfigSettings, roslynRules);

if (editorConfigMissedConfiguration.StyleRuleSeverity.Any())
{
_logger.LogInformation("Missed style rules:");
foreach (RoslynRuleId roslynRuleId in editorConfigMissedConfiguration.StyleRuleSeverity)
_logger.LogTabInformation(1, roslynRuleId.ToString());
}

if (editorConfigMissedConfiguration.QualityRuleSeverity.Any())
{
_logger.LogInformation("Missed quality rules:");
foreach (RoslynRuleId roslynRuleId in editorConfigMissedConfiguration.QualityRuleSeverity)
_logger.LogTabInformation(1, roslynRuleId.ToString());
}
EditorConfigMissedConfiguration editorConfigMissedConfiguration = editorConfigAnalyzer.GetMissedConfigurations(editorConfigSettings, roslynRules);
IReadOnlyCollection<EditorConfigInvalidOptionValue> incorrectOptionValues = editorConfigAnalyzer.GetIncorrectOptionValues(editorConfigSettings, roslynRules);

if (editorConfigMissedConfiguration.StyleRuleOptions.Any())
{
_logger.LogInformation("Missed options:");
foreach (string styleRuleOption in editorConfigMissedConfiguration.StyleRuleOptions)
_logger.LogTabInformation(1, styleRuleOption);
}
reporter.ReportMissedConfigurations(editorConfigMissedConfiguration);
reporter.ReportIncorrectOptionValues(incorrectOptionValues);

return 0;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using Kysect.CommonLib.Collections.Extensions;
using Kysect.CommonLib.Logging;
using Kysect.Configuin.RoslynModels;
using Microsoft.Extensions.Logging;

namespace Kysect.Configuin.EditorConfig;

public class EditorConfigAnalyzeLogReporter : IEditorConfigAnalyzeReporter
{
private readonly ILogger _logger;

public EditorConfigAnalyzeLogReporter(ILogger logger)
{
_logger = logger;
}

public void ReportMissedConfigurations(EditorConfigMissedConfiguration editorConfigMissedConfiguration)
{
if (editorConfigMissedConfiguration.StyleRuleSeverity.Any())
{
_logger.LogInformation("Missed style rules:");
foreach (RoslynRuleId roslynRuleId in editorConfigMissedConfiguration.StyleRuleSeverity)
_logger.LogTabInformation(1, roslynRuleId.ToString());
}

if (editorConfigMissedConfiguration.QualityRuleSeverity.Any())
{
_logger.LogInformation("Missed quality rules:");
foreach (RoslynRuleId roslynRuleId in editorConfigMissedConfiguration.QualityRuleSeverity)
_logger.LogTabInformation(1, roslynRuleId.ToString());
}

if (editorConfigMissedConfiguration.StyleRuleOptions.Any())
{
_logger.LogInformation("Missed options:");
foreach (string styleRuleOption in editorConfigMissedConfiguration.StyleRuleOptions)
_logger.LogTabInformation(1, styleRuleOption);
}
}

public void ReportIncorrectOptionValues(IReadOnlyCollection<EditorConfigInvalidOptionValue> incorrectOptionValues)
{
if (incorrectOptionValues.Any())
_logger.LogInformation("Incorrect option value:");

foreach (EditorConfigInvalidOptionValue editorConfigInvalidOptionValue in incorrectOptionValues)
{
string availableOptions = editorConfigInvalidOptionValue.AvailableOptions.ToSingleString(o => o.Value);
_logger.LogTabInformation(1, $"Option {editorConfigInvalidOptionValue.Key} has value {editorConfigInvalidOptionValue.Value} but available values: [{availableOptions}]");
}
}
}
18 changes: 18 additions & 0 deletions Sources/Kysect.Configuin.EditorConfig/EditorConfigAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,22 @@ public EditorConfigMissedConfiguration GetMissedConfigurations(EditorConfigSetti

return new EditorConfigMissedConfiguration(missedStyleRules, missedQualityRules, missedOptions);
}

public IReadOnlyCollection<EditorConfigInvalidOptionValue> GetIncorrectOptionValues(EditorConfigSettings editorConfigSettings, RoslynRules roslynRules)
{
var result = new List<EditorConfigInvalidOptionValue>();

var optionAvailableValues = roslynRules.GetOptions().ToDictionary(o => o.Name, o => o.Values);

foreach ((string key, string value) in editorConfigSettings.Settings.OfType<RoslynOptionEditorConfigSetting>())
{
if (!optionAvailableValues.TryGetValue(key, out IReadOnlyCollection<RoslynStyleRuleOptionValue>? values))
values = Array.Empty<RoslynStyleRuleOptionValue>();

if (!values.Any(v => v.Value.Equals(value, StringComparison.InvariantCultureIgnoreCase)))
result.Add(new EditorConfigInvalidOptionValue(key, value, values));
}

return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,12 @@ namespace Kysect.Configuin.EditorConfig;
public record EditorConfigMissedConfiguration(
IReadOnlyCollection<RoslynRuleId> StyleRuleSeverity,
IReadOnlyCollection<RoslynRuleId> QualityRuleSeverity,
IReadOnlyCollection<string> StyleRuleOptions);
IReadOnlyCollection<string> StyleRuleOptions
);


public record EditorConfigInvalidOptionValue(
string Key,
string Value,
IReadOnlyCollection<RoslynStyleRuleOptionValue> AvailableOptions
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Kysect.Configuin.EditorConfig;

public interface IEditorConfigAnalyzeReporter
{
void ReportMissedConfigurations(EditorConfigMissedConfiguration editorConfigMissedConfiguration);
void ReportIncorrectOptionValues(IReadOnlyCollection<EditorConfigInvalidOptionValue> incorrectOptionValues);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

public record RoslynStyleRuleOption(
string Name,
IReadOnlyCollection<RoslynStyleRuleOptionValue> Options,
IReadOnlyCollection<RoslynStyleRuleOptionValue> Values,
string? DefaultValue,
string? CsharpCodeSample);
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,20 @@ namespace Kysect.Configuin.Tests.EditorConfig;

public class EditorConfigAnalyzerTests
{
private readonly EditorConfigAnalyzer _editorConfigAnalyzer;

public EditorConfigAnalyzerTests()
{
_editorConfigAnalyzer = new EditorConfigAnalyzer();
}

[Test]
public void GetMissedConfigurations_AllOptionAreMissed_ReturnAllOptions()
{
var editorConfigAnalyzer = new EditorConfigAnalyzer();

var editorConfigSettings = new EditorConfigSettings(Array.Empty<IEditorConfigSetting>());
var roslynRules = new RoslynRules(new[] { WellKnownRoslynRuleDefinitions.CA1064() }, new[] { WellKnownRoslynRuleDefinitions.IDE0040() });

EditorConfigMissedConfiguration editorConfigMissedConfiguration = editorConfigAnalyzer.GetMissedConfigurations(editorConfigSettings, roslynRules);
EditorConfigMissedConfiguration editorConfigMissedConfiguration = _editorConfigAnalyzer.GetMissedConfigurations(editorConfigSettings, roslynRules);

editorConfigMissedConfiguration.QualityRuleSeverity
.Should().HaveCount(1)
Expand All @@ -35,8 +40,6 @@ public void GetMissedConfigurations_AllOptionAreMissed_ReturnAllOptions()
[Test]
public void GetMissedConfigurations_AllOptionExists_ReturnAllOptions()
{
var editorConfigAnalyzer = new EditorConfigAnalyzer();

var editorConfigSettings = new EditorConfigSettings(new IEditorConfigSetting[]
{
new RoslynSeverityEditorConfigSetting(WellKnownRoslynRuleDefinitions.IDE0040().RuleId, RoslynRuleSeverity.Warning),
Expand All @@ -46,10 +49,71 @@ public void GetMissedConfigurations_AllOptionExists_ReturnAllOptions()

var roslynRules = new RoslynRules(new[] { WellKnownRoslynRuleDefinitions.CA1064() }, new[] { WellKnownRoslynRuleDefinitions.IDE0040() });

EditorConfigMissedConfiguration editorConfigMissedConfiguration = editorConfigAnalyzer.GetMissedConfigurations(editorConfigSettings, roslynRules);
EditorConfigMissedConfiguration editorConfigMissedConfiguration = _editorConfigAnalyzer.GetMissedConfigurations(editorConfigSettings, roslynRules);

editorConfigMissedConfiguration.QualityRuleSeverity.Should().BeEmpty();
editorConfigMissedConfiguration.StyleRuleSeverity.Should().BeEmpty();
editorConfigMissedConfiguration.StyleRuleOptions.Should().BeEmpty();
}

[Test]
public void GetIncorrectOptionValues_AllOptionsValid_NoElementReturn()
{
var editorConfigSettings = new EditorConfigSettings(new IEditorConfigSetting[]
{
new RoslynOptionEditorConfigSetting(WellKnownRoslynRuleDefinitions.IDE0040().Options.Single().Name, "always")
});

var roslynRules = new RoslynRules(Array.Empty<RoslynQualityRule>(), new[] { WellKnownRoslynRuleDefinitions.IDE0040() });

IReadOnlyCollection<EditorConfigInvalidOptionValue> invalidOptionValues = _editorConfigAnalyzer.GetIncorrectOptionValues(editorConfigSettings, roslynRules);

invalidOptionValues.Should().BeEmpty();
}

[Test]
public void GetIncorrectOptionValues_ForInvalidOptionValue_ReturnInvalidOption()
{
string incorrectOptionValue = "null";
RoslynStyleRuleOption selectedOptions = WellKnownRoslynRuleDefinitions.IDE0040().Options.Single();

var editorConfigSettings = new EditorConfigSettings(new IEditorConfigSetting[]
{
new RoslynOptionEditorConfigSetting(selectedOptions.Name, incorrectOptionValue)
});

var roslynRules = new RoslynRules(Array.Empty<RoslynQualityRule>(), new[] { WellKnownRoslynRuleDefinitions.IDE0040() });
var expected = new EditorConfigInvalidOptionValue(
selectedOptions.Name,
incorrectOptionValue,
selectedOptions.Values);

IReadOnlyCollection<EditorConfigInvalidOptionValue> invalidOptionValues = _editorConfigAnalyzer.GetIncorrectOptionValues(editorConfigSettings, roslynRules);

invalidOptionValues.Should().HaveCount(1)
.And.Subject.ElementAt(0).Should().BeEquivalentTo(expected);
}

[Test]
public void GetIncorrectOptionValues_ForInvalidOptionKey_ReturnInvalidOption()
{
string incorrectOptionKey = "null";
string incorrectOptionValue = "null";

var editorConfigSettings = new EditorConfigSettings(new IEditorConfigSetting[]
{
new RoslynOptionEditorConfigSetting(incorrectOptionKey, incorrectOptionValue)
});

var roslynRules = new RoslynRules(Array.Empty<RoslynQualityRule>(), new[] { WellKnownRoslynRuleDefinitions.IDE0040() });
var expected = new EditorConfigInvalidOptionValue(
incorrectOptionKey,
incorrectOptionValue,
Array.Empty<RoslynStyleRuleOptionValue>());

IReadOnlyCollection<EditorConfigInvalidOptionValue> invalidOptionValues = _editorConfigAnalyzer.GetIncorrectOptionValues(editorConfigSettings, roslynRules);

invalidOptionValues.Should().HaveCount(1)
.And.Subject.ElementAt(0).Should().BeEquivalentTo(expected);
}
}

0 comments on commit 086b8a4

Please sign in to comment.