mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 23:15:26 +02:00
94 lines
2.3 KiB
Go
94 lines
2.3 KiB
Go
package analyzer
|
|
|
|
import (
|
|
"config-lsp/common"
|
|
sshconfig "config-lsp/handlers/ssh_config"
|
|
"config-lsp/handlers/ssh_config/fields"
|
|
matchparser "config-lsp/handlers/ssh_config/match-parser"
|
|
"config-lsp/utils"
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
func analyzeMatchBlocks(
|
|
d *sshconfig.SSHDocument,
|
|
) []common.LSPError {
|
|
errs := make([]common.LSPError, 0)
|
|
|
|
for _, matchBlock := range d.GetAllMatchBlocks() {
|
|
structureErrs := isMatchStructureValid(matchBlock.MatchValue)
|
|
errs = append(errs, structureErrs...)
|
|
|
|
if len(structureErrs) > 0 {
|
|
continue
|
|
}
|
|
|
|
errs = append(errs, checkMatch(matchBlock.MatchValue)...)
|
|
}
|
|
|
|
return errs
|
|
}
|
|
|
|
func isMatchStructureValid(
|
|
m *matchparser.Match,
|
|
) []common.LSPError {
|
|
errs := make([]common.LSPError, 0)
|
|
|
|
for _, entry := range m.Entries {
|
|
if !utils.KeyExists(fields.MatchSingleOptionCriterias, entry.Criteria.Type) && entry.Value.Value == "" {
|
|
errs = append(errs, common.LSPError{
|
|
Range: entry.LocationRange,
|
|
Err: errors.New(fmt.Sprintf("Argument '%s' requires a value", entry.Criteria.Type)),
|
|
})
|
|
}
|
|
}
|
|
|
|
return errs
|
|
}
|
|
|
|
func checkMatch(
|
|
m *matchparser.Match,
|
|
) []common.LSPError {
|
|
errs := make([]common.LSPError, 0)
|
|
|
|
// Check single options
|
|
allEntries := m.FindEntries("all")
|
|
if len(allEntries) > 1 {
|
|
errs = append(errs, common.LSPError{
|
|
Range: allEntries[1].LocationRange,
|
|
Err: errors.New("'all' may only be used once"),
|
|
})
|
|
}
|
|
|
|
canonicalEntries := m.FindEntries("canonical")
|
|
if len(canonicalEntries) > 1 {
|
|
errs = append(errs, common.LSPError{
|
|
Range: canonicalEntries[1].LocationRange,
|
|
Err: errors.New("'canonical' may only be used once"),
|
|
})
|
|
}
|
|
|
|
finalEntries := m.FindEntries("final")
|
|
if len(finalEntries) > 1 {
|
|
errs = append(errs, common.LSPError{
|
|
Range: finalEntries[1].LocationRange,
|
|
Err: errors.New("'final' may only be used once"),
|
|
})
|
|
}
|
|
|
|
// Check the `all` argument
|
|
if len(allEntries) == 1 {
|
|
allEntry := allEntries[0]
|
|
previousEntry := m.GetPreviousEntry(allEntry)
|
|
|
|
if previousEntry != nil && !utils.KeyExists(fields.MatchAllOptionAllowedPreviousOptions, previousEntry.Criteria.Type) {
|
|
errs = append(errs, common.LSPError{
|
|
Range: allEntry.LocationRange,
|
|
Err: errors.New("'all' should either be the first entry or immediately follow 'final' or 'canonical'"),
|
|
})
|
|
}
|
|
}
|
|
|
|
return errs
|
|
}
|