feat(ssh_config): Add tag support

This commit is contained in:
Myzel394 2024-10-02 16:34:23 +02:00
parent 6c603f5c5b
commit 7359fac2e0
No known key found for this signature in database
GPG Key ID: ED20A1D1D423AF3F
3 changed files with 79 additions and 3 deletions

View File

@ -50,4 +50,6 @@ type SSHIndexes struct {
// a code action to add them to a "IgnoreUnknown" option // a code action to add them to a "IgnoreUnknown" option
// This is a map of <line> to <option> // This is a map of <line> to <option>
UnknownOptions map[uint32]ast.AllOptionInfo UnknownOptions map[uint32]ast.AllOptionInfo
Tags map[string]*ast.SSHMatchBlock
} }

View File

@ -4,6 +4,7 @@ import (
"config-lsp/common" "config-lsp/common"
"config-lsp/handlers/ssh_config/ast" "config-lsp/handlers/ssh_config/ast"
"config-lsp/handlers/ssh_config/fields" "config-lsp/handlers/ssh_config/fields"
matchparser "config-lsp/handlers/ssh_config/match-parser"
"errors" "errors"
"fmt" "fmt"
"regexp" "regexp"
@ -13,14 +14,16 @@ var whitespacePattern = regexp.MustCompile(`\S+`)
func NewSSHIndexes() *SSHIndexes { func NewSSHIndexes() *SSHIndexes {
return &SSHIndexes{ return &SSHIndexes{
AllOptionsPerName: make(map[fields.NormalizedOptionName](map[ast.SSHBlock]([]*ast.SSHOption)), 0), AllOptionsPerName: make(map[fields.NormalizedOptionName](map[ast.SSHBlock]([]*ast.SSHOption))),
Includes: make([]*SSHIndexIncludeLine, 0), Includes: make([]*SSHIndexIncludeLine, 0),
IgnoredOptions: make(map[ast.SSHBlock]SSHIndexIgnoredUnknowns), IgnoredOptions: make(map[ast.SSHBlock]SSHIndexIgnoredUnknowns),
UnknownOptions: make(map[uint32]ast.AllOptionInfo, 0), UnknownOptions: make(map[uint32]ast.AllOptionInfo),
Tags: make(map[string]*ast.SSHMatchBlock),
} }
} }
var includeOption = fields.NormalizedOptionName("Include") var includeOption = fields.CreateNormalizedName("Include")
var matchOption = fields.CreateNormalizedName("Match")
func CreateIndexes(config ast.SSHConfig) (*SSHIndexes, []common.LSPError) { func CreateIndexes(config ast.SSHConfig) (*SSHIndexes, []common.LSPError) {
errs := make([]common.LSPError, 0) errs := make([]common.LSPError, 0)
@ -88,6 +91,33 @@ func CreateIndexes(config ast.SSHConfig) (*SSHIndexes, []common.LSPError) {
} }
} }
// Add tags
for rawBlock := range indexes.AllOptionsPerName[matchOption] {
block := rawBlock.(*ast.SSHMatchBlock)
for _, entry := range block.MatchValue.Entries {
if entry.Criteria.Type != matchparser.MatchCriteriaTypeTagged || entry.Value.Value == "" {
continue
}
for _, value := range entry.Values.Values {
name := value.Value.Value
if existingBlock, found := indexes.Tags[name]; found {
// Tag already exists
errs = append(errs, common.LSPError{
Range: entry.LocationRange,
Err: fmt.Errorf("Tag %s has already been defined on line %d", name, existingBlock.Start.Line+1),
})
continue
}
// Add tag
indexes.Tags[name] = block
}
}
}
return indexes, errs return indexes, errs
} }

View File

@ -3,6 +3,7 @@ package indexes
import ( import (
"config-lsp/handlers/ssh_config/ast" "config-lsp/handlers/ssh_config/ast"
"config-lsp/utils" "config-lsp/utils"
"fmt"
"testing" "testing"
) )
@ -117,3 +118,46 @@ UseKeychain yes
t.Errorf("Expected IgnoreOptions to contain 'UseKeychain' on line 0 and from position 14-24, but got: %v", indexes.IgnoredOptions[nil].IgnoredOptions) t.Errorf("Expected IgnoreOptions to contain 'UseKeychain' on line 0 and from position 14-24, but got: %v", indexes.IgnoredOptions[nil].IgnoredOptions)
} }
} }
func TestTagsExample(
t *testing.T,
) {
input := utils.Dedent(`
Match tagged good_ip
AddressFamily inet
Match tagged myuser
User root
`)
config := ast.NewSSHConfig()
errors := config.Parse(input)
if len(errors) > 0 {
t.Fatalf("Expected no errors, but got %v", len(errors))
}
indexes, errors := CreateIndexes(*config)
if len(errors) > 0 {
t.Fatalf("Expected 1 error, but got %v", errors)
}
if !(len(indexes.Tags) == 2) {
t.Errorf("Expected 2 tags, but got %v", indexes.Tags)
}
rawFirstMatch, _ := config.Options.Get(uint32(0))
firstMatch := rawFirstMatch.(*ast.SSHMatchBlock)
println(fmt.Sprintf("%v", indexes.Tags["good_ip"]))
if !(indexes.Tags["good_ip"].Start.Line == firstMatch.Start.Line) {
t.Errorf("Expected first tag to be 'good_ip', but got %v", indexes.Tags)
}
rawSecondMatch, _ := config.Options.Get(uint32(3))
secondMatch := rawSecondMatch.(*ast.SSHMatchBlock)
if !(indexes.Tags["myuser"].Start.Line == secondMatch.Start.Line) {
t.Errorf("Expected second tag to be 'myuser', but got %v", indexes.Tags)
}
}