skills/check-test-code-quality/rules/R010/SKILL.md
# R010: part_name/subsystem_name不匹配 ## 规则信息 | 属性 | 值 | |------|-----| | 规则编号 | R010 | | 问题类型 | part_name/subsystem_name不匹配 | | 严重级别 | Critical | | 规则复杂度 | complex | | 扫描范围 | BUILD.gn files only | | testcase字段 | `-`(BUILD.gn为非测试文件,无对应it()块) | ## 问题描述 `part_name`/`subsystem_name`不匹配。BUILD.gn中声明的`part_name`必须在对应`subsystem_name`的components列表中存在。 ## 修复建议 使用完整的子系统-组件映射表,确保`part_name`在对应`subsystem`的components中。 ## 映射表数据源 映射表从以下三个配置文件构建(合并所有 subsystem → component 关系,共54个子系统、332个部件): | 配置文件 | 主U
npx skillsauth add openharmonyinsight/openharmony-skills skills/check-test-code-quality/rules/R010Install 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.
| 属性 | 值 |
|------|-----|
| 规则编号 | R010 |
| 问题类型 | part_name/subsystem_name不匹配 |
| 严重级别 | Critical |
| 规则复杂度 | complex |
| 扫描范围 | BUILD.gn files only |
| testcase字段 | -(BUILD.gn为非测试文件,无对应it()块) |
part_name/subsystem_name不匹配。BUILD.gn中声明的part_name必须在对应subsystem_name的components列表中存在。
使用完整的子系统-组件映射表,确保part_name在对应subsystem的components中。
映射表从以下三个配置文件构建(合并所有 subsystem → component 关系,共54个子系统、332个部件):
| 配置文件 | 主URL(推荐) | 备用URL |
|---------|-------------|---------|
| vendor_hihope config.json | https://gitee.com/openharmony/vendor_hihope/raw/master/rk3568/config.json | https://gitcode.com/openharmony/vendor_hihope/raw/master/rk3568/config.json |
| productdefine rich.json | https://gitee.com/openharmony/productdefine_common/raw/master/inherit/rich.json | https://gitcode.com/openharmony/productdefine_common/raw/master/inherit/rich.json |
| productdefine chipset_common.json | https://gitee.com/openharmony/productdefine_common/raw/master/inherit/chipset_common.json | https://gitcode.com/openharmony/productdefine_common/raw/master/inherit/chipset_common.json |
重要: 优先使用gitee.com URL,gitcode.com可能需要认证。如果所有URL均不可达,必须在终端输出明确警告,不可静默返回0个问题。
本地缓存: 获取成功后可将映射表缓存到本地文件(如/tmp/r010_mapping.json),下次扫描优先读取缓存,避免每次都请求远程。
扫描目标目录下所有名为BUILD.gn的文件。
import os
def find_build_gn_files(scan_root):
build_gn_files = []
for dirpath, dirnames, filenames in os.walk(scan_root):
if 'BUILD.gn' in filenames:
build_gn_files.append(os.path.join(dirpath, 'BUILD.gn'))
return build_gn_files
对每个BUILD.gn文件,使用正则表达式提取part_name和subsystem_name字段。
import re
def extract_build_gn_fields(content):
part_name = None
subsystem_name = None
part_match = re.search(r'part_name\s*=\s*["\']([^"\']+)["\']', content)
if part_match:
part_name = part_match.group(1)
subsystem_match = re.search(r'subsystem_name\s*=\s*["\']([^"\']+)["\']', content)
if subsystem_match:
subsystem_name = subsystem_match.group(1)
return part_name, subsystem_name
从三个配置文件中读取并合并映射关系。每个配置文件的结构包含子系统定义,每个子系统下有components列表。
⚠️ 数据格式陷阱: components数组中的元素不是纯字符串,而是对象{"component": "xxx", "features": [...]}。直接用set().update(components)会抛unhashable type: 'dict'异常,导致映射表构建失败、R010静默返回0个问题。必须从每个对象中提取component字段。
import json
MAPPING_URLS = [
'https://gitee.com/openharmony/vendor_hihope/raw/master/rk3568/config.json',
'https://gitee.com/openharmony/productdefine_common/raw/master/inherit/rich.json',
'https://gitee.com/openharmony/productdefine_common/raw/master/inherit/chipset_common.json',
]
CACHE_FILE = '/tmp/r010_mapping.json'
def _parse_config(data, subsystem_map):
subsystems = data.get('subsystems', [])
for subsys in subsystems:
name = subsys.get('subsystem', '')
components = subsys.get('components', [])
if name not in subsystem_map:
subsystem_map[name] = set()
for c in components:
if isinstance(c, str):
subsystem_map[name].add(c)
elif isinstance(c, dict):
subsystem_map[name].add(c.get('component', ''))
def load_subsystem_mapping():
# 优先读取本地缓存
import os
if os.path.exists(CACHE_FILE):
with open(CACHE_FILE, 'r', encoding='utf-8') as f:
return {k: set(v) for k, v in json.load(f).items()}
# 从远程获取
import urllib.request
subsystem_map = {}
for url in MAPPING_URLS:
try:
req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'})
with urllib.request.urlopen(req, timeout=30) as resp:
data = json.loads(resp.read().decode('utf-8'))
_parse_config(data, subsystem_map)
except Exception as e:
print(f" 警告: 获取映射表失败 {url}: {e}", file=sys.stderr, flush=True)
if not subsystem_map:
print(" 警告: R010映射表为空,所有BUILD.gn将被跳过!", file=sys.stderr, flush=True)
# 写入缓存
with open(CACHE_FILE, 'w', encoding='utf-8') as f:
json.dump({k: sorted(v) for k, v in subsystem_map.items()}, f, ensure_ascii=False)
return subsystem_map
对每个BUILD.gn,检查提取出的part_name是否在subsystem_name对应的components集合中。
def validate_part_subsystem(part_name, subsystem_name, subsystem_map):
if not part_name or not subsystem_name:
return True
if subsystem_name not in subsystem_map:
return True
return part_name in subsystem_map[subsystem_name]
def scan_r010(build_gn_files, base_dir):
issues = []
subsystem_map = load_subsystem_mapping()
if not subsystem_map:
return issues
for file_path in build_gn_files:
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
part_name, subsystem_name = extract_build_gn_fields(content)
if not part_name or not subsystem_name:
continue
if not validate_part_subsystem(part_name, subsystem_name, subsystem_map):
rel_path = os.path.relpath(file_path, base_dir)
part_line = 0
for i, line in enumerate(content.splitlines(), 1):
if re.search(r'part_name\s*=\s*["\']' + re.escape(part_name) + '["\']', line):
part_line = i
break
available_parts = sorted(subsystem_map.get(subsystem_name, set()))
issues.append({
'rule': 'R010',
'type': 'part_name/subsystem_name不匹配',
'severity': 'Critical',
'file': rel_path,
'line': part_line,
'testcase': '-',
'snippet': f'part_name = "{part_name}", subsystem_name = "{subsystem_name}"',
'suggestion': (
f'part_name "{part_name}" 不在 subsystem_name "{subsystem_name}" 的components中。'
f'可选的part_name: {available_parts}'
),
})
return issues
# BUILD.gn - 错误:invalid_part不在arkui的components中
ohos_js_app_suite("ActsTest") {
testonly = true
part_name = "invalid_part" # ✗ 错误
subsystem_name = "arkui"
hap_name = "ActsTest"
}
# BUILD.gn - 正确:ace_engine在arkui的components中
ohos_js_app_suite("test") {
testonly = true
part_name = "ace_engine" # ✓ 正确
subsystem_name = "arkui"
hap_name = "ActsTest"
}
subsystem_name本身不在映射表中,跳过验证(可能是新增子系统)严重性: 严重,导致unhashable type: 'dict'异常,映射表构建失败。
三个配置文件中components字段的实际数据格式为对象数组,不是纯字符串数组:
{
"subsystem": "arkui",
"components": [
{"component": "ace_engine", "features": []},
{"component": "napi", "features": []}
]
}
错误做法: 直接set().update(components) → 抛异常
正确做法: 逐个判断类型,对象取component字段:
for c in components:
if isinstance(c, str):
mapping[name].add(c)
elif isinstance(c, dict):
mapping[name].add(c.get('component', ''))
gitcode.com的raw文件URL需要认证才能访问,直接请求会返回HTML登录页而非JSON。必须优先使用gitee.com URL。
如果映射表获取失败(网络不通、认证失败等),映射表为空,所有subsystem_name都不在映射表中,全部被跳过,R010返回0个问题且不报任何错误。必须在映射表为空时输出明确警告。
每条issue的字段:
| 字段 | 值 |
|------|-----|
| rule | R010 |
| type | part_name/subsystem_name不匹配 |
| severity | Critical |
| file | 相对路径(如ability/xxx/BUILD.gn) |
| line | part_name所在行号 |
| testcase | - |
| snippet | part_name = "xxx", subsystem_name = "yyy" |
| suggestion | 问题描述 + 可选的part_name列表 |
挑战: 维护完整的子系统-组件映射表
解决方案:
SUBSYSTEM_PARTS_MAP = {
"account": ["os_account"],
"arkui": ["ace_engine", "napi", "ui_appearance", "ui_lite"],
"bundle": ["bundle_framework"],
"communication": ["bluetooth", "wifi", "netstack", "dsoftbus"],
# ... 共50+个子系统
}
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