strict.lua 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. -- Always warn when creating a global variable, even outside of a function.
  2. -- This ignores mod namespaces (variables with the same name as the current mod).
  3. local WARN_INIT = false
  4. local getinfo = debug.getinfo
  5. function core.global_exists(name)
  6. if type(name) ~= "string" then
  7. error("core.global_exists: " .. tostring(name) .. " is not a string")
  8. end
  9. return rawget(_G, name) ~= nil
  10. end
  11. local meta = {}
  12. local declared = {}
  13. -- Key is source file, line, and variable name; seperated by NULs
  14. local warned = {}
  15. function meta:__newindex(name, value)
  16. local info = getinfo(2, "Sl")
  17. local desc = ("%s:%d"):format(info.short_src, info.currentline)
  18. if not declared[name] then
  19. local warn_key = ("%s\0%d\0%s"):format(info.source,
  20. info.currentline, name)
  21. if not warned[warn_key] and info.what ~= "main" and
  22. info.what ~= "C" then
  23. core.log("warning", ("Assignment to undeclared "..
  24. "global %q inside a function at %s.")
  25. :format(name, desc))
  26. warned[warn_key] = true
  27. end
  28. declared[name] = true
  29. end
  30. -- Ignore mod namespaces
  31. if WARN_INIT and name ~= core.get_current_modname() then
  32. core.log("warning", ("Global variable %q created at %s.")
  33. :format(name, desc))
  34. end
  35. rawset(self, name, value)
  36. end
  37. function meta:__index(name)
  38. local info = getinfo(2, "Sl")
  39. local warn_key = ("%s\0%d\0%s"):format(info.source, info.currentline, name)
  40. if not declared[name] and not warned[warn_key] and info.what ~= "C" then
  41. core.log("warning", ("Undeclared global variable %q accessed at %s:%s")
  42. :format(name, info.short_src, info.currentline))
  43. warned[warn_key] = true
  44. end
  45. return rawget(self, name)
  46. end
  47. setmetatable(_G, meta)