R001: 禁止使用getSync系统接口
SkillDev toolsA skill for dev tools by openharmonyinsight.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the R001: 禁止使用getSync系统接口 skill
What this skill tells your AI
The instructions your AI receives, as published by openharmonyinsight/openharmony-skills in skills/check-test-code-quality/rules/R001/SKILL.md and read by ahel’s review.
规则元数据
| 字段 | 值 |
|---|---|
| 规则ID | R001 |
| 规则名称 | 禁止使用getSync系统接口 |
| 严重级别 | Critical |
| 规则类别 | simple(简单规则,可用grep直接检测) |
| 问题类型 | 源代码规范 |
| 修复建议 | 使用canIUse接口替代或差异化API接口替代 |
问题描述
多设备XTS适配禁止使用任何形式的getSync()系统接口。getSync()是同步阻塞调用,在多设备测试场景中会导致死锁或超时问题。
注意: 本规则只针对系统参数模块的getSync()调用(如@ohos.systemparameter),不针对应用API的getSync()(如mPreference.getSync())。
扫描范围
文件类型(关键)
R001必须扫描所有源代码文件,不仅仅是测试文件:
| 文件类型 | 扩展名 | 是否扫描 |
|---|---|---|
| ArkTS源代码 | .ets | 是 |
| TypeScript源代码 | .ts | 是 |
| JavaScript源代码 | .js | 是 |
| 配置文件 | BUILD.gn, Test.json等 | 否 |
文件扫描函数
def get_all_source_files(directory: str) -> List[str]:
"""
获取所有源代码文件(包括测试文件和非测试文件)
扫描文件类型: .ets, .ts, .js
Args:
directory: 扫描目录
Returns:
源代码文件路径列表
"""
source_files = []
source_extensions = ['.ets', '.ts', '.js']
for root, dirs, files in os.walk(directory):
for file in files:
if any(file.endswith(ext) for ext in source_extensions):
source_files.append(os.path.join(root, file))
return source_files
检测逻辑
第一步:检测系统参数模块的import语句
必须确认文件中存在以下任一import模式,才继续检测getSync调用:
import_patterns = [
r'import\s+.*\s+from\s+[\'"]@ohos\.systemparameter[\'"]',
r'import\s+.*\s+from\s+[\'"]@ohos\.systemParameterEnhance[\'"]',
r'import\s+.*\{.*systemParameter.*\}\s+from\s+[\'"]@kit\.BasicServicesKit[\'"]',
r'import\s+.*\{.*systemParameterEnhance.*\}\s+from\s+[\'"]@kit\.BasicServicesKit[\'"]'
]
关键: 必须先确认import存在,再检测getSync调用。这样可以避免误报应用API的getSync。
注意: @ohos.systemparameter(小写p)和 @ohos.systemParameterEnhance(大写P)是两个不同的模块名,必须分别匹配,不能仅用大小写不敏感的正则。同时必须覆盖 default import(import xxx from)和 named import(import { xxx } from)两种形式。
第二步:检测getSync调用
getsync_pattern = r'(\w+)\.getSync\s*\('
第三步:确认getSync调用对象是系统参数模块的变量
从import语句中提取变量名,然后确认getSync调用使用的变量名与之匹配。
例如:
import parameter from '@ohos.systemparameter'→ 变量名parameter→ 检测parameter.getSync(import systemParameterEnhance from '@ohos.systemParameterEnhance'→ 变量名systemParameterEnhance→ 检测systemParameterEnhance.getSync(import { systemParameter } from '@kit.BasicServicesKit'→ 变量名systemParameter→ 检测systemParameter.getSync(
完整检测代码
import re
import os
def check_r001(file_path: str, base_dir: str = '') -> list:
"""
检测R001问题:禁止使用getSync系统接口
Args:
file_path: 文件绝对路径
base_dir: 基准目录(用于计算相对路径)
Returns:
问题列表,每条问题包含: rule, type, severity, file, line, testcase, snippet, suggestion
"""
issues = []
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
lines = content.split('\n')
full_content = content
# 第一步:检测系统参数模块的import
# 必须同时覆盖 named import 和 default import
# 必须同时覆盖 @ohos.systemparameter 和 @ohos.systemParameterEnhance(大小写不同)
import_patterns = [
# Named import: import { systemParameterEnhance } from '@ohos.systemParameterEnhance'
r'import\s+\{([^}]+)\}\s+from\s+[\'"]@ohos\.systemparameter[\'"]',
r'import\s+\{([^}]+)\}\s+from\s+[\'"]@ohos\.systemParameterEnhance[\'"]',
# Default import: import parameter from '@ohos.systemparameter'
r'import\s+(\w+)\s+from\s+[\'"]@ohos\.systemparameter[\'"]',
r'import\s+(\w+)\s+from\s+[\'"]@ohos\.systemParameterEnhance[\'"]',
# @kit.BasicServicesKit (仅 named import)
r'import\s+\{([^}]*\b(?:systemParameter|systemParameterEnhance)\b[^}]*)\}\s+from\s+[\'"]@kit\.BasicServicesKit[\'"]',
]
has_system_param_import = False
system_param_vars = set()
for pattern in import_patterns:
for match in re.finditer(pattern, full_content):
has_system_param_import = True
if match.lastindex and match.group(1):
system_param_vars.add(match.group(1))
else:
named_match = re.search(
r'\b(systemParameter|systemParameterEnhance)\b',
match.group(0)
)
if named_match:
system_param_vars.add(named_match.group(1))
if not has_system_param_import:
return issues
# 第二步:检测getSync调用
getsync_pattern = r'(\w+)\.getSync\s*\('
for i, line in enumerate(lines, 1):
for match in re.finditer(getsync_pattern, line):
var_name = match.group(1)
# 第三步:确认是系统参数模块的变量
if var_name in system_param_vars:
rel_path = os.path.relpath(file_path, base_dir) if base_dir else file_path
testcase = find_testcase(lines, i)
issues.append({
'rule': 'R001',
'type': '禁止使用getSync系统接口',
'severity': 'Critical',
'file': rel_path,
'line': i,
'testcase': testcase,
'snippet': line.strip(),
'suggestion': (
f"多设备XTS适配禁止使用getSync()系统接口。"
f"请使用canIUse接口替代或差异化API接口替代。"
)
})
return issues
def find_testcase(lines: list, target_line: int) -> str:
"""
查找目标行所在的it()块,提取testcase名称
Args:
lines: 文件所有行(0-indexed list)
target_line: 目标行号(1-indexed)
Returns:
testcase名称,或 '-'
"""
it_pattern = re.compile(r"\bit\s*\(\s*['\"]([^'\"]+)['\"]")
best_it_name = '-'
best_it_start = -1
for i, line in enumerate(lines):
match = it_pattern.search(line)
if match and (i + 1) <= target_line:
if (i + 1) > best_it_start:
best_it_name = match.group(1)
best_it_start = i + 1
if best_it_start > 0 and best_it_start <= target_line:
return best_it_name
return '-'
def scan_directory(directory: str) -> list:
"""
扫描目录中所有源代码文件的R001问题
Args:
directory: 扫描目录
Returns:
所有问题列表
"""
all_issues = []
source_extensions = ['.ets', '.ts', '.js']
for root, dirs, files in os.walk(directory):
for file in files:
if any(file.endswith(ext) for ext in source_extensions):
file_path = os.path.join(root, file)
issues = check_r001(file_path, directory)
all_issues.extend(issues)
return all_issues
检测要点
| 检测项 | 要求 |
|---|---|
| 检测所有形式的getSync()调用 | 必须 |
| 支持多个import语句 | 必须 |
支持变量引用(如parameter.getSync()) | 必须 |
不检测应用API的getSync(如mPreference.getSync()) | 必须 |
| 确认系统参数import存在后才报告 | 必须 |
同时覆盖 @ohos.systemparameter 和 @ohos.systemParameterEnhance 两种大小写 | 必须 |
同时处理 named import({ })和 default import(无 { }) | 必须 |
| 处理多行 import 语句 | 建议 |
输出格式
每条issue必须包含以下字段:
{
'rule': 'R001', # 问题规则编号
'type': '禁止使用getSync系统接口', # 问题类型描述
'severity': 'Critical', # 严重级别
'file': 'rel/path.test.ets', # 相对文件路径
'line': 25, # 问题行号
'testcase': 'testGetSync', # 所属用例名称(it()的第一个参数),无对应用例时为 '-'
'snippet': 'parameter.getSync(...)', # 问题代码片段
'suggestion': '...' # 修复建议
}
testcase字段说明
- 非测试文件(如BUILD.gn、Ability文件、Page文件等)中检测到的问题:testcase字段为
- - 测试文件中不在任何
it()块内的问题(如import语句、describe级别的代码):testcase字段为- - 测试文件中在
it()块内的问题:取it('后面的第一个字符串参数
代码示例
错误示例
错误1:使用parameter.getSync()
import parameter from '@ohos.systemparameter';
export default function test() {
describe('test', () => {
it('test001', () => {
let value = parameter.getSync('key'); // ✗ 错误:使用了getSync系统接口
expect(value).assertEqual('expected');
});
});
}
错误2:使用systemParameterEnhance.getSync()
import systemParameterEnhance from '@ohos.systemParameterEnhance';
export default function test() {
describe('test', () => {
it('test001', () => {
let value = systemParameterEnhance.getSync('key'); // ✗ 错误:使用了getSync系统接口
expect(value).assertEqual('expected');
});
});
}
错误3:从@kit.BasicServicesKit导入并使用getSync
import { systemParameter } from '@kit.BasicServicesKit';
export default function test() {
describe('test', () => {
it('test001', () => {
let value = systemParameter.getSync('key'); // ✗ 错误:使用了getSync系统接口
expect(value).assertEqual('expected');
});
});
}
正确示例
正确1:使用canIUse进行能力判断
import { BusinessError } from '@kit.BasicServicesKit';
export default function test() {
describe('test', () => {
it('test001', () => {
if (canIUse("SystemCapability.xxx")) {
// 基于能力的判断
}
});
});
}
正确2:使用差异化API(异步get替代getSync)
import { BusinessError } from '@kit.BasicServicesKit';
export default function test() {
describe('test', () => {
it('test001', async (done: Function) => {
try {
// 使用异步API替代getSync
let value = await parameter.get('key');
expect(value).assertEqual('expected');
done();
} catch (error) {
expect(error.code).assertEqual(17100001);
done();
}
});
});
}
正确3:使用mPreference等应用API(不是系统接口)
import preferences from '@ohos.data.preferences';
export default function test() {
describe('test', () => {
it('test001', () => {
let value = mPreference.getSync('key'); // ✓ 正确:这是应用API,不是系统接口
expect(value).assertEqual('expected');
});
});
}
陷阱与警告
陷阱:扫描文件类型错误(导致约81个问题漏报)
严重性: 极高
问题描述: R001不仅存在于测试文件(.test.ets)中,也存在于非测试源代码文件(如.ets页面文件、.ts模块文件、Ability文件等)。
错误做法:
# 错误: 只扫描测试文件
test_files = get_test_files(directory) # 只返回 .test.ets/.test.ts/.test.js
for fp in test_files:
check_r001(fp, ...) # 漏掉 Ability/Page 等文件中的 getSync
正确做法:
# 正确: R001 应扫描所有源代码文件
source_files = get_all_source_files(directory) # 返回所有 .ets/.ts/.js
for fp in source_files:
check_r001(fp, ...)
影响: 使用get_test_files()而非get_all_source_files()会导致约81个R001问题漏报。
规则分类参考:
| 规则类别 | 扫描范围 | 相关规则 | 文件扫描函数 |
|---|---|---|---|
| 源代码规范 | 所有源代码文件 | R001, R005, R006 | get_all_source_files() |
| 测试代码规范 | 仅测试文件 | R002, R003, R004, R015, R016, R018 | get_test_files() |
| 配置文件 | 配置文件 | R007, R010, R012, R014, R017 | 特殊处理 |
陷阱:误报应用API的getSync
问题描述: 不是所有getSync()调用都违反R001。只有系统参数模块(@ohos.systemparameter等)的getSync()才是禁止的。应用API(如@ohos.data.preferences的mPreference.getSync())是允许的。
检测策略: 必须先确认文件中存在系统参数模块的import语句,然后再检测getSync调用,且调用变量必须与import的变量名匹配。
陷阱:模块名大小写不匹配(导致约70个问题漏报)
严重性: 严重
问题描述: 系统参数模块存在两种大小写形式的模块名,正则表达式必须同时覆盖,否则会漏检大量问题。
| 模块名形式 | 示例 | 出现频率 |
|---|---|---|
| 小写 | @ohos.systemparameter | 较少 |
| 大写P | @ohos.systemParameterEnhance | 主要形式(约70条) |
正确做法(同时覆盖两种大小写):
import_patterns = [
r'import\s+\{([^}]+)\}\s+from\s+["\']@ohos\.systemparameter["\']',
r'import\s+\{([^}]+)\}\s+from\s+["\']@ohos\.systemParameterEnhance["\']',
r'import\s+\{([^}]+)\}\s+from\s+["\']@kit\.BasicServicesKit["\']',
]
详见 references/TRAPS.md 陷阱3。
陷阱:默认导入(default import)未识别(导致约41个问题漏报)
严重性: 严重
问题描述: 系统参数模块的导入有两种语法形式。如果只处理 named import(大括号形式),会漏检 default import 形式。
| 导入形式 | 语法 | 出现频率 |
|---|---|---|
| Named import | import { systemParameterEnhance } from '@ohos.systemParameterEnhance' | 较多 |
| Default import | import parameter from '@ohos.systemparameter' | 约41条 |
正确做法(同时处理两种导入形式):
# Named import: import { xxx } from '...'
named_import_re = re.compile(
r'import\s+\{([^}]+)\}\s+from\s+["\'](@ohos\.systemparameter(?:Enhance)?|@kit\.BasicServicesKit)["\']'
)
# Default import: import xxx from '...'
default_import_re = re.compile(
r'import\s+(\w+)\s+from\s+["\'](@ohos\.systemparameter(?:Enhance)?|@kit\.BasicServicesKit)["\']'
)
# 使用 re.finditer(而非 re.search)以支持同一文件中的多个导入
详见 references/TRAPS.md 陷阱4。
陷阱:多行导入语句未处理
严重性: 低
部分文件的 import 语句跨多行书写,单行正则无法匹配。扫描前将多行 import 合并为单行即可。
详见 references/TRAPS.md 陷阱2(R001/R005/R006须扫描所有源文件)。
参考文档
- SKILL.md - 主技能文档(规则总览)
- rules/R001/SKILL.md - R001规则完整说明(含示例、实现细节、陷阱说明)
- references/兼容性测试代码设计和编码规范2.0.md - 编码规范参考
- references/用例低级问题.md - 用例低级问题参考
Signals
- GitHub stars
- 34
- Forks
- 7
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
r001- Source
- github.com/openharmonyinsight/openharmony-skills