mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-19 15:35:28 +02:00
feat(dovalues): Return multiple InvalidValue
s from now
This commit is contained in:
parent
7e0e6650eb
commit
433085443a
@ -1,11 +1,68 @@
|
|||||||
package docvalues
|
package docvalues
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"config-lsp/utils"
|
||||||
|
|
||||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Value interface {
|
type Value interface {
|
||||||
GetTypeDescription() []string
|
GetTypeDescription() []string
|
||||||
CheckIsValid(value string) error
|
CheckIsValid(value string) []*InvalidValue
|
||||||
FetchCompletions(line string, cursor uint32) []protocol.CompletionItem
|
FetchCompletions(line string, cursor uint32) []protocol.CompletionItem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type InvalidValue struct {
|
||||||
|
Err error
|
||||||
|
Start uint32
|
||||||
|
End uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *InvalidValue) Shift(offset uint32) {
|
||||||
|
v.Start += offset
|
||||||
|
v.End += offset
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *InvalidValue) GetRange(line uint32, characterStart uint32) protocol.Range {
|
||||||
|
return protocol.Range{
|
||||||
|
Start: protocol.Position{
|
||||||
|
Line: line,
|
||||||
|
Character: characterStart + v.Start,
|
||||||
|
},
|
||||||
|
End: protocol.Position{
|
||||||
|
Line: line,
|
||||||
|
Character: characterStart + v.End,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *InvalidValue) GetMessage() string {
|
||||||
|
return v.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ShiftInvalidValues(offset uint32, invalidValues []*InvalidValue) {
|
||||||
|
if len(invalidValues) > 0 {
|
||||||
|
for _, invalidValue := range invalidValues {
|
||||||
|
invalidValue.Shift(offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func InvalidValuesToErrorDiagnostics(
|
||||||
|
line uint32,
|
||||||
|
offset uint32,
|
||||||
|
values []*InvalidValue,
|
||||||
|
) []protocol.Diagnostic {
|
||||||
|
severity := protocol.DiagnosticSeverityError
|
||||||
|
|
||||||
|
return utils.Map(
|
||||||
|
values,
|
||||||
|
func(value *InvalidValue) protocol.Diagnostic {
|
||||||
|
return protocol.Diagnostic{
|
||||||
|
Range: value.GetRange(line, offset),
|
||||||
|
Severity: &severity,
|
||||||
|
Message: value.GetMessage(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -2,7 +2,9 @@ package docvalues
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"config-lsp/utils"
|
"config-lsp/utils"
|
||||||
|
|
||||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GenerateBase10Completions(prefix string) []protocol.CompletionItem {
|
func GenerateBase10Completions(prefix string) []protocol.CompletionItem {
|
||||||
@ -18,3 +20,24 @@ func GenerateBase10Completions(prefix string) []protocol.CompletionItem {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MergeKeyEnumAssignmentMaps(maps ...map[EnumString]Value) map[EnumString]Value {
|
||||||
|
existingEnums := make(map[string]interface{})
|
||||||
|
result := make(map[EnumString]Value)
|
||||||
|
|
||||||
|
slices.Reverse(maps)
|
||||||
|
|
||||||
|
for _, m := range maps {
|
||||||
|
for key, value := range m {
|
||||||
|
if _, ok := existingEnums[key.InsertText]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
existingEnums[key.InsertText] = nil
|
||||||
|
|
||||||
|
result[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
@ -9,11 +9,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ArrayContainsDuplicatesError struct {
|
type ArrayContainsDuplicatesError struct {
|
||||||
Duplicates []string
|
Value string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e ArrayContainsDuplicatesError) Error() string {
|
func (e ArrayContainsDuplicatesError) Error() string {
|
||||||
return fmt.Sprintf("The following values are duplicated: %s", strings.Join(e.Duplicates, ","))
|
return fmt.Sprintf("'%s' is a duplicate value (and duplicates are not allowed)", e.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
var SimpleDuplicatesExtractor = func(value string) string {
|
var SimpleDuplicatesExtractor = func(value string) string {
|
||||||
@ -52,7 +52,9 @@ func (v ArrayValue) GetTypeDescription() []string {
|
|||||||
subValue.GetTypeDescription()...,
|
subValue.GetTypeDescription()...,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
func (v ArrayValue) CheckIsValid(value string) error {
|
|
||||||
|
func (v ArrayValue) CheckIsValid(value string) []*InvalidValue {
|
||||||
|
errors := []*InvalidValue{}
|
||||||
values := strings.Split(value, v.Separator)
|
values := strings.Split(value, v.Separator)
|
||||||
|
|
||||||
if *v.DuplicatesExtractor != nil {
|
if *v.DuplicatesExtractor != nil {
|
||||||
@ -68,25 +70,48 @@ func (v ArrayValue) CheckIsValid(value string) error {
|
|||||||
valuesOccurrences[duplicateValue]++
|
valuesOccurrences[duplicateValue]++
|
||||||
}
|
}
|
||||||
|
|
||||||
duplicateValues := utils.FilterMapWhere(valuesOccurrences, func(_ string, value int) bool {
|
duplicateValuesAsList := utils.FilterMapWhere(valuesOccurrences, func(_ string, value int) bool {
|
||||||
return value > 1
|
return value > 1
|
||||||
})
|
})
|
||||||
|
duplicateValues := utils.KeysAsSet(duplicateValuesAsList)
|
||||||
|
|
||||||
return ArrayContainsDuplicatesError{
|
duplicateIndexStart := uint32(0)
|
||||||
Duplicates: utils.KeysOfMap(duplicateValues),
|
duplicateIndexEnd := uint32(0)
|
||||||
|
|
||||||
|
currentIndex := uint32(0)
|
||||||
|
for _, rawValue := range values {
|
||||||
|
if _, found := duplicateValues[rawValue]; found {
|
||||||
|
duplicateIndexStart = currentIndex
|
||||||
|
duplicateIndexEnd = currentIndex + uint32(len(rawValue))
|
||||||
|
|
||||||
|
errors = append(errors, &InvalidValue{
|
||||||
|
Err: ArrayContainsDuplicatesError{
|
||||||
|
Value: rawValue,
|
||||||
|
},
|
||||||
|
Start: duplicateIndexStart,
|
||||||
|
End: duplicateIndexEnd,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return errors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentIndex := uint32(0)
|
||||||
for _, subValue := range values {
|
for _, subValue := range values {
|
||||||
err := v.SubValue.CheckIsValid(subValue)
|
newErrors := v.SubValue.CheckIsValid(subValue)
|
||||||
|
|
||||||
if err != nil {
|
if len(newErrors) > 0 {
|
||||||
return err
|
ShiftInvalidValues(currentIndex, newErrors)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errors = append(errors, newErrors...)
|
||||||
|
|
||||||
|
currentIndex += uint32(len(subValue) + len(v.Separator))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return errors
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v ArrayValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem {
|
func (v ArrayValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem {
|
||||||
|
@ -24,7 +24,7 @@ func (v CustomValue) GetTypeDescription() []string {
|
|||||||
return []string{"Custom"}
|
return []string{"Custom"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v CustomValue) CheckIsValid(value string) error {
|
func (v CustomValue) CheckIsValid(value string) []*InvalidValue {
|
||||||
return v.FetchValue(EmptyValueContextInstance).CheckIsValid(value)
|
return v.FetchValue(EmptyValueContextInstance).CheckIsValid(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,11 @@ type ValueNotInEnumError struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e ValueNotInEnumError) Error() string {
|
func (e ValueNotInEnumError) Error() string {
|
||||||
return fmt.Sprintf("This value is not valid. Select one from: %s", strings.Join(e.AvailableValues, ","))
|
if len(e.AvailableValues) <= 6 {
|
||||||
|
return fmt.Sprintf("This value is not valid. Select one from: %s", strings.Join(e.AvailableValues, ","))
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("This value is not valid")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type EnumString struct {
|
type EnumString struct {
|
||||||
@ -63,7 +67,7 @@ func (v EnumValue) GetTypeDescription() []string {
|
|||||||
|
|
||||||
return lines
|
return lines
|
||||||
}
|
}
|
||||||
func (v EnumValue) CheckIsValid(value string) error {
|
func (v EnumValue) CheckIsValid(value string) []*InvalidValue {
|
||||||
if !v.EnforceValues {
|
if !v.EnforceValues {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -75,9 +79,15 @@ func (v EnumValue) CheckIsValid(value string) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ValueNotInEnumError{
|
return []*InvalidValue{
|
||||||
ProvidedValue: value,
|
{
|
||||||
AvailableValues: utils.Map(v.Values, func(value EnumString) string { return value.InsertText }),
|
Err: ValueNotInEnumError{
|
||||||
|
ProvidedValue: value,
|
||||||
|
AvailableValues: utils.Map(v.Values, func(value EnumString) string { return value.InsertText }),
|
||||||
|
},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(value)),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (v EnumValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem {
|
func (v EnumValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem {
|
||||||
|
@ -63,14 +63,20 @@ func (v IPAddressValue) GetTypeDescription() []string {
|
|||||||
return []string{"An IP Address"}
|
return []string{"An IP Address"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v IPAddressValue) CheckIsValid(value string) error {
|
func (v IPAddressValue) CheckIsValid(value string) []*InvalidValue {
|
||||||
var ip net.Prefix
|
var ip net.Prefix
|
||||||
|
|
||||||
if v.AllowRange {
|
if v.AllowRange {
|
||||||
rawIP, err := net.ParsePrefix(value)
|
rawIP, err := net.ParsePrefix(value)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return InvalidIPAddress{}
|
return []*InvalidValue{
|
||||||
|
{
|
||||||
|
Err: InvalidIPAddress{},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(value)),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ip = rawIP
|
ip = rawIP
|
||||||
@ -78,14 +84,24 @@ func (v IPAddressValue) CheckIsValid(value string) error {
|
|||||||
rawIP, err := net.ParseAddr(value)
|
rawIP, err := net.ParseAddr(value)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return InvalidIPAddress{}
|
return []*InvalidValue{{
|
||||||
|
Err: InvalidIPAddress{},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(value)),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ip = net.PrefixFrom(rawIP, 32)
|
ip = net.PrefixFrom(rawIP, 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ip.IsValid() {
|
if !ip.IsValid() {
|
||||||
return InvalidIPAddress{}
|
return []*InvalidValue{{
|
||||||
|
Err: InvalidIPAddress{},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(value)),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.AllowedIPs != nil {
|
if v.AllowedIPs != nil {
|
||||||
@ -95,13 +111,23 @@ func (v IPAddressValue) CheckIsValid(value string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return IpRangeNotAllowedError{}
|
return []*InvalidValue{{
|
||||||
|
Err: IPAddressNotAllowedError{},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(value)),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.DisallowedIPs != nil {
|
if v.DisallowedIPs != nil {
|
||||||
for _, disallowedIP := range *v.DisallowedIPs {
|
for _, disallowedIP := range *v.DisallowedIPs {
|
||||||
if disallowedIP.Contains(ip.Addr()) {
|
if disallowedIP.Contains(ip.Addr()) {
|
||||||
return IPAddressNotAllowedError{}
|
return []*InvalidValue{{
|
||||||
|
Err: IPAddressNotAllowedError{},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(value)),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,7 +140,12 @@ func (v IPAddressValue) CheckIsValid(value string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return InvalidIPAddress{}
|
return []*InvalidValue{{
|
||||||
|
Err: InvalidIPAddress{},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(value)),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v IPAddressValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem {
|
func (v IPAddressValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem {
|
||||||
|
@ -9,8 +9,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type KeyEnumAssignmentValue struct {
|
type KeyEnumAssignmentValue struct {
|
||||||
Values map[EnumString]Value
|
Values map[EnumString]Value
|
||||||
Separator string
|
Separator string
|
||||||
ValueIsOptional bool
|
ValueIsOptional bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,14 +19,13 @@ func (v KeyEnumAssignmentValue) GetTypeDescription() []string {
|
|||||||
firstKey := utils.KeysOfMap(v.Values)[0]
|
firstKey := utils.KeysOfMap(v.Values)[0]
|
||||||
valueDescription := v.Values[firstKey].GetTypeDescription()
|
valueDescription := v.Values[firstKey].GetTypeDescription()
|
||||||
|
|
||||||
if (len(valueDescription) == 1) {
|
if len(valueDescription) == 1 {
|
||||||
return []string{
|
return []string{
|
||||||
fmt.Sprintf("Key-Value pair in form of '<%s>%s<%s>'", firstKey.DescriptionText, v.Separator, valueDescription[0]),
|
fmt.Sprintf("Key-Value pair in form of '<%s>%s<%s>'", firstKey.DescriptionText, v.Separator, valueDescription[0]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var result []string
|
var result []string
|
||||||
for key, value := range v.Values {
|
for key, value := range v.Values {
|
||||||
result = append(result, key.Documentation)
|
result = append(result, key.Documentation)
|
||||||
@ -42,17 +41,17 @@ func (v KeyEnumAssignmentValue) getValue(findKey string) (*Value, bool) {
|
|||||||
for key, value := range v.Values {
|
for key, value := range v.Values {
|
||||||
if key.InsertText == findKey {
|
if key.InsertText == findKey {
|
||||||
switch value.(type) {
|
switch value.(type) {
|
||||||
case CustomValue:
|
case CustomValue:
|
||||||
customValue := value.(CustomValue)
|
customValue := value.(CustomValue)
|
||||||
context := KeyValueAssignmentContext{
|
context := KeyValueAssignmentContext{
|
||||||
SelectedKey: findKey,
|
SelectedKey: findKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchedValue := customValue.FetchValue(context)
|
fetchedValue := customValue.FetchValue(context)
|
||||||
|
|
||||||
return &fetchedValue, true
|
return &fetchedValue, true
|
||||||
default:
|
default:
|
||||||
return &value, true
|
return &value, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,7 +59,7 @@ func (v KeyEnumAssignmentValue) getValue(findKey string) (*Value, bool) {
|
|||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v KeyEnumAssignmentValue) CheckIsValid(value string) error {
|
func (v KeyEnumAssignmentValue) CheckIsValid(value string) []*InvalidValue {
|
||||||
parts := strings.Split(value, v.Separator)
|
parts := strings.Split(value, v.Separator)
|
||||||
|
|
||||||
if len(parts) == 0 || parts[0] == "" {
|
if len(parts) == 0 || parts[0] == "" {
|
||||||
@ -73,22 +72,35 @@ func (v KeyEnumAssignmentValue) CheckIsValid(value string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return KeyValueAssignmentError{}
|
return []*InvalidValue{
|
||||||
|
{
|
||||||
|
Err: KeyValueAssignmentError{},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(parts[0]) + len(v.Separator)),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkValue, found := v.getValue(parts[0])
|
checkValue, found := v.getValue(parts[0])
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
return ValueNotInEnumError{
|
return []*InvalidValue{
|
||||||
AvailableValues: utils.Map(utils.KeysOfMap(v.Values), func(key EnumString) string { return key.InsertText }),
|
{
|
||||||
ProvidedValue: parts[0],
|
Err: ValueNotInEnumError{
|
||||||
|
AvailableValues: utils.Map(utils.KeysOfMap(v.Values), func(key EnumString) string { return key.InsertText }),
|
||||||
|
ProvidedValue: parts[0],
|
||||||
|
},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(parts[0])),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := (*checkValue).CheckIsValid(parts[1])
|
errors := (*checkValue).CheckIsValid(parts[1])
|
||||||
|
|
||||||
if err != nil {
|
if len(errors) > 0 {
|
||||||
return err
|
ShiftInvalidValues(uint32(len(parts[0])+len(v.Separator)), errors)
|
||||||
|
return errors
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -65,7 +65,7 @@ func (v KeyValueAssignmentValue) getValue(selectedKey string) Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v KeyValueAssignmentValue) CheckIsValid(value string) error {
|
func (v KeyValueAssignmentValue) CheckIsValid(value string) []*InvalidValue {
|
||||||
parts := strings.Split(value, v.Separator)
|
parts := strings.Split(value, v.Separator)
|
||||||
|
|
||||||
if len(parts) == 0 || parts[0] == "" {
|
if len(parts) == 0 || parts[0] == "" {
|
||||||
@ -84,13 +84,20 @@ func (v KeyValueAssignmentValue) CheckIsValid(value string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return KeyValueAssignmentError{}
|
return []*InvalidValue{
|
||||||
|
{
|
||||||
|
Err: KeyValueAssignmentError{},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(parts[0]) + len(v.Separator)),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = v.getValue(parts[0]).CheckIsValid(parts[1])
|
errors := v.getValue(parts[0]).CheckIsValid(parts[1])
|
||||||
|
|
||||||
if err != nil {
|
if len(errors) > 0 {
|
||||||
return err
|
ShiftInvalidValues(uint32(len(parts[0])+len(v.Separator)), errors)
|
||||||
|
return errors
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -48,15 +48,27 @@ func (v NumberValue) GetTypeDescription() []string {
|
|||||||
|
|
||||||
return []string{"A number"}
|
return []string{"A number"}
|
||||||
}
|
}
|
||||||
func (v NumberValue) CheckIsValid(value string) error {
|
func (v NumberValue) CheckIsValid(value string) []*InvalidValue {
|
||||||
number, err := strconv.Atoi(value)
|
number, err := strconv.Atoi(value)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NotANumberError{}
|
return []*InvalidValue{
|
||||||
|
{
|
||||||
|
Err: NotANumberError{},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(value)),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v.Min != nil && number < *v.Min) || (v.Max != nil && number > *v.Max) {
|
if (v.Min != nil && number < *v.Min) || (v.Max != nil && number > *v.Max) {
|
||||||
return NumberNotInRangeError{v.Min, v.Max}
|
return []*InvalidValue{
|
||||||
|
{
|
||||||
|
Err: NumberNotInRangeError{v.Min, v.Max},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(value)),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -33,20 +33,20 @@ func (v OrValue) GetTypeDescription() []string {
|
|||||||
lines...,
|
lines...,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
func (v OrValue) CheckIsValid(value string) error {
|
func (v OrValue) CheckIsValid(value string) []*InvalidValue {
|
||||||
var lastError error = nil
|
errors := make([]*InvalidValue, 0)
|
||||||
|
|
||||||
for _, subValue := range v.Values {
|
for _, subValue := range v.Values {
|
||||||
err := subValue.CheckIsValid(value)
|
valueErrors := subValue.CheckIsValid(value)
|
||||||
|
|
||||||
if err == nil {
|
if len(valueErrors) == 0 {
|
||||||
return nil
|
return nil
|
||||||
} else {
|
|
||||||
lastError = err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errors = append(errors, valueErrors...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return lastError
|
return errors
|
||||||
}
|
}
|
||||||
func (v OrValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem {
|
func (v OrValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem {
|
||||||
completions := make([]protocol.CompletionItem, 0)
|
completions := make([]protocol.CompletionItem, 0)
|
||||||
|
@ -46,9 +46,14 @@ func (v PathValue) GetTypeDescription() []string {
|
|||||||
return []string{strings.Join(hints, ", ")}
|
return []string{strings.Join(hints, ", ")}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v PathValue) CheckIsValid(value string) error {
|
func (v PathValue) CheckIsValid(value string) []*InvalidValue {
|
||||||
if !utils.DoesPathExist(value) {
|
if !utils.DoesPathExist(value) {
|
||||||
return PathDoesNotExistError{}
|
return []*InvalidValue{{
|
||||||
|
Err: PathDoesNotExistError{},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(value)),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isValid := false
|
isValid := false
|
||||||
@ -65,7 +70,12 @@ func (v PathValue) CheckIsValid(value string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return PathInvalidError{}
|
return []*InvalidValue{{
|
||||||
|
Err: PathInvalidError{},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(value)),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v PathValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem {
|
func (v PathValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem {
|
||||||
|
77
doc-values/value-power-of-two.go
Normal file
77
doc-values/value-power-of-two.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package docvalues
|
||||||
|
|
||||||
|
import (
|
||||||
|
"config-lsp/utils"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NotAPowerOfTwoError struct{}
|
||||||
|
|
||||||
|
func (e NotAPowerOfTwoError) Error() string {
|
||||||
|
return "This must be a power of 2 (e.g. 32, 64, 128, 265, 512, 1024,, 1024, ...)"
|
||||||
|
}
|
||||||
|
|
||||||
|
type PowerOfTwoValue struct{}
|
||||||
|
|
||||||
|
func (v PowerOfTwoValue) GetTypeDescription() []string {
|
||||||
|
return []string{"A power of 2"}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isPowerOfTwo(number int) bool {
|
||||||
|
count := 0
|
||||||
|
|
||||||
|
for number > 0 {
|
||||||
|
count += number & 1
|
||||||
|
number >>= 1
|
||||||
|
|
||||||
|
if count > 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v PowerOfTwoValue) CheckIsValid(value string) []*InvalidValue {
|
||||||
|
number, err := strconv.Atoi(value)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return []*InvalidValue{{
|
||||||
|
Err: NotANumberError{},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(value)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if number <= 0 || !isPowerOfTwo(number) {
|
||||||
|
return []*InvalidValue{{
|
||||||
|
Err: NotAPowerOfTwoError{},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(value)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var powers = []int{1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536}
|
||||||
|
|
||||||
|
func (v PowerOfTwoValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem {
|
||||||
|
textFormat := protocol.InsertTextFormatPlainText
|
||||||
|
kind := protocol.CompletionItemKindEnum
|
||||||
|
|
||||||
|
return utils.Map(
|
||||||
|
powers,
|
||||||
|
func(power int) protocol.CompletionItem {
|
||||||
|
return protocol.CompletionItem{
|
||||||
|
Label: strconv.Itoa(power),
|
||||||
|
InsertTextFormat: &textFormat,
|
||||||
|
Kind: &kind,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
@ -30,7 +30,7 @@ func (v PrefixWithMeaningValue) GetTypeDescription() []string {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v PrefixWithMeaningValue) CheckIsValid(value string) error {
|
func (v PrefixWithMeaningValue) CheckIsValid(value string) []*InvalidValue {
|
||||||
return v.SubValue.CheckIsValid(value)
|
return v.SubValue.CheckIsValid(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,9 +25,14 @@ func (v RegexValue) GetTypeDescription() []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v RegexValue) CheckIsValid(value string) error {
|
func (v RegexValue) CheckIsValid(value string) []*InvalidValue {
|
||||||
if value == "" {
|
if value == "" {
|
||||||
return EmptyStringError{}
|
return []*InvalidValue{{
|
||||||
|
Err: EmptyStringError{},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(value)),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -16,9 +16,14 @@ func (v StringValue) GetTypeDescription() []string {
|
|||||||
return []string{"String"}
|
return []string{"String"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v StringValue) CheckIsValid(value string) error {
|
func (v StringValue) CheckIsValid(value string) []*InvalidValue {
|
||||||
if value == "" {
|
if value == "" {
|
||||||
return EmptyStringError{}
|
return []*InvalidValue{{
|
||||||
|
Err: EmptyStringError{},
|
||||||
|
Start: 0,
|
||||||
|
End: uint32(len(value)),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
Loading…
x
Reference in New Issue
Block a user