mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 23:15:26 +02:00
fix: Fix BinarySearchFunc handling
This commit is contained in:
parent
ea2e531393
commit
31c3d755a2
@ -16,15 +16,15 @@ func GetValueAtCursor(
|
||||
index, found := slices.BinarySearchFunc(
|
||||
entry.Values.Values,
|
||||
cursor,
|
||||
func(entry ast.AliasValueInterface, pos uint32) int {
|
||||
value := entry.GetAliasValue()
|
||||
func(current ast.AliasValueInterface, target uint32) int {
|
||||
value := current.GetAliasValue()
|
||||
|
||||
if pos > value.Location.End.Character {
|
||||
return -1
|
||||
if target < value.Location.Start.Character {
|
||||
return 1
|
||||
}
|
||||
|
||||
if pos < value.Location.Start.Character {
|
||||
return 1
|
||||
if target > value.Location.End.Character {
|
||||
return -1
|
||||
}
|
||||
|
||||
return 0
|
||||
|
74
handlers/sshd_config/fields/match-parser/full_test.go
Normal file
74
handlers/sshd_config/fields/match-parser/full_test.go
Normal file
@ -0,0 +1,74 @@
|
||||
package matchparser
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFullExample(
|
||||
t *testing.T,
|
||||
) {
|
||||
input := "User alice,adam Address 192.168.1.1 Host *.example.com"
|
||||
match := NewMatch()
|
||||
errs := match.Parse(input, 0, 0)
|
||||
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("Failed to parse match: %v", errs)
|
||||
}
|
||||
|
||||
entry := match.GetEntryByCursor(0)
|
||||
if !(entry == match.Entries[0]) {
|
||||
t.Errorf("Expected entry at 0 to be %v, but got %v", match.Entries[0], entry)
|
||||
}
|
||||
|
||||
entry = match.GetEntryByCursor(5)
|
||||
if !(entry == match.Entries[0]) {
|
||||
t.Errorf("Expected entry at 5 to be %v, but got %v", match.Entries[0], entry)
|
||||
}
|
||||
|
||||
entry = match.GetEntryByCursor(13)
|
||||
if !(entry == match.Entries[0]) {
|
||||
t.Errorf("Expected entry at 13 to be %v, but got %v", match.Entries[1], entry)
|
||||
}
|
||||
|
||||
entry = match.GetEntryByCursor(16)
|
||||
if !(entry == match.Entries[1]) {
|
||||
t.Errorf("Expected entry at 16 to be %v, but got %v", match.Entries[1], entry)
|
||||
}
|
||||
|
||||
entry = match.GetEntryByCursor(24)
|
||||
if !(entry == match.Entries[1]) {
|
||||
t.Errorf("Expected entry at 24 to be %v, but got %v", match.Entries[2], entry)
|
||||
}
|
||||
|
||||
entry = match.GetEntryByCursor(36)
|
||||
if !(entry == match.Entries[2]) {
|
||||
t.Errorf("Expected entry at 36 to be %v, but got %v", match.Entries[2], entry)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetEntryForIncompleteExample(
|
||||
t *testing.T,
|
||||
) {
|
||||
input := "User "
|
||||
match := NewMatch()
|
||||
errs := match.Parse(input, 0, 0)
|
||||
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("Failed to parse match: %v", errs)
|
||||
}
|
||||
|
||||
entry := match.GetEntryByCursor(0)
|
||||
if !(entry == match.Entries[0]) {
|
||||
t.Errorf("Expected entry at 0 to be %v, but got %v", match.Entries[0], entry)
|
||||
}
|
||||
|
||||
entry = match.GetEntryByCursor(4)
|
||||
if !(entry == match.Entries[0]) {
|
||||
t.Errorf("Expected entry at 4 to be %v, but got %v", match.Entries[0], entry)
|
||||
}
|
||||
|
||||
entry = match.GetEntryByCursor(5)
|
||||
if !(entry == match.Entries[0]) {
|
||||
t.Errorf("Expected entry at 5 to be %v, but got %v", match.Entries[0], entry)
|
||||
}
|
||||
}
|
@ -6,12 +6,12 @@ func (m Match) GetEntryByCursor(cursor uint32) *MatchEntry {
|
||||
index, found := slices.BinarySearchFunc(
|
||||
m.Entries,
|
||||
cursor,
|
||||
func(entry *MatchEntry, cursor uint32) int {
|
||||
if cursor < entry.Start.Character {
|
||||
func(current *MatchEntry, target uint32) int {
|
||||
if target < current.Start.Character {
|
||||
return 1
|
||||
}
|
||||
|
||||
if cursor > entry.End.Character {
|
||||
if target > current.End.Character {
|
||||
return -1
|
||||
}
|
||||
|
||||
@ -40,12 +40,12 @@ func (e MatchEntry) GetValueByCursor(cursor uint32) *MatchValue {
|
||||
index, found := slices.BinarySearchFunc(
|
||||
e.Values.Values,
|
||||
cursor,
|
||||
func(value *MatchValue, cursor uint32) int {
|
||||
if cursor < value.Start.Character {
|
||||
func(current *MatchValue, target uint32) int {
|
||||
if target < current.Start.Character {
|
||||
return 1
|
||||
}
|
||||
|
||||
if cursor > value.End.Character {
|
||||
if target > current.End.Character {
|
||||
return -1
|
||||
}
|
||||
|
||||
|
@ -16,13 +16,13 @@ func GetIncludeOptionLocation(
|
||||
index, found := slices.BinarySearchFunc(
|
||||
include.Values,
|
||||
cursor,
|
||||
func(i *indexes.SSHDIndexIncludeValue, cursor uint32) int {
|
||||
if cursor < i.Start.Character {
|
||||
return -1
|
||||
func(current *indexes.SSHDIndexIncludeValue, target uint32) int {
|
||||
if target < current.Start.Character {
|
||||
return 1
|
||||
}
|
||||
|
||||
if cursor > i.End.Character {
|
||||
return 1
|
||||
if target > current.End.Character {
|
||||
return -1
|
||||
}
|
||||
|
||||
return 0
|
||||
|
38
handlers/sshd_config/handlers/formatting.go
Normal file
38
handlers/sshd_config/handlers/formatting.go
Normal file
@ -0,0 +1,38 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
sshdconfig "config-lsp/handlers/sshd_config"
|
||||
"config-lsp/handlers/sshd_config/ast"
|
||||
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
func FormatDocument(
|
||||
d *sshdconfig.SSHDocument,
|
||||
textRange protocol.Range,
|
||||
options protocol.FormattingOptions,
|
||||
) ([]protocol.TextEdit, error) {
|
||||
edits := make([]protocol.TextEdit, 0)
|
||||
|
||||
it := d.Config.Options.Iterator()
|
||||
for it.Next() {
|
||||
line := it.Key().(uint32)
|
||||
entry := it.Value().(ast.SSHDEntry)
|
||||
|
||||
if !(line >= textRange.Start.Line && line <= textRange.End.Line) {
|
||||
continue
|
||||
}
|
||||
|
||||
switch entry.(type) {
|
||||
case *ast.SSHDOption:
|
||||
option := entry.(*ast.SSHDOption)
|
||||
edits = append(edits, formatSSHDOption(option, options)...)
|
||||
case *ast.SSHDMatchBlock:
|
||||
matchBlock := entry.(*ast.SSHDMatchBlock)
|
||||
|
||||
edits = formatSSHDMatchBlock(matchBlock, options)
|
||||
}
|
||||
}
|
||||
|
||||
return edits, nil
|
||||
}
|
107
handlers/sshd_config/handlers/formatting_nodes.go
Normal file
107
handlers/sshd_config/handlers/formatting_nodes.go
Normal file
@ -0,0 +1,107 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"config-lsp/common/formatting"
|
||||
"config-lsp/handlers/sshd_config/ast"
|
||||
matchparser "config-lsp/handlers/sshd_config/fields/match-parser"
|
||||
"config-lsp/utils"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
func formatSSHDOption(
|
||||
option *ast.SSHDOption,
|
||||
options protocol.FormattingOptions,
|
||||
) []protocol.TextEdit {
|
||||
template := formatting.FormatTemplate(
|
||||
"%s/t%s",
|
||||
)
|
||||
|
||||
var key string
|
||||
|
||||
if option.Key != nil {
|
||||
key = option.Key.Key
|
||||
} else {
|
||||
key = ""
|
||||
}
|
||||
|
||||
var value string
|
||||
|
||||
if option.OptionValue != nil {
|
||||
value = option.OptionValue.Value.Raw
|
||||
} else {
|
||||
value = ""
|
||||
}
|
||||
|
||||
return []protocol.TextEdit{
|
||||
{
|
||||
Range: option.ToLSPRange(),
|
||||
NewText: template.Format(options, key, value),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func formatSSHDMatchBlock(
|
||||
matchBlock *ast.SSHDMatchBlock,
|
||||
options protocol.FormattingOptions,
|
||||
) []protocol.TextEdit {
|
||||
edits := make([]protocol.TextEdit, 0)
|
||||
|
||||
template := formatting.FormatTemplate(
|
||||
"%s/t%s",
|
||||
)
|
||||
edits = append(edits, protocol.TextEdit{
|
||||
Range: matchBlock.ToLSPRange(),
|
||||
NewText: template.Format(options, matchBlock.MatchEntry.Key.Key, formatMatchToString(matchBlock.MatchValue, options)),
|
||||
})
|
||||
|
||||
it := matchBlock.Options.Iterator()
|
||||
for it.Next() {
|
||||
option := it.Value().(*ast.SSHDOption)
|
||||
|
||||
edits = append(edits, formatSSHDOption(option, options)...)
|
||||
}
|
||||
|
||||
return edits
|
||||
}
|
||||
|
||||
func formatMatchToString(
|
||||
match *matchparser.Match,
|
||||
options protocol.FormattingOptions,
|
||||
) string {
|
||||
entriesAsStrings := utils.Map(
|
||||
match.Entries,
|
||||
func(entry *matchparser.MatchEntry) string {
|
||||
return formatMatchEntryToString(entry, options)
|
||||
},
|
||||
)
|
||||
|
||||
return strings.Join(entriesAsStrings, " ")
|
||||
}
|
||||
|
||||
func formatMatchEntryToString(
|
||||
entry *matchparser.MatchEntry,
|
||||
options protocol.FormattingOptions,
|
||||
) string {
|
||||
return fmt.Sprintf(
|
||||
"%s %s",
|
||||
string(entry.Criteria.Type),
|
||||
formatMatchValuesToString(entry.Values, options),
|
||||
)
|
||||
}
|
||||
|
||||
func formatMatchValuesToString(
|
||||
values *matchparser.MatchValues,
|
||||
options protocol.FormattingOptions,
|
||||
) string {
|
||||
valuesAsStrings := utils.Map(
|
||||
values.Values,
|
||||
func(value *matchparser.MatchValue) string {
|
||||
return value.Value.Raw
|
||||
},
|
||||
)
|
||||
|
||||
return strings.Join(valuesAsStrings, ",")
|
||||
}
|
62
handlers/sshd_config/handlers/formatting_test.go
Normal file
62
handlers/sshd_config/handlers/formatting_test.go
Normal file
@ -0,0 +1,62 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
sshdconfig "config-lsp/handlers/sshd_config"
|
||||
"config-lsp/handlers/sshd_config/ast"
|
||||
"config-lsp/handlers/sshd_config/indexes"
|
||||
"config-lsp/utils"
|
||||
"testing"
|
||||
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
func TestSimpleFormattingExampleWorks(
|
||||
t *testing.T,
|
||||
) {
|
||||
input := utils.Dedent(`
|
||||
PermitRootLogin yes
|
||||
a b
|
||||
`)
|
||||
config := ast.NewSSHConfig()
|
||||
errors := config.Parse(input)
|
||||
|
||||
if len(errors) > 0 {
|
||||
t.Fatalf("Failed to parse SSHD config: %v", errors)
|
||||
}
|
||||
|
||||
i, errors := indexes.CreateIndexes(*config)
|
||||
|
||||
if len(errors) > 0 {
|
||||
t.Fatalf("Failed to create indexes: %v", errors)
|
||||
}
|
||||
|
||||
d := sshdconfig.SSHDocument{
|
||||
Config: config,
|
||||
Indexes: i,
|
||||
}
|
||||
|
||||
options := protocol.FormattingOptions{}
|
||||
options["insertSpaces"] = true
|
||||
options["tabSize"] = float64(4)
|
||||
|
||||
edits, err := FormatDocument(
|
||||
&d,
|
||||
protocol.Range{
|
||||
Start: protocol.Position{
|
||||
Line: 0,
|
||||
Character: protocol.UInteger(0),
|
||||
},
|
||||
End: protocol.Position{
|
||||
Line: 1,
|
||||
Character: protocol.UInteger(0),
|
||||
},
|
||||
},
|
||||
options,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Failed to format document: %v", err)
|
||||
}
|
||||
|
||||
_ = edits
|
||||
}
|
22
handlers/sshd_config/lsp/text-document-range-formatting.go
Normal file
22
handlers/sshd_config/lsp/text-document-range-formatting.go
Normal file
@ -0,0 +1,22 @@
|
||||
package lsp
|
||||
|
||||
import (
|
||||
sshdconfig "config-lsp/handlers/sshd_config"
|
||||
"config-lsp/handlers/sshd_config/handlers"
|
||||
|
||||
"github.com/tliron/glsp"
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
func TextDocumentRangeFormatting(
|
||||
context *glsp.Context,
|
||||
params *protocol.DocumentRangeFormattingParams,
|
||||
) ([]protocol.TextEdit, error) {
|
||||
d := sshdconfig.DocumentParserMap[params.TextDocument.URI]
|
||||
|
||||
return handlers.FormatDocument(
|
||||
d,
|
||||
params.Range,
|
||||
params.Options,
|
||||
)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user