From ffdf5bac468325d6e6d5df8d017207f1ae23f4b2 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Sun, 18 Aug 2024 15:47:49 +0200 Subject: [PATCH] feat(wireguard): Improve analyzer; Analyze values --- doc-values/value-ip-address.go | 20 +++++ handlers/wireguard/analyzer.go | 142 ++++++++++++++++++++++++++++++- handlers/wireguard/wg-section.go | 13 +++ 3 files changed, 174 insertions(+), 1 deletion(-) diff --git a/doc-values/value-ip-address.go b/doc-values/value-ip-address.go index 927c9bf..8c2bca4 100644 --- a/doc-values/value-ip-address.go +++ b/doc-values/value-ip-address.go @@ -4,6 +4,8 @@ import ( "config-lsp/utils" "fmt" net "net/netip" + "strconv" + "strings" protocol "github.com/tliron/glsp/protocol_3_16" ) @@ -161,6 +163,24 @@ func (v IPAddressValue) FetchCompletions(line string, cursor uint32) []protocol. }) } + if v.AllowRange { + slashIndex := strings.LastIndex(line, "/") + + if slashIndex > -1 && cursor >= uint32(slashIndex) { + completions := make([]protocol.CompletionItem, 33) + + for i := 0; i < len(completions); i++ { + kind := protocol.CompletionItemKindValue + completions[i] = protocol.CompletionItem{ + Label: strconv.Itoa(i), + Kind: &kind, + } + } + + return completions + } + } + return []protocol.CompletionItem{} } diff --git a/handlers/wireguard/analyzer.go b/handlers/wireguard/analyzer.go index 5643081..916ea43 100644 --- a/handlers/wireguard/analyzer.go +++ b/handlers/wireguard/analyzer.go @@ -1,6 +1,7 @@ package wireguard import ( + docvalues "config-lsp/doc-values" "config-lsp/utils" "fmt" "slices" @@ -9,13 +10,152 @@ import ( ) func (p wireguardParser) analyze() []protocol.Diagnostic { - diagnostics := []protocol.Diagnostic{} + validCheckErrors := p.checkIfValuesAreValid() + if len(validCheckErrors) > 0 { + return validCheckErrors + } + + diagnostics := []protocol.Diagnostic{} diagnostics = append(diagnostics, p.checkForDuplicateProperties()...) return diagnostics } +func (p wireguardParser) checkIfValuesAreValid() []protocol.Diagnostic { + diagnostics := []protocol.Diagnostic{} + + for _, section := range p.Sections { + sectionDiagnostics := section.analyzeSection() + + if len(sectionDiagnostics) > 0 { + diagnostics = append(diagnostics, sectionDiagnostics...) + continue + } + + for lineNumber, property := range section.Properties { + diagnostics = append( + diagnostics, + property.analyzeProperty(section, lineNumber)..., + ) + } + } + + return diagnostics +} + +func (p wireguardSection) analyzeSection() []protocol.Diagnostic { + diagnostics := []protocol.Diagnostic{} + + if p.Name == nil { + // No section name + severity := protocol.DiagnosticSeverityError + diagnostics = append(diagnostics, protocol.Diagnostic{ + Message: "This section is missing a name", + Severity: &severity, + Range: p.getRange(), + }) + return diagnostics + } + + if _, found := optionsHeaderMap[*p.Name]; !found { + // Unknown section + severity := protocol.DiagnosticSeverityError + diagnostics = append(diagnostics, protocol.Diagnostic{ + Message: fmt.Sprintf("Unknown section '%s'. It must be one of: [Interface], [Peer]", *p.Name), + Severity: &severity, + Range: protocol.Range{ + Start: protocol.Position{ + Line: p.StartLine, + Character: 0, + }, + End: protocol.Position{ + Line: p.StartLine, + Character: 99999999, + }, + }, + }) + + return diagnostics + } + + return diagnostics +} + +// Check if the property is valid. +// Returns a list of diagnostics. +// `belongingSection` is the section to which the property belongs. This value is +// expected to be non-nil and expected to be a valid Wireguard section. +func (p wireguardProperty) analyzeProperty( + belongingSection *wireguardSection, + propertyLine uint32, +) []protocol.Diagnostic { + sectionOptions := optionsHeaderMap[*belongingSection.Name] + option, found := sectionOptions[p.Key.Name] + + if !found { + // Unknown property + severity := protocol.DiagnosticSeverityError + return []protocol.Diagnostic{ + { + Message: fmt.Sprintf("Unknown property '%s'", p.Key.Name), + Severity: &severity, + Range: protocol.Range{ + Start: protocol.Position{ + Line: propertyLine, + Character: p.Key.Location.Start, + }, + End: protocol.Position{ + Line: propertyLine, + Character: p.Key.Location.End, + }, + }, + }, + } + } + + if p.Value == nil { + // No value to check + severity := protocol.DiagnosticSeverityWarning + return []protocol.Diagnostic{ + { + Message: "Property is missing a value", + Severity: &severity, + Range: protocol.Range{ + Start: protocol.Position{ + Line: propertyLine, + Character: 0, + }, + End: protocol.Position{ + Line: propertyLine, + Character: 99999999, + }, + }, + }, + } + } + + errors := option.CheckIsValid(p.Value.Value) + + return utils.Map(errors, func(err *docvalues.InvalidValue) protocol.Diagnostic { + severity := protocol.DiagnosticSeverityError + return protocol.Diagnostic{ + Message: err.GetMessage(), + Severity: &severity, + Range: protocol.Range{ + Start: protocol.Position{ + Line: propertyLine, + Character: p.Value.Location.Start + err.Start, + }, + End: protocol.Position{ + Line: propertyLine, + Character: p.Value.Location.Start + err.End, + }, + }, + } + }) +} + func (p wireguardParser) checkForDuplicateProperties() []protocol.Diagnostic { diagnostics := []protocol.Diagnostic{} diff --git a/handlers/wireguard/wg-section.go b/handlers/wireguard/wg-section.go index 44d403e..db8b0c0 100644 --- a/handlers/wireguard/wg-section.go +++ b/handlers/wireguard/wg-section.go @@ -37,6 +37,19 @@ type wireguardSection struct { Properties wireguardProperties } +func (s wireguardSection) getRange() protocol.Range { + return protocol.Range{ + Start: protocol.Position{ + Line: s.StartLine, + Character: 0, + }, + End: protocol.Position{ + Line: s.EndLine, + Character: 99999999, + }, + } +} + func (s wireguardSection) String() string { var name string