Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions doccov/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,19 +255,30 @@ func shortName(name string) string {
}

var (
fencedBlock = regexp.MustCompile("(?s)```.*?```")
backtickSpan = regexp.MustCompile("`[^`]+`")
wordToken = regexp.MustCompile(`[A-Za-z_][A-Za-z0-9_]*`)
)

// backtickWords collects every identifier word appearing inside a backtick span
// of the document.
// backtickWords collects every identifier word that appears inside code in the
// document — both ```fenced``` blocks and `inline` spans. Fenced blocks are
// processed and removed first so their backticks don't throw off the
// single-backtick span matcher (which otherwise mis-pairs across a fence, so a
// `code` reference in a table *after* a fenced example could be missed).
func backtickWords(doc string) map[string]bool {
out := map[string]bool{}
for _, span := range backtickSpan.FindAllString(doc, -1) {
for _, w := range wordToken.FindAllString(span, -1) {
add := func(s string) {
for _, w := range wordToken.FindAllString(s, -1) {
out[w] = true
}
}
rest := fencedBlock.ReplaceAllStringFunc(doc, func(block string) string {
add(block)
return "\n"
})
for _, span := range backtickSpan.FindAllString(rest, -1) {
add(span)
}
return out
}

Expand Down
12 changes: 12 additions & 0 deletions doccov/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ func TestBacktickWords(t *testing.T) {
}
}

func TestBacktickWordsAcrossFences(t *testing.T) {
// Regression: a `code` reference in a table AFTER a ```fenced``` block must
// still be detected (the fenced block must not corrupt inline-span pairing).
doc := "Intro `inline_one`.\n\n```go\ncode := example()\n```\n\n| opt | accessors |\n|---|---|\n| width | `get_width` / `set_width` |\n"
words := backtickWords(doc)
for _, w := range []string{"inline_one", "example", "get_width", "set_width"} {
if !words[w] {
t.Errorf("expected %q documented across the fence, got %v", w, words)
}
}
}

func TestRunGood(t *testing.T) {
if err := run("testdata/good", "README.md", nil, false); err != nil {
t.Fatalf("good fixture should pass, got: %v", err)
Expand Down
Loading