mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 23:15:26 +02:00
feat: Add simple diagnostics; Improvements
This commit is contained in:
parent
da4577ac22
commit
184cf63411
35
common/errors.go
Normal file
35
common/errors.go
Normal file
@ -0,0 +1,35 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ParserError interface {}
|
||||
|
||||
type OptionAlreadyExistsError struct {
|
||||
Option string
|
||||
FoundOnLine uint32
|
||||
}
|
||||
func (e OptionAlreadyExistsError) Error() string {
|
||||
return fmt.Sprintf("Option %s already exists", e.Option)
|
||||
}
|
||||
|
||||
type OptionUnknownError struct {
|
||||
Option string
|
||||
}
|
||||
func (e OptionUnknownError) Error() string {
|
||||
return fmt.Sprintf("Option '%s' does not exist", e.Option)
|
||||
}
|
||||
|
||||
type MalformedLineError struct {
|
||||
Line string
|
||||
}
|
||||
func (e MalformedLineError) Error() string {
|
||||
return fmt.Sprintf("Malformed line: %s", e.Line)
|
||||
}
|
||||
|
||||
type LineNotFoundError struct {}
|
||||
func (e LineNotFoundError) Error() string {
|
||||
return "Line not found"
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
@ -34,29 +33,6 @@ type SimpleConfigParser struct {
|
||||
Options SimpleConfigOptions
|
||||
}
|
||||
|
||||
type OptionAlreadyExistsError struct {
|
||||
Option string
|
||||
}
|
||||
func (e OptionAlreadyExistsError) Error() string {
|
||||
return fmt.Sprintf("Option %s already exists", e.Option)
|
||||
}
|
||||
type OptionUnknownError struct {
|
||||
Option string
|
||||
}
|
||||
func (e OptionUnknownError) Error() string {
|
||||
return fmt.Sprintf("Option '%s' does not exist", e.Option)
|
||||
}
|
||||
type MalformedLineError struct {
|
||||
Line string
|
||||
}
|
||||
func (e MalformedLineError) Error() string {
|
||||
return fmt.Sprintf("Malformed line: %s", e.Line)
|
||||
}
|
||||
type LineNotFoundError struct {}
|
||||
func (e LineNotFoundError) Error() string {
|
||||
return "Line not found"
|
||||
}
|
||||
|
||||
func (p *SimpleConfigParser) AddLine(line string, lineNumber int) error {
|
||||
parts := strings.SplitN(line, p.Options.Separator, 2)
|
||||
|
||||
@ -83,6 +59,7 @@ func (p *SimpleConfigParser) AddLine(line string, lineNumber int) error {
|
||||
if _, exists := p.Lines[option]; exists {
|
||||
return OptionAlreadyExistsError{
|
||||
Option: option,
|
||||
FoundOnLine: uint32(lineNumber),
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,6 +95,22 @@ func (p *SimpleConfigParser) UpsertOption(option string, value string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *SimpleConfigParser) GetOption(option string) (SimpleConfigLine, error) {
|
||||
if _, exists := p.Lines[option]; exists {
|
||||
return p.Lines[option], nil
|
||||
}
|
||||
|
||||
return SimpleConfigLine{
|
||||
Value: "",
|
||||
Position: SimpleConfigPosition{
|
||||
Line: 0,
|
||||
},
|
||||
},
|
||||
OptionUnknownError{
|
||||
Option: option,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *SimpleConfigParser) ParseFromFile(content string) []error {
|
||||
lines := strings.Split(content, "\n")
|
||||
errors := make([]error, 0)
|
||||
@ -142,7 +135,7 @@ func (p *SimpleConfigParser) Clear() {
|
||||
}
|
||||
|
||||
// TODO: Use better approach: Store an extra array of lines in order; with references to the SimpleConfigLine
|
||||
func (p SimpleConfigParser) FindByLineNumber(lineNumber int) (string, SimpleConfigLine, error) {
|
||||
func (p *SimpleConfigParser) FindByLineNumber(lineNumber int) (string, SimpleConfigLine, error) {
|
||||
for option, line := range p.Lines {
|
||||
if line.Position.Line == lineNumber {
|
||||
return option, line, nil
|
||||
|
56
handlers/openssh/diagnostics.go
Normal file
56
handlers/openssh/diagnostics.go
Normal file
@ -0,0 +1,56 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"config-lsp/common"
|
||||
"fmt"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/tliron/glsp"
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
func ClearDiagnostics(context *glsp.Context, uri protocol.DocumentUri) {
|
||||
context.Notify(
|
||||
"textDocument/publishDiagnostics",
|
||||
protocol.PublishDiagnosticsParams{
|
||||
URI: uri,
|
||||
Diagnostics: []protocol.Diagnostic{},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func SendDiagnosticsFromParserErrors(context *glsp.Context, uri protocol.DocumentUri, parserErrors []error) {
|
||||
diagnosticErrors := make([]protocol.Diagnostic, 0)
|
||||
|
||||
for _, parserError := range parserErrors {
|
||||
switch parserError.(type) {
|
||||
case common.OptionAlreadyExistsError: {
|
||||
err := parserError.(common.OptionAlreadyExistsError)
|
||||
existingOption, _ := Parser.GetOption(err.Option)
|
||||
|
||||
diagnosticErrors = append(diagnosticErrors, protocol.Diagnostic{
|
||||
Range: protocol.Range{
|
||||
Start: protocol.Position{
|
||||
Line: err.FoundOnLine,
|
||||
Character: 0,
|
||||
},
|
||||
End: protocol.Position{
|
||||
Line: err.FoundOnLine,
|
||||
Character: uint32(utf8.RuneCountInString(err.Option)),
|
||||
},
|
||||
},
|
||||
Message: fmt.Sprintf("Option '%s' has already been declared on line %v", err.Option, existingOption.Position.Line + 1),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.Notify(
|
||||
"textDocument/publishDiagnostics",
|
||||
protocol.PublishDiagnosticsParams{
|
||||
URI: uri,
|
||||
Diagnostics: diagnosticErrors,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -10,7 +10,14 @@ func TextDocumentDidChange(context *glsp.Context, params *protocol.DidChangeText
|
||||
content := params.ContentChanges[0].(protocol.TextDocumentContentChangeEventWhole).Text
|
||||
|
||||
Parser.Clear()
|
||||
Parser.ParseFromFile(content)
|
||||
errors := Parser.ParseFromFile(content)
|
||||
|
||||
if len(errors) > 0 {
|
||||
SendDiagnosticsFromParserErrors(context, params.TextDocument.URI, errors)
|
||||
} else {
|
||||
ClearDiagnostics(context, params.TextDocument.URI)
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ func TextDocumentDidOpen(context *glsp.Context, params *protocol.DidOpenTextDocu
|
||||
errors := Parser.ParseFromFile(string(readBytes))
|
||||
|
||||
if len(errors) > 0 {
|
||||
return errors[0]
|
||||
SendDiagnosticsFromParserErrors(context, params.TextDocument.URI, errors)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
Loading…
x
Reference in New Issue
Block a user