skills/check-test-code-quality/rules/R017/SKILL.md
# R017: syscap.json配置多个能力 - **规则编号**: R017 - **严重级别**: Critical - **规则复杂度**: complex(需要JSON解析) - **问题类型**: 一个XTS工程的syscap.json文件中配置了多个syscap能力 - **修复方式**: 仅配置一个syscap能力 - **预期问题数量**: 3000+ ## 扫描范围 仅扫描`syscap.json`文件。 **文件定位规则**:在每个XTS工程目录下查找`syscap.json`文件(通常位于工程根目录或`src`目录下)。 ## 问题描述 一个XTS工程的`syscap.json`文件中配置了多个syscap能力。根据规范,每个XTS工程应仅配置一个syscap能力,即被测API对应的能力。 ## 检测逻辑 ### 核心算法 ```python import json import os import re def find_syscap_files(directory: str) -> list: """ 在目录下递归查找
npx skillsauth add openharmonyinsight/openharmony-skills skills/check-test-code-quality/rules/R017Install this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
仅扫描syscap.json文件。
文件定位规则:在每个XTS工程目录下查找syscap.json文件(通常位于工程根目录或src目录下)。
一个XTS工程的syscap.json文件中配置了多个syscap能力。根据规范,每个XTS工程应仅配置一个syscap能力,即被测API对应的能力。
import json
import os
import re
def find_syscap_files(directory: str) -> list:
"""
在目录下递归查找所有syscap.json文件。
Args:
directory: 扫描根目录
Returns:
syscap.json文件绝对路径列表
"""
syscap_files = []
for root, dirs, files in os.walk(directory):
if 'syscap.json' in files:
syscap_files.append(os.path.join(root, 'syscap.json'))
return syscap_files
def scan_r017(file_path: str) -> list:
"""
检查syscap.json文件是否配置了多个syscap能力。
Args:
file_path: syscap.json文件路径
Returns:
问题列表
"""
issues = []
try:
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
except (json.JSONDecodeError, UnicodeDecodeError) as e:
return [{
'rule': 'R017',
'type': 'syscap.json配置多个能力',
'severity': 'Critical',
'file': file_path,
'line': 1,
'testcase': '-',
'snippet': f'syscap.json解析失败: {e}',
'suggestion': f'路径: {file_path}, 行号: 1, 问题描述: syscap.json文件格式错误,无法解析。',
}]
# 检查devices.custom[].xts数组
devices = data.get('devices', {})
custom_devices = devices.get('custom', [])
for device_idx, device in enumerate(custom_devices):
xts_list = device.get('xts', [])
if len(xts_list) > 1:
# 在文件中定位xts数组所在行
line_num = find_xts_array_line(file_path, data)
snippet = ', '.join(xts_list[:3])
if len(xts_list) > 3:
snippet += f', ... (共{len(xts_list)}个)'
issues.append({
'rule': 'R017',
'type': 'syscap.json配置多个能力',
'severity': 'Critical',
'file': file_path,
'line': line_num,
'testcase': '-',
'snippet': snippet,
'suggestion': (
f"路径: {file_path}, 行号: {line_num}, "
f"问题描述: 配置了{len(xts_list)}个syscap能力,应仅配置1个。"
f"请保留被测API对应的能力,移除其余能力。"
),
})
return issues
def find_xts_array_line(file_path: str, data: dict) -> int:
"""
在syscap.json文件中定位xts数组所在的行号。
Args:
file_path: 文件路径
data: 已解析的JSON数据
Returns:
xts数组第一个元素所在行号,找不到返回1
"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
lines = f.readlines()
xts_list = data.get('devices', {}).get('custom', [{}])[0].get('xts', [])
if xts_list:
first_cap = xts_list[0]
for i, line in enumerate(lines, 1):
if first_cap in line:
return i
except Exception:
pass
return 1
def batch_scan_r017(directory: str) -> list:
"""
扫描目录下所有syscap.json文件。
Args:
directory: 扫描根目录
Returns:
所有问题列表
"""
all_issues = []
syscap_files = find_syscap_files(directory)
for file_path in syscap_files:
rel_path = os.path.relpath(file_path, directory)
issues = scan_r017(rel_path)
all_issues.extend(issues)
return all_issues
{
"devices": {
"general": [],
"custom": [
{
"xts": [
"SystemCapability.Ability.AbilityRuntime.Core"
]
}
]
}
}
必须严格按层级类型取值,不可跳层或混淆层级类型。
| JSON路径 | 类型 | 说明 |
|---------|------|------|
| data.devices | dict {str: ...} | 设备配置根节点,包含 "general" 和 "custom" 两个key |
| data.devices.custom | list [dict, ...] | 自定义设备配置数组,每个元素是一个dict |
| data.devices.custom[].xts | list [str, ...] | XTS syscap能力字符串数组(检测目标) |
正确取值方式(两步,不可合并为一步):
# 第1步:从dict中取出custom列表
devices = data.get('devices', {}) # → dict {"general": [], "custom": [...]}
custom_devices = devices.get('custom', []) # → list [dict, ...]
# 第2步:遍历列表中的每个dict
for device in custom_devices: # device → dict {"xts": [...]}
xts_list = device.get('xts', []) # → list [str, ...]
常见错误(会导致100%漏检):
# ✗ 错误:把devices dict直接当列表遍历,遍历的是key字符串
for dev in data.get('devices', []): # dev是"general"或"custom"字符串
dev.get('custom') # → AttributeError: 'str' has no 'get'
# ✗ 错误:合并取值后类型丢失
custom = data.get('devices', {}).get('custom', []) # 正确
for dev in custom:
xts = dev.get('xts', []) # dev必须是dict,如果custom被错误赋值为list of list则会报错
// 错误:配置了多个能力
{
"devices": {
"general": [],
"custom": [
{
"xts": [
"SystemCapability.Ability.AbilityRuntime.Core",
"SystemCapability.Ability.AbilityRuntime.FAModel",
"SystemCapability.Ability.AbilityRuntime.AbilityCore"
]
}
]
}
}
// ✗ 错误:配置了3个syscap能力,应仅配置1个
// 错误:配置了2个能力
{
"devices": {
"general": [],
"custom": [
{
"xts": [
"SystemCapability.Account.OsAccount",
"SystemCapability.Account.AppAccount"
]
}
]
}
}
// ✗ 错误:配置了2个syscap能力,应仅配置1个
// 正确:仅配置一个能力
{
"devices": {
"general": [],
"custom": [
{
"xts": [
"SystemCapability.Ability.AbilityRuntime.Core"
]
}
]
}
}
// ✓ 正确:仅配置了1个syscap能力
// 正确:仅配置一个能力
{
"devices": {
"general": [],
"custom": [
{
"xts": [
"SystemCapability.Web.Webview"
]
}
]
}
}
// ✓ 正确:仅配置了1个syscap能力
{
'rule': 'R017',
'type': 'syscap.json配置多个能力',
'severity': 'Critical',
'file': 'ability/AccessManager/entry/syscap.json',
'line': 5,
'testcase': '-',
'snippet': 'SystemCapability.Ability.AbilityRuntime.Core, SystemCapability.Ability.AbilityRuntime.FAModel, SystemCapability.Ability.AbilityRuntime.AbilityCore',
'suggestion': '路径: ability/AccessManager/entry/syscap.json, 行号: 5, 问题描述: 配置了3个syscap能力,应仅配置1个。请保留被测API对应的能力,移除其余能力。'
}
| 列序 | 列名 | 示例 |
|------|------|------|
| 1 | 问题ID | R017 |
| 2 | 问题类型 | syscap.json配置多个能力 |
| 3 | 严重级别 | Critical |
| 4 | 文件路径 | ability/AccessManager/entry/syscap.json |
| 5 | 行号 | 5 |
| 6 | 所属用例 | - |
| 7 | 代码片段 | SystemCapability.Ability.AbilityRuntime.Core, ... |
| 8 | 修复建议 | 路径: ..., 行号: 5, 问题描述: 配置了3个syscap能力,应仅配置1个... |
注意:所属用例字段始终为-,因为syscap.json不是测试文件,不存在testcase概念。
xts数组中仅保留该能力// 修复前
{
"devices": {
"custom": [
{
"xts": [
"SystemCapability.Ability.AbilityRuntime.Core",
"SystemCapability.Ability.AbilityRuntime.FAModel",
"SystemCapability.Ability.AbilityRuntime.AbilityCore"
]
}
]
}
}
// 修复后(假设被测API属于Core能力)
{
"devices": {
"custom": [
{
"xts": [
"SystemCapability.Ability.AbilityRuntime.Core"
]
}
]
}
}
xts数组为空([])时不报告,因为0个能力不违反"应仅配置1个"的规则。但实际使用中这种情况极少。
custom数组为空时不报告。
如果syscap.json文件缺少devices节点,JSON解析不会报错但不会产生问题报告。可根据实际需要决定是否将缺少devices节点作为额外问题报告。
如果syscap.json文件格式错误(非有效JSON),解析会抛出异常,此时报告为解析错误,便于用户定位和修复。
data['devices'] 是 dict(包含 "general" 和 "custom" 两个key),不是设备列表。必须通过 .get('custom', []) 再取一层才能得到设备列表。如果直接遍历 data['devices'],遍历的是dict的key字符串("general"、"custom"),对字符串调用 .get() 会导致 AttributeError,异常被静默捕获后所有文件全部跳过,造成100%漏检。
验证方法:实现完成后,用以下命令快速验证是否漏检:
grep -r '"SystemCapability' --include='syscap.json' -l | xargs grep -c '"SystemCapability' | grep -v ':1$' | wc -l
如果该命令输出的数量远大于扫描结果数量,说明存在漏检。
来源: EXAMPLES.md
以下为补充示例(与上方已有示例互补):
错误示例:
// 错误:配置多个能力
{
"devices": {
"general": [],
"custom": [
{
"xts": [
"SystemCapability.Ability.AbilityRuntime.Core",
"SystemCapability.Ability.AbilityRuntime.FAModel",
"SystemCapability.Ability.AbilityRuntime.AbilityCore"
]
}
]
}
}
正确示例:
// 正确:仅配置一个能力
{
"devices": {
"general": [],
"custom": [
{
"xts": [
"SystemCapability.Ability.AbilityRuntime.Core"
]
}
]
}
}
来源: IMPLEMENTATION_DETAILS.md
检测范围: syscap.json文件
检测方法: 检查 devices.custom[].xts 数组,如果长度大于1则报错
def check_syscap_json(file_path: str):
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
for device in data['devices']['custom']:
xts_list = device.get('xts', [])
if len(xts_list) > 1:
report_issue(f"配置了{len(xts_list)}个syscap能力,应仅配置1个")
来源: V3_UPGRADE_GUIDE.md
development
Run local code quality checks covering a subset of OpenHarmony gate CI (copyright, CodeArts C/C++) plus additional local checks (pylint/flake8, shellcheck/bashate, gn format). Use before committing to reduce gate failures. Triggers on: /oh-precommit-codecheck, "门禁检查", "门禁预检", "检查代码", "run codecheck", "check code quality", "lint my code", "代码检查", or after completing code implementation. WHEN to use: before git commit, before creating PR, after modifying C/C++/Python/Shell/GN files, when gate CI fails with codecheck defects, or when you want to preview what gate will flag.
development
OpenHarmony PR full lifecycle workflow. Five modes: - Commit: standardized commit with DCO sign-off and Issue linking - Create PR: commit + push to fork + create Issue + create PR on upstream - Fix Codecheck: fetch gate CI codecheck defects from a PR and auto-fix them - Review PR: fetch a PR's changes to local for code review - Fix Review: fetch unresolved review comments from a PR and auto-fix them Triggers on: /oh-pr-workflow, "提交代码", "创建PR", "提个PR", "commit", "修复告警", "修复门禁", "修复codecheck", "fix codecheck", "review pr", "review这个pr", "看下这个pr", "检视pr", "修复review", "修复检视意见", "fix review", or a GitCode PR URL with fix/review intent.
testing
分析 HM Desktop PRD 文档,提取需求信息、验证完整性、检查章节顺序(需求来源→需求背景→需求价值分析→竞品分析→需求描述)、检查 KEP 定义、检测需求冲突并生成结构化分析报告。适用于用户请求:(1) 分析或审查 PRD 文档, (2) 从需求中提取 KEP 列表, (3) 检查 PRD 完整性或一致性, (4) 将需求映射到模块架构, (5) 验证 PRD 格式合规性, (6) 验证竞品分析章节完整性。关键词:PRD分析, requirement extraction, KEP验证, completeness check, chapter order validation, 竞品分析检查, analyze PRD, 需求提取, 完整性检查, 章节顺序验证
development
基于 PRD 文档自动生成鸿蒙系统设计文档,包括架构设计文档和功能设计文档。生成前会分析 OpenHarmony 存量代码结构,确保与现有架构兼容。架构设计文档第2章必须为竞品方案分析,位于需求背景之后。适用于用户请求:(1) 生成架构设计文档, (2) 生成功能设计文档, (3) 从 PRD 生成设计文档, (4) 创建系统架构设计, (5) 编写功能规格说明, (6) 分析 OH 代码结构。关键词:architecture design, functional design, design doc, 竞品方案分析, OpenHarmony code analysis, 架构设计, 功能设计, 设计文档生成, OH代码分析, analyze codebase, competitor analysis