From 2a8ad5689c8f810902dce3fc3e7d849f5e89bf12 Mon Sep 17 00:00:00 2001 From: Amy Boyd Date: Wed, 22 Jun 2016 23:58:10 +0100 Subject: [PATCH] Add function GetRulesToApplyToSourcePath. --- editorconfig/apply.go | 73 ++++++++++++++++++++++++++++++++ editorconfig/apply_test.go | 34 +++++++++++++++ editorconfig/config_file.go | 5 ++- editorconfig/tests/.editorconfig | 3 ++ 4 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 editorconfig/apply.go create mode 100644 editorconfig/apply_test.go diff --git a/editorconfig/apply.go b/editorconfig/apply.go new file mode 100644 index 0000000..b96d165 --- /dev/null +++ b/editorconfig/apply.go @@ -0,0 +1,73 @@ +package editorconfig + +import ( + "path/filepath" + "sort" + "strings" +) + +func GetRulesToApplyToSourcePath(sourcePath string, cfs []ConfigFile) map[string]string { + applicable := FilterConfigFilesToApplyToSourcePath(sourcePath, cfs) + applicableSorted := SortConfigFilesByPrecendence(applicable) + + rules := make(map[string]string) + + for _, cf := range applicableSorted { + for _, rule := range cf.DefaultRuleSet { + rules[rule.Name] = rule.Value + } + + for _, rs := range cf.FileConstrainedRuleSets { + if rs.ConstraintRegexp.MatchString(sourcePath) { + for _, rule := range rs.Rules { + rules[rule.Name] = rule.Value + } + } + } + } + + delete(rules, "root") + + return rules +} + +func FilterConfigFilesToApplyToSourcePath(sourcePath string, cfs []ConfigFile) []ConfigFile { + applicable := []ConfigFile{} + + for _, cf := range cfs { + absSourcePath, err := filepath.Abs(sourcePath) + if err != nil { + ExitBecauseOfInternalError("Could not get absolute path for " + sourcePath) + } + absCfDir, err := filepath.Abs(cf.Dir()) + if err != nil { + ExitBecauseOfInternalError("Could not get absolute path for " + cf.Dir()) + } + if strings.HasPrefix(absSourcePath, absCfDir) { + applicable = append(applicable, cf) + } + } + + return applicable +} + +// ByPrecedence implements sort.Interface for []ConfigFile based on how many slashes are in the file's path. +type ByPrecedence []ConfigFile + +func (a ByPrecedence) Len() int { + return len(a) +} +func (a ByPrecedence) Swap(i, j int) { + a[i], a[j] = a[j], a[i] +} +func (a ByPrecedence) Less(i, j int) bool { + return a[i].Precedence() < a[j].Precedence() +} + +/** + * @return Least important files first, most important files last. + */ +func SortConfigFilesByPrecendence(cfs []ConfigFile) []ConfigFile { + sort.Sort(ByPrecedence(cfs)) + return cfs +} diff --git a/editorconfig/apply_test.go b/editorconfig/apply_test.go new file mode 100644 index 0000000..593e7cd --- /dev/null +++ b/editorconfig/apply_test.go @@ -0,0 +1,34 @@ +package editorconfig + +import ( + "testing" +) + +func TestGetRulesToApplyToSourcePath(t *testing.T) { + result := GetRulesToApplyToSourcePath( + "tests/a/b/file.go", + []ConfigFile{ + CreateConfigFileStruct("tests/.editorconfig"), + }, + ) + + if result["end_of_line"] != "lf" { + t.Error("The end_of_line rule should come from the * file pattern") + } + if result["indent_style"] != "tabs" { + t.Error("The indent_style rule should come from the **.go file pattern, overriding the *'s indent_style") + } +} + +func TestGetRulesToApplyToSourcePathWhenNoRulesShouldApply(t *testing.T) { + result := GetRulesToApplyToSourcePath( + "some-file-not-affected-by-rules", + []ConfigFile{ + CreateConfigFileStruct("tests/.editorconfig"), + }, + ) + + if len(result) != 0 { + t.Error("No rules should be applied for the file") + } +} diff --git a/editorconfig/config_file.go b/editorconfig/config_file.go index ee56c14..2d4dde7 100644 --- a/editorconfig/config_file.go +++ b/editorconfig/config_file.go @@ -2,6 +2,7 @@ package editorconfig import ( "github.com/go-ini/ini" + "path/filepath" "regexp" "strings" ) @@ -51,9 +52,11 @@ type FileConstrainedRuleSet struct { } func CreateConfigFileStruct(path string) ConfigFile { + absPath, _ := filepath.Abs(path) + ini, err := ini.Load(path) if err != nil { - ExitBecauseOfInternalError("Could not parse " + path) + ExitBecauseOfInternalError("Could not parse " + absPath) } cf := ConfigFile{} diff --git a/editorconfig/tests/.editorconfig b/editorconfig/tests/.editorconfig index 7e9d9b5..36c6853 100644 --- a/editorconfig/tests/.editorconfig +++ b/editorconfig/tests/.editorconfig @@ -10,3 +10,6 @@ insert_final_newline = true [keep-trailing-spaces] trim_trailing_whitespace = false + +[**.go] +indent_style = tabs