feat: sap-cli skill v2.1.0 — self-contained distributable package

- assets/: sap-cli source (v2.1.0, 26 commands, 16 object types)
- references/: tool constraints + error handling (self-contained)
- scripts/setup.py: one-click install/config/verify
- SKILL.md: full command reference + dual-platform install guide
- VERSION: 2.1.0

Built from D:/Codespace/sap-cli via scripts/pack_skill.py
This commit is contained in:
2026-06-13 20:52:24 +08:00
commit 1e39b6da88
49 changed files with 7172 additions and 0 deletions
+131
View File
@@ -0,0 +1,131 @@
"""代码质量命令:check (ATC) / format (Pretty Printer)。"""
from __future__ import annotations
import argparse
import logging
from sapcli.client import ADTClient
from sapcli.types import get_type_config, parse_object_name
logger = logging.getLogger("sapcli.commands.quality")
def cmd_check(args: argparse.Namespace, client: ADTClient) -> None:
"""ATC 代码检查。"""
name: str = args.name
obj_type: str = args.type
variant: str | None = getattr(args, "variant", None)
parsed = parse_object_name(name, obj_type)
type_label = get_type_config(obj_type).label
print("=" * 60)
print(" SAP ATC 代码检查")
print("=" * 60)
print(f" 对象名称: {parsed.display_name}")
print(f" 对象类型: {type_label}")
if variant:
print(f" 检查变体: {variant}")
print(f"\n → 正在执行 ATC 检查...")
try:
success, findings = client.atc_check(name, parsed.obj_uri, variant)
except Exception as e:
print(f" ✗ ATC 检查失败: {e}")
return
if success and not findings:
print(" ✓ ATC 检查通过,无发现项")
return
errors = [f for f in findings if f["type"] in ("E", "1")]
warnings = [f for f in findings if f["type"] in ("W", "2")]
infos = [f for f in findings if f["type"] in ("I", "3")]
print(f"\n {'' * 50}")
if success:
print(f" ✓ ATC 检查完成(无严重错误)")
else:
print(f" ✗ ATC 检查发现 {len(errors)} 个错误")
print(f" 错误: {len(errors)} | 警告: {len(warnings)} | 信息: {len(infos)}")
print(f" {'' * 50}")
for finding in findings:
severity_icon = {"E": "", "1": "", "W": "", "2": "", "I": "", "3": ""}.get(
finding["type"], "?"
)
line = finding.get("line", "?")
text = finding.get("text", "")
print(f" {severity_icon} [{finding['type']}] 行 {line}: {text}")
def cmd_format(args: argparse.Namespace, client: ADTClient) -> None:
"""代码格式化(ABAP Pretty Printer)。"""
name: str = args.name
obj_type: str = args.type
parsed = parse_object_name(name, obj_type)
type_label = get_type_config(obj_type).label
if parsed.src_uri is None:
print(f"\n{type_label}没有源代码,不支持格式化操作")
return
print("=" * 60)
print(" SAP ABAP 代码格式化")
print("=" * 60)
print(f" 对象名称: {parsed.display_name}")
print(f" 对象类型: {type_label}")
# 读取当前源码
print(f"\n → 正在读取源代码...")
try:
source = client.get_source(parsed.src_uri)
except Exception as e:
print(f" ✗ 读取源代码失败: {e}")
return
print(f" ✓ 源代码读取成功 ({len(source)} 字符)")
# 调用 Pretty Printer
print(f"\n → 正在调用 Pretty Printer...")
try:
formatted = client.pretty_print(source)
except Exception as e:
print(f" ✗ 格式化失败: {e}")
return
if formatted == source:
print(" 代码已经是格式化的,无需修改")
return
print(f" ✓ 格式化完成")
# 写回 SAP
print(f"\n → 正在写回 SAP...")
try:
lock_handle, corr_nr = client.lock(parsed.obj_uri)
try:
client.set_source(parsed.src_uri, formatted, lock_handle, corr_nr)
print(f" ✓ 源代码已写回")
finally:
client.unlock(parsed.obj_uri, lock_handle)
except Exception as e:
print(f" ✗ 写回失败: {e}")
return
# 激活
try:
success, messages = client.activate(name, parsed.obj_uri)
if success:
print(f" ✓ 激活成功")
else:
errors = [m for m in messages if m["type"] == "E"]
print(f" ⚠ 激活返回 {len(errors)} 个错误")
for e in errors:
print(f" [错误] 行 {e['line']}: {e['text']}")
except Exception as e:
print(f" ⚠ 激活失败: {e}")
print(f"\n ✓ 格式化操作完成!")