📝 docs(spec): design args parser startup errors
This commit is contained in:
@@ -0,0 +1,123 @@
|
|||||||
|
# 参数解析与启动错误处理设计
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
`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 中不混入日志。
|
||||||
@@ -36,7 +36,8 @@
|
|||||||
## Workflow State
|
## Workflow State
|
||||||
|
|
||||||
<!-- workflow-state:start -->
|
<!-- workflow-state:start -->
|
||||||
phase: done
|
phase: planning
|
||||||
|
spec: docs/superpowers/specs/2026-07-11-args-parser-startup-errors-design.md
|
||||||
plan: docs/superpowers/plans/2026-05-24-conan-dependency-upgrade.md
|
plan: docs/superpowers/plans/2026-05-24-conan-dependency-upgrade.md
|
||||||
executor: executing-plans
|
executor: executing-plans
|
||||||
constraints: karpathy-guidelines,.agents,AGENT_RULES
|
constraints: karpathy-guidelines,.agents,AGENT_RULES
|
||||||
|
|||||||
Reference in New Issue
Block a user