reports

package
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Sep 13, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

README

reports

What a templates repository says about itself: the documentation of its templates, and the audit of what it holds.

import "github.com/go-openapi/codegen/templates-repo/reports"

A repository executes templates. Describing them is a separate job, and the types that describe them outnumber the ones that run them. They live here so that a program which only renders templates imports none of it.

Documentation

Repository.Documentation returns a Documentation, grouped by asset so it follows the tree an author edits, and ordered throughout so the same templates produce the same document every time.

Each Template in it carries the comments documenting it, the data paths it reads, the functions it calls, and the templates it calls with the data passed to each. Transitive holds the same once the templates it calls are folded in, with their paths rebased onto the data handed to them.

Dump renders a documentation as markdown:

documentation, err := repository.Documentation()
if err != nil {
    return err
}

err = reports.Dump(w, documentation)

WithTemplate lays it out otherwise, and WithFuncMap adds functions such a layout may call. Walk the Documentation directly for anything a text template cannot produce.

err = reports.Dump(w, documentation, reports.WithTemplate(myLayout))

Repository.Dump is the same thing in one call, for the common case of rendering markdown once.

Audit

Repository.Audit returns an Audit, listing what compiles and runs but still deserves a look:

Overridden templates more than one asset declared, and which definition stands
Unused templates no other template calls
Empty templates that render nothing
Dynamic templates calling a function carried by their data
UnusedFuncs funcmap entries no template calls

None of it is an error. The repository rejects what it cannot resolve when it is built, so everything reported here already works. A function no funcmap provides never reaches the audit either: templates are parsed against the funcmap, so that fails the build instead.

Unused and UnusedFuncs are observations rather than verdicts. Nothing calls a generator's entry points either, and a general-purpose funcmap is mostly unused by design. Scope the repository to its roots and Unused answers for itself.

Errors

Everything this package reports matches ErrReport and wraps its cause, so a caller may match the underlying template error with errors.Is and errors.As all the same.

Tests

go test ./...
golangci-lint run

Documentation

Overview

Package reports holds what a templates repository says about itself.

A repository executes templates. Describing them is a separate job, and the types that describe them are the bulk of what a caller would otherwise import without ever executing anything. They live here so that a program rendering templates imports none of it.

Usage

github.com/go-openapi/codegen/templates-repo.Repository builds these values, and this package declares them and renders them:

documentation, err := repository.Documentation()
if err != nil {
	return err
}

err = reports.Dump(w, documentation)

Dump writes markdown by default. Pass WithTemplate to lay a document out otherwise, or walk the Documentation and render it however a text template cannot.

What the reports cover

Documentation describes the templates a repository holds: the comments on each one, the data paths it reads, the functions it calls, and the templates it calls with the data handed to each. It is grouped by asset, so it follows the tree an author edits, and it is ordered throughout, so a document generated twice from the same templates is the same document twice.

Audit lists what compiles and runs but still deserves a look: a template two assets declared, a template nothing calls, a template that renders nothing, a template calling a function carried by its data, and a func map entry no template calls.

Index

Constants

View Source
const ErrReport reportError = "templates report"

ErrReport is matched by every error this package reports.

Errors wrap the cause as well, so a caller may match on a template parse error with errors.Is and errors.As all the same.

Variables

This section is empty.

Functions

func Dump

func Dump(w io.Writer, documentation Documentation, opts ...DumpOption) error

Dump writes a documentation, as markdown by default.

Use WithTemplate to lay the document out otherwise, or walk the Documentation directly for a format a text template cannot produce.

Example:

documentation, err := repository.Documentation()
if err != nil {
	return err
}

err = reports.Dump(w, documentation)

Types

type Asset

type Asset struct {
	// Path is the asset path, as mounted.
	Path string

	// Templates holds the templates the asset declares, the one named after the asset first,
	// then those declared by a "define" statement, ordered by name.
	Templates []Template
}

Asset is the documentation of a single template asset.

type Audit

type Audit struct {
	// Overridden lists the templates that more than one asset declared, with the definition that
	// stands and the ones it replaced.
	Overridden []Override

	// Unused lists the templates nothing else calls, ordered by name.
	//
	// A repository scoped with [WithRoots] leaves its roots out of this, since a run starts there.
	// One that keeps every template it read cannot tell an entry point from a dead template, so
	// its entry points are listed too.
	Unused []string

	// Empty lists the templates that render nothing, ordered by name. An asset holding only
	// "define" statements declares one, under its own name.
	Empty []string

	// Dynamic lists the templates invoking a function held by their data, with the "call" builtin.
	//
	// Nothing settles such a call before the template runs, so what it reaches is unknown to the
	// repository and to the documentation alike.
	Dynamic []string

	// UnusedFuncs lists the func map entries no template calls, ordered by name.
	UnusedFuncs []string
}

Audit lists what a repository holds that deserves a second look.

None of it is an error. [New] rejects what it cannot resolve, so everything here compiles and runs. These are the things a set of templates gets wrong quietly: a macro replaced by accident, a template nobody calls any more, a name that renders nothing.

