Documentation
¶
Index ¶
- Constants
- func ControlClose(n Node) string
- func ControlOpen(n Node) (string, bool)
- func ErrorAt(filename, source string, localOffset, baseOffset int, message string) error
- func ErrorAtPosition(filename, source string, localOffset, baseOffset int, basePos Position, ...) error
- func ExprString(e Expr) string
- func PrintModule(module *Module, roots []RootPrinter, options PrintOptions) (string, error)
- func TypeRefString(t TypeRef) string
- type Annotation
- type AnnotationArg
- type AwaitBinding
- type AwaitNode
- type BinaryExpr
- type BodyContext
- func (c *BodyContext) ErrorAt(offset int, message string) error
- func (c *BodyContext) Filename() string
- func (c *BodyContext) Offset() int
- func (c *BodyContext) ParseEmbedded(fragment Embedded, context string) (Node, *Terminator, error)
- func (c *BodyContext) Position(offset int) Position
- func (c *BodyContext) SetOffset(offset int)
- func (c *BodyContext) Source() string
- type BodyPrinter
- type CallExpr
- type Comment
- type ConditionalExpr
- type DeclComment
- type DeclFormatter
- type Declaration
- type Embedded
- type EnumDecl
- type EnumMember
- type Expr
- type ExpressionNode
- type ExternalDecl
- type Field
- type ForNode
- type FormatParser
- type IdentifierExpr
- type IfNode
- type ImportDecl
- type IndexExpr
- type LiteralExpr
- type MemberExpr
- type Module
- type NameRule
- type Node
- type PackageDecl
- type Parameter
- type ParseError
- type Position
- type PrintOptions
- type Printer
- func (p *Printer) AtLineStart() bool
- func (p *Printer) Blank()
- func (p *Printer) Column() int
- func (p *Printer) Dedent()
- func (p *Printer) Depth() int
- func (p *Printer) Indent()
- func (p *Printer) Line()
- func (p *Printer) Options() PrintOptions
- func (p *Printer) Raw() string
- func (p *Printer) String() string
- func (p *Printer) Width() int
- func (p *Printer) Write(text string)
- func (p *Printer) WriteRaw(text string)
- type RootDeclaration
- type RootPrinter
- type TemplateDecl
- type Terminator
- type TerminatorKind
- type TypeDecl
- type TypeRef
- type UnaryExpr
Constants ¶
const DefaultIndent = " "
DefaultIndent is two spaces rather than a tab, because inside an HTML body the indentation is character data and a tab renders differently there.
const DefaultWidth = 100
DefaultWidth is the soft line width every layout pass aims at. It is soft because a construct that cannot break without changing meaning stays long.
Variables ¶
This section is empty.
Functions ¶
func ControlClose ¶ added in v0.3.1
ControlClose renders the closing marker of a shared control node.
func ControlOpen ¶ added in v0.3.1
ControlOpen renders the opening marker of a shared control node, without the braces the format owns. It reports false for a node that is not a control node.
func ErrorAtPosition ¶
func ErrorAtPosition(filename, source string, localOffset, baseOffset int, basePos Position, message string) error
ErrorAtPosition constructs a diagnostic for a source fragment while keeping its file-global byte offset and line/column position.
func ExprString ¶ added in v0.3.1
ExprString renders an expression back to source. Parentheses are reinserted from precedence rather than remembered, so a redundant pair the author wrote is dropped and a necessary one is never lost.
func PrintModule ¶ added in v0.3.1
func PrintModule(module *Module, roots []RootPrinter, options PrintOptions) (string, error)
PrintModule prints a whole module: the shared declaration part here, and each declaration body through the format printer registered for its kind.
func TypeRefString ¶ added in v0.3.1
TypeRefString renders a type expression. The AST does not distinguish the [T] and T[] spellings of an array, so both print as T[].
Types ¶
type Annotation ¶ added in v0.1.16
type Annotation struct {
Pos Position `json:"pos"`
Name string `json:"name"`
Args []AnnotationArg `json:"args,omitempty"`
}
Annotation is one `@name(key: "value")` line attached to the declaration below it. The shared parser owns the grammar; each output format decides which names it accepts, so an unknown name is a generation error rather than a silently ignored line.
func (Annotation) Argument ¶ added in v0.1.16
func (a Annotation) Argument(name string) (AnnotationArg, bool)
Argument returns the value of a named annotation argument.
type AnnotationArg ¶ added in v0.1.16
type AwaitBinding ¶ added in v0.1.16
type AwaitBinding struct {
Pos Position `json:"pos"`
Name string `json:"name"`
Call Expr `json:"call"`
}
AwaitBinding names one asynchronous call whose result the primary subtree reads.
type AwaitNode ¶ added in v0.1.16
type AwaitNode struct {
Kind string `json:"kind"`
Pos Position `json:"pos"`
Context string `json:"context"`
Bindings []AwaitBinding `json:"bindings"`
Primary []Node `json:"primary"`
Fallback []Node `json:"fallback"`
// HasRecover distinguishes a declared but empty recover subtree from an
// omitted one, which keeps the committed fallback instead.
HasRecover bool `json:"hasRecover,omitempty"`
Recover []Node `json:"recover,omitempty"`
ErrorName string `json:"errorName,omitempty"`
ErrorPos Position `json:"errorPos,omitempty"`
}
AwaitNode is one asynchronous boundary. Its bindings run concurrently; the primary subtree reads them, the fallback subtree is emitted while they are pending, and the optional recover subtree replaces the fallback on failure.
How many times the boundary renders is a property of what its bindings name, not of the clause: a binding on a settle-once source produces one render, and a binding on a live source produces one per delivery. The clause says which values the subtree waits for, and the declarations say how those values arrive, so nothing here has to be repeated at the wait site.
type BinaryExpr ¶
type BodyContext ¶
type BodyContext struct {
// contains filtered or unexported fields
}
BodyContext is the shared cursor and control orchestrator for one declaration body. Format parsers must use it instead of owning an independent cursor.
func (*BodyContext) Filename ¶
func (c *BodyContext) Filename() string
func (*BodyContext) Offset ¶
func (c *BodyContext) Offset() int
func (*BodyContext) ParseEmbedded ¶
func (c *BodyContext) ParseEmbedded(fragment Embedded, context string) (Node, *Terminator, error)
ParseEmbedded parses one fragment after the active format parser has found its boundaries. It returns either a shared node or a control terminator.
func (*BodyContext) Position ¶
func (c *BodyContext) Position(offset int) Position
func (*BodyContext) SetOffset ¶
func (c *BodyContext) SetOffset(offset int)
func (*BodyContext) Source ¶
func (c *BodyContext) Source() string
type BodyPrinter ¶ added in v0.3.1
type BodyPrinter interface {
PrintBody(p *Printer, decl *TemplateDecl) error
}
BodyPrinter lays out one declaration body, from just after the opening brace to just before the closing one. It is the printing half of FormatParser: a format that can be parsed can be printed.
The body printer owns its own indentation and the line breaks at both braces, because whether a body may open on its own line is a property of the format: SQL whitespace is insignificant and HTML whitespace is content.
type Comment ¶ added in v0.3.1
type Comment struct {
Pos Position `json:"pos"`
// Text is the comment including its own delimiters, so a printer never has
// to reconstruct whether it was a line or a block comment.
Text string `json:"text"`
// Block reports a /* */ comment.
Block bool `json:"block,omitempty"`
// Trailing reports a comment that began on a line which already had code on
// it, which is what decides whether a printer keeps it on that line.
Trailing bool `json:"trailing,omitempty"`
// BlankBefore reports a blank line between the previous content and this
// comment, so a deliberately detached comment stays detached.
BlankBefore bool `json:"blankBefore,omitempty"`
// contains filtered or unexported fields
}
Comment is one comment read from the declaration part of a source file. The parser keeps it because a formatter that drops comments is a formatter nobody may run; every compiler stage ignores it.
func CommentsBefore ¶ added in v0.3.1
CommentsBefore returns the module comments positioned before pos, and the remainder. A printer walks its declarations in order and flushes what belongs above each one, which is why attachment needs no separate pass.
type ConditionalExpr ¶
type DeclComment ¶ added in v0.3.6
type DeclComment struct {
Line int
Text string
Trailing bool
BlankBefore bool
// contains filtered or unexported fields
}
DeclComment is one comment kept for requirement:template-comment-retention.
func ScanDeclComments ¶ added in v0.3.6
func ScanDeclComments(source string) []DeclComment
ScanDeclComments collects every comment with the line it sits on.
It scans the raw source rather than the token stream, so a comment survives a grammar that discards it. Only "//" comments exist in these languages.
type DeclFormatter ¶ added in v0.3.6
type DeclFormatter struct {
P *Printer
// contains filtered or unexported fields
}
DeclFormatter places scanned comments around whatever a grammar's own formatter writes. It owns the blank lines between constructs, so a comment stays attached to what it documents.
func NewDeclFormatter ¶ added in v0.3.6
func NewDeclFormatter(p *Printer, comments []DeclComment) *DeclFormatter
NewDeclFormatter starts a formatter over one source's comments.
func (*DeclFormatter) FlushBefore ¶ added in v0.3.6
func (f *DeclFormatter) FlushBefore(line int)
FlushBefore writes the standalone comments that stood above the given line.
func (*DeclFormatter) FlushRemaining ¶ added in v0.3.6
func (f *DeclFormatter) FlushRemaining()
FlushRemaining writes the comments that stood after every construct, so a trailing note at the end of a file is not dropped.
func (*DeclFormatter) FlushTrailing ¶ added in v0.3.6
func (f *DeclFormatter) FlushTrailing(line int)
FlushTrailing writes the comment that ended the given line, if any.
func (*DeclFormatter) MarkWrote ¶ added in v0.3.6
func (f *DeclFormatter) MarkWrote()
MarkWrote records that the grammar's own formatter wrote something.
func (*DeclFormatter) SeparateFor ¶ added in v0.3.6
func (f *DeclFormatter) SeparateFor(line int)
SeparateFor opens the blank line above a construct, unless a comment sits directly on the line above it.
func (*DeclFormatter) Wrote ¶ added in v0.3.6
func (f *DeclFormatter) Wrote() bool
Wrote reports whether anything has been written yet, which is what decides whether a separator is wanted.
type Declaration ¶
type Declaration interface {
// contains filtered or unexported methods
}
Declaration is implemented by all root declarations.
type Embedded ¶
Embedded is one brace-delimited template fragment discovered by a format parser. Offsets are file-global byte offsets.
type EnumDecl ¶
type EnumDecl struct {
Kind string `json:"kind"`
Pos Position `json:"pos"`
Name string `json:"name"`
Members []EnumMember `json:"members"`
}
type EnumMember ¶
type Expr ¶
type Expr interface {
// contains filtered or unexported methods
}
Expr is the shared expression AST embedded by every output format.
func ParseExpression ¶
ParseExpression parses a complete shared template expression.
type ExpressionNode ¶
type ExpressionNode struct {
Kind string `json:"kind"`
Pos Position `json:"pos"`
Context string `json:"context"`
Expression Expr `json:"expression"`
}
func (*ExpressionNode) NodeType ¶
func (n *ExpressionNode) NodeType() string
type ExternalDecl ¶
type ExternalDecl struct {
Kind string `json:"kind"`
Pos Position `json:"pos"`
Name string `json:"name"`
// Async marks a function that runs concurrently and may fail. It is a
// keyword rather than an annotation because it changes the Go signature the
// package must provide.
Async bool `json:"async,omitempty"`
// Live marks a function that yields many values over time rather than
// settling once. It is a keyword for the same reason Async is: the Go
// signature becomes an iter.Seq2 over the result type, with a leading
// context that is mandatory rather than optional, because an endless source
// has to be stoppable.
Live bool `json:"live,omitempty"`
Parameters []Parameter `json:"parameters,omitempty"`
Result TypeRef `json:"result"`
}
type ForNode ¶
type FormatParser ¶
type FormatParser interface {
ParseBody(*BodyContext, string) ([]Node, *Terminator, error)
}
FormatParser owns format tokenization and discovers embedded template boundaries. The shared BodyContext parses those boundaries and recursively calls the same format parser for control bodies.
type IdentifierExpr ¶
type IfNode ¶
type ImportDecl ¶
type LiteralExpr ¶
type MemberExpr ¶
type Module ¶
type Module struct {
Pos Position `json:"pos"`
Package *PackageDecl `json:"package,omitempty"`
Imports []ImportDecl `json:"imports,omitempty"`
Declarations []Declaration `json:"declarations"`
// Comments holds every comment in the declaration part of the file, in
// source order. They are attached by position rather than to nodes, because
// a printer walks declarations in order anyway and node-by-node plumbing
// would touch every declaration type for no extra information.
Comments []Comment `json:"comments,omitempty"`
}
Module is the format-neutral root of a template source file.
func ParseModule ¶
func ParseModule(filename, source string, roots []RootDeclaration) (*Module, error)
ParseModule parses standard declarations plus the registered format roots.
type NameRule ¶ added in v0.3.1
type NameRule struct {
// PascalCase requires an uppercase initial, exported or not. HTML sets it
// because in markup an element whose tag name starts uppercase is the
// component-call syntax: a lowercase component could never be called, and
// would collide with a standard element.
PascalCase bool
// ExportedNameIsGo says the public generated identifier is the declaration
// name itself, so an exported declaration needs an exported name. A format
// that composes its public name instead leaves this off.
ExportedNameIsGo bool
// PrivateNameIsGo says the private generated identifier is also the name
// itself, so an unexported declaration needs an unexported name. A format
// that prefixes its private name leaves this off, and may then keep an
// uppercase name on a private declaration.
PrivateNameIsGo bool
}
NameRule is the per-format declaration name policy of decision:declaration-name-policy. Each field states a fact about what the format's emitter does with the name, so the constraint is derived from the generated code rather than asserted as a convention.
type Node ¶
type Node interface {
NodeType() string
}
Node is a body AST node produced either by the shared parser or a registered format parser. Type IDs are namespaced as <language>:<node-type>.
type PackageDecl ¶
type ParseError ¶
ParseError reports a stable source location for syntax diagnostics.
func (*ParseError) Error ¶
func (e *ParseError) Error() string
type Position ¶
Position is a one-based source position. Offset is intentionally not part of the serialized AST; parsers use offsets internally while later compiler stages report the stable line and column pair.
type PrintOptions ¶ added in v0.3.1
type PrintOptions struct {
// Width is the soft line width; zero uses DefaultWidth.
Width int
// Indent is one indentation level; empty uses DefaultIndent.
Indent string
// PreserveWhitespace mirrors the generator option of the same name. With it
// set, static whitespace is no longer collapsed at generation time, so an
// HTML layout pass may only touch positions the HTML parser discards.
PreserveWhitespace bool
}
PrintOptions configures the shared printer and every format printer.
type Printer ¶ added in v0.3.1
type Printer struct {
// contains filtered or unexported fields
}
Printer is the shared output buffer with indentation state. Format printers write through it so one file has one notion of a line and a level.
func NewPrinter ¶ added in v0.3.1
func NewPrinter(options PrintOptions) *Printer
NewPrinter creates a standalone printer, for a format printer under test.
func (*Printer) AtLineStart ¶ added in v0.3.1
AtLineStart reports that nothing has been written on the current line, which is when a layout drops the leading space a construct carries.
func (*Printer) Blank ¶ added in v0.3.1
func (p *Printer) Blank()
Blank ends the current line and leaves one empty line after it.
func (*Printer) Column ¶ added in v0.3.1
Column reports how many bytes are already on the current line, for a layout deciding whether the next construct still fits the width.
func (*Printer) Line ¶ added in v0.3.1
func (p *Printer) Line()
Line ends the current line. The newline and the next line's indentation are written lazily, so a line that turns out to be empty leaves no trailing spaces behind.
func (*Printer) Options ¶ added in v0.3.1
func (p *Printer) Options() PrintOptions
Options returns the active options.
func (*Printer) Raw ¶ added in v0.3.1
Raw returns the buffer as written, without the trailing-whitespace cleanup String applies. An inline measurement needs it, because a trailing space it produced is a space the layout has to keep.
func (*Printer) String ¶ added in v0.3.1
String returns the printed text with exactly one trailing newline.
type RootDeclaration ¶
type RootDeclaration struct {
Keyword string
NodeType string
OutputPrefix string
Context string
Parser FormatParser
// Names states what this format needs from a declaration name. The zero
// value asks for nothing, which is what a format wants when every generated
// identifier is composed rather than copied.
Names NameRule
}
RootDeclaration registers one format-specific declaration with the shared root driver.
type RootPrinter ¶ added in v0.3.1
type RootPrinter struct {
// Kind is the TemplateDecl.Kind the format parser assigned.
Kind string
// Keyword is the root declaration keyword to print.
Keyword string
Printer BodyPrinter
}
RootPrinter registers one format's body printer against the declaration kind its parser produced.
type TemplateDecl ¶
type TemplateDecl struct {
Kind string `json:"kind"`
Pos Position `json:"pos"`
Exported bool `json:"exported"`
Annotations []Annotation `json:"annotations,omitempty"`
Name string `json:"name"`
Parameters []Parameter `json:"parameters,omitempty"`
Output TypeRef `json:"output"`
Body any `json:"body"`
}
func (*TemplateDecl) Annotation ¶ added in v0.1.16
func (d *TemplateDecl) Annotation(name string) (Annotation, bool)
Annotation returns the declaration's annotation with the given name.
type Terminator ¶
type Terminator struct {
Kind TerminatorKind
Pos Position
Header string
HeaderOffset int
ContentOffset int
}
Terminator is discovered by a format parser and interpreted by the shared control parser.
type TerminatorKind ¶
type TerminatorKind string
const ( TerminatorRoot TerminatorKind = "root" TerminatorElse TerminatorKind = "else" TerminatorElseIf TerminatorKind = "else-if" TerminatorEndIf TerminatorKind = "end-if" TerminatorEndFor TerminatorKind = "end-for" TerminatorFallback TerminatorKind = "fallback" TerminatorRecover TerminatorKind = "recover" TerminatorEndAwait TerminatorKind = "end-await" )
type TypeRef ¶
type TypeRef struct {
Pos Position `json:"pos"`
Name string `json:"name"`
Arguments []TypeRef `json:"arguments,omitempty"`
Array bool `json:"array,omitempty"`
Optional bool `json:"optional,omitempty"`
// Async marks a value the caller starts and the template waits for in an
// await clause. It modifies the whole type expression, so `async Order[]`
// is one pending array rather than an array of pending values.
Async bool `json:"async,omitempty"`
}
TypeRef represents named, generic, array, optional, and asynchronous types without binding them to Go types during parsing.