mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 15:05:28 +02:00
refactor(server): ssh_config improvements
Signed-off-by: Myzel394 <github.7a2op@simplelogin.co>
This commit is contained in:
parent
0b2690910f
commit
1cfb9bbfba
@ -54,6 +54,7 @@ func Analyze(
|
||||
}
|
||||
}
|
||||
|
||||
analyzeValuesAreValid(ctx)
|
||||
analyzeTokens(ctx)
|
||||
analyzeIgnoreUnknownHasNoUnnecessary(ctx)
|
||||
analyzeDependents(ctx)
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"config-lsp/common"
|
||||
docvalues "config-lsp/doc-values"
|
||||
"config-lsp/handlers/ssh_config/ast"
|
||||
"config-lsp/handlers/ssh_config/diagnostics"
|
||||
"config-lsp/handlers/ssh_config/fields"
|
||||
"config-lsp/utils"
|
||||
"fmt"
|
||||
@ -63,31 +62,16 @@ func checkOption(
|
||||
|
||||
if !optionFound {
|
||||
// Diagnostics will be handled by `values.go`
|
||||
if !ctx.document.Indexes.CanOptionBeIgnored(option, block) {
|
||||
ctx.diagnostics = append(
|
||||
ctx.diagnostics,
|
||||
diagnostics.GenerateUnknownOption(
|
||||
option.Key.ToLSPRange(),
|
||||
option.Key.Value.Value,
|
||||
),
|
||||
)
|
||||
ctx.document.Indexes.UnknownOptions[option.Start.Line] = ast.AllOptionInfo{
|
||||
Option: option,
|
||||
Block: block,
|
||||
}
|
||||
}
|
||||
|
||||
// Since we don't know the option, we can't verify the value
|
||||
return
|
||||
} else {
|
||||
// Check for values that are not allowed in Host blocks
|
||||
if block != nil && block.GetBlockType() == ast.SSHBlockTypeHost && utils.KeyExists(fields.HostDisallowedOptions, option.Key.Key) {
|
||||
ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{
|
||||
Range: option.Key.LocationRange.ToLSPRange(),
|
||||
Message: fmt.Sprintf("Option '%s' is not allowed in Host blocks", option.Key.Key),
|
||||
Severity: &common.SeverityError,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Check for values that are not allowed in Host blocks
|
||||
if block != nil && block.GetBlockType() == ast.SSHBlockTypeHost && utils.KeyExists(fields.HostDisallowedOptions, option.Key.Key) {
|
||||
ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{
|
||||
Range: option.Key.LocationRange.ToLSPRange(),
|
||||
Message: fmt.Sprintf("Option '%s' is not allowed in Host blocks", option.Key.Key),
|
||||
Severity: &common.SeverityError,
|
||||
})
|
||||
}
|
||||
|
||||
///// Check if the value is valid
|
||||
|
@ -112,79 +112,3 @@ Match
|
||||
t.Fatalf("Expected 1 error, got %v", ctx.diagnostics)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnknownOptionExample(
|
||||
t *testing.T,
|
||||
) {
|
||||
d := testutils_test.DocumentFromInput(t, `
|
||||
ThisOptionDoesNotExist okay
|
||||
`)
|
||||
ctx := &analyzerContext{
|
||||
document: d,
|
||||
diagnostics: make([]protocol.Diagnostic, 0),
|
||||
}
|
||||
|
||||
analyzeStructureIsValid(ctx)
|
||||
|
||||
if !(len(ctx.diagnostics) == 1) {
|
||||
t.Errorf("Expected 1 error, got %v", len(ctx.diagnostics))
|
||||
}
|
||||
|
||||
if !(len(ctx.document.Indexes.UnknownOptions) == 1) {
|
||||
t.Errorf("Expected 1 unknown option, got %v", len(ctx.document.Indexes.UnknownOptions))
|
||||
}
|
||||
|
||||
if !(ctx.document.Indexes.UnknownOptions[0].Option.Key.Value.Value == "ThisOptionDoesNotExist") {
|
||||
t.Errorf("Expected 'ThisOptionDoesNotExist', got %v", ctx.document.Indexes.UnknownOptions[0].Option.Key.Value.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnknownOptionButIgnoredExample(
|
||||
t *testing.T,
|
||||
) {
|
||||
d := testutils_test.DocumentFromInput(t, `
|
||||
IgnoreUnknown ThisOptionDoesNotExist
|
||||
ThisOptionDoesNotExist okay
|
||||
`)
|
||||
ctx := &analyzerContext{
|
||||
document: d,
|
||||
diagnostics: make([]protocol.Diagnostic, 0),
|
||||
}
|
||||
|
||||
analyzeStructureIsValid(ctx)
|
||||
|
||||
if len(ctx.diagnostics) > 0 {
|
||||
t.Fatalf("Expected no errors, but got %v", len(ctx.diagnostics))
|
||||
}
|
||||
|
||||
if !(len(ctx.document.Indexes.UnknownOptions) == 0) {
|
||||
t.Errorf("Expected 0 unknown options, got %v", len(ctx.document.Indexes.UnknownOptions))
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnknownOptionIgnoredIsAfterDefinitionExample(
|
||||
t *testing.T,
|
||||
) {
|
||||
d := testutils_test.DocumentFromInput(t, `
|
||||
ThisOptionDoesNotExist okay
|
||||
IgnoreUnknown ThisOptionDoesNotExist
|
||||
`)
|
||||
ctx := &analyzerContext{
|
||||
document: d,
|
||||
diagnostics: make([]protocol.Diagnostic, 0),
|
||||
}
|
||||
|
||||
analyzeStructureIsValid(ctx)
|
||||
|
||||
if !(len(ctx.diagnostics) == 1) {
|
||||
t.Errorf("Expected 1 error, got %v", len(ctx.diagnostics))
|
||||
}
|
||||
|
||||
if !(len(ctx.document.Indexes.UnknownOptions) == 1) {
|
||||
t.Errorf("Expected 1 unknown option, got %v", len(ctx.document.Indexes.UnknownOptions))
|
||||
}
|
||||
|
||||
if !(ctx.document.Indexes.UnknownOptions[0].Option.Key.Value.Value == "ThisOptionDoesNotExist") {
|
||||
t.Errorf("Expected 'ThisOptionDoesNotExist', got %v", ctx.document.Indexes.UnknownOptions[0].Option.Key.Value.Value)
|
||||
}
|
||||
}
|
||||
|
36
server/handlers/ssh_config/analyzer/values.go
Normal file
36
server/handlers/ssh_config/analyzer/values.go
Normal file
@ -0,0 +1,36 @@
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"config-lsp/handlers/ssh_config/diagnostics"
|
||||
"config-lsp/handlers/ssh_config/fields"
|
||||
)
|
||||
|
||||
func analyzeValuesAreValid(
|
||||
ctx *analyzerContext,
|
||||
) {
|
||||
// Check if there are unknown options
|
||||
for _, info := range ctx.document.Config.GetAllOptions() {
|
||||
option := info.Option
|
||||
block := info.Block
|
||||
|
||||
_, found := fields.Options[option.Key.Key]
|
||||
|
||||
if !found {
|
||||
if ctx.document.Indexes.CanOptionBeIgnored(option, block) {
|
||||
// Skip
|
||||
continue
|
||||
}
|
||||
|
||||
ctx.diagnostics = append(
|
||||
ctx.diagnostics,
|
||||
diagnostics.GenerateUnknownOption(
|
||||
option.Key.ToLSPRange(),
|
||||
option.Key.Value.Value,
|
||||
),
|
||||
)
|
||||
ctx.document.Indexes.UnknownOptions[info.Option.Start.Line] = info
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
84
server/handlers/ssh_config/analyzer/values_test.go
Normal file
84
server/handlers/ssh_config/analyzer/values_test.go
Normal file
@ -0,0 +1,84 @@
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
testutils_test "config-lsp/handlers/ssh_config/test_utils"
|
||||
"testing"
|
||||
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
func TestUnknownOptionExample(
|
||||
t *testing.T,
|
||||
) {
|
||||
d := testutils_test.DocumentFromInput(t, `
|
||||
ThisOptionDoesNotExist okay
|
||||
`)
|
||||
ctx := &analyzerContext{
|
||||
document: d,
|
||||
diagnostics: make([]protocol.Diagnostic, 0),
|
||||
}
|
||||
|
||||
analyzeValuesAreValid(ctx)
|
||||
|
||||
if !(len(ctx.diagnostics) == 1) {
|
||||
t.Errorf("Expected 1 error, got %v", len(ctx.diagnostics))
|
||||
}
|
||||
|
||||
if !(len(ctx.document.Indexes.UnknownOptions) == 1) {
|
||||
t.Errorf("Expected 1 unknown option, got %v", len(ctx.document.Indexes.UnknownOptions))
|
||||
}
|
||||
|
||||
if !(ctx.document.Indexes.UnknownOptions[0].Option.Key.Value.Value == "ThisOptionDoesNotExist") {
|
||||
t.Errorf("Expected 'ThisOptionDoesNotExist', got %v", ctx.document.Indexes.UnknownOptions[0].Option.Key.Value.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnknownOptionButIgnoredExample(
|
||||
t *testing.T,
|
||||
) {
|
||||
d := testutils_test.DocumentFromInput(t, `
|
||||
IgnoreUnknown ThisOptionDoesNotExist
|
||||
ThisOptionDoesNotExist okay
|
||||
`)
|
||||
ctx := &analyzerContext{
|
||||
document: d,
|
||||
diagnostics: make([]protocol.Diagnostic, 0),
|
||||
}
|
||||
|
||||
analyzeValuesAreValid(ctx)
|
||||
|
||||
if len(ctx.diagnostics) > 0 {
|
||||
t.Fatalf("Expected no errors, but got %v", len(ctx.diagnostics))
|
||||
}
|
||||
|
||||
if !(len(ctx.document.Indexes.UnknownOptions) == 0) {
|
||||
t.Errorf("Expected 0 unknown options, got %v", len(ctx.document.Indexes.UnknownOptions))
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnknownOptionIgnoredIsAfterDefinitionExample(
|
||||
t *testing.T,
|
||||
) {
|
||||
d := testutils_test.DocumentFromInput(t, `
|
||||
ThisOptionDoesNotExist okay
|
||||
IgnoreUnknown ThisOptionDoesNotExist
|
||||
`)
|
||||
ctx := &analyzerContext{
|
||||
document: d,
|
||||
diagnostics: make([]protocol.Diagnostic, 0),
|
||||
}
|
||||
|
||||
analyzeValuesAreValid(ctx)
|
||||
|
||||
if !(len(ctx.diagnostics) == 1) {
|
||||
t.Errorf("Expected 1 error, got %v", len(ctx.diagnostics))
|
||||
}
|
||||
|
||||
if !(len(ctx.document.Indexes.UnknownOptions) == 1) {
|
||||
t.Errorf("Expected 1 unknown option, got %v", len(ctx.document.Indexes.UnknownOptions))
|
||||
}
|
||||
|
||||
if !(ctx.document.Indexes.UnknownOptions[0].Option.Key.Value.Value == "ThisOptionDoesNotExist") {
|
||||
t.Errorf("Expected 'ThisOptionDoesNotExist', got %v", ctx.document.Indexes.UnknownOptions[0].Option.Key.Value.Value)
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ func FormatDocument(
|
||||
// it := d.Config.Options.Iterator()
|
||||
// for it.Next() {
|
||||
// line := it.Key().(uint32)
|
||||
// entry := it.Value().(ast.SSHEntry)
|
||||
// entry := it.Name().(ast.SSHEntry)
|
||||
//
|
||||
// if !(line >= textRange.Start.Line && line <= textRange.End.Line) {
|
||||
// continue
|
||||
|
@ -20,6 +20,7 @@ func TextDocumentDidChange(
|
||||
document := sshconfig.DocumentParserMap[params.TextDocument.URI]
|
||||
document.Config.Clear()
|
||||
|
||||
println("reparsing everything")
|
||||
diagnostics := make([]protocol.Diagnostic, 0)
|
||||
errors := document.Config.Parse(content)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user