renderer: Don't 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.

This change verifies that a node renderer is available for that node
kind before attempting to use it, and instead of panicking, returns an
informative error message.
This commit is contained in:
Abhinav Gupta 2020-03-05 22:41:48 -08:00
parent 21437947a3
commit a2b8e64617
2 changed files with 34 additions and 1 deletions

View file

@ -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) {
return s, fmt.Errorf("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)
}

25
renderer/renderer_test.go Normal file
View file

@ -0,0 +1,25 @@
package renderer
import (
"io/ioutil"
"strings"
"testing"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/text"
)
func TestRenderUnknownNode(t *testing.T) {
src := []byte("# Foo\n\nHello world")
node := parser.NewParser().Parse(text.NewReader(src))
r := NewRenderer()
err := r.Render(ioutil.Discard, src, node)
if err == nil {
t.Fatalf("Render() expected error")
}
if !strings.Contains(err.Error(), "unrecognized node kind Document") {
t.Errorf("Render() failed with unexpected error: %v", err)
}
}