skills/check-test-code-quality/rules/R005/SKILL.md
# R005: 组件尺寸使用固定值 ## 规则信息 | 属性 | 值 | |------|------| | 规则编号 | R005 | | 问题类型 | 组件尺寸使用固定值 | | 严重级别 | Warning | | 规则复杂度 | complex | ## 问题描述 UI组件的width/height属性使用了固定像素值,导致多设备上页面适用性差,引起XTS适配问题。应使用百分比方式实现自适应布局。 **规范来源**: 用例低级问题.md 第5条 — "页面设计涉及组件尺寸大小,禁止使用固定值,考虑百分比方式" ## 扫描范围 **⚠️ 关键陷阱**: R005必须扫描**所有源代码文件**,不是测试文件!仅扫描`.test.ets`会漏报47226个问题(检出率0%)。 > 详见 [references/TRAPS.md](../../references/TRAPS.md) 陷阱2/7。 ## 检测逻辑 ### 步骤1: 收集文件 ```python def get_r005_scan_files(directory: str) -> list[str]
npx skillsauth add openharmonyinsight/openharmony-skills skills/check-test-code-quality/rules/R005Install 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.
| 属性 | 值 | |------|------| | 规则编号 | R005 | | 问题类型 | 组件尺寸使用固定值 | | 严重级别 | Warning | | 规则复杂度 | complex |
UI组件的width/height属性使用了固定像素值,导致多设备上页面适用性差,引起XTS适配问题。应使用百分比方式实现自适应布局。
规范来源: 用例低级问题.md 第5条 — "页面设计涉及组件尺寸大小,禁止使用固定值,考虑百分比方式"
⚠️ 关键陷阱: R005必须扫描所有源代码文件,不是测试文件!仅扫描.test.ets会漏报47226个问题(检出率0%)。
详见 references/TRAPS.md 陷阱2/7。
def get_r005_scan_files(directory: str) -> list[str]:
source_files = get_all_source_files(directory) # .ets, .ts, .js
return source_files
对每个文件逐行扫描,检测以下模式:
模式A — 数值参数形式:
import re
# .width(100), .width( 200 ), .height(50)
numeric_pattern = re.compile(r'\.(width|height)\s*\(\s*\d+\s*\)')
模式B — 字符串参数形式:
# .width('100px'), .width("100vp"), .height('200fp'), .height("50lpx")
string_pattern = re.compile(
r"""\.(width|height)\s*\(\s*['"]\s*\d+\s*(?:px|vp|fp|lpx)?\s*['"]\s*\)""",
re.IGNORECASE
)
排除模式(不应报告):
# 百分比 — 正确用法
# .width('50%'), .width("100%")
percent_pattern = re.compile(r'\.(width|height)\s*\(\s*['"]?\s*\d+\.?\d*\s*%')
# 变量引用 — 正确用法
# .width(widthValue), .height(this.height)
variable_pattern = re.compile(r'\.(width|height)\s*\(\s*[a-zA-Z_$]')
对于源代码文件(非测试文件),testcase 字段固定为 -。
对于测试文件(.test.ets/.test.ts/.test.js),需要解析该行所在的 it() 块,取 it(' 后的第一个字符串参数作为 testcase 名称。
def find_testcase_for_line(lines: list[str], target_line: int) -> str:
if not is_test_file(filepath):
return '-'
# 向上搜索最近的 it('...') 声明
for i in range(target_line - 1, -1, -1):
match = re.search(r"\bit\s*\(\s*['\"]([^'\"]+)['\"]", lines[i])
if match:
return match.group(1)
return '-'
每检测到一个问题,生成以下格式的数据:
{
'rule': 'R005',
'type': '组件尺寸使用固定值',
'severity': 'Warning',
'file': relative_file_path,
'line': line_number,
'testcase': testcase_name,
'snippet': matched_line.strip(),
'suggestion': f'路径: {relative_file_path}, 行号: {line_number}, 问题描述: {prop}使用了固定像素值,建议使用百分比方式实现自适应布局'
}
| 列名 | 说明 |
|------|------|
| 问题ID | R005 |
| 问题类型 | 组件尺寸使用固定值 |
| 严重级别 | Warning |
| 文件路径 | 相对路径 |
| 行号 | 问题所在行号 |
| 所属用例 | it(' 后的参数,非测试文件为 - |
| 代码片段 | 匹配到的代码行 |
| 修复建议 | 路径+行号+问题描述 |
// 错误1: width和height都使用固定数值
@Component
struct MyComponent {
build() {
Text('Hello')
.width(100) // ✗ 错误:使用固定像素值
.height(50); // ✗ 错误:使用固定像素值
}
}
// 错误2: height使用固定数值
@Component
struct MyComponent {
build() {
Text('Hello')
.width('50%')
.height(200); // ✗ 错误:使用固定像素值
}
}
// 错误3: 使用字符串形式的固定值
@Component
struct MyComponent {
build() {
Image($r('app.media.icon'))
.width('100px') // ✗ 错误:使用固定像素值
.height("100vp"); // ✗ 错误:使用固定像素值
}
}
// 错误4: 带空格的数值参数
Column() {
Row()
.width( 300 ) // ✗ 错误:使用固定像素值
.height( 200 ) // ✗ 错误:使用固定像素值
}
// 正确1: 使用百分比
@Component
struct MyComponent {
build() {
Text('Hello')
.width('50%') // ✓ 正确:使用百分比
.height('30%'); // ✓ 正确:使用百分比
}
}
// 正确2: 使用自适应布局
@Component
struct MyComponent {
build() {
Text('Hello')
.width('100%') // ✓ 正确:自适应宽度
.layoutWeight(1); // ✓ 正确:自适应高度
}
}
// 正确3: 使用变量(从配置或计算获取)
@Component
struct MyComponent {
@State componentWidth: number = 0
@State componentHeight: string = '50%'
aboutToAppear() {
this.componentWidth = 200
}
build() {
Text('Hello')
.width(this.componentWidth) // ✓ 正确:使用变量
.height(this.componentHeight) // ✓ 正确:使用变量
}
}
# 使用grep快速扫描(仅数值形式)
grep -rn '\.width\s*(\s*[0-9]' --include='*.ets' --include='*.ts' --include='*.js' /path/to/code
# 使用grep快速扫描(字符串形式)
grep -rn "\.width\s*(\s*['\"]" --include='*.ets' --include='*.ts' --include='*.js' /path/to/code
.ets, .ts, .js),不能只扫描测试文件'50%'、"100%")不算违规.width(someVar))不算违规--level warning 或 --level all挑战: 准确识别固定值,排除百分比和变量
解决方案:
patterns = [
r'\.width\s*\(\s*(\d+)\s*\)', # .width(100)
r'\.height\s*\(\s*(\d+)\s*\)', # .height(100)
r'\.width\s*\(\s*["\'](\d+)px["\']\s*\)', # .width('100px')
]
# 排除百分比
exclude_patterns = [
r'\.width\s*\(\s*["\']\d+%["\']', # .width('50%')
]
---
## 最新评估结果与实现状态(2026-04-14)
### 实现状态
**当前状态**: ❌ **未实现**(使用占位符扫描器)
**技术原因**:
- R005属于"模型生成规则",需要根据本文档的检测逻辑动态生成扫描代码
- 在 `scripts/main.py` 的 `load_rule_scanners()` 函数中,R005被替换为noop扫描器(空操作)
- 当前实现返回空列表,无法检测任何问题
### 改进方案
**方案1:实现为预置脚本(推荐)**
在 `scripts/simple_rules.py` 中添加R005的扫描实现:
```python
# ======================== R005: 组件尺寸使用固定值 ========================
# Source: rules/R005/SKILL.md
_R005_NUMERIC_RE = re.compile(r'\.(width|height)\s*\(\s*(\d+)\s*\)')
_R005_STRING_RE = re.compile(
r"""\.(width|height)\s*\(\s*['"]\s*(\d+)\s*(?:px|vp|fp|lpx)?\s*['"]\s*\)""",
re.IGNORECASE
)
_R005_PERCENT_RE = re.compile(r'\.(width|height)\s*\(\s*['"]?\s*\d+\.?\d*\s*%')
_R005_VARIABLE_RE = re.compile(r'\.(width|height)\s*\(\s*[a-zA-Z_$]')
def scan_r005(files, base_dir):
issues = []
for fp in files:
try:
with open(fp, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
except Exception:
continue
lines = content.split('\n')
for i, line in enumerate(lines, 1):
# 排除百分比和变量引用
if _R005_PERCENT_RE.search(line) or _R005_VARIABLE_RE.search(line):
continue
# 检测数值形式
m_num = _R005_NUMERIC_RE.search(line)
if m_num:
prop = m_num.group(1)
tc = _find_testcase(content, i)
issues.append(_make_issue(
'R005', '组件尺寸使用固定值', 'Warning',
fp, base_dir, i, line,
f'路径: {os.path.relpath(fp, base_dir)}, 行号: {i}, 问题描述: {prop}使用了固定像素值,建议使用百分比方式实现自适应布局',
testcase=tc))
continue
# 检测字符串形式
m_str = _R005_STRING_RE.search(line)
if m_str:
prop = m_str.group(1)
tc = _find_testcase(content, i)
issues.append(_make_issue(
'R005', '组件尺寸使用固定值', 'Warning',
fp, base_dir, i, line,
f'路径: {os.path.relpath(fp, base_dir)}, 行号: {i}, 问题描述: {prop}使用了固定像素值,建议使用百分比方式实现自适应布局',
testcase=tc))
return issues
方案2:动态生成检测代码
修改 scripts/main.py,在扫描时根据本文档的检测逻辑动态生成并执行R005检测代码。
方案3:独立扫描脚本
创建独立的 scripts/scan_r005.py 文件,实现R005的完整检测逻辑。
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