Documentation
¶
Overview ¶
Package bricolint provides a go/analysis analyzer that guards the fleet-wide "no hand-drawn UI" rule: every visible element must be a go-widgets/toolkit widget, never chrome painted by hand onto a raw painter surface, and never a throwaway widget rebuilt on every paint.
"Bricolage" — improvised, hand-rolled drawing — is how a UI quietly loses press/hover/focus feedback, theming, HiDPI scaling and accessibility. Once an app has been migrated onto the toolkit, this analyzer keeps it that way: a pull request that reintroduces manual drawing fails CI instead of merging.
The analyzer reports two rules, and only in packages that actually touch the toolkit stack (it is a no-op everywhere else):
Painter primitive in application code. A method call whose receiver's static type resolves to a type in github.com/go-widgets/painter (the Painter interface itself, or a concrete *PixelPainter / *CellPainter), and whose method is a drawing primitive (FillRect, FillRoundRect, StrokeRect, StrokeRoundRect, FillPath, StrokePath, DrawImage, DrawMask, PutPixel, Text, and the conventional aliases DrawText/DrawGlyph/ DrawLine/Blit). Because the receiver is resolved through go/types, a same-named method on an unrelated type (strings.Builder, bytes.Buffer, a local helper) is never touched.
Throwaway widget per frame. A toolkit constructor call (toolkit.New<X>) made syntactically inside a method named Draw, Paint or Render. A widget constructed on every paint is never persisted, so it can hold no interaction state — the anti-pattern that kills press/hover/focus feedback. The fix is to build the widget once, store it as a field, and drive it through a go-widgets/mvvm binding.
Genuine render leaves — a game framebuffer, a painter BACK-END such as go-pdfkit, a document/minimap raster, the toolkit's own widget internals — opt out explicitly, so the exemption is a conscious, documented choice:
- A trailing (or immediately preceding) line comment //bricolint:allow <reason> exempts that single line.
- A file-level comment //bricolint:allowfile <reason> exempts the whole file.
The reason is mandatory: a directive with no reason is ignored, so the violation keeps failing until a justification is written down.
Index ¶
Constants ¶
const MVVMPath = "github.com/go-widgets/mvvm"
MVVMPath is the import path of the go-widgets MVVM library, named in the throwaway-widget diagnostic as the sanctioned way to hold widget state.
const PainterPath = "github.com/go-widgets/painter"
PainterPath is the import path of the go-widgets painter surface.
const ToolkitPath = "github.com/go-widgets/toolkit"
ToolkitPath is the import path of the go-widgets pixel/cell toolkit.
Variables ¶
var Analyzer = newAnalyzer()
Analyzer is the bricolint go/analysis analyzer. Use it with singlechecker, or as a go vet tool: go vet -vettool=$(which bricolint) ./...
var DefaultPrimitives = []string{
"Blit",
"DrawGlyph",
"DrawImage",
"DrawLine",
"DrawMask",
"DrawText",
"FillPath",
"FillRect",
"FillRoundRect",
"PutPixel",
"StrokePath",
"StrokeRect",
"StrokeRoundRect",
"Text",
}
DefaultPrimitives is the built-in set of painter drawing methods that count as hand-drawn chrome when called on a painter surface from application code.
It covers the real painter API (FillRect/StrokeRect/…/PutPixel/Text) plus the conventional primitive names an app is tempted to reach for (DrawText/DrawGlyph/DrawLine/Blit). Structural, non-drawing methods of the painter (Size, PushClip/PopClip, PushTranslate/PopTranslate) are deliberately absent: querying the surface or clipping is not bricolage.
Functions ¶
This section is empty.
Types ¶
This section is empty.