以下为 HarmonyOS 5 DevEco Studio中仓颉语言的实时错误检查与快速修复完整指南,包含错误检测、快速修复及自定义规则的代码级实现:
1. 实时检查架构
2. 核心错误检测
2.1 语法错误检查
// syntax-check.cj
#[diagnostic(syntax)]
fn check_missing_semicolon(ast: &AST) -> Vec<Error> {
ast.statements.iter().filter_map(|stmt| {
if stmt.ends_with_semicolon().is_none() {
Some(Error::new("E001", "缺少分号")
.at(stmt.span())
.with_fix("插入分号", || stmt.add_semicolon()))
} else {
None
}
}).collect()
}
2.2 类型推断检查
// type-check.cj
fn check_type_mismatch(expr: &Expr, expected: &Type) -> Option<Error> {
let actual = infer_type(expr);
if !actual.is_subtype_of(expected) {
Some(Error::new("E302", format!("类型不匹配: 需要 {}, 发现 {}", expected, actual))
.with_fix("添加类型转换", || {
format!("{}.into()", expr.to_string())
}))
} else {
None
}
}
3. 快速修复机制
3.1 自动导入修复
// auto-import.cj
fn fix_missing_import(error: &Error) -> QuickFix {
let symbol = error.context::<UnresolvedSymbol>();
let candidates = find_symbol_in_deps(&symbol.name);
QuickFix {
title: "导入模块",
edits: candidates.map(|candidate| {
Edit::insert(
Position::start_of_file(),
format!("use {};\n", candidate.path)
)
})
}
}
3.2 所有权修复
// ownership-fix.cj
fn fix_use_after_move(error: &Error) -> QuickFix {
let moved_var = error.context::<MovedVariable>();
QuickFix {
title: "克隆值",
edits: vec![
Edit::replace(
moved_var.span,
format!("{}.clone()", moved_var.name)
)
]
}
}
4. 安全规则检查
4.1 空指针防护
// null-check.cj
#[diagnostic(safety)]
fn check_null_deref(expr: &Expr) -> Option<Error> {
if let Expr::Deref(ptr) = expr {
if ptr.may_be_null() {
return Some(Error::new("E501", "可能的空指针解引用")
.with_fix("添加空检查", || {
format!("if {} != null {{ {} }}", ptr, expr)
}));
}
}
None
}
4.2 并发安全
// concurrency-check.cj
fn check_data_race(fn_def: &Function) -> Vec<Error> {
let mut errors = vec![];
for (var, accesses) in collect_shared_accesses(fn_def) {
if has_concurrent_access(&accesses) {
errors.push(Error::new("E601", format!("数据竞争风险: {}", var))
.with_fix("添加互斥锁", || {
format!("let {} = Mutex::new({});", var, var)
}));
}
}
errors
}
5. 自定义检查规则
5.1 项目特定规则
// custom-rule.cj
#[project_rule("no-raw-ptr")]
fn check_raw_pointers(ast: &AST) -> Vec<Error> {
ast.find_all::<RawPointer>().map(|ptr| {
Error::new("P001", "禁止使用裸指针")
.with_fix("替换为SafePtr", || {
format!("SafePtr::new({})", ptr.expr)
})
}).collect()
}
5.2 样式约束
// style-rule.cj
#[style_rule("camelCase")]
fn check_naming(ident: &Ident) -> Option<Error> {
if !ident.text.is_camel_case() {
Some(Error::new("S101", "命名需使用驼峰式")
.with_fix("重命名", || {
ident.text.to_camel_case()
}))
} else {
None
}
}
6. 实时检查集成
6.1 IDE适配器
// ide-adapter.cj
impl LSPHandler {
fn handle_did_change(&mut self, text: &str) {
let errors = Analyzer::check_all(text);
self.client.publish_diagnostics(errors);
}
fn handle_code_action(&self, range: Range) -> Vec<CodeAction> {
self.errors.in_range(range)
.map(|e| e.to_code_action())
.collect()
}
}
6.2 快速修复协议
// LSP协议示例
{
"method": "textDocument/codeAction",
"params": {
"textDocument": { "uri": "file:///project/main.cj" },
"range": { /* 错误位置 */ },
"context": { "diagnostics": [...] }
}
}
7. 开发者工作流
7.1 错误面板交互
// 界面伪代码
class ErrorPanel {
showErrors(errors: Diagnostic[]) {
errors.forEach(err => {
this.addEntry(err.message, {
quickFix: () => applyFix(err.fixes[0]),
learnMore: () => openDocs(err.code)
});
});
}
}
7.2 快速修复快捷键
// keybindings.json
{
"key": "Ctrl+.",
"command": "editor.codeAction.quickFix",
"when": "editorHasError"
}
8. 完整示例场景
8.1 检测到错误
// 原始代码(有错误)
fn calculate(a: i32, b: i32) -> i32 {
a + b // 缺少分号
}
IDE显示:
E001: 缺少分号 [行3, 列10]
建议修复:
1. 插入分号 (Ctrl+.)
8.2 应用修复后
// 修复后代码
fn calculate(a: i32, b: i32) -> i32 {
a + b;
}
9. 检查器配置
9.1 规则配置文件
// .cangjielint
{
"rules": {
"syntax": true,
"types": {
"strict": true,
"ignore_tests": false
},
"security": {
"null_checks": true,
"data_races": true
}
}
}
9.2 禁用规则
// 局部禁用检查
#[allow("E501")] // 允许空指针检查
unsafe fn raw_operation() {
// 不安全操作
}
10. 性能优化
10.1 增量检查
// incremental-check.cj
struct IncrementalChecker {
prev_ast: Option<AST>,
file_deps: FileDependencyGraph
}
impl IncrementalChecker {
fn check_changes(&mut self, new_text: &str) -> Vec<Error> {
let new_ast = parse(new_text);
let diff = ast_diff(&self.prev_ast, &new_ast);
self.file_deps.update(&diff);
check_affected(&diff, &self.file_deps)
}
}
10.2 并行检查
// parallel-check.cj
fn parallel_check(files: &[Path]) -> Vec<Error> {
files.par_iter()
.flat_map(|file| {
let content = read_file(file);
Analyzer::check(&content)
})
.collect()
}
11. 扩展开发接口
11.1 自定义检查插件
// plugin.cj
#[diagnostic_plugin]
struct MyPlugin {
rules: Vec<Box<dyn CheckRule>>,
fn analyze(&self, ast: &AST) -> Vec<Error> {
self.rules.iter()
.flat_map(|rule| rule.check(ast))
.collect()
}
}
11.2 动态规则加载
# 加载外部规则
cangjie check --load-plugin ./security-rules.cjso
12. 关键检查指标
| 检查类型 | 平均延迟 | 内存开销 | 可修复率 |
|---|---|---|---|
| 语法检查 | 50ms | 5MB | 95% |
| 类型检查 | 120ms | 20MB | 85% |
| 安全规则 | 200ms | 30MB | 70% |
| 自定义规则 | 80ms | 10MB | 60% |
通过DevEco Studio集成可实现:
- 毫秒级 错误反馈
- 一键修复 常见问题
- 可扩展 检查规则
- 无缝集成 构建系统