Files
sap-cli-skill/docs/功能矩阵分析.md
T
吴让宇 c5905a5b1e refactor: 本仓升为唯一源(原 sap-cli 源码仓归档)
方向反转:此前 SKILL.md 是「模板渲染产物」、sap-cli 是源;现 sap-cli 归档,
sap-cli-skill 承接开发与分发,SKILL.md 回归手工维护的正本。

迁移(来自 sap-cli,共 104 文件):
- tests/           692 例测试(15 个文件的内联 sys.path 改指 assets/)
- openspec/        SDD 规格与归档变更(42 文件)
- docs/            开发文档与 ADT 原理(含 dev/CLAUDE.md、AGENTS.md)
- .claude/         rules 副本 + settings.json(供 Claude Code)
- .github/ .hermes/ .pre-commit-config.yaml .editorconfig CLAUDE.md
- scripts/ 保持仅 setup.py(pack_skill.py 已随旧仓归档,不迁)

修复(迁移暴露的真实缺陷):
- assets/pyproject.toml 的 build-backend 写作 `setuptools.backends._legacy:_Backend`,
  该模块在 setuptools 中不存在 → `pip install -e` 从来装不上。改为 build_meta。
  实测:临时 venv 安装成功,sap-cli --help 正常列出 31 个命令
- pyproject readme 指向不存在的 assets/README.md(editable 安装会失败)→ 改内联文本
- pyproject urls 改指 sap-cli-skill

机制调整:
- .github/workflows/ci.yml 适配 assets/ 布局;顶部注明该工作流仅 GitHub 执行,
  本仓在 Gitee 不会自动跑
- pre-commit 增本地测试门禁(Gitee 上真正生效的那道)
- .gitignore 合并旧仓完整规则(保留 log/ 下 md 知识库入库,只忽略运行日志)
- 大文件上限 100KB→1MB(架构图 512KB)

守卫测试 tests/unit/test_repo_guards.py(10 → 18 例):
- SKILL.md 须记录 parser 全部 CLI 命令 / 铁律 1-5 须为真实小节标题 / 示例不得违反铁律 5
- references/ 规则齐备;.claude/rules 与 references 必须一致(实测抓到一次真实漂移)
- VERSION == sapcli.__version__ == README 版本
- 仓内不得再出现 pack_skill.py / skill-src(防废弃流程回潮)

698 tests OK;editable 安装与 CLI 入口经临时 venv 实测通过。
docs/RELEASING.md 重写为单源开发流程。
2026-09-11 00:40:15 +08:00

15 KiB
Raw Blame History

sap-cli 功能矩阵分析报告

