mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 23:15:26 +02:00
141 lines
3.7 KiB
Go
141 lines
3.7 KiB
Go
package analyzer
|
|
|
|
import (
|
|
"config-lsp/common"
|
|
docvalues "config-lsp/doc-values"
|
|
"config-lsp/handlers/sshd_config/fields"
|
|
"config-lsp/handlers/sshd_config/match-parser"
|
|
"config-lsp/utils"
|
|
"fmt"
|
|
"strings"
|
|
|
|
protocol "github.com/tliron/glsp/protocol_3_16"
|
|
)
|
|
|
|
var matchOption = fields.CreateNormalizedName("Match")
|
|
|
|
func analyzeMatchBlocks(
|
|
ctx *analyzerContext,
|
|
) {
|
|
for matchBlock, options := range ctx.document.Indexes.AllOptionsPerName[matchOption] {
|
|
option := options[0]
|
|
// Check if the match block has filled out all fields
|
|
if matchBlock == nil || matchBlock.MatchValue == nil || len(matchBlock.MatchValue.Entries) == 0 {
|
|
ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{
|
|
Range: option.ToLSPRange(),
|
|
Message: "A match expression is required",
|
|
Severity: &common.SeverityError,
|
|
})
|
|
|
|
continue
|
|
}
|
|
|
|
for _, entry := range matchBlock.MatchValue.Entries {
|
|
if entry.Values == nil {
|
|
ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{
|
|
Range: entry.ToLSPRange(),
|
|
Message: fmt.Sprintf("A value for %s is required", entry.Criteria.Type),
|
|
Severity: &common.SeverityError,
|
|
})
|
|
|
|
continue
|
|
}
|
|
|
|
analyzeMatchValuesContainsPositiveValue(ctx, entry.Values)
|
|
|
|
for _, value := range entry.Values.Values {
|
|
analyzeMatchValueNegation(ctx, value)
|
|
analyzeMatchValueIsValid(ctx, value, entry.Criteria.Type)
|
|
}
|
|
}
|
|
|
|
// Check if match blocks are not empty
|
|
if matchBlock.Options.Size() == 0 {
|
|
ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{
|
|
Range: option.ToLSPRange(),
|
|
Message: "This match block is empty",
|
|
Severity: &common.SeverityInformation,
|
|
Tags: []protocol.DiagnosticTag{
|
|
protocol.DiagnosticTagUnnecessary,
|
|
},
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func analyzeMatchValueNegation(
|
|
ctx *analyzerContext,
|
|
value *matchparser.MatchValue,
|
|
) {
|
|
positionsAsList := utils.AllIndexes(value.Value.Raw, "!")
|
|
positions := utils.SliceToMap(positionsAsList, struct{}{})
|
|
|
|
delete(positions, 0)
|
|
|
|
for position := range positions {
|
|
ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{
|
|
Range: common.LocationRange{
|
|
Start: common.Location{
|
|
Line: value.Start.Line,
|
|
Character: uint32(position) + value.Start.Character,
|
|
},
|
|
End: common.Location{
|
|
Line: value.End.Line,
|
|
Character: uint32(position) + value.End.Character,
|
|
},
|
|
}.ToLSPRange(),
|
|
Message: "The negation operator (!) may only occur at the beginning of a value",
|
|
Severity: &common.SeverityError,
|
|
})
|
|
}
|
|
}
|
|
|
|
func analyzeMatchValuesContainsPositiveValue(
|
|
ctx *analyzerContext,
|
|
values *matchparser.MatchValues,
|
|
) {
|
|
if len(values.Values) == 0 {
|
|
return
|
|
}
|
|
|
|
containsPositive := false
|
|
|
|
for _, value := range values.Values {
|
|
if !strings.HasPrefix(value.Value.Value, "!") {
|
|
containsPositive = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !containsPositive {
|
|
ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{
|
|
Range: values.LocationRange.ToLSPRange(),
|
|
Message: "At least one positive value is required. A negated match will never produce a positive result by itself",
|
|
Severity: &common.SeverityError,
|
|
})
|
|
}
|
|
}
|
|
|
|
func analyzeMatchValueIsValid(
|
|
ctx *analyzerContext,
|
|
value *matchparser.MatchValue,
|
|
criteria matchparser.MatchCriteriaType,
|
|
) {
|
|
if value.Value.Raw == "" {
|
|
return
|
|
}
|
|
|
|
docOption := fields.MatchValueFieldMap[criteria]
|
|
invalidValues := docOption.DeprecatedCheckIsValid(value.Value.Raw)
|
|
|
|
for _, invalidValue := range invalidValues {
|
|
err := docvalues.LSPErrorFromInvalidValue(value.Start.Line, *invalidValue).ShiftCharacter(value.Start.Character)
|
|
|
|
ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{
|
|
Range: err.Range.ToLSPRange(),
|
|
Message: err.Err.Error(),
|
|
Severity: &common.SeverityError,
|
|
})
|
|
}
|
|
}
|