mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 15:05:28 +02:00
feat(server): Add typo fix suggestion to ssh_config
This commit is contained in:
parent
67c7f7f4b7
commit
026e0349a1
@ -27,6 +27,9 @@ type ServerOptionsType struct {
|
||||
var ServerOptions = new(ServerOptionsType)
|
||||
|
||||
func InitServerOptions() {
|
||||
ServerOptions.NoUndetectableErrors = false
|
||||
ServerOptions.NoTypoSuggestions = false
|
||||
|
||||
if slices.Contains(os.Args, "--no-undetectable-errors") {
|
||||
Log.Info("config-lsp will not return errors for undetectable files")
|
||||
ServerOptions.NoUndetectableErrors = true
|
||||
|
@ -15,6 +15,7 @@ require (
|
||||
require (
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/hbollon/go-edlib v1.6.0 // indirect
|
||||
github.com/iancoleman/strcase v0.3.0 // indirect
|
||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
|
@ -9,6 +9,8 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hbollon/go-edlib v1.6.0 h1:ga7AwwVIvP8mHm9GsPueC0d71cfRU/52hmPJ7Tprv4E=
|
||||
github.com/hbollon/go-edlib v1.6.0/go.mod h1:wnt6o6EIVEzUfgbUZY7BerzQ2uvzp354qmS2xaLkrhM=
|
||||
github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
|
||||
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM=
|
||||
|
@ -29,8 +29,6 @@ func analyzeValuesAreValid(
|
||||
),
|
||||
)
|
||||
ctx.document.Indexes.UnknownOptions[info.Option.Start.Line] = info
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
103
server/handlers/ssh_config/handlers/code-action-typos.go
Normal file
103
server/handlers/ssh_config/handlers/code-action-typos.go
Normal file
@ -0,0 +1,103 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"config-lsp/common"
|
||||
sshconfig "config-lsp/handlers/ssh_config"
|
||||
"config-lsp/handlers/ssh_config/diagnostics"
|
||||
"config-lsp/handlers/ssh_config/fields"
|
||||
"fmt"
|
||||
|
||||
"github.com/hbollon/go-edlib"
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
func getKeywordTypoFixes(
|
||||
d *sshconfig.SSHDocument,
|
||||
params *protocol.CodeActionParams,
|
||||
) []protocol.CodeAction {
|
||||
if common.ServerOptions.NoTypoSuggestions {
|
||||
return nil
|
||||
}
|
||||
|
||||
line := params.Range.Start.Line
|
||||
|
||||
if typoOption, found := d.Indexes.UnknownOptions[line]; found {
|
||||
name := typoOption.Option.Key.Value.Value
|
||||
|
||||
suggestedOptions := findSimilarOptions(name)
|
||||
|
||||
actions := make([]protocol.CodeAction, 0, len(suggestedOptions))
|
||||
|
||||
kind := protocol.CodeActionKindQuickFix
|
||||
for index, normalizedOptionName := range suggestedOptions {
|
||||
isPreferred := index == 0
|
||||
optionName := fields.FieldsNameFormattedMap[normalizedOptionName]
|
||||
|
||||
actions = append(actions, protocol.CodeAction{
|
||||
Title: fmt.Sprintf("Typo Fix: %s", optionName),
|
||||
IsPreferred: &isPreferred,
|
||||
Kind: &kind,
|
||||
Diagnostics: []protocol.Diagnostic{
|
||||
diagnostics.GenerateUnknownOption(
|
||||
typoOption.Option.Key.ToLSPRange(),
|
||||
typoOption.Option.Key.Value.Value,
|
||||
),
|
||||
},
|
||||
Edit: &protocol.WorkspaceEdit{
|
||||
Changes: map[protocol.DocumentUri][]protocol.TextEdit{
|
||||
params.TextDocument.URI: {
|
||||
{
|
||||
Range: typoOption.Option.Key.ToLSPRange(),
|
||||
NewText: optionName,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return actions
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Find options that are similar to the given option name.
|
||||
// This is used to find typos & suggest the correct option name.
|
||||
// Once an option is found that has a Damerau-Levenshtein distance of 1, it is immediately returned.
|
||||
// If not, then the next 2 options of similarity 2, or 3 options of similarity 3 are returned.
|
||||
// If no options with similarity <= 3 are found, then an empty slice is returned.
|
||||
func findSimilarOptions(
|
||||
optionName string,
|
||||
) []fields.NormalizedOptionName {
|
||||
normalizedOptionName := string(fields.CreateNormalizedName(optionName))
|
||||
|
||||
optionsPerSimilarity := map[uint8][]fields.NormalizedOptionName{
|
||||
2: make([]fields.NormalizedOptionName, 0, 2),
|
||||
3: make([]fields.NormalizedOptionName, 0, 3),
|
||||
}
|
||||
|
||||
for name := range fields.Options {
|
||||
normalizedName := string(name)
|
||||
similarity := edlib.DamerauLevenshteinDistance(normalizedName, normalizedOptionName)
|
||||
|
||||
switch similarity {
|
||||
case 1:
|
||||
return []fields.NormalizedOptionName{name}
|
||||
case 2:
|
||||
optionsPerSimilarity[2] = append(optionsPerSimilarity[2], name)
|
||||
|
||||
if len(optionsPerSimilarity[2]) >= 2 {
|
||||
return optionsPerSimilarity[2]
|
||||
}
|
||||
case 3:
|
||||
optionsPerSimilarity[3] = append(optionsPerSimilarity[3], name)
|
||||
|
||||
if len(optionsPerSimilarity[3]) >= 3 {
|
||||
return optionsPerSimilarity[3]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return append(optionsPerSimilarity[2], optionsPerSimilarity[3]...)
|
||||
}
|
@ -12,12 +12,22 @@ func FetchCodeActions(
|
||||
d *sshconfig.SSHDocument,
|
||||
params *protocol.CodeActionParams,
|
||||
) []protocol.CodeAction {
|
||||
line := params.Range.Start.Line
|
||||
|
||||
if d.Indexes == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
actions := getAddToUnknownCodeAction(d, params)
|
||||
actions = append(actions, getKeywordTypoFixes(d, params)...)
|
||||
|
||||
return actions
|
||||
}
|
||||
|
||||
func getAddToUnknownCodeAction(
|
||||
d *sshconfig.SSHDocument,
|
||||
params *protocol.CodeActionParams,
|
||||
) []protocol.CodeAction {
|
||||
line := params.Range.Start.Line
|
||||
|
||||
if unknownOption, found := d.Indexes.UnknownOptions[line]; found {
|
||||
var blockLine *uint32
|
||||
|
||||
@ -39,7 +49,7 @@ func FetchCodeActions(
|
||||
},
|
||||
}
|
||||
kind := protocol.CodeActionKindQuickFix
|
||||
codeAction := &protocol.CodeAction{
|
||||
codeAction := protocol.CodeAction{
|
||||
Title: fmt.Sprintf("Add %s to unknown options", unknownOption.Option.Key.Key),
|
||||
Command: &command,
|
||||
Kind: &kind,
|
||||
@ -52,7 +62,7 @@ func FetchCodeActions(
|
||||
}
|
||||
|
||||
return []protocol.CodeAction{
|
||||
*codeAction,
|
||||
codeAction,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,9 +61,6 @@ func initFile(
|
||||
uri protocol.DocumentUri,
|
||||
advertisedLanguage string,
|
||||
) (*shared.SupportedLanguage, error) {
|
||||
println("Initializing the file")
|
||||
println(advertisedLanguage)
|
||||
println(uri)
|
||||
language, err := utils.DetectLanguage(content, advertisedLanguage, uri)
|
||||
|
||||
if err != nil {
|
||||
|
Loading…
x
Reference in New Issue
Block a user