mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 15:05:28 +02:00
feat(wireguard): Add code action: Create peer like this
This commit is contained in:
parent
3857bd5694
commit
15ce5958da
@ -22,7 +22,7 @@ func analyzeDNSPropertyContainsFallback(
|
||||
|
||||
interfaceSection := sections[0]
|
||||
|
||||
property := interfaceSection.FindFirstPropertyByName("DNS")
|
||||
_, property := interfaceSection.FindFirstPropertyByName("DNS")
|
||||
|
||||
if property == nil {
|
||||
return
|
||||
@ -44,7 +44,10 @@ func analyzeKeepAlivePropertyIsSet(
|
||||
) {
|
||||
for _, section := range ctx.document.Indexes.SectionsByName["Peer"] {
|
||||
// If an endpoint is set, then we should only check for the keepalive property
|
||||
if section.FindFirstPropertyByName("Endpoint") != nil && section.FindFirstPropertyByName("PersistentKeepalive") == nil {
|
||||
_, endpoint := section.FindFirstPropertyByName("Endpoint")
|
||||
_, persistentKeepAlive := section.FindFirstPropertyByName("PersistentKeepalive")
|
||||
|
||||
if endpoint != nil && persistentKeepAlive == nil {
|
||||
ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{
|
||||
Message: "PersistentKeepalive is not set. It is recommended to set this property, as it helps to maintain the connection when users are behind NAT",
|
||||
Severity: &common.SeverityHint,
|
||||
@ -58,11 +61,11 @@ func analyzeSymmetricPropertiesSet(
|
||||
ctx *analyzerContext,
|
||||
) {
|
||||
for _, section := range ctx.document.Indexes.SectionsByName["Interface"] {
|
||||
preUpProperty := section.FindFirstPropertyByName("PreUp")
|
||||
preDownProperty := section.FindFirstPropertyByName("PreDown")
|
||||
_, preUpProperty := section.FindFirstPropertyByName("PreUp")
|
||||
_, preDownProperty := section.FindFirstPropertyByName("PreDown")
|
||||
|
||||
postUpProperty := section.FindFirstPropertyByName("PostUp")
|
||||
postDownProperty := section.FindFirstPropertyByName("PostDown")
|
||||
_, postUpProperty := section.FindFirstPropertyByName("PostUp")
|
||||
_, postDownProperty := section.FindFirstPropertyByName("PostDown")
|
||||
|
||||
if preUpProperty != nil && preDownProperty == nil {
|
||||
ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{
|
||||
@ -94,7 +97,7 @@ func analyzeSymmetricPropertiesSet(
|
||||
}
|
||||
}
|
||||
|
||||
type key int
|
||||
type key uint8
|
||||
|
||||
const (
|
||||
lineKey key = iota
|
||||
@ -109,7 +112,7 @@ func analyzeDuplicateAllowedIPs(
|
||||
ipHostSet := utils.CreateIPv4HostSet()
|
||||
|
||||
for _, section := range ctx.document.Indexes.SectionsByName["Peer"] {
|
||||
property := section.FindFirstPropertyByName("AllowedIPs")
|
||||
_, property := section.FindFirstPropertyByName("AllowedIPs")
|
||||
|
||||
if property == nil {
|
||||
continue
|
||||
@ -123,12 +126,15 @@ func analyzeDuplicateAllowedIPs(
|
||||
}
|
||||
|
||||
if ipContext, _ := ipHostSet.ContainsIP(ipAddress); ipContext != nil {
|
||||
definedLine := (*ipContext).Value(lineKey).(uint32)
|
||||
ctxx := *ipContext
|
||||
definedLineRaw := ctxx.Value(lineKey)
|
||||
|
||||
definedLine := definedLineRaw.(uint32)
|
||||
|
||||
ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{
|
||||
Message: fmt.Sprintf("This IP range is already covered on line %d", definedLine+1),
|
||||
Severity: &common.SeverityError,
|
||||
Range: property.ToLSPRange(),
|
||||
Range: property.Value.ToLSPRange(),
|
||||
})
|
||||
} else {
|
||||
ipContext := context.WithValue(
|
||||
|
@ -35,7 +35,7 @@ type WGHeader struct {
|
||||
type WGSection struct {
|
||||
common.LocationRange
|
||||
Header WGHeader
|
||||
// [uint32]WGProperty: line number -> WGProperty
|
||||
// [uint32]*WGProperty: line number -> *WGProperty
|
||||
Properties *treemap.Map
|
||||
}
|
||||
|
||||
|
@ -10,11 +10,11 @@ func (c *WGConfig) FindSectionByLine(line uint32) *WGSection {
|
||||
line,
|
||||
func(current *WGSection, target uint32) int {
|
||||
if target < current.Start.Line {
|
||||
return -1
|
||||
return 1
|
||||
}
|
||||
|
||||
if target > current.End.Line {
|
||||
return 1
|
||||
return -1
|
||||
}
|
||||
|
||||
return 0
|
||||
@ -42,28 +42,17 @@ func (c *WGConfig) FindPropertyByLine(line uint32) *WGProperty {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *WGSection) FindFirstPropertyByName(name string) *WGProperty {
|
||||
func (s *WGSection) FindFirstPropertyByName(name string) (uint32, *WGProperty) {
|
||||
it := s.Properties.Iterator()
|
||||
for it.Next() {
|
||||
line := it.Key().(uint32)
|
||||
property := it.Value().(*WGProperty)
|
||||
if property.Key.Name == name {
|
||||
return property
|
||||
return line, property
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *WGSection) FindPropertyByName(name string) *WGProperty {
|
||||
it := s.Properties.Iterator()
|
||||
for it.Next() {
|
||||
property := it.Value().(*WGProperty)
|
||||
if property.Key.Name == name {
|
||||
return property
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (s *WGSection) GetLastProperty() *WGProperty {
|
||||
|
@ -1,9 +1,7 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"config-lsp/handlers/wireguard"
|
||||
"config-lsp/handlers/wireguard/ast"
|
||||
wgcommands "config-lsp/handlers/wireguard/commands"
|
||||
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
@ -13,6 +11,7 @@ type CodeActionName string
|
||||
const (
|
||||
CodeActionGeneratePrivateKey CodeActionName = "generatePrivateKey"
|
||||
CodeActionGeneratePresharedKey CodeActionName = "generatePresharedKey"
|
||||
CodeActionCreatePeer CodeActionName = "createPeer"
|
||||
)
|
||||
|
||||
type CodeAction interface {
|
||||
@ -20,105 +19,3 @@ type CodeAction interface {
|
||||
}
|
||||
|
||||
type CodeActionArgs interface{}
|
||||
|
||||
type CodeActionGeneratePrivateKeyArgs struct {
|
||||
URI protocol.DocumentUri
|
||||
Line uint32
|
||||
}
|
||||
|
||||
func CodeActionGeneratePrivateKeyArgsFromArguments(arguments map[string]any) CodeActionGeneratePrivateKeyArgs {
|
||||
return CodeActionGeneratePrivateKeyArgs{
|
||||
URI: arguments["URI"].(protocol.DocumentUri),
|
||||
Line: uint32(arguments["Line"].(float64)),
|
||||
}
|
||||
}
|
||||
|
||||
func (args CodeActionGeneratePrivateKeyArgs) RunCommand(d *wireguard.WGDocument) (*protocol.ApplyWorkspaceEditParams, error) {
|
||||
privateKey, err := wgcommands.CreateNewPrivateKey()
|
||||
|
||||
if err != nil {
|
||||
return &protocol.ApplyWorkspaceEditParams{}, err
|
||||
}
|
||||
|
||||
section := d.Config.FindSectionByLine(args.Line)
|
||||
property := d.Config.FindPropertyByLine(args.Line)
|
||||
|
||||
if section == nil || property == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
label := "Generate Private Key"
|
||||
return &protocol.ApplyWorkspaceEditParams{
|
||||
Label: &label,
|
||||
Edit: protocol.WorkspaceEdit{
|
||||
Changes: map[protocol.DocumentUri][]protocol.TextEdit{
|
||||
args.URI: {
|
||||
{
|
||||
NewText: " " + privateKey,
|
||||
Range: protocol.Range{
|
||||
Start: protocol.Position{
|
||||
Line: property.End.Line,
|
||||
Character: property.End.Character,
|
||||
},
|
||||
End: protocol.Position{
|
||||
Line: property.End.Line,
|
||||
Character: property.End.Character,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
type CodeActionGeneratePresharedKeyArgs struct {
|
||||
URI protocol.DocumentUri
|
||||
Line uint32
|
||||
}
|
||||
|
||||
func CodeActionGeneratePresharedKeyArgsFromArguments(arguments map[string]any) CodeActionGeneratePresharedKeyArgs {
|
||||
return CodeActionGeneratePresharedKeyArgs{
|
||||
URI: arguments["URI"].(protocol.DocumentUri),
|
||||
Line: uint32(arguments["Line"].(float64)),
|
||||
}
|
||||
}
|
||||
|
||||
func (args CodeActionGeneratePresharedKeyArgs) RunCommand(d *wireguard.WGDocument) (*protocol.ApplyWorkspaceEditParams, error) {
|
||||
presharedKey, err := wgcommands.CreatePresharedKey()
|
||||
|
||||
if err != nil {
|
||||
return &protocol.ApplyWorkspaceEditParams{}, err
|
||||
}
|
||||
|
||||
section := d.Config.FindSectionByLine(args.Line)
|
||||
property := d.Config.FindPropertyByLine(args.Line)
|
||||
|
||||
if section == nil || property == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
label := "Generate Preshared Key"
|
||||
return &protocol.ApplyWorkspaceEditParams{
|
||||
Label: &label,
|
||||
Edit: protocol.WorkspaceEdit{
|
||||
Changes: map[protocol.DocumentUri][]protocol.TextEdit{
|
||||
args.URI: {
|
||||
{
|
||||
NewText: " " + presharedKey,
|
||||
Range: protocol.Range{
|
||||
Start: protocol.Position{
|
||||
Line: property.End.Line,
|
||||
Character: property.End.Character,
|
||||
},
|
||||
End: protocol.Position{
|
||||
Line: property.End.Line,
|
||||
Character: property.End.Character,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
191
server/handlers/wireguard/handlers/code-actions_create-peer.go
Normal file
191
server/handlers/wireguard/handlers/code-actions_create-peer.go
Normal file
@ -0,0 +1,191 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"config-lsp/common"
|
||||
"config-lsp/handlers/wireguard"
|
||||
"config-lsp/handlers/wireguard/ast"
|
||||
wgcommands "config-lsp/handlers/wireguard/commands"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
type CodeActionCreatePeerArgs struct {
|
||||
URI protocol.DocumentUri
|
||||
Line uint32
|
||||
}
|
||||
|
||||
func CodeActionCreatePeerArgsFromArguments(arguments map[string]any) CodeActionCreatePeerArgs {
|
||||
return CodeActionCreatePeerArgs{
|
||||
URI: arguments["URI"].(protocol.DocumentUri),
|
||||
Line: uint32(arguments["Line"].(float64)),
|
||||
}
|
||||
}
|
||||
|
||||
func (args CodeActionCreatePeerArgs) RunCommand(d *wireguard.WGDocument) (*protocol.ApplyWorkspaceEditParams, error) {
|
||||
interfaceSection := d.Indexes.SectionsByName["Interface"][0]
|
||||
section := d.Config.FindSectionByLine(args.Line)
|
||||
|
||||
label := fmt.Sprintf("Add Peer based on peer on line %d", args.Line)
|
||||
|
||||
newSection := section
|
||||
|
||||
// IP Address
|
||||
ipAddressLine, ipAddress := newSection.FindFirstPropertyByName("AllowedIPs")
|
||||
_, address := interfaceSection.FindFirstPropertyByName("Address")
|
||||
if ipAddress != nil && address != nil {
|
||||
_, network, err := net.ParseCIDR(address.Value.Value)
|
||||
|
||||
if err == nil {
|
||||
newIPAddress := createNewIP(*network, ipAddress.Value.Value)
|
||||
|
||||
valueEnd := common.Location{
|
||||
Line: ipAddress.End.Line,
|
||||
Character: ipAddress.Value.Start.Character + uint32(len(newIPAddress)) + 1,
|
||||
}
|
||||
|
||||
newSection.Properties.Put(
|
||||
ipAddressLine,
|
||||
&ast.WGProperty{
|
||||
LocationRange: common.LocationRange{
|
||||
Start: ipAddress.Start,
|
||||
End: valueEnd,
|
||||
},
|
||||
Key: ipAddress.Key,
|
||||
RawValue: newIPAddress,
|
||||
Separator: address.Separator,
|
||||
Value: &ast.WGPropertyValue{
|
||||
LocationRange: common.LocationRange{
|
||||
Start: ipAddress.Value.Start,
|
||||
End: valueEnd,
|
||||
},
|
||||
Value: newIPAddress,
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Preshared Key
|
||||
presharedKeyLine, presharedKey := newSection.FindFirstPropertyByName("PresharedKey")
|
||||
|
||||
if presharedKey != nil {
|
||||
var newKey string
|
||||
|
||||
if wgcommands.AreWireguardToolsAvailable() {
|
||||
createdKey, err := wgcommands.CreatePresharedKey()
|
||||
|
||||
if err == nil {
|
||||
newKey = createdKey
|
||||
}
|
||||
} else {
|
||||
newKey = "[preshared key]"
|
||||
}
|
||||
|
||||
valueEnd := common.Location{
|
||||
Line: presharedKey.End.Line,
|
||||
Character: presharedKey.Value.Start.Character + uint32(len(newKey)) + 1,
|
||||
}
|
||||
newSection.Properties.Put(
|
||||
presharedKeyLine,
|
||||
&ast.WGProperty{
|
||||
LocationRange: common.LocationRange{
|
||||
Start: presharedKey.Start,
|
||||
End: valueEnd,
|
||||
},
|
||||
Key: presharedKey.Key,
|
||||
RawValue: newKey,
|
||||
Separator: presharedKey.Separator,
|
||||
Value: &ast.WGPropertyValue{
|
||||
LocationRange: common.LocationRange{
|
||||
Start: presharedKey.Value.Start,
|
||||
End: valueEnd,
|
||||
},
|
||||
Value: newKey,
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
lastProperty := newSection.GetLastProperty()
|
||||
println("last line")
|
||||
println(lastProperty.End.Line)
|
||||
println(fmt.Sprintf("~~~%s~~~", writeSection(*newSection)))
|
||||
newText := writeSection(*newSection)
|
||||
return &protocol.ApplyWorkspaceEditParams{
|
||||
Label: &label,
|
||||
Edit: protocol.WorkspaceEdit{
|
||||
Changes: map[protocol.DocumentUri][]protocol.TextEdit{
|
||||
args.URI: {
|
||||
{
|
||||
Range: protocol.Range{
|
||||
Start: protocol.Position{
|
||||
Line: lastProperty.End.Line,
|
||||
Character: lastProperty.End.Character,
|
||||
},
|
||||
End: protocol.Position{
|
||||
Line: lastProperty.End.Line,
|
||||
Character: lastProperty.End.Character,
|
||||
},
|
||||
},
|
||||
NewText: newText,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func writeSection(section ast.WGSection) string {
|
||||
text := "\n\n"
|
||||
|
||||
text += fmt.Sprintf("[%s]\n", section.Header.Name)
|
||||
|
||||
it := section.Properties.Iterator()
|
||||
for it.Next() {
|
||||
property := it.Value().(*ast.WGProperty)
|
||||
text += fmt.Sprintf("%s = %s\n", property.Key.Name, property.Value.Value)
|
||||
}
|
||||
|
||||
return text
|
||||
}
|
||||
|
||||
// Try incrementing the IP address
|
||||
func createNewIP(
|
||||
network net.IPNet,
|
||||
rawIP string,
|
||||
) string {
|
||||
parsedIP, _, err := net.ParseCIDR(rawIP)
|
||||
parsedIP = parsedIP.To4()
|
||||
|
||||
if parsedIP == nil {
|
||||
// IPv6 is not supported
|
||||
return ""
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
lastAddress := uint32(network.IP[0])<<24 | uint32(network.IP[1])<<16 | uint32(network.IP[2])<<8 | uint32(network.IP[3])
|
||||
|
||||
networkMask, _ := network.Mask.Size()
|
||||
for index := range 32 - networkMask {
|
||||
lastAddress |= 1 << index
|
||||
}
|
||||
|
||||
newIP := uint32(parsedIP[0])<<24 | uint32(parsedIP[1])<<16 | uint32(parsedIP[2])<<8 | uint32(parsedIP[3])
|
||||
newIP += 1
|
||||
|
||||
if newIP >= lastAddress || newIP == 0 {
|
||||
// The IP is the last one, which can't be used
|
||||
// or even worse, it did a whole overflow
|
||||
return ""
|
||||
}
|
||||
|
||||
// Here, we successfully incremented the IP correctly
|
||||
|
||||
// Let's return the formatted IP now.
|
||||
return fmt.Sprintf("%d.%d.%d.%d/32", newIP>>24, newIP>>16&0xFF, newIP>>8&0xFF, newIP&0xFF)
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCreateNewIPSimple24Mask(t *testing.T) {
|
||||
_, network, _ := net.ParseCIDR("10.0.0.0/24")
|
||||
newIP := createNewIP(*network, "10.0.0.1/32")
|
||||
|
||||
if newIP != "10.0.0.2/32" {
|
||||
t.Errorf("Expected 10.0.0.2/32, got %s", newIP)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateNewIPDoesNotWorkWithLast24Mask(t *testing.T) {
|
||||
_, network, _ := net.ParseCIDR("10.0.0.0/24")
|
||||
newIP := createNewIP(*network, "10.0.0.254/32")
|
||||
|
||||
if newIP != "" {
|
||||
t.Errorf("Expected empty string, got %s", newIP)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateNewIPDoesNotWorkWithLast24Mask2(t *testing.T) {
|
||||
_, network, _ := net.ParseCIDR("10.0.0.0/24")
|
||||
newIP := createNewIP(*network, "10.0.0.255/32")
|
||||
|
||||
if newIP != "" {
|
||||
t.Errorf("Expected empty string, got %s", newIP)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateNewIPComplex20Mask(t *testing.T) {
|
||||
_, network, _ := net.ParseCIDR("10.0.0.0/20")
|
||||
newIP := createNewIP(*network, "10.0.0.255/32")
|
||||
|
||||
if newIP != "10.0.1.0/32" {
|
||||
t.Errorf("Expected 10.0.1.0/32, got %s", newIP)
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"config-lsp/handlers/wireguard"
|
||||
wgcommands "config-lsp/handlers/wireguard/commands"
|
||||
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
type CodeActionGeneratePrivateKeyArgs struct {
|
||||
URI protocol.DocumentUri
|
||||
Line uint32
|
||||
}
|
||||
|
||||
func CodeActionGeneratePrivateKeyArgsFromArguments(arguments map[string]any) CodeActionGeneratePrivateKeyArgs {
|
||||
return CodeActionGeneratePrivateKeyArgs{
|
||||
URI: arguments["URI"].(protocol.DocumentUri),
|
||||
Line: uint32(arguments["Line"].(float64)),
|
||||
}
|
||||
}
|
||||
|
||||
func (args CodeActionGeneratePrivateKeyArgs) RunCommand(d *wireguard.WGDocument) (*protocol.ApplyWorkspaceEditParams, error) {
|
||||
privateKey, err := wgcommands.CreateNewPrivateKey()
|
||||
|
||||
if err != nil {
|
||||
return &protocol.ApplyWorkspaceEditParams{}, err
|
||||
}
|
||||
|
||||
section := d.Config.FindSectionByLine(args.Line)
|
||||
property := d.Config.FindPropertyByLine(args.Line)
|
||||
|
||||
if section == nil || property == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
label := "Generate Private Key"
|
||||
return &protocol.ApplyWorkspaceEditParams{
|
||||
Label: &label,
|
||||
Edit: protocol.WorkspaceEdit{
|
||||
Changes: map[protocol.DocumentUri][]protocol.TextEdit{
|
||||
args.URI: {
|
||||
{
|
||||
NewText: " " + privateKey,
|
||||
Range: protocol.Range{
|
||||
Start: protocol.Position{
|
||||
Line: property.End.Line,
|
||||
Character: property.End.Character,
|
||||
},
|
||||
End: protocol.Position{
|
||||
Line: property.End.Line,
|
||||
Character: property.End.Character,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"config-lsp/handlers/wireguard"
|
||||
wgcommands "config-lsp/handlers/wireguard/commands"
|
||||
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
type CodeActionGeneratePresharedKeyArgs struct {
|
||||
URI protocol.DocumentUri
|
||||
Line uint32
|
||||
}
|
||||
|
||||
func CodeActionGeneratePresharedKeyArgsFromArguments(arguments map[string]any) CodeActionGeneratePresharedKeyArgs {
|
||||
return CodeActionGeneratePresharedKeyArgs{
|
||||
URI: arguments["URI"].(protocol.DocumentUri),
|
||||
Line: uint32(arguments["Line"].(float64)),
|
||||
}
|
||||
}
|
||||
|
||||
func (args CodeActionGeneratePresharedKeyArgs) RunCommand(d *wireguard.WGDocument) (*protocol.ApplyWorkspaceEditParams, error) {
|
||||
presharedKey, err := wgcommands.CreatePresharedKey()
|
||||
|
||||
if err != nil {
|
||||
return &protocol.ApplyWorkspaceEditParams{}, err
|
||||
}
|
||||
|
||||
section := d.Config.FindSectionByLine(args.Line)
|
||||
property := d.Config.FindPropertyByLine(args.Line)
|
||||
|
||||
if section == nil || property == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
label := "Generate Preshared Key"
|
||||
return &protocol.ApplyWorkspaceEditParams{
|
||||
Label: &label,
|
||||
Edit: protocol.WorkspaceEdit{
|
||||
Changes: map[protocol.DocumentUri][]protocol.TextEdit{
|
||||
args.URI: {
|
||||
{
|
||||
NewText: presharedKey,
|
||||
Range: property.Value.ToLSPRange(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"config-lsp/handlers/wireguard"
|
||||
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
func GetAddPeerLikeThis(
|
||||
d *wireguard.WGDocument,
|
||||
params *protocol.CodeActionParams,
|
||||
) []protocol.CodeAction {
|
||||
// First, check if is on peer line
|
||||
|
||||
line := params.Range.Start.Line
|
||||
|
||||
section := d.Config.FindSectionByLine(line)
|
||||
|
||||
// Check if section can be copied
|
||||
if section == nil || section.Start.Line != line || section.Header.Name != "Peer" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Then add option
|
||||
commandID := "wireguard." + CodeActionCreatePeer
|
||||
command := protocol.Command{
|
||||
Title: "Create new Peer based on this one",
|
||||
Command: string(commandID),
|
||||
Arguments: []any{
|
||||
CodeActionCreatePeerArgs{
|
||||
URI: params.TextDocument.URI,
|
||||
Line: line,
|
||||
},
|
||||
},
|
||||
}
|
||||
return []protocol.CodeAction{
|
||||
{
|
||||
Title: "Create new Peer based on this one",
|
||||
Command: &command,
|
||||
},
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"config-lsp/handlers/wireguard"
|
||||
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
func GetKeepaliveCodeActions(
|
||||
d *wireguard.WGDocument,
|
||||
params *protocol.CodeActionParams,
|
||||
) []protocol.CodeAction {
|
||||
line := params.Range.Start.Line
|
||||
|
||||
for _, section := range d.Indexes.SectionsByName["Peer"] {
|
||||
if section.Start.Line >= line && line <= section.End.Line {
|
||||
_, endpoint := section.FindFirstPropertyByName("Endpoint")
|
||||
_, persistentKeepAlive := section.FindFirstPropertyByName("PersistentKeepalive")
|
||||
|
||||
if endpoint != nil && persistentKeepAlive == nil {
|
||||
var insertionLine uint32
|
||||
lastProperty := section.GetLastProperty()
|
||||
|
||||
if lastProperty == nil {
|
||||
insertionLine = section.End.Line
|
||||
} else {
|
||||
insertionLine = lastProperty.End.Line + 1
|
||||
}
|
||||
|
||||
return []protocol.CodeAction{
|
||||
{
|
||||
Title: "Add PersistentKeepalive",
|
||||
Edit: &protocol.WorkspaceEdit{
|
||||
Changes: map[protocol.DocumentUri][]protocol.TextEdit{
|
||||
params.TextDocument.URI: {
|
||||
{
|
||||
Range: protocol.Range{
|
||||
Start: protocol.Position{
|
||||
Line: insertionLine,
|
||||
Character: 0,
|
||||
},
|
||||
End: protocol.Position{
|
||||
Line: insertionLine,
|
||||
Character: 0,
|
||||
},
|
||||
},
|
||||
NewText: "PersistentKeepalive = 25\n",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -7,55 +7,6 @@ import (
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
func GetKeepaliveCodeActions(
|
||||
d *wireguard.WGDocument,
|
||||
params *protocol.CodeActionParams,
|
||||
) []protocol.CodeAction {
|
||||
line := params.Range.Start.Line
|
||||
|
||||
for _, section := range d.Indexes.SectionsByName["Peer"] {
|
||||
if section.Start.Line >= line && line <= section.End.Line {
|
||||
if section.FindPropertyByName("Endpoint") != nil && section.FindFirstPropertyByName("PersistentKeepalive") == nil {
|
||||
var insertionLine uint32
|
||||
lastProperty := section.GetLastProperty()
|
||||
|
||||
if lastProperty == nil {
|
||||
insertionLine = section.End.Line
|
||||
} else {
|
||||
insertionLine = lastProperty.End.Line + 1
|
||||
}
|
||||
|
||||
return []protocol.CodeAction{
|
||||
{
|
||||
Title: "Add PersistentKeepalive",
|
||||
Edit: &protocol.WorkspaceEdit{
|
||||
Changes: map[protocol.DocumentUri][]protocol.TextEdit{
|
||||
params.TextDocument.URI: {
|
||||
{
|
||||
Range: protocol.Range{
|
||||
Start: protocol.Position{
|
||||
Line: insertionLine,
|
||||
Character: 0,
|
||||
},
|
||||
End: protocol.Position{
|
||||
Line: insertionLine,
|
||||
Character: 0,
|
||||
},
|
||||
},
|
||||
NewText: "PersistentKeepalive = 25\n",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetKeyGenerationCodeActions(
|
||||
d *wireguard.WGDocument,
|
||||
params *protocol.CodeActionParams,
|
@ -15,6 +15,7 @@ func TextDocumentCodeAction(context *glsp.Context, params *protocol.CodeActionPa
|
||||
|
||||
actions = append(actions, handlers.GetKeyGenerationCodeActions(d, params)...)
|
||||
actions = append(actions, handlers.GetKeepaliveCodeActions(d, params)...)
|
||||
actions = append(actions, handlers.GetAddPeerLikeThis(d, params)...)
|
||||
|
||||
if len(actions) > 0 {
|
||||
return actions, nil
|
||||
|
@ -24,6 +24,12 @@ func WorkspaceExecuteCommand(context *glsp.Context, params *protocol.ExecuteComm
|
||||
|
||||
d := wireguard.DocumentParserMap[args.URI]
|
||||
|
||||
return args.RunCommand(d)
|
||||
case string(handlers.CodeActionCreatePeer):
|
||||
args := handlers.CodeActionCreatePeerArgsFromArguments(params.Arguments[0].(map[string]any))
|
||||
|
||||
d := wireguard.DocumentParserMap[args.URI]
|
||||
|
||||
return args.RunCommand(d)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user