You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gitea-fork-majority-judgment/vendor/github.com/editorconfig/editorconfig-core-go/v2/definition.go

195 lines
5.3 KiB

package editorconfig
import (
"fmt"
"strconv"
"strings"
"golang.org/x/mod/semver"
"gopkg.in/ini.v1"
)
// Definition represents a definition inside the .editorconfig file.
// E.g. a section of the file.
// The definition is composed of the selector ("*", "*.go", "*.{js.css}", etc),
// plus the properties of the selected files.
type Definition struct {
Selector string `ini:"-" json:"-"`
Charset string `ini:"charset" json:"charset,omitempty"`
IndentStyle string `ini:"indent_style" json:"indent_style,omitempty"`
IndentSize string `ini:"indent_size" json:"indent_size,omitempty"`
TabWidth int `ini:"-" json:"-"`
EndOfLine string `ini:"end_of_line" json:"end_of_line,omitempty"`
TrimTrailingWhitespace *bool `ini:"-" json:"-"`
InsertFinalNewline *bool `ini:"-" json:"-"`
Raw map[string]string `ini:"-" json:"-"`
version string
}
// NewDefinition builds a definition from a given config.
func NewDefinition(config Config) (*Definition, error) {
return config.Load(config.Path)
}
// normalize fixes some values to their lowercase value.
func (d *Definition) normalize() error {
d.Charset = strings.ToLower(d.Charset)
d.EndOfLine = strings.ToLower(d.Raw["end_of_line"])
d.IndentStyle = strings.ToLower(d.Raw["indent_style"])
trimTrailingWhitespace, ok := d.Raw["trim_trailing_whitespace"]
if ok && trimTrailingWhitespace != UnsetValue {
trim, err := strconv.ParseBool(trimTrailingWhitespace)
if err != nil {
return fmt.Errorf("trim_trailing_whitespace=%s is not an acceptable value. %w", trimTrailingWhitespace, err)
}
d.TrimTrailingWhitespace = &trim
}
insertFinalNewline, ok := d.Raw["insert_final_newline"]
if ok && insertFinalNewline != UnsetValue {
insert, err := strconv.ParseBool(insertFinalNewline)
if err != nil {
return fmt.Errorf("insert_final_newline=%s is not an acceptable value. %w", insertFinalNewline, err)
}
d.InsertFinalNewline = &insert
}
// tab_width from Raw
tabWidth, ok := d.Raw["tab_width"]
if ok && tabWidth != UnsetValue {
num, err := strconv.Atoi(tabWidth)
if err != nil {
return fmt.Errorf("tab_width=%s is not an acceptable value. %w", tabWidth, err)
}
d.TabWidth = num
}
// tab_width defaults to indent_size:
// https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#tab_width
num, err := strconv.Atoi(d.IndentSize)
if err == nil && d.TabWidth <= 0 {
d.TabWidth = num
}
return nil
}
// merge the parent definition into the child definition.
func (d *Definition) merge(md *Definition) {
if len(d.Charset) == 0 {
d.Charset = md.Charset
}
if len(d.IndentStyle) == 0 {
d.IndentStyle = md.IndentStyle
}
if len(d.IndentSize) == 0 {
d.IndentSize = md.IndentSize
}
if d.TabWidth <= 0 {
d.TabWidth = md.TabWidth
}
if len(d.EndOfLine) == 0 {
d.EndOfLine = md.EndOfLine
}
if trimTrailingWhitespace, ok := d.Raw["trim_trailing_whitespace"]; !ok || trimTrailingWhitespace != UnsetValue {
if d.TrimTrailingWhitespace == nil {
d.TrimTrailingWhitespace = md.TrimTrailingWhitespace
}
}
if insertFinalNewline, ok := d.Raw["insert_final_newline"]; !ok || insertFinalNewline != UnsetValue {
if d.InsertFinalNewline == nil {
d.InsertFinalNewline = md.InsertFinalNewline
}
}
for k, v := range md.Raw {
if _, ok := d.Raw[k]; !ok {
d.Raw[k] = v
}
}
}
// InsertToIniFile writes the definition into a ini file.
func (d *Definition) InsertToIniFile(iniFile *ini.File) { // nolint: funlen,gocognit,cyclop
iniSec := iniFile.Section(d.Selector)
for k, v := range d.Raw {
switch k {
case "insert_final_newline":
if d.InsertFinalNewline != nil {
v = strconv.FormatBool(*d.InsertFinalNewline)
} else {
insertFinalNewline, ok := d.Raw["insert_final_newline"]
if !ok {
break
}
v = strings.ToLower(insertFinalNewline)
}
case "trim_trailing_whitespace":
if d.TrimTrailingWhitespace != nil {
v = strconv.FormatBool(*d.TrimTrailingWhitespace)
} else {
trimTrailingWhitespace, ok := d.Raw["trim_trailing_whitespace"]
if !ok {
break
}
v = strings.ToLower(trimTrailingWhitespace)
}
case "charset":
v = d.Charset
case "end_of_line":
v = d.EndOfLine
case "indent_style":
v = d.IndentStyle
case "tab_width":
tabWidth, ok := d.Raw["tab_width"]
if ok && tabWidth == UnsetValue {
v = tabWidth
} else {
v = strconv.Itoa(d.TabWidth)
}
case "indent_size":
v = d.IndentSize
}
iniSec.NewKey(k, v) // nolint: errcheck
}
if _, ok := d.Raw["indent_size"]; !ok {
tabWidth, ok := d.Raw["tab_width"]
switch {
case ok && tabWidth == UnsetValue:
// do nothing
case d.TabWidth > 0:
iniSec.NewKey("indent_size", strconv.Itoa(d.TabWidth)) // nolint: errcheck
case d.IndentStyle == IndentStyleTab && (d.version == "" || semver.Compare(d.version, "v0.9.0") >= 0):
iniSec.NewKey("indent_size", IndentStyleTab) // nolint: errcheck
}
}
if _, ok := d.Raw["tab_width"]; !ok {
if d.IndentSize == UnsetValue {
iniSec.NewKey("tab_width", d.IndentSize) // nolint: errcheck
} else {
_, err := strconv.Atoi(d.IndentSize)
if err == nil {
iniSec.NewKey("tab_width", d.Raw["indent_size"]) // nolint: errcheck
}
}
}
}