诊断

Lux 诊断的目标是指向源码规则,而不是让开发者从生成 Lua 里倒推错误。构建失败时, 应优先阅读 diagnostic code、主标签和建议修复方式。

严重级别

error    阻止生成,必须修复
warning  允许继续生成,但存在风险或迁移债务

当前最典型的 warning 是 REALM_UNKNOWN:未知外部符号默认允许,但编译器无法证明 运行域安全。

解析错误

解析错误使用 PARSExxx 代码。解析错误发生在语义检查之前,所以后续模块、运行域和 导出错误可能暂时不会显示。先修语法,再看下一批诊断。

extern 缺少运行域
extern ThirdPartyAddon

模块图错误

模块相关诊断使用 MODULExxx,常见原因:

  • 导入的模块不存在。
  • 导入名称不是目标模块公开 API。
  • 导出公开名重复。
  • 导出试图转发 imported binding。
  • 模块依赖形成循环。

典型修复是确认目标模块导出的公开名,再按公开名导入。

公开名不等于内部名
local player_inventory = {}

export { p_inv = player_inventory }

如果目标模块只导出了 p_inv,使用方不能导入 player_inventory

part 顺序错误

part 顺序诊断使用 PARTxxx。常见原因:

  • 多 part 模块没有入口 part。
  • 多 part 模块有多个入口 part。
  • part order 不在入口 part。
  • part order 目标不存在或重复。
  • 短名目标有歧义。
  • part before / part after 形成循环。

推荐修复方式是在入口 part 写完整顺序。

part order 修复
part order { "module", "sh_items", "sv_store", "cl_panel" }

不要用大量 part before / part after 模拟完整编排。

运行域错误

运行域错误使用 REALMxxx

error[REALM001]: symbol `grantItem` is not available in shared context

修复方式之一是把使用点放进明确运行域。

使用点进入 server block
shared fn install(player, item) {
  server {
    grantItem(player, item)
  }
}

另一个方式是标记整个函数。

标记整个函数运行域
server fn install(player, item) {
  grantItem(player, item)
}

REALM_UNKNOWN 是 warning,表示外部符号未知。

warning[REALM_UNKNOWN]:
cannot verify realm availability of external symbol `ThirdPartyAddon`

externlux.toml 修复。

extern 修复未知外部符号
extern server ThirdPartyAddon

匹配错误

MATCHxxx 用于枚举和 match

  • 非穷尽匹配。
  • 分支被前面分支覆盖。
  • fallback 分支已经不可达。
非穷尽 match
fn label(kind) =
  match kind {
    FillKind.Solid => "solid"
  }

Lint 诊断

Lint 代码当前包括:

LINT001  可疑的尾表调用或换行调用形状
LINT002  尾表达式被分号压制,可能不是预期
LINT003  可疑自赋值
LINT004  GMod 回调可能隐式返回副作用表达式

局部关闭应贴近触发点,不要在文件顶部大范围压制。

局部关闭 lint
fn PANEL:Paint(w, h) {
  -- lux-lint: allow LINT004
  drawBody(self, w, h)
}

宏和宿主变换错误

宏错误使用 MACROxxx,编译期加载错误使用 CTLOAD001。常见原因:

  • 宏调用参数数量不对。
  • 语句宏用在表达式位置。
  • 宏返回了非 AST 值。
  • 编译期包导出 host transform,但没有声明 export host package
  • 宿主变换生成了无效 IR。

宏作者应使用 @lux/compile/macro@lux/compile/host 的 helper 报错,不要拼接 原始 Lua 字符串。

排错顺序

  1. 先修 PARSExxx
  2. 再修模块导入导出和 part 顺序。
  3. 再修运行域错误。
  4. 最后处理 lint 和未知外部 warning。

GMod 运行时报错时,用 map-error 从生成 Lua 行号查回 Lux 源码,再回到对应页面判断 是语言问题、运行域问题还是普通 GLua 运行时问题。