Skip to content

Commit fff7377

Browse files
committed
feat: pull diagnostics
1 parent 652da2b commit fff7377

File tree

7 files changed

+125
-5
lines changed

7 files changed

+125
-5
lines changed

crates/pg_diagnostics_categories/src/categories.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ define_categories! {
2525
"flags/invalid",
2626
"project",
2727
"internalError/panic",
28+
"syntax",
2829
"dummy",
2930
}

crates/pg_workspace_new/src/workspace.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,22 @@ pub struct ChangeFileParams {
3030
pub changes: Vec<ChangeParams>,
3131
}
3232

33+
#[derive(Debug, serde::Serialize, serde::Deserialize)]
34+
pub struct PullDiagnosticsParams {
35+
pub path: PgLspPath,
36+
// pub categories: RuleCategories,
37+
pub max_diagnostics: u64,
38+
// pub only: Vec<RuleSelector>,
39+
// pub skip: Vec<RuleSelector>,
40+
}
41+
42+
#[derive(Debug, serde::Serialize, serde::Deserialize)]
43+
pub struct PullDiagnosticsResult {
44+
pub diagnostics: Vec<pg_diagnostics::serde::Diagnostic>,
45+
pub errors: usize,
46+
pub skipped_diagnostics: u64,
47+
}
48+
3349
#[derive(Debug, serde::Serialize, serde::Deserialize)]
3450
pub struct ChangeParams {
3551
/// The range of the file that changed. If `None`, the whole file changed.
@@ -72,6 +88,12 @@ pub struct ServerInfo {
7288
}
7389

7490
pub trait Workspace: Send + Sync + RefUnwindSafe {
91+
/// Retrieves the list of diagnostics associated to a file
92+
fn pull_diagnostics(
93+
&self,
94+
params: PullDiagnosticsParams,
95+
) -> Result<PullDiagnosticsResult, WorkspaceError>;
96+
7597
/// Refresh the schema cache for this workspace
7698
fn refresh_schema_cache(&self) -> Result<(), WorkspaceError>;
7799

crates/pg_workspace_new/src/workspace/client.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,11 @@ where
120120
fn refresh_schema_cache(&self) -> Result<(), WorkspaceError> {
121121
self.request("pglsp/refresh_schema_cache", ())
122122
}
123+
124+
fn pull_diagnostics(
125+
&self,
126+
params: super::PullDiagnosticsParams,
127+
) -> Result<super::PullDiagnosticsResult, WorkspaceError> {
128+
self.request("pglsp/pull_diagnostics", params)
129+
}
123130
}

crates/pg_workspace_new/src/workspace/server.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,20 @@ use std::{fs, future::Future, panic::RefUnwindSafe, path::Path, sync::RwLock};
33
use change::StatementChange;
44
use dashmap::{DashMap, DashSet};
55
use document::{Document, StatementRef};
6+
use pg_diagnostics::{serde::Diagnostic as SDiagnostic, Diagnostic, DiagnosticExt, Severity};
67
use pg_fs::{ConfigName, PgLspPath};
78
use pg_query::PgQueryStore;
89
use pg_schema_cache::SchemaCache;
910
use sqlx::PgPool;
1011
use std::sync::LazyLock;
1112
use store::Store;
1213
use tokio::runtime::Runtime;
14+
use tracing::info;
1315
use tree_sitter::TreeSitterStore;
1416

1517
use crate::{
1618
settings::{Settings, SettingsHandle, SettingsHandleMut},
19+
workspace::PullDiagnosticsResult,
1720
WorkspaceError,
1821
};
1922

@@ -291,6 +294,50 @@ impl Workspace for WorkspaceServer {
291294
fn is_path_ignored(&self, params: IsPathIgnoredParams) -> Result<bool, WorkspaceError> {
292295
Ok(self.is_ignored(params.pglsp_path.as_path()))
293296
}
297+
298+
fn pull_diagnostics(
299+
&self,
300+
params: super::PullDiagnosticsParams,
301+
) -> Result<super::PullDiagnosticsResult, WorkspaceError> {
302+
// get all statements form the requested document and pull diagnostics out of every
303+
// sourcece
304+
let doc = self
305+
.documents
306+
.get(&params.path)
307+
.ok_or(WorkspaceError::not_found())?;
308+
309+
let diagnostics: Vec<SDiagnostic> = doc
310+
.statement_refs_with_ranges()
311+
.iter()
312+
.flat_map(|(stmt, r)| {
313+
let mut stmt_diagnostics = vec![];
314+
315+
stmt_diagnostics.extend(self.pg_query.pull_diagnostics(stmt));
316+
317+
stmt_diagnostics
318+
.into_iter()
319+
.map(|d| {
320+
SDiagnostic::new(
321+
d.with_file_path(params.path.as_path().display().to_string())
322+
.with_file_span(r),
323+
)
324+
})
325+
.collect::<Vec<_>>()
326+
})
327+
.collect();
328+
329+
let errors = diagnostics
330+
.iter()
331+
.filter(|d| d.severity() == Severity::Error)
332+
.count();
333+
334+
info!("Pulled {:?} diagnostic(s)", diagnostics.len());
335+
Ok(PullDiagnosticsResult {
336+
diagnostics,
337+
errors,
338+
skipped_diagnostics: 0,
339+
})
340+
}
294341
}
295342

296343
/// Returns `true` if `path` is a directory or

crates/pg_workspace_new/src/workspace/server/document.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ impl Document {
7474
.collect()
7575
}
7676

77+
pub fn statement_refs_with_ranges(&self) -> Vec<(StatementRef, TextRange)> {
78+
self.statements
79+
.iter()
80+
.map(|inner_ref| (self.statement_ref(inner_ref), inner_ref.1))
81+
.collect()
82+
}
83+
7784
#[allow(dead_code)]
7885
/// Returns the statement ref at the given offset
7986
pub fn statement_ref_at_offset(&self, offset: &TextSize) -> Option<StatementRef> {

crates/pg_workspace_new/src/workspace/server/pg_query.rs

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,56 @@
11
use std::sync::Arc;
22

33
use dashmap::DashMap;
4+
use pg_diagnostics::{serde::Diagnostic as SDiagnostic, Diagnostic, MessageAndDescription};
5+
use text_size::TextRange;
46

57
use super::{
68
change::ChangedStatement,
79
document::{Statement, StatementRef},
810
store::Store,
911
};
1012

13+
/// A specialized diagnostic for the libpg_query parser.
14+
///
15+
/// Parser diagnostics are always **errors**.
16+
#[derive(Clone, Debug, Diagnostic)]
17+
#[diagnostic(category = "syntax", severity = Error)]
18+
pub struct SyntaxDiagnostic {
19+
/// The location where the error is occurred
20+
#[location(span)]
21+
span: Option<TextRange>,
22+
#[message]
23+
#[description]
24+
pub message: MessageAndDescription,
25+
}
26+
1127
pub struct PgQueryStore {
1228
ast_db: DashMap<StatementRef, Arc<pg_query_ext::NodeEnum>>,
13-
native_diagnostics: DashMap<StatementRef, Arc<pg_query_ext::Error>>,
29+
diagnostics: DashMap<StatementRef, pg_query_ext::Error>,
30+
}
31+
32+
impl From<&pg_query_ext::Error> for SyntaxDiagnostic {
33+
fn from(err: &pg_query_ext::Error) -> Self {
34+
SyntaxDiagnostic {
35+
span: None,
36+
message: MessageAndDescription::from(err.to_string()),
37+
}
38+
}
1439
}
1540

1641
impl PgQueryStore {
1742
pub fn new() -> PgQueryStore {
1843
PgQueryStore {
1944
ast_db: DashMap::new(),
20-
native_diagnostics: DashMap::new(),
45+
diagnostics: DashMap::new(),
2146
}
2247
}
48+
49+
pub fn pull_diagnostics(&self, ref_: &StatementRef) -> Vec<SDiagnostic> {
50+
self.diagnostics.get(ref_).map_or_else(Vec::new, |err| {
51+
vec![SDiagnostic::new(SyntaxDiagnostic::from(err.value()))]
52+
})
53+
}
2354
}
2455

2556
impl Store<pg_query_ext::NodeEnum> for PgQueryStore {
@@ -32,14 +63,14 @@ impl Store<pg_query_ext::NodeEnum> for PgQueryStore {
3263
if let Ok(ast) = r {
3364
self.ast_db.insert(statement.ref_.clone(), Arc::new(ast));
3465
} else {
35-
self.native_diagnostics
36-
.insert(statement.ref_.clone(), Arc::new(r.unwrap_err()));
66+
self.diagnostics
67+
.insert(statement.ref_.clone(), r.unwrap_err());
3768
}
3869
}
3970

4071
fn remove_statement(&self, statement: &StatementRef) {
4172
self.ast_db.remove(statement);
42-
self.native_diagnostics.remove(statement);
73+
self.diagnostics.remove(statement);
4374
}
4475

4576
fn modify_statement(&self, change: &ChangedStatement) {

justfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,8 @@ new-crate name:
138138
# dry-run-release *args='':
139139
# knope release --dry-run {{args}}
140140

141+
clear-branches:
142+
git branch --merged | egrep -v "(^\\*|main)" | xargs git branch -d
143+
144+
reset-git:
145+
git checkout main && git pull && pnpm run clear-branches

0 commit comments

Comments
 (0)