Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions internal/grammar/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

core "typefox.dev/fastbelt"
"typefox.dev/fastbelt/util/collections"
"typefox.dev/fastbelt/util/service"
)

const (
Expand Down Expand Up @@ -63,7 +64,7 @@ var reservedFieldNames = map[string]string{
// GrammarImpl.Validate checks grammar-level constraints:
// - Rule names must be unique within the grammar.
// - Interface names must be unique within the grammar.
func (g *GrammarImpl) Validate(_ context.Context, _ string, accept core.ValidationAcceptor) {
func (g *GrammarImpl) Validate(_ context.Context, _ *service.Container, _ string, accept core.ValidationAcceptor) {
checkUniqueRuleNames(g, accept)
checkUniqueInterfaceNames(g, accept)
}
Expand Down Expand Up @@ -129,7 +130,7 @@ func checkUniqueInterfaceNames(g Grammar, accept core.ValidationAcceptor) {

// TokenImpl.Validate checks terminal rule constraints:
// - The regular expression should not match the empty string.
func (t *TokenImpl) Validate(_ context.Context, _ string, accept core.ValidationAcceptor) {
func (t *TokenImpl) Validate(_ context.Context, _ *service.Container, _ string, accept core.ValidationAcceptor) {
checkEmptyTerminalRule(t, accept)
}

Expand Down Expand Up @@ -162,7 +163,7 @@ func checkEmptyTerminalRule(t Token, accept core.ValidationAcceptor) {
// - Keywords cannot be empty.
// - Keywords cannot consist only of whitespace.
// - Keywords should not contain whitespace characters (warning).
func (k *KeywordImpl) Validate(_ context.Context, _ string, accept core.ValidationAcceptor) {
func (k *KeywordImpl) Validate(_ context.Context, _ *service.Container, _ string, accept core.ValidationAcceptor) {
checkKeyword(k, accept)
}

Expand Down Expand Up @@ -198,7 +199,7 @@ func checkKeyword(k Keyword, accept core.ValidationAcceptor) {
}
}

func (rule *ParserRuleImpl) Validate(ctx context.Context, _ string, accept core.ValidationAcceptor) {
func (rule *ParserRuleImpl) Validate(ctx context.Context, _ *service.Container, _ string, accept core.ValidationAcceptor) {
checkRuleReturnType(rule, ctx, accept)
}

Expand All @@ -224,7 +225,7 @@ func checkRuleReturnType(rule ParserRule, _ context.Context, accept core.Validat
}
}

func (i *InterfaceImpl) Validate(ctx context.Context, _ string, accept core.ValidationAcceptor) {
func (i *InterfaceImpl) Validate(ctx context.Context, _ *service.Container, _ string, accept core.ValidationAcceptor) {
checkInterfaceExtends(i, ctx, accept)
checkInterfaceFieldNames(i, ctx, accept)
checkInterfaceFieldTypes(i, accept)
Expand Down Expand Up @@ -443,7 +444,7 @@ func appearsInExtends(target Interface, current Interface, ctx context.Context,
return false
}

func (r *RuleCallImpl) Validate(ctx context.Context, _ string, accept core.ValidationAcceptor) {
func (r *RuleCallImpl) Validate(ctx context.Context, _ *service.Container, _ string, accept core.ValidationAcceptor) {
assignment := core.ContainerOfType[Assignment](r)
if assignment == nil {
// Some validations only apply to unassigned rule calls
Expand Down Expand Up @@ -518,7 +519,7 @@ func checkRuleCallPosition(call RuleCall, _ context.Context, accept core.Validat
}
}

func (a *ActionImpl) Validate(ctx context.Context, _ string, accept core.ValidationAcceptor) {
func (a *ActionImpl) Validate(ctx context.Context, _ *service.Container, _ string, accept core.ValidationAcceptor) {
checkActionAssignmentType(a, ctx, accept)
checkActionPropertyType(a, ctx, accept)
}
Expand Down Expand Up @@ -598,7 +599,7 @@ func checkActionPropertyType(a Action, ctx context.Context, accept core.Validati
}
}

func (a *AssignmentImpl) Validate(ctx context.Context, _ string, accept core.ValidationAcceptor) {
func (a *AssignmentImpl) Validate(ctx context.Context, _ *service.Container, _ string, accept core.ValidationAcceptor) {
checkAssignmentType(a, ctx, accept)
}

Expand Down Expand Up @@ -790,7 +791,7 @@ func doInterfaceIsAssignableTo(source Interface, target Interface, visited colle
return false
}

func (tg *TokenGroupImpl) Validate(_ context.Context, _ string, accept core.ValidationAcceptor) {
func (tg *TokenGroupImpl) Validate(_ context.Context, _ *service.Container, _ string, accept core.ValidationAcceptor) {
checkRecursiveTokenGroup(tg, accept)
checkInvalidTokensInGroup(tg, accept)
}
Expand Down Expand Up @@ -867,7 +868,7 @@ func checkInvalidTokensInGroup(tg TokenGroup, accept core.ValidationAcceptor) {
// - Operators must be keywords, tokens, or token groups (not hidden or
// comment tokens), and no operator may appear in two precedence groups.
// - The name of the generated operator token group must be available.
func (rule *InfixRuleImpl) Validate(ctx context.Context, _ string, accept core.ValidationAcceptor) {
func (rule *InfixRuleImpl) Validate(ctx context.Context, _ *service.Container, _ string, accept core.ValidationAcceptor) {
checkInfixNodeType(rule, ctx, accept)
checkInfixOperandRule(rule, ctx, accept)
checkInfixOperators(rule, ctx, accept)
Expand Down Expand Up @@ -1139,7 +1140,7 @@ func doFindInterfaceField(iface Interface, name string, ctx context.Context, vis
return nil
}

func (cr *CrossRefImpl) Validate(ctx context.Context, _ string, accept core.ValidationAcceptor) {
func (cr *CrossRefImpl) Validate(ctx context.Context, _ *service.Container, _ string, accept core.ValidationAcceptor) {
checkCrossRefHasTerminal(cr, ctx, accept)
checkCrossRefToken(cr, ctx, accept)
}
Expand Down
9 changes: 7 additions & 2 deletions validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@

package fastbelt

import "context"
import (
"context"

"typefox.dev/fastbelt/util/service"
)

// DiagnosticSeverity mirrors LSP DiagnosticSeverity values.
type DiagnosticSeverity int
Expand Down Expand Up @@ -76,9 +80,10 @@ type ValidationAcceptor func(diagnostic *Diagnostic)
// Validator can be implemented by AST node Impl structs to provide custom validation checks.
type Validator interface {
// Validate performs validation on the receiver node.
// sc is the service container of the running language server.
// The level parameter identifies when validation runs (e.g. "on-type", "on-save").
// The accept callback is used to collect diagnostics.
Validate(ctx context.Context, level string, accept ValidationAcceptor)
Validate(ctx context.Context, sc *service.Container, level string, accept ValidationAcceptor)
}

// DiagnosticOption configures optional fields of a [Diagnostic] created by [NewDiagnostic].
Expand Down
2 changes: 1 addition & 1 deletion workspace/document_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (s *DefaultDocumentValidator) Validate(ctx context.Context, doc *core.Docum
break
}
if validator, ok := node.(core.Validator); ok {
validator.Validate(ctx, level, accept)
validator.Validate(ctx, s.sc, level, accept)
}
}
return diagnostics
Expand Down