Skip to main content建议按“解析 → 分派 → 数据 → 并发”分层排查。
先用错误类型快速定位,再补齐现场信息(target/参数/变量/线程)以缩小范围。
快速定位
下面列出各阶段的典型错误与立即检查项:
- 解析:
MultipleParseException
- 立即检查:
ex.formatDiagnostic() 打印源码摘录
- REPL:语句前加
$ 输出 AST
- 分派:
FunctionNotFoundError / EvaluatorNotFoundError
- 立即检查:
Environment#getRootFunctions() / getRootExtensionFunctions()
- 命名空间与 target 类型是否匹配
- 数据:
ArgumentTypeMismatchError / VariableNotFoundError / IndexAccessError / VoidError
- 立即检查:
FunctionContext#toString()(函数名/target/参数)
- 参考:
availableVariables、IndexErrorType
- 并发:主线程函数跑在后台 / 异步任务堆积
- 立即检查:
registerPrimarySyncFunction 用法
- 观察:
ThreadPoolManager#getActiveTaskCount() 与执行器配置
解析错误(MultipleParseException)
Parser#parse 聚合所有语法错误;ex.formatDiagnostic() 可直接打印行列与源码摘录。
- REPL 语句前加
$,控制台会输出词法/语法树,便于确认括号、then/else 是否成对。
- 网络/数据库来源的脚本注意行尾统一,否则列号可能偏移。
调用分派问题
FunctionNotFoundError
- 注册是否生效:
Environment#getRootFunctions() / getRootExtensionFunctions() 查看。
缺失则重新注册并调用 runtime.newEnvironment() 触发 bake。
- 命名空间:
registerFunction("fs", "readText", …) 对应脚本 fs:readText,漏前缀会直接失败。
- target 类型:扩展函数要求
target 与注册类型一致;null::fn() 会因 target 为空而匹配不到。
- 目录一致性:必要时重跑
./gradlew :core:dumpFluxonCatalog,确认导出的签名与预期一致。
EvaluatorNotFoundError
- 新增语法未提供求值器导致。
- 检查是否在
runtime.function / index 注册 evaluator。
- 如果语法应被禁止,在解析阶段直接抛
ParseException,避免运行时才失败。
数据与类型问题
ArgumentTypeMismatchError
FunctionContext#getNumber/getArgumentByType 会在消息中标注参数索引与实际值;先核实脚本入参是否符合签名。
- 多参数版本只检查参数个数,不会自动装箱;需要在实现内区分
Number/String 等类型。
- 扩展函数建议先用
hasArgument(idx) 判空,避免 null 触发类型错误。
VariableNotFoundError
:vars(REPL)或 Environment#getRootVariables() 查看当前可见变量;确认作用域与命名是否一致。
- 函数体中新增局部变量时,确保解析器同步更新
localVariableNames,否则赋值索引会错位。
IndexAccessError
OUT_OF_BOUNDS:检查索引与集合大小。
UNSUPPORTED_TYPE / UNSUPPORTED_SET_TYPE:该类型未实现 IndexAccessor,需要添加实现或更换访问方式。
NULL_TARGET:目标为 null;脚本侧加判空或默认值(Elvis)再访问。
VoidError
函数返回 Function.VOID 却继续参与运算时触发。仅在确实无需返回值的路径返回 VOID,其他场景返回真实结果或 null。
并发与执行器
- 主线程函数:仅通过
registerPrimarySyncFunction / registerSyncExtensionFunction 标记。
- 执行器:使用
FluxonRuntime#setPrimaryThreadExecutor 指向宿主主线程。
- 异步任务:
ThreadPoolManager#getActiveTaskCount() 观察堆积。
- 若出现
CallerRunsPolicy,表示队列满,新任务会落到调用线程;需要拆批或扩容。
- 关闭:
ThreadPoolManager#shutdown() 前最好等待 awaitTermination,避免异步任务被硬中断。
现场信息速查
Environment#getRootFunctions()/getRootExtensionFunctions()/getRootVariables():注册表与可见符号。
FunctionContext#toString():函数名、target、参数实参。
FluxonRuntime#getSystemFunctions() / #getExtensionFunctions():宿主侧直接查看注册状态。
./gradlew :core:dumpFluxonCatalog + vscode-extension/scripts/sync-catalog.js:当补全或文档与运行时不一致时优先刷新。
按上述顺序(定位异常 → 获取现场 → 修正注册/类型/线程配置)即可快速收敛问题,减少反复试错。
相关链接