diff --git a/handlers/sshd_config/ast/parser_test.go b/handlers/sshd_config/ast/parser_test.go index 46c6338..2a024d5 100644 --- a/handlers/sshd_config/ast/parser_test.go +++ b/handlers/sshd_config/ast/parser_test.go @@ -31,13 +31,13 @@ PasswordAuthentication yes firstEntry.LocationRange.Start.Line == 0 && firstEntry.LocationRange.End.Line == 0 && firstEntry.LocationRange.Start.Character == 0 && - firstEntry.LocationRange.End.Character == 17 && + firstEntry.LocationRange.End.Character == 18 && firstEntry.Key.Value.Value == "PermitRootLogin" && firstEntry.Key.LocationRange.Start.Character == 0 && - firstEntry.Key.LocationRange.End.Character == 14 && + firstEntry.Key.LocationRange.End.Character == 15 && firstEntry.OptionValue.Value.Value == "no" && firstEntry.OptionValue.LocationRange.Start.Character == 16 && - firstEntry.OptionValue.LocationRange.End.Character == 17) { + firstEntry.OptionValue.LocationRange.End.Character == 18) { t.Errorf("Expected first entry to be PermitRootLogin no, but got: %v", firstEntry) } @@ -48,13 +48,13 @@ PasswordAuthentication yes secondEntry.LocationRange.Start.Line == 1 && secondEntry.LocationRange.End.Line == 1 && secondEntry.LocationRange.Start.Character == 0 && - secondEntry.LocationRange.End.Character == 25 && + secondEntry.LocationRange.End.Character == 26 && secondEntry.Key.Value.Value == "PasswordAuthentication" && secondEntry.Key.LocationRange.Start.Character == 0 && - secondEntry.Key.LocationRange.End.Character == 21 && + secondEntry.Key.LocationRange.End.Character == 22 && secondEntry.OptionValue.Value.Value == "yes" && secondEntry.OptionValue.LocationRange.Start.Character == 23 && - secondEntry.OptionValue.LocationRange.End.Character == 25) { + secondEntry.OptionValue.LocationRange.End.Character == 26) { t.Errorf("Expected second entry to be PasswordAuthentication yes, but got: %v", secondEntry) } } @@ -92,7 +92,7 @@ Match Address 192.168.0.1 t.Errorf("Expected second entry to be 'Match Address 192.168.0.1', but got: %v", secondEntry.MatchEntry.Value) } - if !(secondEntry.Start.Line == 2 && secondEntry.Start.Character == 0 && secondEntry.End.Line == 3 && secondEntry.End.Character == 26) { + if !(secondEntry.Start.Line == 2 && secondEntry.Start.Character == 0 && secondEntry.End.Line == 3 && secondEntry.End.Character == 27) { t.Errorf("Expected second entry's location to be 2:0-3:25, but got: %v", secondEntry.LocationRange) } @@ -240,14 +240,14 @@ Match Address 192.168.0.2 t.Errorf("Expected match option to be 'Match User lena', but got: %v, %v", matchOption, matchBlock) } - if !(matchOption.Start.Line == 2 && matchOption.End.Line == 2 && matchOption.Start.Character == 0 && matchOption.End.Character == 14) { + if !(matchOption.Start.Line == 2 && matchOption.End.Line == 2 && matchOption.Start.Character == 0 && matchOption.End.Character == 15) { t.Errorf("Expected match option to be at 2:0-14, but got: %v", matchOption.LocationRange) } if !(matchBlock.Start.Line == 2 && matchBlock.Start.Character == 0 && matchBlock.End.Line == 4 && - matchBlock.End.Character == 20) { + matchBlock.End.Character == 21) { t.Errorf("Expected match block to be at 2:0-4:20, but got: %v", matchBlock.LocationRange) } } diff --git a/handlers/sshd_config/fields/match-parser/match_fields.go b/handlers/sshd_config/fields/match-parser/match_fields.go index f9c2d4a..547986d 100644 --- a/handlers/sshd_config/fields/match-parser/match_fields.go +++ b/handlers/sshd_config/fields/match-parser/match_fields.go @@ -1,17 +1,20 @@ package matchparser -import "slices" +import ( + "config-lsp/common" + "slices" +) -func (m Match) GetEntryByCursor(cursor uint32) *MatchEntry { +func (m Match) GetEntryByCursor(cursor common.CursorPosition) *MatchEntry { index, found := slices.BinarySearchFunc( m.Entries, cursor, - func(current *MatchEntry, target uint32) int { - if target < current.Start.Character { + func(current *MatchEntry, target common.CursorPosition) int { + if current.Start.IsAfterCursorPosition(target) { return 1 } - if target > current.End.Character { + if current.End.IsBeforeCursorPosition(target) { return -1 } diff --git a/handlers/sshd_config/fields/match-parser/parser_test.go b/handlers/sshd_config/fields/match-parser/parser_test.go index 558ce21..e35647f 100644 --- a/handlers/sshd_config/fields/match-parser/parser_test.go +++ b/handlers/sshd_config/fields/match-parser/parser_test.go @@ -25,15 +25,15 @@ func TestComplexExample( t.Fatalf("Expected User, but got %v", match.Entries[0]) } - if !(match.Entries[0].Values.Values[0].Value.Value == "root" && match.Entries[0].Values.Values[0].Start.Character == 5+offset && match.Entries[0].Values.Values[0].End.Character == 8+offset && match.Entries[0].Start.Character == 0+offset && match.Entries[0].End.Character == 20+offset) { + if !(match.Entries[0].Values.Values[0].Value.Value == "root" && match.Entries[0].Values.Values[0].Start.Character == 5+offset && match.Entries[0].Values.Values[0].End.Character == 8+offset+1 && match.Entries[0].Start.Character == 0+offset && match.Entries[0].End.Character == 20+offset+1) { t.Errorf("Expected root, but got %v", match.Entries[0].Values.Values[0]) } - if !(match.Entries[0].Values.Values[1].Value.Value == "admin" && match.Entries[0].Values.Values[1].Start.Character == 10+offset && match.Entries[0].Values.Values[1].End.Character == 14+offset) { + if !(match.Entries[0].Values.Values[1].Value.Value == "admin" && match.Entries[0].Values.Values[1].Start.Character == 10+offset && match.Entries[0].Values.Values[1].End.Character == 14+offset+1) { t.Errorf("Expected admin, but got %v", match.Entries[0].Values.Values[1]) } - if !(match.Entries[0].Values.Values[2].Value.Value == "alice" && match.Entries[0].Values.Values[2].Start.Character == 16+offset && match.Entries[0].Values.Values[2].End.Character == 20+offset) { + if !(match.Entries[0].Values.Values[2].Value.Value == "alice" && match.Entries[0].Values.Values[2].Start.Character == 16+offset && match.Entries[0].Values.Values[2].End.Character == 20+offset+1) { t.Errorf("Expected alice, but got %v", match.Entries[0].Values.Values[2]) } @@ -41,11 +41,11 @@ func TestComplexExample( t.Errorf("Expected Address, but got %v", match.Entries[1]) } - if !(match.Entries[1].Values.Values[0].Value.Value == "*" && match.Entries[1].Values.Values[0].Start.Character == 30+offset && match.Entries[1].Values.Values[0].End.Character == 30+offset) { + if !(match.Entries[1].Values.Values[0].Value.Value == "*" && match.Entries[1].Values.Values[0].Start.Character == 30+offset && match.Entries[1].Values.Values[0].End.Character == 30+offset+1) { t.Errorf("Expected *, but got %v", match.Entries[1].Values.Values[0]) } - if !(match.Entries[1].Values.Values[1].Value.Value == "!192.168.0.1" && match.Entries[1].Values.Values[1].Start.Character == 32+offset && match.Entries[1].Values.Values[1].End.Character == 43+offset) { + if !(match.Entries[1].Values.Values[1].Value.Value == "!192.168.0.1" && match.Entries[1].Values.Values[1].Start.Character == 32+offset && match.Entries[1].Values.Values[1].End.Character == 43+offset+1) { t.Errorf("Expected !192.168.0.1, but got %v", match.Entries[1].Values.Values[1]) } } @@ -103,7 +103,7 @@ func TestIncompleteBetweenEntriesExample( t.Errorf("Expected 3 values, but got %v", len(match.Entries[0].Values.Values)) } - if !(match.Entries[0].Start.Character == 0 && match.Entries[0].End.Character == 20) { + if !(match.Entries[0].Start.Character == 0 && match.Entries[0].End.Character == 21) { t.Errorf("Expected 0-20, but got %v", match.Entries[0]) } } diff --git a/handlers/sshd_config/handlers/completions.go b/handlers/sshd_config/handlers/completions.go index aafbb99..bd1c7e6 100644 --- a/handlers/sshd_config/handlers/completions.go +++ b/handlers/sshd_config/handlers/completions.go @@ -71,7 +71,7 @@ func GetOptionCompletions( d *sshdconfig.SSHDocument, entry *ast.SSHDOption, matchBlock *ast.SSHDMatchBlock, - cursor uint32, + cursor common.CursorPosition, ) ([]protocol.CompletionItem, error) { option, found := fields.Options[entry.Key.Key] @@ -82,8 +82,8 @@ func GetOptionCompletions( if entry.Key.Key == "Match" { return getMatchCompletions( d, + cursor, matchBlock.MatchValue, - cursor-matchBlock.MatchEntry.Start.Character, ) } @@ -92,8 +92,12 @@ func GetOptionCompletions( } line := entry.OptionValue.Value.Raw + // NEW: docvalues index return option.FetchCompletions( line, - common.CursorToCharacterIndex(cursor-entry.OptionValue.Start.Character), + common.DeprecatedImprovedCursorToIndex( + entry.OptionValue.Start.GetRelativeCursorPosition(cursor), + line, + ), ), nil } diff --git a/handlers/sshd_config/handlers/completions_match.go b/handlers/sshd_config/handlers/completions_match.go index 773727f..17a8900 100644 --- a/handlers/sshd_config/handlers/completions_match.go +++ b/handlers/sshd_config/handlers/completions_match.go @@ -1,6 +1,7 @@ package handlers import ( + "config-lsp/common" sshdconfig "config-lsp/handlers/sshd_config" "config-lsp/handlers/sshd_config/fields" matchparser "config-lsp/handlers/sshd_config/fields/match-parser" @@ -10,8 +11,8 @@ import ( func getMatchCompletions( d *sshdconfig.SSHDocument, + cursor common.CursorPosition, match *matchparser.Match, - cursor uint32, ) ([]protocol.CompletionItem, error) { if match == nil || len(match.Entries) == 0 { completions := getMatchCriteriaCompletions() @@ -22,7 +23,7 @@ func getMatchCompletions( entry := match.GetEntryByCursor(cursor) - if entry == nil || entry.Criteria.IsCursorBetween(cursor) { + if entry == nil || entry.Criteria.ContainsCursorPosition(cursor) { return getMatchCriteriaCompletions(), nil } @@ -75,7 +76,7 @@ func getMatchAllKeywordCompletion() protocol.CompletionItem { func getMatchValueCompletions( entry *matchparser.MatchEntry, - cursor uint32, + cursor common.CursorPosition, ) []protocol.CompletionItem { value := entry.GetValueByCursor(entry.End.Character) @@ -84,7 +85,10 @@ func getMatchValueCompletions( if value != nil { line = value.Value.Raw - relativeCursor = cursor - value.Start.Character + relativeCursor = common.DeprecatedImprovedCursorToIndex( + value.Start.GetRelativeCursorPosition(cursor), + line, + ) } else { line = "" relativeCursor = 0 diff --git a/handlers/sshd_config/handlers/definition.go b/handlers/sshd_config/handlers/definition.go index bec6955..02cf5de 100644 --- a/handlers/sshd_config/handlers/definition.go +++ b/handlers/sshd_config/handlers/definition.go @@ -1,9 +1,9 @@ package handlers import ( + "config-lsp/common" "config-lsp/handlers/sshd_config/indexes" "config-lsp/utils" - "fmt" "slices" protocol "github.com/tliron/glsp/protocol_3_16" @@ -11,17 +11,17 @@ import ( func GetIncludeOptionLocation( include *indexes.SSHDIndexIncludeLine, - cursor uint32, + index common.IndexPosition, ) []protocol.Location { - index, found := slices.BinarySearchFunc( + foundIndex, found := slices.BinarySearchFunc( include.Values, - cursor, - func(current *indexes.SSHDIndexIncludeValue, target uint32) int { - if target < current.Start.Character { + index, + func(current *indexes.SSHDIndexIncludeValue, target common.IndexPosition) int { + if current.Start.IsAfterIndexPosition(target) { return 1 } - if target > current.End.Character { + if current.End.IsBeforeIndexPosition(target) { return -1 } @@ -33,8 +33,7 @@ func GetIncludeOptionLocation( return nil } - path := include.Values[index] - println("paths", fmt.Sprintf("%v", path.Paths)) + path := include.Values[foundIndex] return utils.Map( path.Paths, diff --git a/handlers/sshd_config/handlers/formatting_nodes.go b/handlers/sshd_config/handlers/formatting_nodes.go index da84cba..4045b36 100644 --- a/handlers/sshd_config/handlers/formatting_nodes.go +++ b/handlers/sshd_config/handlers/formatting_nodes.go @@ -54,7 +54,7 @@ func formatSSHDMatchBlock( ) edits = append(edits, protocol.TextEdit{ Range: matchBlock.ToLSPRange(), - NewText: template.Format(options, matchBlock.MatchEntry.Key.Key, formatMatchToString(matchBlock.MatchValue, options)), + NewText: template.Format(options, matchBlock.MatchEntry.Key.Key, formatMatchToString(matchBlock.MatchValue)), }) it := matchBlock.Options.Iterator() @@ -69,12 +69,11 @@ func formatSSHDMatchBlock( func formatMatchToString( match *matchparser.Match, - options protocol.FormattingOptions, ) string { entriesAsStrings := utils.Map( match.Entries, func(entry *matchparser.MatchEntry) string { - return formatMatchEntryToString(entry, options) + return formatMatchEntryToString(entry) }, ) @@ -83,18 +82,16 @@ func formatMatchToString( func formatMatchEntryToString( entry *matchparser.MatchEntry, - options protocol.FormattingOptions, ) string { return fmt.Sprintf( "%s %s", string(entry.Criteria.Type), - formatMatchValuesToString(entry.Values, options), + formatMatchValuesToString(entry.Values), ) } func formatMatchValuesToString( values *matchparser.MatchValues, - options protocol.FormattingOptions, ) string { valuesAsStrings := utils.Map( values.Values, diff --git a/handlers/sshd_config/handlers/hover.go b/handlers/sshd_config/handlers/hover.go index f8ad890..8e41121 100644 --- a/handlers/sshd_config/handlers/hover.go +++ b/handlers/sshd_config/handlers/hover.go @@ -1,6 +1,7 @@ package handlers import ( + "config-lsp/common" docvalues "config-lsp/doc-values" "config-lsp/handlers/sshd_config/ast" "config-lsp/handlers/sshd_config/fields" @@ -13,7 +14,7 @@ func GetHoverInfoForOption( option *ast.SSHDOption, matchBlock *ast.SSHDMatchBlock, line uint32, - cursor uint32, + index common.IndexPosition, ) (*protocol.Hover, error) { var docValue *docvalues.DocumentationValue @@ -28,7 +29,7 @@ func GetHoverInfoForOption( } } - if cursor >= option.Key.Start.Character && cursor <= option.Key.End.Character { + if option.Key.ContainsIndexPosition(index) { if docValue != nil { contents := []string{ "## " + option.Key.Key, @@ -52,9 +53,12 @@ func GetHoverInfoForOption( } } - if option.OptionValue != nil && cursor >= option.OptionValue.Start.Character && cursor <= option.OptionValue.End.Character { - relativeCursor := cursor - option.OptionValue.Start.Character - contents := docValue.FetchHoverInfo(option.OptionValue.Value.Raw, relativeCursor) + if option.OptionValue != nil && option.OptionValue.ContainsIndexPosition(index) { + line := option.OptionValue.Value.Raw + contents := docValue.FetchHoverInfo( + line, + uint32(option.OptionValue.Start.GetRelativeIndexPosition(index)), + ) return &protocol.Hover{ Contents: strings.Join(contents, "\n"), diff --git a/handlers/sshd_config/indexes/handlers.go b/handlers/sshd_config/indexes/handlers.go index 371a200..533825c 100644 --- a/handlers/sshd_config/indexes/handlers.go +++ b/handlers/sshd_config/indexes/handlers.go @@ -63,7 +63,7 @@ func CreateIndexes(config ast.SSHDConfig) (*SSHDIndexes, []common.LSPError) { }, End: common.Location{ Line: includeOption.Start.Line, - Character: uint32(endIndex) + offset - 1, + Character: uint32(endIndex) + offset, }, }, Value: rawPath, diff --git a/handlers/sshd_config/indexes/indexes_test.go b/handlers/sshd_config/indexes/indexes_test.go index 7992ba0..cc4be38 100644 --- a/handlers/sshd_config/indexes/indexes_test.go +++ b/handlers/sshd_config/indexes/indexes_test.go @@ -79,7 +79,7 @@ Include /etc/ssh/sshd_config.d/*.conf hello_world indexes.Includes[1].Values[0].Start.Line == 1 && indexes.Includes[1].Values[0].End.Line == 1 && indexes.Includes[1].Values[0].Start.Character == 8 && - indexes.Includes[1].Values[0].End.Character == 36) { + indexes.Includes[1].Values[0].End.Character == 37) { t.Errorf("Expected '/etc/ssh/sshd_config.d/*.conf' on line 1, but got %v on line %v", indexes.Includes[1].Values[0].Value, indexes.Includes[1].Values[0].Start.Line) } @@ -87,7 +87,7 @@ Include /etc/ssh/sshd_config.d/*.conf hello_world indexes.Includes[1].Values[1].Start.Line == 1 && indexes.Includes[1].Values[1].End.Line == 1 && indexes.Includes[1].Values[1].Start.Character == 38 && - indexes.Includes[1].Values[1].End.Character == 48) { + indexes.Includes[1].Values[1].End.Character == 49) { t.Errorf("Expected 'hello_world' on line 1, but got %v on line %v", indexes.Includes[1].Values[1].Value, indexes.Includes[1].Values[1].Start.Line) } } diff --git a/handlers/sshd_config/lsp/text-document-completion.go b/handlers/sshd_config/lsp/text-document-completion.go index fa13229..24e592a 100644 --- a/handlers/sshd_config/lsp/text-document-completion.go +++ b/handlers/sshd_config/lsp/text-document-completion.go @@ -1,6 +1,7 @@ package lsp import ( + "config-lsp/common" sshdconfig "config-lsp/handlers/sshd_config" "config-lsp/handlers/sshd_config/handlers" "regexp" @@ -13,7 +14,7 @@ var isEmptyPattern = regexp.MustCompile(`^\s*$`) func TextDocumentCompletion(context *glsp.Context, params *protocol.CompletionParams) (any, error) { line := params.Position.Line - cursor := params.Position.Character + cursor := common.LSPCharacterAsCursorPosition(params.Position.Character) d := sshdconfig.DocumentParserMap[params.TextDocument.URI] @@ -26,7 +27,7 @@ func TextDocumentCompletion(context *glsp.Context, params *protocol.CompletionPa if entry == nil || entry.Separator == nil || entry.Key == nil || - cursor <= entry.Key.End.Character { + entry.Key.Start.IsAfterCursorPosition(cursor) { return handlers.GetRootCompletions( d, @@ -36,7 +37,7 @@ func TextDocumentCompletion(context *glsp.Context, params *protocol.CompletionPa ) } - if entry.Separator != nil && cursor >= entry.Separator.End.Character { + if entry.Separator != nil && entry.Separator.End.IsBeforeCursorPosition(cursor) { return handlers.GetOptionCompletions( d, entry, diff --git a/handlers/sshd_config/lsp/text-document-definition.go b/handlers/sshd_config/lsp/text-document-definition.go index 627c400..118f46c 100644 --- a/handlers/sshd_config/lsp/text-document-definition.go +++ b/handlers/sshd_config/lsp/text-document-definition.go @@ -1,6 +1,7 @@ package lsp import ( + "config-lsp/common" sshdconfig "config-lsp/handlers/sshd_config" "config-lsp/handlers/sshd_config/handlers" @@ -10,13 +11,14 @@ import ( func TextDocumentDefinition(context *glsp.Context, params *protocol.DefinitionParams) ([]protocol.Location, error) { d := sshdconfig.DocumentParserMap[params.TextDocument.URI] - cursor := params.Position.Character + index := common.LSPCharacterAsIndexPosition(params.Position.Character) line := params.Position.Line if include, found := d.Indexes.Includes[line]; found { - relativeCursor := cursor - include.Option.LocationRange.Start.Character - - return handlers.GetIncludeOptionLocation(include, relativeCursor), nil + return handlers.GetIncludeOptionLocation( + include, + index, + ), nil } return nil, nil diff --git a/handlers/sshd_config/lsp/text-document-hover.go b/handlers/sshd_config/lsp/text-document-hover.go index 1782116..93bfd81 100644 --- a/handlers/sshd_config/lsp/text-document-hover.go +++ b/handlers/sshd_config/lsp/text-document-hover.go @@ -1,6 +1,7 @@ package lsp import ( + "config-lsp/common" sshdconfig "config-lsp/handlers/sshd_config" "config-lsp/handlers/sshd_config/handlers" @@ -13,7 +14,7 @@ func TextDocumentHover( params *protocol.HoverParams, ) (*protocol.Hover, error) { line := params.Position.Line - cursor := params.Position.Character + index := common.LSPCharacterAsIndexPosition(params.Position.Character) d := sshdconfig.DocumentParserMap[params.TextDocument.URI] @@ -28,6 +29,6 @@ func TextDocumentHover( option, matchBlock, line, - cursor, + index, ) }