Compare commits

..

2 Commits

Author SHA1 Message Date
Axel Meyer
a169c6c74b fix(parse_readme_api): support namespace-less function names
The previous single-pattern approach used a greedy `[^.\x60]*` segment
that mis-captured H3 headers without a namespace prefix (e.g. test-lib
entrypoints documented as `### \`run_tests(ctx)\``).

Replace with a two-pass match: pattern 1 captures `### \`ns.func(...)\``
(namespaced) and pattern 2 captures `### \`func(...)\`` (no namespace).
A seen-set prevents the namespace-less pass from re-matching names
already collected by the namespaced pass.

Enables test-libs to declare a public surface in their READMEs and
satisfy --lint's missing-docs check.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 17:51:27 +02:00
Axel Meyer
78cf0eb980 fix(parse_lua_surface): strip Lua line-comments before matching
Previous implementation matched function-declaration patterns inside
Lua line-comments, causing false-positive missing_docs warnings for
commented-out forward-compat stubs (e.g. DEPRECATED-MVP placeholders
in camera and render libs, 5 each).

Pre-process source with gsub to strip "--" through end-of-line before
running the two gmatch passes. Block comments (--[[...]]) are not
handled; not used in this project's Lua sources.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 17:51:10 +02:00

View File

@@ -8,6 +8,15 @@ local M = {}
-- (`function M.foo`) — Lua treats them semantically identical.
-- Returns: { public = ["foo","bar",...], private = ["_baz",...] }
function M.parse_lua_surface(source_string)
-- Strip Lua line-comments (-- to end-of-line) before pattern matching.
-- This prevents false-positive matches inside commented-out forward-compat
-- stubs (e.g. DEPRECATED-MVP placeholders).
-- Block comments (--[[...]]) are not handled; not used in Sporel-lib code.
-- Caveat: a literal "--" inside a string would also be stripped; acceptable
-- for the lint-tool's purpose (false-negatives in pathological string cases
-- are preferable to false-positives on commented stubs).
local stripped = string.gsub(source_string, "%-%-[^\n]*", "")
local public = {}
local private = {}
local seen = {}
@@ -23,12 +32,12 @@ function M.parse_lua_surface(source_string)
end
-- Form 1: M.foo = function(...)
for name in string.gmatch(source_string, "M%.([_%w]+)%s*=%s*function") do
for name in string.gmatch(stripped, "M%.([_%w]+)%s*=%s*function") do
classify(name)
end
-- Form 2: function M.foo(...)
for name in string.gmatch(source_string, "function%s+M%.([_%w]+)") do
for name in string.gmatch(stripped, "function%s+M%.([_%w]+)") do
classify(name)
end
@@ -41,6 +50,8 @@ end
-- Returns: { documented = ["bind","unbind",...] }
function M.parse_readme_api(markdown_string)
local documented = {}
local seen = {}
-- Find "## API" section start (allow trailing whitespace/content)
local api_start = string.find(markdown_string, "\n## API[%s\n]")
if not api_start then
@@ -50,10 +61,24 @@ function M.parse_readme_api(markdown_string)
local api_end = string.find(markdown_string, "\n## ", api_start + 5)
local section = string.sub(markdown_string, api_start, api_end or #markdown_string)
-- Match H3 headers: "### `[namespace.]name(...)`" — capture name portion
for line in string.gmatch(section, "###%s+`[^.`]*%.?([_%w]+)%s*[%(`]") do
table.insert(documented, line)
-- Two-pass matching to handle both namespace-prefixed and namespace-less
-- function-names in H3 headers.
-- Pattern 1: namespaced — "### `ns.func(...)`" -> capture "func"
for name in string.gmatch(section, "###%s+`[%w_]+%.([_%w]+)") do
if not seen[name] then
seen[name] = true
table.insert(documented, name)
end
end
-- Pattern 2: namespace-less — "### `func(...)`" -> capture "func"
-- The seen-set prevents re-matching names already captured by pattern 1.
for name in string.gmatch(section, "###%s+`([_%w]+)%s*[%(`]") do
if not seen[name] then
seen[name] = true
table.insert(documented, name)
end
end
return { documented = documented }
end