-
-
Notifications
You must be signed in to change notification settings - Fork 89
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding support for reading editorconfigs
closes #630
- Loading branch information
Showing
18 changed files
with
861 additions
and
294 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace CSharpier.Cli.EditorConfig; | ||
|
||
internal class ConfigFile | ||
{ | ||
public required List<Section> Sections { get; init; } | ||
public bool IsRoot { get; init; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
using System.IO.Abstractions; | ||
using System.Text.RegularExpressions; | ||
|
||
namespace CSharpier.Cli.EditorConfig; | ||
|
||
internal static class ConfigFileParser | ||
{ | ||
private static readonly Regex SectionRegex = new(@"^\s*\[(([^#;]|\\#|\\;)+)\]\s*([#;].*)?$"); | ||
private static readonly Regex CommentRegex = new(@"^\s*[#;]"); | ||
private static readonly Regex PropertyRegex = | ||
new(@"^\s*([\w\.\-_]+)\s*[=:]\s*(.*?)\s*([#;].*)?$"); | ||
|
||
private static readonly HashSet<string> KnownProperties = | ||
new( | ||
new[] { "indent_style", "indent_size", "tab_width", "max_line_length", "root", }, | ||
StringComparer.OrdinalIgnoreCase | ||
); | ||
|
||
public static ConfigFile Parse(string filePath, IFileSystem fileSystem) | ||
{ | ||
var lines = fileSystem.File.ReadLines(filePath); | ||
|
||
var isRoot = false; | ||
var propertiesBySection = new Dictionary<string, Dictionary<string, string?>>(); | ||
var sectionName = string.Empty; | ||
foreach (var line in lines) | ||
{ | ||
if (string.IsNullOrWhiteSpace(line) || CommentRegex.IsMatch(line)) | ||
{ | ||
continue; | ||
} | ||
|
||
var propertyMatches = PropertyRegex.Matches(line); | ||
if (propertyMatches.Count > 0) | ||
{ | ||
var key = propertyMatches[0].Groups[1].Value.Trim().ToLowerInvariant(); | ||
var value = propertyMatches[0].Groups[2].Value.Trim(); | ||
|
||
if (KnownProperties.Contains(key)) | ||
{ | ||
value = value.ToLowerInvariant(); | ||
} | ||
|
||
if (sectionName is "") | ||
{ | ||
if (key == "root" && bool.TryParse(value, out var parsedValue)) | ||
{ | ||
isRoot = parsedValue; | ||
} | ||
} | ||
else | ||
{ | ||
propertiesBySection[sectionName][key] = value; | ||
} | ||
} | ||
else | ||
{ | ||
var sectionMatches = SectionRegex.Matches(line); | ||
if (sectionMatches.Count <= 0) | ||
{ | ||
continue; | ||
} | ||
|
||
sectionName = sectionMatches[0].Groups[1].Value; | ||
propertiesBySection[sectionName] = new Dictionary<string, string?>(); | ||
} | ||
} | ||
|
||
var directory = fileSystem.Path.GetDirectoryName(filePath); | ||
return new ConfigFile | ||
{ | ||
IsRoot = isRoot, | ||
Sections = propertiesBySection | ||
.Select(o => new Section(o.Key, directory, o.Value)) | ||
.ToList() | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
using System.IO.Abstractions; | ||
|
||
namespace CSharpier.Cli.EditorConfig; | ||
|
||
internal static class EditorConfigParser | ||
{ | ||
public static List<EditorConfigSections> GetAllForDirectory( | ||
string directoryName, | ||
IFileSystem fileSystem | ||
) | ||
{ | ||
if (directoryName is "") | ||
{ | ||
return new List<EditorConfigSections>(); | ||
} | ||
|
||
var editorConfigFiles = fileSystem.DirectoryInfo | ||
.FromDirectoryName(directoryName) | ||
.EnumerateFiles(".editorconfig", SearchOption.AllDirectories); | ||
|
||
return editorConfigFiles | ||
.Select( | ||
o => | ||
new EditorConfigSections | ||
{ | ||
DirectoryName = fileSystem.Path.GetDirectoryName(o.FullName), | ||
SectionsIncludingParentFiles = FindSections(o.FullName, fileSystem) | ||
} | ||
) | ||
.OrderBy(o => o.DirectoryName) | ||
.ToList(); | ||
} | ||
|
||
private static List<Section> FindSections(string filePath, IFileSystem fileSystem) | ||
{ | ||
var editorConfigFiles = ParseConfigFiles( | ||
fileSystem.Path.GetDirectoryName(filePath), | ||
fileSystem | ||
) | ||
.Reverse() | ||
.ToList(); | ||
return editorConfigFiles.SelectMany(configFile => configFile.Sections).ToList(); | ||
} | ||
|
||
private static IEnumerable<ConfigFile> ParseConfigFiles( | ||
string directoryPath, | ||
IFileSystem fileSystem | ||
) | ||
{ | ||
var directory = fileSystem.DirectoryInfo.FromDirectoryName(directoryPath); | ||
while (directory != null) | ||
{ | ||
var potentialPath = fileSystem.Path.Combine(directory.FullName, ".editorconfig"); | ||
if (fileSystem.File.Exists(potentialPath)) | ||
{ | ||
var configFile = ConfigFileParser.Parse(potentialPath, fileSystem); | ||
|
||
DebugLogger.Log(potentialPath); | ||
yield return configFile; | ||
if (configFile.IsRoot) | ||
{ | ||
yield break; | ||
} | ||
} | ||
|
||
directory = directory.Parent; | ||
} | ||
} | ||
} |
Oops, something went wrong.