A function no template can resolve is not among them. Templates are parsed against the func map, so calling a function nothing provides fails the build.

type Dependency

type Dependency struct {
	// Name is the template called.
	Name string

	// Data is the path handed to it, rooted like the paths of the calling template.
	//
	// It is "." when the caller hands over its own data, and empty when the analysis could not
	// place it.
	Data string

	// Folded is the number of paths the called template reads, itself and through its own calls.
	//
	// It locates the weight of a caller's own fold, so a reader can see which of its calls to
	// follow first.
	Folded int
}

Dependency is a template called by another one.

type Documentation

type Documentation struct {
	// Assets holds one entry per asset that declares a template, ordered by path.
	Assets []Asset
}

Documentation is the structure of a repository, as far as a reader of its templates cares.

It is grouped by asset rather than by template, so that it follows the tree its author edits, and it is ordered, so that a document generated from it twice is the same document twice.

type DumpOption

type DumpOption func(dumpOptions) dumpOptions

DumpOption configures a single call to [Repository.Dump].

Rendering settings belong to the call rather than to the repository: how a document looks is the business of whoever asks for it, and the template that lays it out is compiled when it is used.

An option that cannot be honoured reports an error from Dump, rather than at the point where it is constructed.

func WithFuncMap

func WithFuncMap(funcs template.FuncMap) DumpOption

WithFuncMap adds functions a dump template of the caller's own may call.

func WithTemplate

func WithTemplate(text string) DumpOption

WithTemplate lays the document out with a template of the caller's own.

The template is executed against a Documentation. It is compiled when [Repository.Dump] runs, so a template that does not parse is reported by that call.

type Override

type Override struct {
	// Name is the template that was declared more than once.
	Name string

	// Standing is the path of the asset whose definition the repository holds.
	Standing string

	// Replaced holds the paths of the assets whose definitions it replaced, in the order they
	// were read.
	Replaced []string
}

Override is a template a source declared and a later one replaced.

Stacking sources exists in order to override, so this is not an error. It is worth reporting all the same: nothing else reveals a template set that replaced a definition by accident.

type Root

type Root struct {
	// Field is the field the paths start at.
	Field string

	// Paths is how many of them there are.
	Paths int
}

Root is a field of the data, with the number of paths that hang from it.

type Template

type Template struct {
	// Name is what [github.com/go-openapi/codegen/templates-repo.Repository.Get] answers to.
	Name string

	// Doc holds the comments documenting the template, one entry per comment.
	Doc []string

	// Reads lists the data paths the template may read, rooted at the data it is executed on.
	//
	// It closes over every branch, so it describes what the data must be able to answer, not a
	// list of what it must hold: a path guarded by a condition may never be reached.
	Reads []string

	// RootReads lists the paths read through "$", a reach past the current dot back to the data
	// the template was executed on.
	RootReads []string

	// Funcs lists the func map functions the template calls, sorted. Builtins are left out.
	Funcs []string

	// Dependencies lists the templates this one calls, with the data handed to each.
	Dependencies []Dependency

	// UsedBy lists the templates that refer to this one directly, sorted.
	UsedBy []string

	// Inner reports whether the template is declared by a "define" statement rather than by an
	// asset of its own.
	Inner bool

	// Empty reports whether the template holds nothing but white space and comments, so that
	// executing it renders nothing.
	//
	// An asset made of "define" statements alone declares such a template under its own name,
	// which is reachable like any other and renders nothing.
	Empty bool

	// Unresolved counts the data accesses the analysis could not place, because the value they
	// hang from comes out of a function call.
	Unresolved int

	// Dynamic reports whether the template invokes a function held by its data, with the builtin
	// "call", which makes its contract incomplete by construction.
	Dynamic bool

	// Transitive holds the data the template reads once the templates it calls are folded into it.
	Transitive Transitive
}

Template is the documentation of a single template.

type Transitive

type Transitive struct {
	// Reads lists the data paths the template may read, itself or through the templates it calls.
	Reads []string

	// Funcs lists the func map functions reached the same way.
	Funcs []string

	// Reaches lists the templates it calls, directly or not, sorted.
	Reaches []string

	// Unresolved counts what could not be folded in.
	Unresolved int

	// Recursive reports whether the closure ran into a template that calls itself, directly or
	// not, and stopped there.
	Recursive bool
}

Transitive holds the data paths a template reads once the templates it calls are folded into it.

The paths a called template reads are rebased onto the data handed to it, so a template reading ".GoName" called with ".Properties[]" contributes ".Properties[].GoName" to its caller.

type Weights

type Weights struct {
	// Heavy holds the fields more than one path hangs from, heaviest first.
	Heavy []Root

	// Single holds the fields read once, sorted.
	Single []string
}

Weights groups the paths of a fold by the fields they hang from.

They spread very unevenly: a handful of fields hold a subtree the templates walk into, and everything else is read once. Separating the two shows which part of the data a template works on, without a list of counts that are all one.

Jump to

Keyboard shortcuts

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