Files
tsl-devkit/docs/superpowers/specs/2026-07-11-args-parser-startup-errors-design.md
T

124 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 参数解析与启动错误处理设计
## 背景
`lsp.utils.args_parser` 当前同时承担参数解析、全局配置存储、帮助输出和
日志初始化。无效线程数与日志文件打开失败可能触发未捕获异常,帮助文本输出
字面量 `\n`,而将日志写入 stdout 会破坏 LSP stdio 协议流。
本设计处理审查项 1、2、3、5。解释器路径中的 `~` 展开留到后续任务。
## 目标
- stdout 只承载 LSP 协议消息。
- 参数解析无全局可变状态,可直接单元测试。
- 所有参数都进行完整校验,错误参数返回明确诊断和退出码 2。
- 日志初始化或服务器运行失败返回退出码 1,不触发 abort。
- 帮助文本使用真实换行并准确反映受支持参数。
## 非目标
- 不处理解释器路径展开或路径存在性验证。
- 不保留旧参数兼容层。
- 不引入第三方命令行解析库。
## 参数解析接口
删除 `ArgsParser` 单例、`GetConfig()` 和内部 `config_`。模块改为导出无状态
解析接口,结果通过 C++23 `std::expected` 返回:
```cpp
enum class ParseAction
{
kRun,
kShowHelp,
};
struct ParseResult
{
ParseAction action = ParseAction::kRun;
ServerConfig config;
};
std::expected<ParseResult, std::string> ParseArgs(
int argc,
char* const argv[]);
void PrintHelp(std::ostream& output, std::string_view program_name);
```
`ServerConfig` 只保留运行配置:线程数、日志级别、日志文件和解释器路径。
帮助请求由 `ParseAction` 表达,不再混入服务器配置。
## 参数规则
支持以下参数:
- `--help`
- `--log=trace|debug|info|warn|error|off`
- `--log-file=<path>`
- `--threads=<count>`
- `--interpreter=<path>`
删除 `--log-stdout``--log-stderr``--use-stdio`。没有指定日志文件时,
日志始终写入 stderr。
解析遵循以下规则:
- 未知参数返回错误,不再静默忽略。
- `--threads` 使用 `std::from_chars` 完整解析,只接受 `1``256`
- `--threads` 的空值、负数、尾随字符和数值溢出均返回错误。
- `--log` 只接受列出的六个级别。
- `--log-file``--interpreter` 不接受空值。
- `--help` 在参数列表中具有最高优先级;只要出现便返回帮助动作,不校验
其他参数,也不初始化日志或服务器。
- 普通参数重复出现时,以最后一次出现的值为准。
## 启动与错误处理
日志初始化从参数解析模块移到 `lsp.cli.launcher` 的私有实现。初始化规则为:
- `log_file` 非空时创建文件 logger。
- 否则创建 stderr logger。
- 不提供 stdout logger 路径。
`Run()` 按阶段处理错误:
1. 调用 `ParseArgs()`;错误写入 stderr,并返回 2。
2. `kShowHelp` 将帮助写入 stdout,并返回 0。
3. 初始化日志;异常写入 stderr,并返回 1。
4. 构造并运行 `LspServer`;异常写入 stderr,记录到已初始化的 logger
并返回 1。
5. 正常停止后关闭 spdlog,并返回 0。
日志初始化失败时不调用 spdlog 记录该错误,避免在 logger 未就绪时产生二次
异常。
## 测试设计
新增参数解析单元测试,覆盖:
- 默认配置与所有有效日志级别。
- `--threads=1``--threads=256` 两个边界。
- 空值、零、负数、257、尾随字符和溢出线程数。
- 空日志文件、空解释器路径和未知参数。
- 已删除的三个日志输出参数被报告为未知参数。
- 帮助动作和帮助文本的真实换行。
新增或扩展 CLI 行为测试,覆盖:
- 无日志文件时日志只进入 stderr,stdout 不出现日志文本。
- 无法创建日志文件时进程返回 1,并输出可读错误,而非因信号终止。
- 参数错误返回 2,且不会初始化服务器。
验证命令至少包括目标构建、参数解析测试和 CLI 行为测试。现有 LSP JSON
测试也需要通过,以确认 stdout 协议流未受影响。
## 完成条件
- 旧单例和 stdout logger 路径已删除。
- 所有参数规则均有自动化测试。
- `--help` 输出为多行文本。
- 无效线程数、不可写日志文件均受控退出。
- LSP stdio 测试通过,stdout 中不混入日志。