pytest_language_server/providers/
diagnostics.rs1use super::Backend;
4use tower_lsp_server::ls_types::*;
5use tracing::info;
6
7impl Backend {
8 pub async fn publish_diagnostics_for_file(&self, uri: &Uri, file_path: &std::path::Path) {
10 let mut diagnostics: Vec<Diagnostic> = Vec::new();
11
12 let config = self.config.read().await;
14 let config = &*config; if !config.is_diagnostic_disabled("undeclared-fixture") {
18 let undeclared = self.fixture_db.get_undeclared_fixtures(file_path);
19 for fixture in undeclared {
20 let line = Self::internal_line_to_lsp(fixture.line);
21 diagnostics.push(Diagnostic {
22 range: Self::create_range(
23 line,
24 fixture.start_char as u32,
25 line,
26 fixture.end_char as u32,
27 ),
28 severity: Some(DiagnosticSeverity::WARNING),
29 code: Some(NumberOrString::String("undeclared-fixture".to_string())),
30 code_description: None,
31 source: Some("pytest-lsp".to_string()),
32 message: format!(
33 "Fixture '{}' is used but not declared as a parameter",
34 fixture.name
35 ),
36 related_information: None,
37 tags: None,
38 data: None,
39 });
40 }
41 }
42
43 if !config.is_diagnostic_disabled("circular-dependency") {
45 let cycles = self.fixture_db.detect_fixture_cycles_in_file(file_path);
46 for cycle in cycles {
47 let line = Self::internal_line_to_lsp(cycle.fixture.line);
48 let cycle_str = cycle.cycle_path.join(" → ");
49 diagnostics.push(Diagnostic {
50 range: Self::create_range(
51 line,
52 cycle.fixture.start_char as u32,
53 line,
54 cycle.fixture.end_char as u32,
55 ),
56 severity: Some(DiagnosticSeverity::ERROR),
57 code: Some(NumberOrString::String("circular-dependency".to_string())),
58 code_description: None,
59 source: Some("pytest-lsp".to_string()),
60 message: format!("Circular fixture dependency detected: {}", cycle_str),
61 related_information: None,
62 tags: None,
63 data: None,
64 });
65 }
66 }
67
68 if !config.is_diagnostic_disabled("scope-mismatch") {
70 let mismatches = self.fixture_db.detect_scope_mismatches_in_file(file_path);
71 for mismatch in mismatches {
72 let line = Self::internal_line_to_lsp(mismatch.fixture.line);
73 diagnostics.push(Diagnostic {
74 range: Self::create_range(
75 line,
76 mismatch.fixture.start_char as u32,
77 line,
78 mismatch.fixture.end_char as u32,
79 ),
80 severity: Some(DiagnosticSeverity::WARNING),
81 code: Some(NumberOrString::String("scope-mismatch".to_string())),
82 code_description: None,
83 source: Some("pytest-lsp".to_string()),
84 message: format!(
85 "{}-scoped fixture '{}' depends on {}-scoped fixture '{}'",
86 mismatch.fixture.scope.as_str(),
87 mismatch.fixture.name,
88 mismatch.dependency.scope.as_str(),
89 mismatch.dependency.name
90 ),
91 related_information: None,
92 tags: None,
93 data: None,
94 });
95 }
96 }
97
98 info!("Publishing {} diagnostics for {:?}", diagnostics.len(), uri);
99 self.client
100 .publish_diagnostics(uri.clone(), diagnostics, None)
101 .await;
102 }
103}