Open-source project
dave/dst avatar
dave/dst

dave/dst: editing Go syntax trees without losing comments

Decorated Syntax Tree - manipulate Go source with perfect fidelity.

1,445 stars65 forksGoNOASSERTION

At a glance

What is it?
dave/dst is a Go library for rewriting source code while retaining comments and line spacing attached to syntax nodes. It is useful for refactoring tools, code generators, and AST-based analysis, but its Go version requirement and custom licensing terms require attention before adoption.
Who is it for?
Engineers building Go refactoring tools or generators should evaluate dave/dst when comments and formatting must follow transformed nodes, while teams that need unrestricted standard-library tooling should review LICENSE first. Verify compatibility with Go 1.26.0, inspect decoration attachment points, and exercise parse, transform, and print operations against representative source files before adoption.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 43 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why go/ast complicates source-preserving rewrites

dave/dst addresses a specific weakness in the standard `go/ast` workflow: comments are associated with byte offsets rather than attached directly to the syntax nodes they describe. That model works for inspection, but it becomes awkward when a tool rearranges declarations, statements, or expressions. A transformed tree can therefore print a syntactically valid file with comments attached to the wrong statement. For refactoring tools and source generators, this is more than a cosmetic issue because generated output can differ unexpectedly from the input in its explanatory text and layout. The README contrasts this with `dst`, where comments and line spacing are represented as decorations attached to nodes. When nodes move, their decorations move with them. The practical target is not AST analysis alone. It is source transformation in which a tool changes program structure without discarding human-readable context. The README gives a concrete example in which two variable declarations are reversed. With `go/ast`, the comments appear detached. With `dst`, the output retains `// bar` with the string declaration and `// foo` with the integer declaration.

The decorator package and decoration attachment model

The main entry points are in `decorator`. The package provides convenience functions for parsing Go source into a `dst` tree and printing the modified tree. The README shows `decorator.Parse(code)` and `decorator.Print(f)` as the basic cycle. For finer control, it also documents `Decorator` for converting an `ast` tree into a `dst` tree and `Restorer` for converting the result back. This separation matters for tools that already use `go/ast` and need to preserve source details around a focused transformation. A `dst` node carries decoration properties. `Start` and `End` hold comments or other decorations associated with positions around the node, while `Before` and `After` control line spacing. The README states that `Before` is rendered before decorations at the `Start` point, and `After` is rendered after the node and its `End` decorations. Common decoration operations include `Append`, `Prepend`, `Replace`, `Clear`, and `All`. Comment text includes its marker, such as `//` or `/*`, and line comments receive a newline automatically. The full attachment-point list is generated in `decorations-types-generated.go`, which is useful when a tool needs to place comments precisely rather than rely on general formatting behavior.

A first transformation with decorator.Parse and decorator.Print

The README does not document a standalone installation command. It identifies the module as `github.com/dave/dst`, and `go.mod` declares Go version `1.26.0`. A project consuming this library would therefore need a compatible Go toolchain and a dependency entry for this module, although the repository does not provide a separate install command to copy. The following is the README's basic parse, modify, and print example. It reverses two declarations inside `main`, which makes the effect on attached comments visible in the printed output.

Installation and first real use

The README does not document an installation command or a quick-start command. The repository metadata identifies the module path as `github.com/dave/dst`, and `go.mod` sets `go 1.26.0`. A consumer should first confirm that its Go toolchain satisfies that module requirement and that its dependency configuration can resolve `github.com/dave/dst`. The first useful workflow shown in the README parses source, swaps two statements, and prints the resulting tree. The code below uses the API shown there. The expected result is that the `// bar` comment stays with `var b string` and `// foo` stays with `var a int`.

go
code := `package a

func main(){
	var a int    // foo
	var b string // bar
}`
f, err := decorator.Parse(code)
if err != nil {
	panic(err)
}

list := f.Decls[0].(*dst.FuncDecl).Body.List
list[0], list[1] = list[1], list[0]

if err := decorator.Print(f); err != nil {
	panic(err)
}

Adding comments and controlling line spacing

The decoration API is useful when a refactoring tool needs to insert explanatory comments or preserve deliberate visual separation. The README demonstrates adding comments at the beginning, inside, and at the end of a call expression. It also demonstrates changing `Before` and `After` to `dst.EmptyLine`, while setting argument spacing to `dst.NewLine`. This gives a source generator control over layout without rebuilding the entire textual program. The distinction is important for generated code. A formatter may normalize spacing, but the decorations are part of the `dst` representation and are rendered according to their attachment points. The `Decorations()` method is available on the `dst.Node` interface for the four common properties, so code can manipulate decorations generically when it does not know the concrete node type. The `dstutil.Decorations` helper is intended for debugging. It returns the node's before and after values together with attachment points and their decorations. That makes it possible to inspect where comments currently reside before designing a transformation. The examples show that spacing decisions and comment placement are separate controls, which is more precise than editing a rendered string.

Where dave/dst is the wrong fit

dave/dst is not a replacement for every use of `go/ast`. The standard package remains the direct choice when a tool only reads syntax, performs type-oriented analysis, or needs the exact standard AST API without source-preserving transformations. The added value of `dst` comes from its different node and decoration model. A project that does not modify source or does not need comments and spacing to survive node movement gains little from that abstraction. The library also imposes an explicit Go toolchain boundary. The repository's `go.mod` declares `go 1.26.0`, so consumers need to verify their build environment and dependency graph before adding it. There is another practical constraint for tool authors: placement behavior is tied to generated attachment-point definitions. A transformation that appears correct for declarations may need different handling for expressions, statements, or other nodes. The README documents the attachment points, but it does not claim that every arbitrary source transformation will preserve all formatting automatically. Tools should treat parsing, node movement, decoration inspection, and printing as separate steps and verify the resulting source against representative inputs.

Comparison with go/ast and the licensing boundary

The direct alternative is `go/ast` combined with `parser.ParseFile`, `format.Node`, and explicit comment handling. Its approach is based on the Go standard AST and byte-offset comments. That approach offers direct compatibility with standard tooling, but the README demonstrates that moving nodes can leave comments associated with the wrong output. `dst` takes a different approach by decorating nodes and providing conversion through `decorator.Decorator` and `decorator.Restorer`. A tool can retain standard AST integration at its boundaries while using `dst` for the source-sensitive phase. The repository also has no GitHub releases, so upgrade planning cannot be based on release artifacts documented there. Maintenance status is supported by repository activity: the repository is not archived, and its last push was on 2026-09-10. That fact does not describe API compatibility, release cadence, or support policy, none of which are documented in the repository. The license is listed as custom, and the repository points to `LICENSE` for its terms. Since the license file contents are not included here, redistribution, modification, and dependency obligations cannot be evaluated from this metadata alone.

Editorial conclusion

Engineers building Go refactoring tools or generators should evaluate dave/dst when comments and formatting must follow transformed nodes, while teams that need unrestricted standard-library tooling should review LICENSE first. Verify compatibility with Go 1.26.0, inspect decoration attachment points, and exercise parse, transform, and print operations against representative source files before adoption.

Frequently asked questions

What is dave/dst used for?

dave/dst is used to manipulate Go syntax trees while keeping comments and line spacing attached to nodes during modifications. The README focuses on source-preserving transformations, such as rearranging statements.

How do I parse and print Go code with dave/dst?

The README uses `decorator.Parse(code)` to parse a string and `decorator.Print(f)` to print the modified tree. `Decorator` and `Restorer` provide finer-grained conversion between `ast` and `dst` trees.

What Go version does dave/dst require?

The repository's `go.mod` declares `go 1.26.0`. Consumers should verify that their toolchain and build configuration support that version before using the module.

Can dave/dst preserve comments when nodes are reordered?

That is the central behavior described by the README. Its example swaps two declarations and shows each comment remaining with the declaration it originally documented.

What license applies to dave/dst?

The repository is classified as using a custom license, and its `LICENSE` file is the relevant source. The license file contents are not included in the available repository information, so its exact permissions and obligations cannot be summarized here.

Official sources

  1. dave/dst on GitHub
  2. Issues
  3. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dave-dst.svg)](https://hysenlabs.com/projects/dave-dst)

Was this useful?