mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 23:15:26 +02:00
fix(wireguard): Add line indexes
This commit is contained in:
parent
dfba267b40
commit
9eedc063a2
2
go.mod
2
go.mod
@ -11,7 +11,9 @@ require (
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/iancoleman/strcase v0.3.0 // indirect
|
||||
github.com/k0kubun/pp v3.0.1+incompatible // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
|
6
go.sum
6
go.sum
@ -5,8 +5,13 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
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/pp v3.0.1+incompatible h1:3tqvf7QgUnZ5tXO6pNAZlrvHgl6DvifjDrd9g2S9Z40=
|
||||
github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
@ -37,6 +42,7 @@ golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
|
@ -86,5 +86,7 @@ func (p wireguardSection) analyzeInterfaceSection() []protocol.Diagnostic {
|
||||
}
|
||||
|
||||
func (p wireguardParser) analyzeAllowedIPIsInRange() []protocol.Diagnostic {
|
||||
diagnostics := []protocol.Diagnostic{}
|
||||
|
||||
return diagnostics
|
||||
}
|
||||
|
@ -314,3 +314,8 @@ Oocal NAT-ed node to remote public node
|
||||
var peerAllowedDuplicateFields = map[string]struct{}{
|
||||
"AllowedIPs": {},
|
||||
}
|
||||
|
||||
var optionsHeaderMap = map[string](map[string]docvalues.DocumentationValue){
|
||||
"Interface": interfaceOptions,
|
||||
"Peer": peerOptions,
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package wireguard
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/k0kubun/pp"
|
||||
)
|
||||
|
||||
func dedent(s string) string {
|
||||
@ -66,6 +68,22 @@ PublicKey = 5555
|
||||
if !(parser.Sections[2].Properties[10].Key.Name == "PublicKey") {
|
||||
t.Fatalf("parseFromString failed to collect properties of section 2 %v", parser.Sections[2].Properties)
|
||||
}
|
||||
|
||||
// Check if line indexes are correct
|
||||
if !(parser.LineIndexes[0].Type == LineTypeHeader &&
|
||||
parser.LineIndexes[1].Type == LineTypeProperty &&
|
||||
parser.LineIndexes[2].Type == LineTypeProperty &&
|
||||
parser.LineIndexes[3].Type == LineTypeEmpty &&
|
||||
parser.LineIndexes[4].Type == LineTypeComment &&
|
||||
parser.LineIndexes[5].Type == LineTypeHeader &&
|
||||
parser.LineIndexes[6].Type == LineTypeProperty &&
|
||||
parser.LineIndexes[7].Type == LineTypeProperty &&
|
||||
parser.LineIndexes[8].Type == LineTypeEmpty &&
|
||||
parser.LineIndexes[9].Type == LineTypeHeader &&
|
||||
parser.LineIndexes[10].Type == LineTypeProperty) {
|
||||
pp.Println(parser.LineIndexes)
|
||||
t.Fatal("parseFromString: Invalid line indexes")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptySectionAtStartWorksFine(
|
||||
@ -138,7 +156,7 @@ func TestEmptyFileWorksFine(
|
||||
t.Fatalf("parseFromString failed with error %v", errors)
|
||||
}
|
||||
|
||||
if !(len(parser.Sections) == 0) {
|
||||
if !(len(parser.Sections) == 1) {
|
||||
t.Fatalf("parseFromString failed to collect sections %v", parser.Sections)
|
||||
}
|
||||
}
|
||||
@ -221,7 +239,7 @@ func TestFileWithOnlyComments(
|
||||
t.Fatalf("parseFromString failed with error: %v", errors)
|
||||
}
|
||||
|
||||
if !(len(parser.Sections) == 0) {
|
||||
if !(len(parser.Sections) == 1) {
|
||||
t.Fatalf("parseFromString failed to collect sections: %v", parser.Sections)
|
||||
}
|
||||
|
||||
|
@ -79,38 +79,46 @@ PublicKey = 1234567890
|
||||
|
||||
section := parser.getBelongingSectionByLine(0)
|
||||
|
||||
// Comment
|
||||
if section != nil {
|
||||
t.Fatalf("getBelongingSectionByLine: Expected line 0 to be in no section, but it is in %v", section)
|
||||
}
|
||||
|
||||
section = parser.getBelongingSectionByLine(1)
|
||||
|
||||
if section != nil {
|
||||
t.Fatalf("getBelongingSectionByLine: Expected line 1 to be in no section, but it is in %v", section)
|
||||
if section != parser.Sections[1] {
|
||||
t.Fatalf("getBelongingSectionByLine: Expected line 1 to be in global section, but it is in %v", section)
|
||||
}
|
||||
|
||||
section = parser.getBelongingSectionByLine(2)
|
||||
if section != nil {
|
||||
t.Fatalf("getBelongingSectionByLine: Expected line 2 to be in no section, but it is in %v", section)
|
||||
if section != parser.Sections[1] {
|
||||
t.Fatalf("getBelongingSectionByLine: Expected line 2 to be in global section, but it is in %v", section)
|
||||
}
|
||||
|
||||
section = parser.getBelongingSectionByLine(3)
|
||||
if section == nil || *section.Name != "Interface" {
|
||||
if section != parser.Sections[2] {
|
||||
t.Fatalf("getBelongingSectionByLine: Expected line 3 to be in section Interface, but it is in %v", section)
|
||||
}
|
||||
|
||||
section = parser.getBelongingSectionByLine(4)
|
||||
if section == nil || *section.Name != "Interface" {
|
||||
if section != parser.Sections[2] {
|
||||
t.Fatalf("getBelongingSectionByLine: Expected line 4 to be in section Interface, but it is in %v", section)
|
||||
}
|
||||
|
||||
section = parser.getBelongingSectionByLine(6)
|
||||
if section == nil || *section.Name != "Interface" {
|
||||
if section != parser.Sections[2] {
|
||||
t.Fatalf("getBelongingSectionByLine: Expected line 6 to be in section Interface, but it is in %v", section)
|
||||
}
|
||||
|
||||
section = parser.getBelongingSectionByLine(10)
|
||||
if section == nil || *section.Name != "Peer" {
|
||||
if section != parser.Sections[3] {
|
||||
t.Fatalf("getBelongingSectionByLine: Expected line 10 to be in section Peer, but it is in %v", section)
|
||||
}
|
||||
|
||||
section = parser.getBelongingSectionByLine(12)
|
||||
|
||||
// Comment
|
||||
if section != nil {
|
||||
t.Fatalf("getBelongingSectionByLine: Expected line 12 to be in no section, but it is in %v", section)
|
||||
}
|
||||
}
|
||||
|
@ -25,10 +25,6 @@ func TextDocumentCompletion(context *glsp.Context, params *protocol.CompletionPa
|
||||
|
||||
return section.getCompletionsForEmptyLine()
|
||||
case LineTypeProperty:
|
||||
if section == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
completions, err := section.getCompletionsForPropertyLine(lineNumber, params.Position.Character)
|
||||
|
||||
if completions == nil && err != nil {
|
||||
|
@ -18,23 +18,41 @@ type characterLocation struct {
|
||||
End uint32
|
||||
}
|
||||
|
||||
type wireguardLineIndex struct {
|
||||
Type lineType
|
||||
BelongingSection *wireguardSection
|
||||
}
|
||||
|
||||
type wireguardParser struct {
|
||||
GlobalSection *wireguardSection
|
||||
// <key = name>: if nil then does not belong to a section
|
||||
Sections map[string]wireguardSection
|
||||
Sections []*wireguardSection
|
||||
// Used to identify where not to show diagnostics
|
||||
CommentLines map[uint32]struct{}
|
||||
|
||||
// Indexes
|
||||
LineIndexes map[uint32]wireguardLineIndex
|
||||
}
|
||||
|
||||
func (p *wireguardParser) clear() {
|
||||
p.Sections = map[string]wireguardSection{}
|
||||
p.Sections = []*wireguardSection{}
|
||||
p.CommentLines = map[uint32]struct{}{}
|
||||
p.LineIndexes = map[uint32]wireguardLineIndex{}
|
||||
}
|
||||
|
||||
func (p wireguardParser) getInterfaceSection() (*wireguardSection, bool) {
|
||||
for _, section := range p.Sections {
|
||||
if section.Name != nil && *section.Name == "Interface" {
|
||||
return section, true
|
||||
}
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (p wireguardParser) getRootCompletionsForEmptyLine() []protocol.CompletionItem {
|
||||
completions := []protocol.CompletionItem{}
|
||||
|
||||
if _, found := p.Sections["Interface"]; !found {
|
||||
if _, found := p.getInterfaceSection(); !found {
|
||||
completions = append(completions, headerInterfaceEnum.ToCompletionItem())
|
||||
}
|
||||
|
||||
@ -76,7 +94,7 @@ func getLineType(line string) lineType {
|
||||
}
|
||||
|
||||
func (p *wireguardParser) parseFromString(input string) []common.ParseError {
|
||||
errors := []common.ParseError{}
|
||||
var errors []common.ParseError
|
||||
lines := strings.Split(
|
||||
input,
|
||||
"\n",
|
||||
@ -86,7 +104,6 @@ func (p *wireguardParser) parseFromString(input string) []common.ParseError {
|
||||
|
||||
collectedProperties := wireguardProperties{}
|
||||
var lastPropertyLine *uint32
|
||||
var earliestPropertyLine *uint32
|
||||
|
||||
for index, line := range lines {
|
||||
currentLineNumber := uint32(len(lines) - index - 1)
|
||||
@ -95,6 +112,10 @@ func (p *wireguardParser) parseFromString(input string) []common.ParseError {
|
||||
switch lineType {
|
||||
case LineTypeComment:
|
||||
p.CommentLines[currentLineNumber] = struct{}{}
|
||||
p.LineIndexes[currentLineNumber] = wireguardLineIndex{
|
||||
Type: LineTypeComment,
|
||||
BelongingSection: nil,
|
||||
}
|
||||
|
||||
case LineTypeEmpty:
|
||||
continue
|
||||
@ -110,8 +131,6 @@ func (p *wireguardParser) parseFromString(input string) []common.ParseError {
|
||||
continue
|
||||
}
|
||||
|
||||
earliestPropertyLine = ¤tLineNumber
|
||||
|
||||
if lastPropertyLine == nil {
|
||||
lastPropertyLine = ¤tLineNumber
|
||||
}
|
||||
@ -126,14 +145,26 @@ func (p *wireguardParser) parseFromString(input string) []common.ParseError {
|
||||
lastLine = *lastPropertyLine
|
||||
}
|
||||
|
||||
name, section := createWireguardSection(
|
||||
section := createWireguardSection(
|
||||
currentLineNumber,
|
||||
lastLine,
|
||||
line,
|
||||
collectedProperties,
|
||||
)
|
||||
|
||||
p.Sections[name] = section
|
||||
p.Sections = append(p.Sections, §ion)
|
||||
|
||||
// Add indexes
|
||||
for lineNumber := range collectedProperties {
|
||||
p.LineIndexes[lineNumber] = wireguardLineIndex{
|
||||
Type: LineTypeProperty,
|
||||
BelongingSection: §ion,
|
||||
}
|
||||
}
|
||||
p.LineIndexes[currentLineNumber] = wireguardLineIndex{
|
||||
Type: LineTypeHeader,
|
||||
BelongingSection: §ion,
|
||||
}
|
||||
|
||||
// Reset
|
||||
collectedProperties = wireguardProperties{}
|
||||
@ -141,12 +172,80 @@ func (p *wireguardParser) parseFromString(input string) []common.ParseError {
|
||||
}
|
||||
}
|
||||
|
||||
var emptySection *wireguardSection
|
||||
|
||||
if len(collectedProperties) > 0 {
|
||||
p.GlobalSection = &wireguardSection{
|
||||
StartLine: *earliestPropertyLine,
|
||||
EndLine: *lastPropertyLine,
|
||||
emptySection = &wireguardSection{
|
||||
StartLine: 0,
|
||||
EndLine: p.Sections[len(p.Sections)-1].StartLine - 1,
|
||||
Properties: collectedProperties,
|
||||
}
|
||||
|
||||
p.Sections = append(p.Sections, emptySection)
|
||||
|
||||
for lineNumber := range collectedProperties {
|
||||
p.LineIndexes[lineNumber] = wireguardLineIndex{
|
||||
Type: LineTypeProperty,
|
||||
BelongingSection: emptySection,
|
||||
}
|
||||
}
|
||||
p.Sections = append(p.Sections, emptySection)
|
||||
} else {
|
||||
// Add empty section
|
||||
var endLine = uint32(len(lines))
|
||||
|
||||
if len(p.Sections) > 0 {
|
||||
endLine = p.Sections[len(p.Sections)-1].StartLine
|
||||
}
|
||||
|
||||
// Add empty section
|
||||
if endLine != 0 {
|
||||
emptySection = &wireguardSection{
|
||||
StartLine: 0,
|
||||
EndLine: endLine,
|
||||
Properties: collectedProperties,
|
||||
}
|
||||
|
||||
p.Sections = append(p.Sections, emptySection)
|
||||
|
||||
for newLine := uint32(0); newLine < endLine; newLine++ {
|
||||
if _, found := p.LineIndexes[newLine]; found {
|
||||
continue
|
||||
}
|
||||
|
||||
p.LineIndexes[newLine] = wireguardLineIndex{
|
||||
Type: LineTypeEmpty,
|
||||
BelongingSection: emptySection,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Since we parse the content from bottom to top, we need to reverse the sections
|
||||
// so its in correct order
|
||||
slices.Reverse(p.Sections)
|
||||
|
||||
// Fill empty lines between sections
|
||||
for lineNumber, section := range p.Sections {
|
||||
var endLine uint32
|
||||
|
||||
if len(p.Sections) > lineNumber+1 {
|
||||
nextSection := p.Sections[lineNumber+1]
|
||||
endLine = nextSection.StartLine
|
||||
} else {
|
||||
endLine = uint32(len(lines))
|
||||
}
|
||||
|
||||
for newLine := section.StartLine; newLine < endLine; newLine++ {
|
||||
if _, found := p.LineIndexes[newLine]; found {
|
||||
continue
|
||||
}
|
||||
|
||||
p.LineIndexes[newLine] = wireguardLineIndex{
|
||||
Type: LineTypeEmpty,
|
||||
BelongingSection: section,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors
|
||||
@ -158,20 +257,8 @@ func (p wireguardParser) getTypeByLine(line uint32) lineType {
|
||||
return LineTypeComment
|
||||
}
|
||||
|
||||
// Check if line is a section
|
||||
for _, section := range p.Sections {
|
||||
if section.StartLine <= line && section.EndLine >= line {
|
||||
if section.StartLine == line && section.Name != nil {
|
||||
return LineTypeHeader
|
||||
}
|
||||
|
||||
// Check for properties
|
||||
for propertyLineNumber := range section.Properties {
|
||||
if propertyLineNumber == line {
|
||||
return LineTypeProperty
|
||||
}
|
||||
}
|
||||
}
|
||||
if info, found := p.LineIndexes[line]; found {
|
||||
return info.Type
|
||||
}
|
||||
|
||||
return LineTypeEmpty
|
||||
@ -186,15 +273,10 @@ func (p wireguardParser) getTypeByLine(line uint32) lineType {
|
||||
// [Peer]
|
||||
//
|
||||
// This would return the section [Interface]
|
||||
func (p wireguardParser) getBelongingSectionByLine(line uint32) *wireguardSection {
|
||||
for index := range p.Sections {
|
||||
section := p.Sections[len(p.Sections)-index-1]
|
||||
|
||||
if section.StartLine <= line && section.Name != nil {
|
||||
return §ion
|
||||
}
|
||||
func (p *wireguardParser) getBelongingSectionByLine(line uint32) *wireguardSection {
|
||||
if info, found := p.LineIndexes[line]; found {
|
||||
return info.BelongingSection
|
||||
}
|
||||
|
||||
// Global section
|
||||
return nil
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"config-lsp/utils"
|
||||
"fmt"
|
||||
"maps"
|
||||
"math"
|
||||
"regexp"
|
||||
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
@ -23,7 +22,16 @@ func (e propertyNotFullyTypedError) Error() string {
|
||||
return "Property not fully typed"
|
||||
}
|
||||
|
||||
type wireguardSectionType uint
|
||||
|
||||
const (
|
||||
wireguardSectionUnknownType wireguardSectionType = 0
|
||||
wireguardSectionInterfaceType wireguardSectionType = 1
|
||||
wireguardSectionPeerType wireguardSectionType = 2
|
||||
)
|
||||
|
||||
type wireguardSection struct {
|
||||
Name *string
|
||||
StartLine uint32
|
||||
EndLine uint32
|
||||
Properties wireguardProperties
|
||||
@ -130,36 +138,27 @@ func (p wireguardSection) getCompletionsForPropertyLine(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if property.Separator == nil {
|
||||
if p.Name != nil {
|
||||
switch *p.Name {
|
||||
case "Interface":
|
||||
if _, found := interfaceOptions[property.Key.Name]; found {
|
||||
return getSeparatorCompletion(*property, character)
|
||||
}
|
||||
case "Peer":
|
||||
if _, found := peerOptions[property.Key.Name]; found {
|
||||
return getSeparatorCompletion(*property, character)
|
||||
}
|
||||
if p.Name == nil {
|
||||
return nil, propertyNotFoundError{}
|
||||
}
|
||||
|
||||
options, found := optionsHeaderMap[*p.Name]
|
||||
|
||||
if !found {
|
||||
return nil, propertyNotFoundError{}
|
||||
}
|
||||
|
||||
if property.Separator == nil {
|
||||
if _, found := options[property.Key.Name]; found {
|
||||
return getSeparatorCompletion(*property, character)
|
||||
}
|
||||
// Get empty line completions
|
||||
return nil, propertyNotFullyTypedError{}
|
||||
}
|
||||
|
||||
return nil, propertyNotFoundError{}
|
||||
}
|
||||
option, found := options[property.Key.Name]
|
||||
|
||||
var option docvalues.Value
|
||||
|
||||
switch *p.Name {
|
||||
case "Interface":
|
||||
option = interfaceOptions[property.Key.Name]
|
||||
case "Peer":
|
||||
option = peerOptions[property.Key.Name]
|
||||
}
|
||||
|
||||
if option == nil {
|
||||
if !found {
|
||||
return nil, propertyNotFoundError{}
|
||||
}
|
||||
|
||||
@ -183,7 +182,7 @@ func createWireguardSection(
|
||||
endLine uint32,
|
||||
headerLine string,
|
||||
props wireguardProperties,
|
||||
) (string, wireguardSection) {
|
||||
) wireguardSection {
|
||||
match := validHeaderPattern.FindStringSubmatch(headerLine)
|
||||
|
||||
var header string
|
||||
@ -195,7 +194,8 @@ func createWireguardSection(
|
||||
header = match[1]
|
||||
}
|
||||
|
||||
return header, wireguardSection{
|
||||
return wireguardSection{
|
||||
Name: &header,
|
||||
StartLine: startLine,
|
||||
EndLine: endLine,
|
||||
Properties: props,
|
||||
|
Loading…
x
Reference in New Issue
Block a user