分析基于源码静态审查(sapcli/types.pysapcli/cli/parser.pysapcli/commands/*sapcli/client/*)。 生成时间:2026-06-18


第一部分:已实现的命令完整列表

25 个顶层命令(含子命令则为 38 个操作)。命令分发逻辑见 sapcli/cli/app.pycommand_map(外加 config/auth 两个不走 SAP 连接的命令)。

# 命令 子命令 所在文件 功能描述 是否需 SAP 连接
1 download commands/crud.py::cmd_download 下载对象源代码到本地文件
2 sync commands/crud.py::cmd_sync 同步单对象源码并激活(检查→写入→语法检查→激活)
2b sync --all commands/batch.py::cmd_sync_all 批量同步清单内所有对象(拓扑排序)
3 upload commands/upload.py::cmd_upload 仅上传源码(锁定→写入→解锁,不检查不激活)
4 syntax-check commands/syntax_check.py::cmd_syntax_check 远程对象语法检查(不上传不激活)
5 activate commands/activate.py::cmd_activate 单独激活对象(单/批量模式)
6 delete commands/crud.py::cmd_delete 从 SAP 删除对象(交互确认)
7 info commands/crud.py::cmd_info 查询对象元数据
8 create commands/crud.py::cmd_create 创建开发对象(含 DDIC/函数组)
9 diff commands/diff_cmd.py::cmd_diff 本地 vs SAP 代码差异对比
10 list commands/search.py::cmd_list 列出 SAP 对象(类型/包/前缀过滤)
11 whereused commands/search.py::cmd_whereused Where-Used 引用查询
12 search commands/search.py::cmd_search 源代码搜索
13 check commands/quality.py::cmd_check ATC 代码检查
14 format commands/quality.py::cmd_format 代码格式化(Pretty Printer + 写回 + 激活)
15 transport list commands/transport.py::_transport_list 列出可修改的传输请求
15b info ::_transport_info 查看传输请求详情
15c release ::_transport_release 释放传输请求(交互确认)
15d objects ::_transport_objects 列出传输请求中对象
16 package create commands/package_cmd.py::_package_create 创建 ABAP 包
16b info ::_package_info 查看包详情
16c list ::_package_list 列出包中对象
17 cds download commands/cds.py::_cds_download 下载 CDS View DDL 源码
17b sync ::_cds_sync 同步本地 DDL 到 SAP(含创建/激活)
17c create ::_cds_create 创建新的 CDS View
18 init commands/batch.py::cmd_init 扫描本地→查询 SAP→生成 manifest.json
19 refresh commands/batch.py::cmd_refresh 刷新清单中对象状态
20 analyze commands/analyze.py::cmd_analyze 本地依赖自动分析(正则匹配)
21 scaffold commands/scaffold.py::cmd_scaffold 项目模板创建(4 种模板) (本地)
22 config show/list-profiles/set commands/config_cmd.py::cmd_config 配置管理
23 auth login/logout/status auth.py::cmd_auth_* keyring 密钥管理
24 show-table commands/ddl_query.py::cmd_show_table 查看 DDIC 表字段结构(SE11
25 read-table commands/ddl_query.py::cmd_read_table 查询表数据(freestyle SQL
26 run-program commands/program_run.py::cmd_run_program 远程执行 ABAP 程序(SA38

第二部分:已注册的对象类型完整列表

16 个对象类型,全部在 sapcli/types.py 中通过 _register() 注册。

# key label 对象端点 (obj_uri) 源码端点 (src_uri) has_source create_content_type
1 report 程序(REPORT) /programs/programs/{name} /programs/programs/{name}/source/main vnd.sap.adt.programs.programs.v2+xml
2 class 类(CLASS) /oo/classes/{name} /oo/classes/{name}/source/main vnd.sap.adt.oo.classes.v1+xml
3 function 函数模块 /functions/groups/{group}/fmodules/{name} .../source/main vnd.sap.adt.functions.fmodules.v1+xml
4 functiongroup 函数组 /functions/groups/{name} — (None) vnd.sap.adt.functions.groups.v2+xml
5 interface 接口 /oo/interfaces/{name} /oo/interfaces/{name}/source/main vnd.sap.adt.oo.interfaces.v1+xml
6 domain 域(DOMAIN) /ddic/domains/{name} /ddic/domains/{name}/source/main vnd.sap.adt.domains.v2+xml
7 dataelement 数据元素 /ddic/dataelements/{name} .../source/main vnd.sap.adt.dataelements.v2+xml
8 table 透明表 /ddic/tables/{name} .../source/main vnd.sap.adt.ddic.tables.v1+xml
9 structure 结构 /ddic/structures/{name} .../source/main vnd.sap.adt.ddic.structures.v1+xml
10 tabletype 表类型 /vit/.../object_name/{name} — (None) vnd.sap.adt.ddic.tabletypes.v1+xml
11 include Include程序 /programs/includes/{name} .../source/main vnd.sap.adt.programs.includes.v2+xml
12 cdsview CDS视图 /dds/ddl/sources/{name} /dds/ddl/sources/{name}/content text/plain
13 messageclass 消息类 /oo/t100/messages/classes/{name} — (None) vnd.sap.adt.t100.message.classes.v1+xml
14 view 数据库视图 /ddic/views/{name} .../source/main vnd.sap.adt.ddic.views.v1+xml
15 searchhelp 搜索帮助 /ddic/searchhelps/{name} — (None) vnd.sap.adt.ddic.searchhelps.v1+xml
16 lockobject 锁对象 /ddic/lockobjects/{name} — (None) vnd.sap.adt.ddic.lockobjects.v1+xml

关键判定规则has_source=False 的 5 种类型(functiongroup / tabletype / messageclass / searchhelp / lockobject无法执行源码类操作(download / sync / upload / syntax-check / format / diff),命令会在 parse_object_name 后因 src_uri is NoneInvalidNameError

client.py 中各操作的 HTTP 实现

操作 client 方法 HTTP 调用 所在 Mixin
读源码 get_source GET {src_uri} (text/plain) _source.py
写源码 set_source PUT {src_uri} (含 corrNr 重试) _source.py
锁定 lock POST {obj_uri}?_action=LOCK _source.py
解锁 unlock POST {obj_uri}?_action=UNLOCK _source.py
激活 activate POST /adt/activation?method=activate _source.py
语法检查 syntax_check POST /adt/activation?method=check _source.py
删除 delete_object DELETE {obj_uri} (先锁) _ddic.py
创建(通用) create_object POST {collection_uri} _ddic.py
创建(DDIC) create_ddic_object POST/PUT {src_uri} (DDL) _ddic.py
状态查询 get_object_status GET {obj_uri} (+ lock 探测 corrNr) _ddic.py
存在检查 object_exists GET {obj_uri} (200/404) _base.py
函数组创建 create_function_group POST {collection} _ddic.py
CDS 源码 get_cds_source/create_cds GET/POST /ddic/ddlsources/* _ddic.py
对象列表 list_objects GET /repository/informationsystem/search _search.py
引用查询 where_used POST /usage/whereusedlist _search.py
代码搜索 search_code POST /repository/structuredsearch _search.py
ATC 检查 atc_check POST /atos/checks _ddic.py
格式化 pretty_print POST /prettyprinter _ddic.py
表结构 get_table_fields GET /datapreview/ddic/{name}/metadata _ddic.py
表数据 query_table_data POST /datapreview/freestyle _ddic.py
运行程序 run_program POST /programs/programrun/{name} _ddic.py

第三部分:半实现 / 受限功能列表

🔴 关键限制(会导致功能不可用)

  1. create 通用命令不支持 6 种类型client/_ddic.py::_build_create_body 仅覆盖 9 种类型,对其余直接 raise ValueError("不支持的对象类型")

    • includecdsviewmessageclassviewsearchhelplockobject
    • 其中 cdsview 有独立的 cds create 命令可绕过;其余 5 种完全无法创建
  2. CDS View 端点不一致(潜在 Bug) — 两套 URI 并存:

    • types.py 注册的 cdsview/sap/bc/adt/dds/ddl/sources/{name} + /content
    • cds.py 命令 & client._ddic.py 硬编码:/sap/bc/adt/ddic/ddlsources/{name} + /source/main
    • 后果:download --type cdsview 走 types.py 的 URI,可能 404;而 cds download 走另一套 URI。
  3. tabletype 创建必须传 --definition_create_ddic 对 tabletype 无默认模板,缺 line_type 时直接 raise CreateError

🟡 功能降级(有 fallback 但不完整)

  1. info 命令 Accept 头映射不全cmd_infoINFO_ACCEPT 字典只覆盖 9 种类型,以下 7 种回退到 application/xml(可能触发 406 后再回退):

    • ⚠️ structureincludecdsviewmessageclassviewsearchhelplockobject
  2. list/whereused/search 的 ADT 类型码映射不全search.py::_TYPE_FILTER_MAP 缺 2 种:

    • ⚠️ searchhelplockobject(会原样传 key 当类型码,ADT 端可能不识别)
  3. NW 7.40 激活空响应client/_source.py::activate 注释标注:NW 7.40 返回空响应时已实现「双重激活」变通,但仍可能提示「对象仍 inactive,请在 SE09 手动激活」(返回 W 级消息)。

  4. tabletype 用 VIT 端点parse_object_name 对 tabletype 做大写处理,注释说明「VIT 端点需要大写名称以返回完整元数据」,暗示该端点行为特殊。

🟢 设计限制(非 Bug

  1. functiongroup 是容器对象has_source=Falsedownload/sync/upload/format 等源码操作明确拒绝(提示「不包含可编辑的源代码文件」)。

  2. scaffold 模板中的 TODOscaffold.py 模板字符串内的 \" TODO: 填充数据 / \" TODO: 调用 BAPI 函数生成的代码占位符,非 CLI 自身 TODO。

  3. DDIC 源码下载语义 — domain/dataelement/table/structure 虽有 src_uri,但其 source/main 返回的是 DDL/XML 定义而非可编辑 ABAP 文本,download 技术可用但语义需注意。

未发现的问题

  • 未发现 NotImplementedErrorpass 占位方法、或裸 ... 存根。
  • 所有 parser 注册的命令在 app.py 均有对应 handler(无悬空命令)。

第四部分:命令 × 类型 完整交叉矩阵

图例 完全支持 ⚠️ 部分支持/有降级 不支持 不适用(命令与对象类型无关)

仅列出「带 --type 参数、面向单个对象类型」的 14 个命令。init/refresh/sync --all/analyze/config/auth/transport/package/scaffold/show-table/read-table/run-program/cds 为项目级或领域专属命令,对所有类型行为一致,不纳入交叉矩阵。

命令 \ 类型 report class function functiongroup interface domain dataelement table structure tabletype include cdsview messageclass view searchhelp lockobject
download ¹
sync ¹
upload ¹
syntax-check ¹
format ¹
diff ¹
info ⚠️² ⚠️² ⚠️² ⚠️² ⚠️² ⚠️² ⚠️² ⚠️²
delete
activate
create ³ ³ ⚠️ ⚠️
check (ATC)
whereused ⚠️ ⚠️
list ⚠️ ⚠️
search ⚠️ ⚠️

脚注

  • ¹ cdsview 经通用源码命令:走 types.py/dds/ddl/sources/{name}/content 端点,与专用 cds 命令的 /ddic/ddlsources/{name}/source/main 不一致,可能失败(见第三部分#2)。
  • ² info 降级:无显式 Accept 头,回退 application/xml(见第三部分#4)。
  • ³ function/functiongroup 特殊创建function 自动创建函数组;functiongroup 走 create_function_group 专用路径。
  • tabletype 创建受限:必须 --definition 指定 line_type,无默认模板(见第三部分#3)。
  • create 不支持_build_create_body 直接 ValueError(见第三部分#1)。messageclass/view/searchhelp/lockobject/include 无任何创建路径。
  • cdsview 经通用 create 失败:但可用专用 cds create 命令。
  • ADT 类型码缺失_TYPE_FILTER_MAP 无 searchhelp/lockobject 映射,过滤参数原样透传(见第三部分#5)。

支持度统计

命令 完全 ⚠️ 部分 不支持
download/sync/upload/syntax-check/format/diff 11 0 5
info 9 7 0
delete 16 0 0
activate / check 16 0 0
create 9 2 5
whereused / list / search 14 2 0

结论delete/activate/check 三命令对全部 16 种类型通用;源码类 6 命令对 11 种 has_source 类型通用;create 是缺口最大的命令6 种类型无法创建)。


报告结束。如需复查某条判定,可按文中引用的文件路径与行号定位源码。