mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 23:15:26 +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)
|
var ServerOptions = new(ServerOptionsType)
|
||||||
|
|
||||||
func InitServerOptions() {
|
func InitServerOptions() {
|
||||||
|
ServerOptions.NoUndetectableErrors = false
|
||||||
|
ServerOptions.NoTypoSuggestions = false
|
||||||
|
|
||||||
if slices.Contains(os.Args, "--no-undetectable-errors") {
|
if slices.Contains(os.Args, "--no-undetectable-errors") {
|
||||||
Log.Info("config-lsp will not return errors for undetectable files")
|
Log.Info("config-lsp will not return errors for undetectable files")
|
||||||
ServerOptions.NoUndetectableErrors = true
|
ServerOptions.NoUndetectableErrors = true
|
||||||
|
@ -15,6 +15,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
github.com/gorilla/websocket v1.5.3 // 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/iancoleman/strcase v0.3.0 // indirect
|
||||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect
|
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 // 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.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 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
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 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
|
||||||
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
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=
|
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
|
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,
|
d *sshconfig.SSHDocument,
|
||||||
params *protocol.CodeActionParams,
|
params *protocol.CodeActionParams,
|
||||||
) []protocol.CodeAction {
|
) []protocol.CodeAction {
|
||||||
line := params.Range.Start.Line
|
|
||||||
|
|
||||||
if d.Indexes == nil {
|
if d.Indexes == nil {
|
||||||
return 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 {
|
if unknownOption, found := d.Indexes.UnknownOptions[line]; found {
|
||||||
var blockLine *uint32
|
var blockLine *uint32
|
||||||
|
|
||||||
@ -39,7 +49,7 @@ func FetchCodeActions(
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
kind := protocol.CodeActionKindQuickFix
|
kind := protocol.CodeActionKindQuickFix
|
||||||
codeAction := &protocol.CodeAction{
|
codeAction := protocol.CodeAction{
|
||||||
Title: fmt.Sprintf("Add %s to unknown options", unknownOption.Option.Key.Key),
|
Title: fmt.Sprintf("Add %s to unknown options", unknownOption.Option.Key.Key),
|
||||||
Command: &command,
|
Command: &command,
|
||||||
Kind: &kind,
|
Kind: &kind,
|
||||||
@ -52,7 +62,7 @@ func FetchCodeActions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return []protocol.CodeAction{
|
return []protocol.CodeAction{
|
||||||
*codeAction,
|
codeAction,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,9 +61,6 @@ func initFile(
|
|||||||
uri protocol.DocumentUri,
|
uri protocol.DocumentUri,
|
||||||
advertisedLanguage string,
|
advertisedLanguage string,
|
||||||
) (*shared.SupportedLanguage, error) {
|
) (*shared.SupportedLanguage, error) {
|
||||||
println("Initializing the file")
|
|
||||||
println(advertisedLanguage)
|
|
||||||
println(uri)
|
|
||||||
language, err := utils.DetectLanguage(content, advertisedLanguage, uri)
|
language, err := utils.DetectLanguage(content, advertisedLanguage, uri)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user