fix(server): Improve structure analyzer for ssh_config

Signed-off-by: Myzel394 <github.7a2op@simplelogin.co>
This commit is contained in:
Myzel394 2025-02-17 22:40:47 +01:00 committed by Myzel394
parent 706b8137dd
commit 98f76fd839
No known key found for this signature in database
GPG Key ID: B603E877F73D4ABB
3 changed files with 40 additions and 42 deletions

View File

@ -39,9 +39,26 @@ func checkOption(
option *ast.SSHOption, option *ast.SSHOption,
block ast.SSHBlock, block ast.SSHBlock,
) { ) {
if option.Key == nil {
return
}
///// General checks
checkIsUsingDoubleQuotes(ctx, option.Key.Value, option.Key.LocationRange) checkIsUsingDoubleQuotes(ctx, option.Key.Value, option.Key.LocationRange)
checkQuotesAreClosed(ctx, option.Key.Value, option.Key.LocationRange) checkQuotesAreClosed(ctx, option.Key.Value, option.Key.LocationRange)
if option.Separator == nil || option.Separator.Value.Value == "" {
ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{
Range: option.Key.LocationRange.ToLSPRange(),
Message: fmt.Sprintf("There should be a separator between an option and its value"),
Severity: &common.SeverityError,
})
} else {
checkIsUsingDoubleQuotes(ctx, option.Separator.Value, option.Separator.LocationRange)
checkQuotesAreClosed(ctx, option.Separator.Value, option.Separator.LocationRange)
}
///// Check if the key is valid
docOption, optionFound := fields.Options[option.Key.Key] docOption, optionFound := fields.Options[option.Key.Key]
if !optionFound { if !optionFound {
@ -58,22 +75,13 @@ func checkOption(
Option: option, Option: option,
Block: block, Block: block,
} }
return
} }
}
if block != nil && block.GetBlockType() == ast.SSHBlockTypeHost && utils.KeyExists(fields.HostDisallowedOptions, option.Key.Key) { // Since we don't know the option, we can't verify the value
ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{ return
Range: option.Key.LocationRange.ToLSPRange(), } else {
Message: fmt.Sprintf("Option '%s' is not allowed in Host blocks", option.Key.Key), // Check for values that are not allowed in Host blocks
Severity: &common.SeverityError, if block != nil && block.GetBlockType() == ast.SSHBlockTypeHost && utils.KeyExists(fields.HostDisallowedOptions, option.Key.Key) {
})
}
// Check for values that are not allowed in Host blocks
if block != nil && block.GetBlockType() == ast.SSHBlockTypeHost {
if utils.KeyExists(fields.HostDisallowedOptions, option.Key.Key) {
ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{ ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{
Range: option.Key.LocationRange.ToLSPRange(), Range: option.Key.LocationRange.ToLSPRange(),
Message: fmt.Sprintf("Option '%s' is not allowed in Host blocks", option.Key.Key), Message: fmt.Sprintf("Option '%s' is not allowed in Host blocks", option.Key.Key),
@ -82,7 +90,8 @@ func checkOption(
} }
} }
if option.OptionValue != nil && optionFound { ///// Check if the value is valid
if option.OptionValue != nil {
checkIsUsingDoubleQuotes(ctx, option.OptionValue.Value, option.OptionValue.LocationRange) checkIsUsingDoubleQuotes(ctx, option.OptionValue.Value, option.OptionValue.LocationRange)
checkQuotesAreClosed(ctx, option.OptionValue.Value, option.OptionValue.LocationRange) checkQuotesAreClosed(ctx, option.OptionValue.Value, option.OptionValue.LocationRange)
@ -98,17 +107,6 @@ func checkOption(
}) })
} }
} }
if option.Separator == nil || option.Separator.Value.Value == "" {
ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{
Range: option.Key.LocationRange.ToLSPRange(),
Message: fmt.Sprintf("There should be a separator between an option and its value"),
Severity: &common.SeverityError,
})
} else {
checkIsUsingDoubleQuotes(ctx, option.Separator.Value, option.Separator.LocationRange)
checkQuotesAreClosed(ctx, option.Separator.Value, option.Separator.LocationRange)
}
} }
func checkBlock( func checkBlock(

View File

@ -9,18 +9,6 @@ import (
protocol "github.com/tliron/glsp/protocol_3_16" protocol "github.com/tliron/glsp/protocol_3_16"
) )
func analyzeQuotesAreValid(
ctx *analyzerContext,
) {
for _, info := range ctx.document.Config.GetAllOptions() {
checkIsUsingDoubleQuotes(ctx, info.Option.Key.Value, info.Option.Key.LocationRange)
checkIsUsingDoubleQuotes(ctx, info.Option.OptionValue.Value, info.Option.OptionValue.LocationRange)
checkQuotesAreClosed(ctx, info.Option.Key.Value, info.Option.Key.LocationRange)
checkQuotesAreClosed(ctx, info.Option.OptionValue.Value, info.Option.OptionValue.LocationRange)
}
}
func checkIsUsingDoubleQuotes( func checkIsUsingDoubleQuotes(
ctx *analyzerContext, ctx *analyzerContext,
value commonparser.ParsedString, value commonparser.ParsedString,

View File

@ -7,6 +7,18 @@ import (
protocol "github.com/tliron/glsp/protocol_3_16" protocol "github.com/tliron/glsp/protocol_3_16"
) )
func testQuotes(
ctx *analyzerContext,
) {
for _, info := range ctx.document.Config.GetAllOptions() {
checkIsUsingDoubleQuotes(ctx, info.Option.Key.Value, info.Option.Key.LocationRange)
checkIsUsingDoubleQuotes(ctx, info.Option.OptionValue.Value, info.Option.OptionValue.LocationRange)
checkQuotesAreClosed(ctx, info.Option.Key.Value, info.Option.Key.LocationRange)
checkQuotesAreClosed(ctx, info.Option.OptionValue.Value, info.Option.OptionValue.LocationRange)
}
}
func TestSimpleInvalidQuotesExample( func TestSimpleInvalidQuotesExample(
t *testing.T, t *testing.T,
) { ) {
@ -17,7 +29,7 @@ PermitRootLogin 'yes'
document: d, document: d,
diagnostics: make([]protocol.Diagnostic, 0), diagnostics: make([]protocol.Diagnostic, 0),
} }
analyzeQuotesAreValid(ctx) testQuotes(ctx)
if !(len(ctx.diagnostics) == 1) { if !(len(ctx.diagnostics) == 1) {
t.Errorf("Expected 1 error, got %v", len(ctx.diagnostics)) t.Errorf("Expected 1 error, got %v", len(ctx.diagnostics))
@ -34,7 +46,7 @@ func TestSingleQuotesKeyAndOptionExample(
document: d, document: d,
diagnostics: make([]protocol.Diagnostic, 0), diagnostics: make([]protocol.Diagnostic, 0),
} }
analyzeQuotesAreValid(ctx) testQuotes(ctx)
if !(len(ctx.diagnostics) == 2) { if !(len(ctx.diagnostics) == 2) {
t.Errorf("Expected 2 ctx.diagnostics, got %v", len(ctx.diagnostics)) t.Errorf("Expected 2 ctx.diagnostics, got %v", len(ctx.diagnostics))
@ -51,7 +63,7 @@ PermitRootLogin "yes
document: d, document: d,
diagnostics: make([]protocol.Diagnostic, 0), diagnostics: make([]protocol.Diagnostic, 0),
} }
analyzeQuotesAreValid(ctx) testQuotes(ctx)
if !(len(ctx.diagnostics) == 1) { if !(len(ctx.diagnostics) == 1) {
t.Errorf("Expected 1 error, got %v", len(ctx.diagnostics)) t.Errorf("Expected 1 error, got %v", len(ctx.diagnostics))
@ -68,7 +80,7 @@ func TestIncompleteQuotesExample(
document: d, document: d,
diagnostics: make([]protocol.Diagnostic, 0), diagnostics: make([]protocol.Diagnostic, 0),
} }
analyzeQuotesAreValid(ctx) testQuotes(ctx)
if !(len(ctx.diagnostics) == 1) { if !(len(ctx.diagnostics) == 1) {
t.Errorf("Expected 1 error, got %v", len(ctx.diagnostics)) t.Errorf("Expected 1 error, got %v", len(ctx.diagnostics))