MCPcopy Create free account
hub / github.com/PHPantom-dev/phpantom_lsp / parse_phpstan_json

Function parse_phpstan_json

src/phpstan.rs:245–306  ·  view source on GitHub ↗

Parse PHPStan's JSON output into LSP diagnostics. PHPStan JSON format (with `--error-format=json`): ```json { "totals": { "errors": 0, "file_errors": 2 }, "files": { "/path/to/file.php": { "errors": 2, "messages": [ { "message": "...", "line": 42, "ignorable": true, "identifier": "argument.type" } ] } }, "errors": [] } ``` We extract messages for the file being edited (matching by path) and als

(json_str: &str, file_path: &Path)

Source from the content-addressed store, hash-verified

243/// We extract messages for the file being edited (matching by path)
244/// and also include top-level `errors` (configuration/internal errors).
245fn parse_phpstan_json(json_str: &str, file_path: &Path) -> Result<Vec<Diagnostic>, String> {
246 let output: serde_json::Value = serde_json::from_str(json_str)
247 .map_err(|e| format!("Failed to parse PHPStan JSON: {}", e))?;
248
249 let mut diagnostics = Vec::new();
250
251 // Extract file-level errors.
252 if let Some(files) = output.get("files").and_then(|f| f.as_object()) {
253 // PHPStan keys files by their real path. The --tmp-file flag
254 // causes PHPStan to report errors under the *original* file
255 // path (the --instead-of path), not the temp file path.
256 // We need to match against the original file path.
257 let file_path_str = file_path.to_string_lossy();
258
259 for (path, file_data) in files {
260 // Match the file: PHPStan normalizes to absolute paths,
261 // so compare by checking if either path ends with the other
262 // or if they match exactly.
263 if !paths_match(path, &file_path_str) {
264 continue;
265 }
266
267 if let Some(messages) = file_data.get("messages").and_then(|m| m.as_array()) {
268 for msg in messages {
269 if let Some(diag) = parse_phpstan_message(msg) {
270 diagnostics.push(diag);
271 }
272 }
273 }
274 }
275 }
276
277 // Extract top-level errors (configuration issues, etc.).
278 if let Some(errors) = output.get("errors").and_then(|e| e.as_array()) {
279 for error in errors {
280 if let Some(error_str) = error.as_str() {
281 diagnostics.push(Diagnostic {
282 range: Range {
283 start: Position {
284 line: 0,
285 character: 0,
286 },
287 end: Position {
288 line: 0,
289 character: 0,
290 },
291 },
292 severity: Some(DiagnosticSeverity::ERROR),
293 code: Some(NumberOrString::String("phpstan".to_string())),
294 code_description: None,
295 source: Some("phpstan".to_string()),
296 message: error_str.to_string(),
297 related_information: None,
298 tags: None,
299 data: None,
300 });
301 }
302 }

Calls 5

parse_phpstan_messageFunction · 0.85
pushMethod · 0.80
as_strMethod · 0.80
paths_matchFunction · 0.70
getMethod · 0.45