From 120b8c7c146fe8b5599e16ae8a721caf678364f5 Mon Sep 17 00:00:00 2001 From: Abhinav Gupta Date: Thu, 5 Mar 2020 22:41:48 -0800 Subject: [PATCH] renderer: Helpful panic for unknown NodeKind When rendering a Node, Renderer looks up the NodeRenderer for that node's kind in a slice. That will panic with an "index out of range" error if a node renderer for that node kind has not been registered. panic: runtime error: index out of range [1] with length 1 This changes Renderer to panic with a more helpful error message if the node kind is unrecognized. panic: unrecognized node kind Document cannot be rendered: register a renderer for this node kind first --- renderer/renderer.go | 10 +++++++++- renderer/renderer_test.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 renderer/renderer_test.go diff --git a/renderer/renderer.go b/renderer/renderer.go index 10f6d40..16929f9 100644 --- a/renderer/renderer.go +++ b/renderer/renderer.go @@ -3,6 +3,7 @@ package renderer import ( "bufio" + "fmt" "io" "sync" @@ -161,7 +162,14 @@ func (r *renderer) Render(w io.Writer, source []byte, n ast.Node) error { err := ast.Walk(n, func(n ast.Node, entering bool) (ast.WalkStatus, error) { s := ast.WalkStatus(ast.WalkContinue) var err error - f := r.nodeRendererFuncs[n.Kind()] + + k := n.Kind() + if int(k) >= len(r.nodeRendererFuncs) { + panic(fmt.Sprintf("unrecognized node kind %v cannot be rendered: "+ + "register a renderer for this node kind first", k)) + } + + f := r.nodeRendererFuncs[k] if f != nil { s, err = f(writer, source, n, entering) } diff --git a/renderer/renderer_test.go b/renderer/renderer_test.go new file mode 100644 index 0000000..5df29d4 --- /dev/null +++ b/renderer/renderer_test.go @@ -0,0 +1,35 @@ +package renderer + +import ( + "io/ioutil" + "strings" + "testing" + + "github.com/yuin/goldmark/parser" + "github.com/yuin/goldmark/text" +) + +func TestRenderUnknownNode(t *testing.T) { + defer func() { + r := recover() + if r == nil { + t.Errorf("Render() should panic") + return + } + + msg, ok := r.(string) + if !ok { + t.Errorf("Render() should panic with a string") + } + + if !strings.Contains(msg, "unrecognized node kind Document") { + t.Errorf("Render() panicked with unexpected message: %v", msg) + } + }() + + src := []byte("# Foo\n\nHello world") + node := parser.NewParser().Parse(text.NewReader(src)) + + r := NewRenderer() + r.Render(ioutil.Discard, src, node) +}