R001: 禁止使用getSync系统接口

SkillDev tools

A skill for dev tools by openharmonyinsight.

Available today. Use it from your connected AI after setup.

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.

规则元数据

字段
规则IDR001
规则名称禁止使用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, R006get_all_source_files()
测试代码规范仅测试文件R002, R003, R004, R015, R016, R018get_test_files()
配置文件配置文件R007, R010, R012, R014, R017特殊处理

陷阱:误报应用API的getSync

问题描述: 不是所有getSync()调用都违反R001。只有系统参数模块(@ohos.systemparameter等)的getSync()才是禁止的。应用API(如@ohos.data.preferencesmPreference.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 importimport { systemParameterEnhance } from '@ohos.systemParameterEnhance'较多
Default importimport 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须扫描所有源文件)。

参考文档

Signals

GitHub stars
34
Forks
7
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
r001
Source
github.com/openharmonyinsight/openharmony-skills