lint

package
v1.23.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 18, 2026 License: MIT, MIT Imports: 10 Imported by: 0

Documentation

Overview

Package lint reports on ABNF grammar definitions (RFC 5234, with the RFC 7405 char-val extension and the RFC 9110 Section 5.6.1 "#" list operator): on the whitespace and comments that minification removes, on the expressions that simplification shortens, and on the grammar itself.

Findings carry the bytes of the definition they cover, so that they can be reported against the source, and the text that acting on one puts in their place. Sarif renders them as a SARIF 2.1.0 log.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Sarif

func Sarif(reports []*Report) *sarif.Log

Sarif renders reports as a SARIF 2.1.0 log, with every check declared as a rule of the driver and every finding that can be acted on carrying the replacement as a fix.

Types

type Category

type Category string

Category groups the checks by what acting on them achieves.

const (
	// CategoryFormatting covers findings that minification removes. Acting
	// on them leaves the grammar itself untouched.
	CategoryFormatting Category = "formatting"
	// CategorySimplification covers findings that simplification rewrites.
	// Acting on them preserves the matched language, but changes the shape
	// of the paths that parsing produces.
	CategorySimplification Category = "simplification"
	// CategoryQuality covers findings that report on the grammar itself
	// rather than on how it is written.
	CategoryQuality Category = "quality"
)

type Finding

type Finding struct {
	RuleId RuleId
	// Start and End delimit the bytes the finding covers; Start <= End.
	Start, End *Position
	// Message says what is wrong, in one sentence.
	Message string
	// Replacement is the text that the bytes from Start to End should be
	// replaced with to act on the finding. It is empty for a deletion, and
	// nil for a finding the linter cannot act on.
	Replacement *string
}

Finding is one reported occurrence of a check.

func Lint

func Lint(input []byte, options *Options) ([]*Finding, error)

Lint reports on an ABNF grammar definition. Definitions using LF line endings, which RFC 5234 does not allow, are reported and then read as though they used CRLF, so that the rest of the checks still run.

The "#" list operator of RFC 9110 Section 5.6.1 is read as the standard ABNF it expands to, and reported so that minification writing it out does not come as a surprise.

func (*Finding) Fixable

func (finding *Finding) Fixable() bool

Fixable reports whether the linter knows how to act on the finding.

func (*Finding) Rule

func (finding *Finding) Rule() *Rule

Rule returns the check the finding reports on.

type Options

type Options struct {
	// Simplify includes the checks of CategorySimplification, which report
	// expressions that can be written more shortly without changing what
	// they match. They are left out by default because acting on them
	// changes the shape of the paths that parsing produces.
	Simplify bool
	// Roots names the rules the grammar is parsed from. Given them, the
	// linter reports the rules none of them leads to, which are dead;
	// without them it can only report the rules nothing refers to, which
	// every root rule is by definition.
	Roots []string
}

Options holds the settings of a lint run.

type Position

type Position struct {
	// Offset is the zero-based byte offset.
	Offset int
	// Line and Column are one-based, as editors and SARIF count them.
	Line, Column int
}

Position is a location in a grammar definition, counted over the bytes of the definition as given, before any line-ending normalization.

type Report

type Report struct {
	// Uri locates the definition that was linted.
	Uri      string
	Findings []*Finding
}

Report holds the findings of one grammar definition.

type Rule

type Rule struct {
	Id          RuleId
	Category    Category
	Level       sarif.Level
	Description string
}

Rule describes a check the linter performs.

func Rules

func Rules() []*Rule

Rules returns every check the linter performs, in reporting order.

type RuleId

type RuleId string

RuleId identifies a check the linter performs.

const (
	// RuleIdRedundantWhitespace marks whitespace that carries no meaning.
	// RFC 5234 allows it nearly everywhere; only the separator between the
	// repetitions of a concatenation has to stay, and only as one space.
	RuleIdRedundantWhitespace RuleId = "redundant-whitespace"
	// RuleIdRemovableComment marks a comment, which a grammar definition
	// does not need to carry.
	RuleIdRemovableComment RuleId = "removable-comment"
	// RuleIdNonCrlfLineEnding marks a line that does not end with the CRLF
	// that RFC 5234 requires, including a missing final one.
	RuleIdNonCrlfLineEnding RuleId = "non-crlf-line-ending"
	// RuleIdRedundantRepeat marks a repeat that says more than it needs to,
	// such as the "1*1" of "1*1DIGIT" or the leading zero of "0*3DIGIT".
	RuleIdRedundantRepeat RuleId = "redundant-repeat"
	// RuleIdNonCanonicalLiteral marks a literal written in a longer form
	// than it needs: the explicit "%i" of RFC 7405, which is the default,
	// or an uppercase num-val base.
	RuleIdNonCanonicalLiteral RuleId = "non-canonical-literal"
	// RuleIdIncrementalAlternative marks a rule extended with the "=/" of
	// RFC 5234 Section 3.3, which minification folds into the definition
	// the rule was first given.
	RuleIdIncrementalAlternative RuleId = "incremental-alternative"

	// RuleIdRedundantGroup marks a rule holding parentheses that can be
	// dropped without changing what it matches.
	RuleIdRedundantGroup RuleId = "redundant-group"
	// RuleIdVerboseNumVal marks a rule holding a num-val that a shorter
	// char-val expresses just as exactly.
	RuleIdVerboseNumVal RuleId = "verbose-num-val"
	// RuleIdJoinableLiterals marks a rule holding adjacent literals that a
	// single literal can express.
	RuleIdJoinableLiterals RuleId = "joinable-literals"

	// RuleIdUnmatchableProseVal marks a prose-val, which is a description
	// for a human reader and matches no input at all.
	RuleIdUnmatchableProseVal RuleId = "unmatchable-prose-val"
	// RuleIdDuplicateAlternative marks an alternation offering the same
	// alternative more than once, where the later ones are dead.
	RuleIdDuplicateAlternative RuleId = "duplicate-alternative"
	// RuleIdInconsistentRulenameCase marks a reference that spells a rule
	// name with a different case than the rule was defined with. Rule names
	// are case-insensitive, so the two mean the same rule.
	RuleIdInconsistentRulenameCase RuleId = "inconsistent-rulename-case"
	// RuleIdListExtension marks a rule using the "#" list operator of
	// RFC 9110 Section 5.6.1. pkg/abnf reads it, but it belongs to the HTTP
	// specifications rather than to RFC 5234, so a definition holding one is
	// not portable to a parser that reads RFC 5234 alone.
	RuleIdListExtension RuleId = "list-extension"
	// RuleIdUnreferencedRule marks a rule that no other rule refers to.
	// That is expected of the rule a grammar is parsed from, and suspicious
	// of any other. Naming the rules a grammar is parsed from, through
	// Options.Roots, answers the question far better: see
	// RuleIdUnreachableRule.
	RuleIdUnreferencedRule RuleId = "unreferenced-rule"
	// RuleIdUnreachableRule marks a rule that no rule a grammar is parsed
	// from leads to, directly or through others. Such a rule is dead: no
	// input can ever reach it.
	RuleIdUnreachableRule RuleId = "unreachable-rule"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL