| name | testing |
| description | How to run tests, add error tests, update golden files, and report nice errors in Dang. Use when running or writing tests. |
Testing & Error Reporting
Running Tests
All language and error tests live in tests/ and run via the TestDang suite:
go test ./tests/ -v
go test ./tests/ -run "TestDang/TestLanguage/test_foo" -v
go test ./tests/ -run "TestDang/TestErrorMessages/some_error" -v
go test ./tests/ -run "TestDang/TestFormatLanguage/test_foo" -v
Test Suites
The DangSuite (in tests/integration_test.go) has three sub-suites:
- TestLanguage: Runs each
tests/test_*.dang file and expects it to succeed.
- TestFormatLanguage: Formats each
tests/test_*.dang file, re-parses the formatted output, runs it, and checks it still produces the same result.
- TestErrorMessages: Runs each
tests/errors/*.dang file, expects an error, and compares the output against tests/testdata/<name>.golden.
Editor Highlight Tests
Editor syntax highlighting tests live in editors/ and run via the TestEditors suite:
go test ./editors/ -v
go test ./editors/ -run "TestEditors/TestNeovimHighlights" -update
- TestNeovimHighlights: Renders each case in
editors/highlights/corpus/*.txt through Neovim with the tree-sitter parser and compares highlight spans.
- TestZedHighlightQueryCompatibility: Smoke-tests the Zed highlight queries against the corpus with the
tree-sitter CLI.
These tests Skip unless the editors/nvim and editors/zed submodules are initialized (git submodule update --init).
Error Message Golden Files
Error golden files live in tests/testdata/ and contain the exact error output including ANSI escape codes for colored/highlighted source annotations.
To update golden files after changing error messages:
go test ./tests/ -run "TestDang/TestErrorMessages" -update
Adding a New Error Test
- Create
tests/errors/my_error.dang with code that should produce an error.
- Run with
-update to generate the golden file:
go test ./tests/ -run "TestDang/TestErrorMessages/my_error" -update
- Review
tests/testdata/my_error.golden to confirm the error message is correct.
Reporting Nice Errors
Dang has two error types for attaching source locations:
InferError (type checking phase)
Use NewInferError in Infer() methods to attach source location to type errors. These get converted to SourceError with full source highlighting when displayed.
return nil, NewInferError(fmt.Errorf("descriptive message"), node)
WrapInferError avoids double-wrapping if the error is already an InferError:
return nil, WrapInferError(err, node)
SourceError (display/eval phase)
SourceError holds the error, source location, and source text, and renders with highlighted code snippets:
return nil, NewSourceError(fmt.Errorf("message"), location, sourceCode)
During eval, use the EvalContext helper:
return nil, evalCtx.CreateSourceError(err, node)
Conversion Flow
InferError → ConvertInferError() → SourceError (reads the source file and produces highlighted output). This happens automatically in RunFile.
WithInferErrorHandling / WithEvalErrorHandling
Wrapper helpers that automatically attach source location to errors that don't already have one:
func (n *MyNode) Infer(ctx context.Context, env hm.Env, fresh hm.Fresher) (hm.Type, error) {
return WithInferErrorHandling(n, func() (hm.Type, error) {
})
}
PEG Grammar
The parser is defined in pkg/dang/dang.peg (pigeon PEG parser). After editing:
go generate ./pkg/dang/
This regenerates pkg/dang/dang.peg.go.
Formatter
The formatter lives in pkg/dang/format.go. When adding a new AST node type, update:
formatNode() — add a case to format the node
- Any relevant classification helpers e.g. `.GetSourceLocation() for blank line insertion logic