Skip to content

Commit 5c7aa78

Browse files
committed
progress
1 parent e75ff26 commit 5c7aa78

File tree

4 files changed

+85
-13
lines changed

4 files changed

+85
-13
lines changed

crates/pgls_diagnostics/src/display.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,23 @@ impl<D: Diagnostic + ?Sized> fmt::Display for PrintHeader<'_, D> {
139139
fmt.write_str(" ")?;
140140
}
141141

142+
// Print the database object if present (e.g., "table public.contacts")
143+
if let Some(db_obj) = location.database_object {
144+
if let Some(obj_type) = db_obj.object_type {
145+
fmt.write_markup(markup! {
146+
<Dim>{obj_type}" "</Dim>
147+
})?;
148+
}
149+
if let Some(schema) = db_obj.schema {
150+
fmt.write_markup(markup! {
151+
<Emphasis>{schema}"."</Emphasis>
152+
})?;
153+
}
154+
fmt.write_markup(markup! {
155+
<Emphasis>{db_obj.name}</Emphasis>" "
156+
})?;
157+
}
158+
142159
// Print the category of the diagnostic, with a hyperlink if
143160
// the category has an associated link
144161
if let Some(category) = diagnostic.category() {

crates/pgls_diagnostics/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ pub use crate::display::{
3636
};
3737
pub use crate::display_github::PrintGitHubDiagnostic;
3838
pub use crate::error::{Error, Result};
39-
pub use crate::location::{LineIndex, LineIndexBuf, Location, Resource, SourceCode};
39+
pub use crate::location::{
40+
DatabaseObject, DatabaseObjectOwned, LineIndex, LineIndexBuf, Location, Resource, SourceCode,
41+
};
4042
use pgls_console::fmt::{Formatter, Termcolor};
4143
use pgls_console::markup;
4244
use std::fmt::Write;

crates/pgls_diagnostics/src/location.rs

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,28 @@ use std::fmt::Debug;
44
use std::ops::Range;
55
use std::{borrow::Borrow, ops::Deref};
66

7+
/// Represents a database object (table, function, etc.)
8+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9+
pub struct DatabaseObject<'a> {
10+
/// Optional schema name
11+
pub schema: Option<&'a str>,
12+
/// Object name (required)
13+
pub name: &'a str,
14+
/// Optional object type (e.g., "table", "function", "view")
15+
pub object_type: Option<&'a str>,
16+
}
17+
18+
/// Owned version of DatabaseObject for use in diagnostic structs
19+
#[derive(Debug, Clone, PartialEq, Eq)]
20+
pub struct DatabaseObjectOwned {
21+
/// Optional schema name
22+
pub schema: Option<String>,
23+
/// Object name (required)
24+
pub name: String,
25+
/// Optional object type (e.g., "table", "function", "view")
26+
pub object_type: Option<String>,
27+
}
28+
729
/// Represents the location of a diagnostic in a resource.
830
#[derive(Debug, Default, Clone, Copy)]
931
pub struct Location<'a> {
@@ -12,8 +34,8 @@ pub struct Location<'a> {
1234
/// An optional range of text within the resource associated with the
1335
/// diagnostic.
1436
pub span: Option<TextRange>,
15-
/// An optional tuple identifying a database object
16-
pub database_object: Option<(Option<&'a str>, &'a str)>,
37+
/// An optional database object reference
38+
pub database_object: Option<DatabaseObject<'a>>,
1739
/// The optional source code of the resource.
1840
pub source_code: Option<BorrowedSourceCode<'a>>,
1941
}
@@ -201,7 +223,7 @@ pub struct LocationBuilder<'a> {
201223
resource: Option<Resource<&'a str>>,
202224
span: Option<TextRange>,
203225
source_code: Option<BorrowedSourceCode<'a>>,
204-
database_object: Option<(Option<&'a str>, &'a str)>,
226+
database_object: Option<DatabaseObject<'a>>,
205227
}
206228

207229
impl<'a> LocationBuilder<'a> {
@@ -358,30 +380,34 @@ impl AsSourceCode for String {
358380

359381
/// Utility trait for types that can be converted into a database object reference
360382
pub trait AsDatabaseObject {
361-
fn as_database_object(&self) -> Option<(Option<&'_ str>, &'_ str)>;
383+
fn as_database_object(&self) -> Option<DatabaseObject<'_>>;
362384
}
363385

364386
impl<T: AsDatabaseObject> AsDatabaseObject for Option<T> {
365-
fn as_database_object(&self) -> Option<(Option<&'_ str>, &'_ str)> {
387+
fn as_database_object(&self) -> Option<DatabaseObject<'_>> {
366388
self.as_ref().and_then(T::as_database_object)
367389
}
368390
}
369391

370392
impl<T: AsDatabaseObject + ?Sized> AsDatabaseObject for &'_ T {
371-
fn as_database_object(&self) -> Option<(Option<&'_ str>, &'_ str)> {
393+
fn as_database_object(&self) -> Option<DatabaseObject<'_>> {
372394
T::as_database_object(*self)
373395
}
374396
}
375397

376-
impl AsDatabaseObject for (Option<&str>, &str) {
377-
fn as_database_object(&self) -> Option<(Option<&'_ str>, &'_ str)> {
378-
Some((self.0, self.1))
398+
impl<'a> AsDatabaseObject for DatabaseObject<'a> {
399+
fn as_database_object(&self) -> Option<DatabaseObject<'_>> {
400+
Some(*self)
379401
}
380402
}
381403

382-
impl AsDatabaseObject for (Option<String>, String) {
383-
fn as_database_object(&self) -> Option<(Option<&'_ str>, &'_ str)> {
384-
Some((self.0.as_deref(), self.1.as_str()))
404+
impl AsDatabaseObject for DatabaseObjectOwned {
405+
fn as_database_object(&self) -> Option<DatabaseObject<'_>> {
406+
Some(DatabaseObject {
407+
schema: self.schema.as_deref(),
408+
name: &self.name,
409+
object_type: self.object_type.as_deref(),
410+
})
385411
}
386412
}
387413

crates/pgls_diagnostics/src/serde.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,4 +497,31 @@ mod tests {
497497
//
498498
// assert_eq!(diag, expected);
499499
// }
500+
501+
#[test]
502+
fn test_database_object_location_macro() {
503+
use crate::{DatabaseObjectOwned, Diagnostic};
504+
505+
#[derive(Debug, Diagnostic)]
506+
#[diagnostic(severity = Error, category = "lint")]
507+
struct TestDatabaseObjectDiagnostic {
508+
#[location(database_object)]
509+
db_object: DatabaseObjectOwned,
510+
}
511+
512+
let diag = TestDatabaseObjectDiagnostic {
513+
db_object: DatabaseObjectOwned {
514+
schema: Some("public".to_string()),
515+
name: "contacts".to_string(),
516+
object_type: Some("table".to_string()),
517+
},
518+
};
519+
520+
let location = diag.location();
521+
assert!(location.database_object.is_some());
522+
let db_obj = location.database_object.unwrap();
523+
assert_eq!(db_obj.schema, Some("public"));
524+
assert_eq!(db_obj.name, "contacts");
525+
assert_eq!(db_obj.object_type, Some("table"));
526+
}
500527
}

0 commit comments

Comments
 (0)