mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-19 07:25:27 +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(
|
index, found := slices.BinarySearchFunc(
|
||||||
entry.Values.Values,
|
entry.Values.Values,
|
||||||
cursor,
|
cursor,
|
||||||
func(entry ast.AliasValueInterface, pos uint32) int {
|
func(current ast.AliasValueInterface, target uint32) int {
|
||||||
value := entry.GetAliasValue()
|
value := current.GetAliasValue()
|
||||||
|
|
||||||
if pos > value.Location.End.Character {
|
if target < value.Location.Start.Character {
|
||||||
return -1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if pos < value.Location.Start.Character {
|
if target > value.Location.End.Character {
|
||||||
return 1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
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(
|
index, found := slices.BinarySearchFunc(
|
||||||
m.Entries,
|
m.Entries,
|
||||||
cursor,
|
cursor,
|
||||||
func(entry *MatchEntry, cursor uint32) int {
|
func(current *MatchEntry, target uint32) int {
|
||||||
if cursor < entry.Start.Character {
|
if target < current.Start.Character {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if cursor > entry.End.Character {
|
if target > current.End.Character {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,12 +40,12 @@ func (e MatchEntry) GetValueByCursor(cursor uint32) *MatchValue {
|
|||||||
index, found := slices.BinarySearchFunc(
|
index, found := slices.BinarySearchFunc(
|
||||||
e.Values.Values,
|
e.Values.Values,
|
||||||
cursor,
|
cursor,
|
||||||
func(value *MatchValue, cursor uint32) int {
|
func(current *MatchValue, target uint32) int {
|
||||||
if cursor < value.Start.Character {
|
if target < current.Start.Character {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if cursor > value.End.Character {
|
if target > current.End.Character {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,13 +16,13 @@ func GetIncludeOptionLocation(
|
|||||||
index, found := slices.BinarySearchFunc(
|
index, found := slices.BinarySearchFunc(
|
||||||
include.Values,
|
include.Values,
|
||||||
cursor,
|
cursor,
|
||||||
func(i *indexes.SSHDIndexIncludeValue, cursor uint32) int {
|
func(current *indexes.SSHDIndexIncludeValue, target uint32) int {
|
||||||
if cursor < i.Start.Character {
|
if target < current.Start.Character {
|
||||||
return -1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if cursor > i.End.Character {
|
if target > current.End.Character {
|
||||||
return 1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
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