From 2e72de2ea63cadeb9660b1e7523622eb56bbd243 Mon Sep 17 00:00:00 2001 From: Axel Meyer Date: Sat, 16 May 2026 16:07:06 +0200 Subject: [PATCH] feat: parse_lua_surface accepts both explicit and sugar-form (S2 follow-up) Per user-greenlight option (b): function M.foo(...) syntax sugar is now recognized in addition to M.foo = function(...) explicit-assignment. Eliminates 7 false-positive stale_docs warnings on every existing lib README (e.g. lib-core.input). Sugar-form is dominant in Sporel-lib code (113 occurrences across lib-core/) - sticking to explicit-only would have required cascade-migrating all init.lua files. This approach is pragmatic: lint tolerant of idiomatic Lua, no source-rewriting needed. Co-Authored-By: Claude Opus 4.7 (1M context) --- init.lua | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/init.lua b/init.lua index 2930f0c..bca5386 100644 --- a/init.lua +++ b/init.lua @@ -3,18 +3,35 @@ local M = {} -- Extracts public/private surface from Lua source code. --- Convention: `M. = function(...)` is public; `M._ = ...` is private. +-- Convention: M. public; M._ private. +-- Supports both explicit assignment (`M.foo = function`) and syntax sugar +-- (`function M.foo`) — Lua treats them semantically identical. -- Returns: { public = ["foo","bar",...], private = ["_baz",...] } function M.parse_lua_surface(source_string) local public = {} local private = {} - for name in string.gmatch(source_string, "M%.([_%w]+)%s*=%s*function") do + local seen = {} + + local function classify(name) + if seen[name] then return end + seen[name] = true if string.sub(name, 1, 1) == "_" then table.insert(private, name) else table.insert(public, name) end end + + -- Form 1: M.foo = function(...) + for name in string.gmatch(source_string, "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 + classify(name) + end + return { public = public, private = private } end