From fdb005a75d9591c64f8fe0cb33347f4c35053764 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Mon, 14 Oct 2024 12:04:02 +0200 Subject: [PATCH 01/21] feat(ssh_config): Add include functionality --- .../handlers/ssh_config/analyzer/analyzer.go | 19 +++ .../handlers/ssh_config/analyzer/include.go | 110 ++++++++++++++++++ server/handlers/ssh_config/indexes/indexes.go | 6 +- .../ssh_config/indexes/indexes_handlers.go | 2 +- .../ssh_config/indexes/indexes_test.go | 45 +++++++ .../{handlers.go => indexes_handlers.go} | 0 6 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 server/handlers/ssh_config/analyzer/include.go rename server/handlers/sshd_config/indexes/{handlers.go => indexes_handlers.go} (100%) diff --git a/server/handlers/ssh_config/analyzer/analyzer.go b/server/handlers/ssh_config/analyzer/analyzer.go index 48adb23..31b8d2f 100644 --- a/server/handlers/ssh_config/analyzer/analyzer.go +++ b/server/handlers/ssh_config/analyzer/analyzer.go @@ -35,6 +35,25 @@ func Analyze( d.Indexes = i + analyzeIncludeValues(ctx) + + if len(ctx.diagnostics) == 0 { + for _, include := range d.Indexes.Includes { + for _, value := range include.Values { + for _, path := range value.Paths { + _, err := parseFile(string(path)) + + if err != nil { + ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{ + Range: value.LocationRange.ToLSPRange(), + Message: err.Error(), + }) + } + } + } + } + } + analyzeValuesAreValid(ctx) analyzeIgnoreUnknownHasNoUnnecessary(ctx) analyzeDependents(ctx) diff --git a/server/handlers/ssh_config/analyzer/include.go b/server/handlers/ssh_config/analyzer/include.go new file mode 100644 index 0000000..48c70f7 --- /dev/null +++ b/server/handlers/ssh_config/analyzer/include.go @@ -0,0 +1,110 @@ +package analyzer + +import ( + "config-lsp/common" + sshconfig "config-lsp/handlers/ssh_config" + "config-lsp/handlers/ssh_config/ast" + "config-lsp/handlers/ssh_config/indexes" + "config-lsp/utils" + "errors" + "fmt" + "os" + "path" + "path/filepath" + "regexp" + + protocol "github.com/tliron/glsp/protocol_3_16" +) + +var whitespacePattern = regexp.MustCompile(`\S+`) + +func analyzeIncludeValues( + ctx *analyzerContext, +) { + for _, include := range ctx.document.Indexes.Includes { + for _, value := range include.Values { + validPaths, err := createIncludePaths(value.Value) + + if err != nil { + ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{ + Range: value.LocationRange.ToLSPRange(), + Message: err.Error(), + Severity: &common.SeverityError, + }) + } else { + value.Paths = validPaths + } + } + } +} + +func createIncludePaths( + suggestedPath string, +) ([]indexes.ValidPath, error) { + var absolutePath string + + if path.IsAbs(suggestedPath) { + absolutePath = suggestedPath + } else { + homeFolder, err := os.UserHomeDir() + + if err != nil { + return nil, errors.New(fmt.Sprintf("Could not find home folder (error: %s)", err)) + } + + absolutePath = path.Join(homeFolder, ".ssh", suggestedPath) + } + + files, err := filepath.Glob(absolutePath) + + if err != nil { + return nil, errors.New(fmt.Sprintf("Could not find file %s (error: %s)", absolutePath, err)) + } + + if len(files) == 0 { + return nil, errors.New(fmt.Sprintf("Could not find file %s", absolutePath)) + } + + return utils.Map( + files, + func(file string) indexes.ValidPath { + return indexes.ValidPath(file) + }, + ), nil +} + +func parseFile( + filePath string, +) (*sshconfig.SSHDocument, error) { + if d, ok := sshconfig.DocumentParserMap[filePath]; ok { + return d, nil + } + + c := ast.NewSSHConfig() + + content, err := os.ReadFile(filePath) + + if err != nil { + return nil, err + } + + parseErrors := c.Parse(string(content)) + + if len(parseErrors) > 0 { + return nil, errors.New(fmt.Sprintf("Errors in %s", filePath)) + } + + d := &sshconfig.SSHDocument{ + Config: c, + } + + errs := Analyze(d) + + if len(errs) > 0 { + return nil, errors.New(fmt.Sprintf("Errors in %s", filePath)) + } + + sshconfig.DocumentParserMap[filePath] = d + + return d, nil +} diff --git a/server/handlers/ssh_config/indexes/indexes.go b/server/handlers/ssh_config/indexes/indexes.go index 9d0bf78..37904d0 100644 --- a/server/handlers/ssh_config/indexes/indexes.go +++ b/server/handlers/ssh_config/indexes/indexes.go @@ -44,7 +44,7 @@ type SSHIndexTagInfo struct { type SSHIndexes struct { AllOptionsPerName map[fields.NormalizedOptionName](map[ast.SSHBlock]([]*ast.SSHOption)) - Includes []*SSHIndexIncludeLine + Includes map[uint32]*SSHIndexIncludeLine BlockRanges map[uint32]ast.SSHBlock @@ -57,6 +57,8 @@ type SSHIndexes struct { // This is a map of to