Parse a single PHPCS message object into an LSP `Diagnostic`.
(msg: &serde_json::Value)
| 288 | |
| 289 | /// Parse a single PHPCS message object into an LSP `Diagnostic`. |
| 290 | fn parse_phpcs_message(msg: &serde_json::Value) -> Option<Diagnostic> { |
| 291 | let message = msg.get("message")?.as_str()?; |
| 292 | let line = msg.get("line").and_then(|l| l.as_u64()).unwrap_or(1); |
| 293 | let lsp_line = line.saturating_sub(1) as u32; |
| 294 | |
| 295 | // PHPCS "source" is the sniff name, e.g. "PSR2.Methods.FunctionCallSignature.Indent" |
| 296 | let source_code = msg |
| 297 | .get("source") |
| 298 | .and_then(|s| s.as_str()) |
| 299 | .unwrap_or("phpcs"); |
| 300 | |
| 301 | // PHPCS "type" is "ERROR" or "WARNING" |
| 302 | let severity = match msg.get("type").and_then(|t| t.as_str()) { |
| 303 | Some("ERROR") => DiagnosticSeverity::ERROR, |
| 304 | _ => DiagnosticSeverity::WARNING, |
| 305 | }; |
| 306 | |
| 307 | let fixable = msg |
| 308 | .get("fixable") |
| 309 | .and_then(|f| f.as_bool()) |
| 310 | .unwrap_or(false); |
| 311 | |
| 312 | let data = Some(serde_json::json!({ "fixable": fixable })); |
| 313 | |
| 314 | // PHPCS reports a single `column` per message, but its meaning |
| 315 | // varies by sniff: for `LineLength.TooLong` it is the total line |
| 316 | // length (the *end*), for indentation sniffs it is the offending |
| 317 | // token start, etc. Because there is no reliable way to derive a |
| 318 | // precise range from a single ambiguous position, we underline the |
| 319 | // full line — the same strategy PHPStan uses. |
| 320 | Some(Diagnostic { |
| 321 | range: Range { |
| 322 | start: Position { |
| 323 | line: lsp_line, |
| 324 | character: 0, |
| 325 | }, |
| 326 | end: Position { |
| 327 | line: lsp_line, |
| 328 | character: u32::MAX, |
| 329 | }, |
| 330 | }, |
| 331 | severity: Some(severity), |
| 332 | code: Some(NumberOrString::String(source_code.to_string())), |
| 333 | code_description: None, |
| 334 | source: Some("phpcs".to_string()), |
| 335 | message: message.to_string(), |
| 336 | related_information: None, |
| 337 | tags: None, |
| 338 | data, |
| 339 | }) |
| 340 | } |
| 341 | |
| 342 | /// Check whether two file paths refer to the same file. |
| 343 | /// |
no test coverage detected