Repository navigation
Expand file tree
/
Copy pathsyntax_worker_command.rs
More file actions
165 lines (161 loc) · 6.31 KB
/
Copy pathsyntax_worker_command.rs
File metadata and controls
165 lines (161 loc) · 6.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
//! 私有语法工作进程:只读 stdin 与固定内置 grammar,不解释项目文件或策略。
use crate::syntax_worker_envelope::SyntaxWorkerEnvelope;
use crate::syntax_worker_recovery::SyntaxWorkerRecovery;
use codeguard_adapters::bundled_grammar_candidate;
use codeguard_runtime::{
WasmGrammar, scan_wasm_empty_blocks, scan_wasm_recoveries, scan_wasm_root_child,
};
use sha2::{Digest, Sha256};
use std::io::Read;
use std::process::ExitCode;
const MAX_SOURCE_BYTES: u64 = 1024 * 1024;
const MAX_RECOVERIES: usize = 128;
/// 在独立进程中解析一份 stdin 源码;参数仅允许固定候选语种。
/// 返回原始恢复观察,不赋予 grammar 验收、原生 lint 或交付权威。
pub fn run(args: &[String]) -> ExitCode {
let [language] = args else {
eprintln!("语法工作进程参数无效");
return ExitCode::from(2);
};
let mut source = Vec::new();
match std::io::stdin()
.lock()
.take(MAX_SOURCE_BYTES + 1)
.read_to_end(&mut source)
{
Ok(_) if source.len() as u64 > MAX_SOURCE_BYTES => {
eprintln!("语法工作进程输入超过上限");
return ExitCode::from(3);
}
Ok(_) => {}
Err(_) => {
eprintln!("语法工作进程输入读取失败");
return ExitCode::from(4);
}
}
if std::str::from_utf8(&source).is_err() {
eprintln!("语法工作进程输入不是 UTF-8");
return ExitCode::from(3);
}
match observe(language, &source) {
Ok(report) => match serde_json::to_string(&report) {
Ok(json) => {
println!("{json}");
ExitCode::SUCCESS
}
Err(_) => ExitCode::from(4),
},
Err(reason) => {
eprintln!("语法工作进程未完成:{reason}");
ExitCode::from(3)
}
}
}
fn observe(language: &str, source: &[u8]) -> Result<SyntaxWorkerEnvelope, String> {
let (asset, wasm) = bundled_grammar_candidate(language)?;
if asset.codeguard_runtime_validation != "rust_loader_smoke_passed" {
return Err("grammar 与当前 Rust WASM 运行时不兼容".into());
}
let mut grammar = WasmGrammar::load(
asset.loader_symbol.as_deref().unwrap_or(language),
wasm,
&asset.sha256,
asset.abi_version as usize,
)?;
let tree = grammar.parse(source)?;
let scanned = scan_wasm_recoveries(&tree, MAX_RECOVERIES)?;
let mut structural_observations = Vec::new();
let mut structural_truncated = false;
if language == "python" {
let blocks = scan_wasm_empty_blocks(&tree, MAX_RECOVERIES)?;
structural_truncated = blocks.truncated;
for block in blocks.blocks {
if !codeguard_adapters::is_required_python_suite_parent(&block.parent_syntax_kind) {
continue;
}
if scanned.recoveries.len() + structural_observations.len() == MAX_RECOVERIES {
structural_truncated = true;
break;
}
structural_observations.push(crate::syntax_worker_structure::SyntaxWorkerStructure {
basis: "codeguard_structure_rule".into(),
rule_id: "codeguard.python.required_suite".into(),
rule_version: "1.0.0".into(),
rule_sha256: codeguard_adapters::python_suite_rule_sha256(),
parent_syntax_kind: block.parent_syntax_kind,
start_byte: block.start_byte,
end_byte: block.end_byte,
start_row: block.start_row,
start_column_byte: block.start_column_byte,
end_row: block.end_row,
end_column_byte: block.end_column_byte,
});
}
}
if language == "go" {
// Go入口观察完整文件,片段模式不在此协议内;声明只能来自直接AST子节点。
let root = scan_wasm_root_child(&tree, "package_clause", 200_000)?;
match codeguard_adapters::missing_go_package_candidate(
language,
true,
&root.root_syntax_kind,
&root.child_syntax_kind,
root.present,
root.truncated,
) {
Some(true) if scanned.recoveries.len() < MAX_RECOVERIES => {
structural_observations.push(
crate::syntax_worker_structure::SyntaxWorkerStructure {
basis: "codeguard_structure_rule".into(),
rule_id: "codeguard.go.required_package".into(),
rule_version: "1.0.0".into(),
rule_sha256: codeguard_adapters::go_package_rule_sha256(),
parent_syntax_kind: root.root_syntax_kind,
// 缺整文件声明的零宽锚点,不冒充原生工具指出的错误列。
start_byte: 0,
end_byte: 0,
start_row: 0,
start_column_byte: 0,
end_row: 0,
end_column_byte: 0,
},
);
}
Some(false) => {}
Some(true) | None => structural_truncated = true,
}
}
let recoveries = scanned
.recoveries
.into_iter()
.map(|anchor| SyntaxWorkerRecovery {
kind: anchor.kind.into(),
group_id: anchor.group_id,
syntax_kind: anchor.syntax_kind,
start_byte: anchor.start_byte,
end_byte: anchor.end_byte,
start_row: anchor.start_row,
start_column_byte: anchor.start_column_byte,
end_row: anchor.end_row,
end_column_byte: anchor.end_column_byte,
})
.collect();
Ok(SyntaxWorkerEnvelope {
schema_version: if structural_observations.is_empty() {
"1.0.0"
} else if language == "go" {
"1.2.0"
} else {
"1.1.0"
}
.into(),
report_type: "syntax_worker_candidate".into(),
language: language.into(),
grammar_sha256: asset.sha256.clone(),
grammar_abi_version: asset.abi_version,
source_sha256: format!("{:x}", Sha256::digest(source)),
truncated: scanned.truncated || structural_truncated,
recoveries,
structural_observations,
})
}