Skip to content

Commit c323eb0

Browse files
chore: expose schema_cache & file_context in lint rules (#449)
1 parent 5dd0981 commit c323eb0

File tree

23 files changed

+365
-127
lines changed

23 files changed

+365
-127
lines changed

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/pgt_analyse/Cargo.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ version = "0.0.0"
1313

1414

1515
[dependencies]
16-
pgt_console.workspace = true
17-
pgt_diagnostics.workspace = true
18-
pgt_query_ext.workspace = true
19-
rustc-hash = { workspace = true }
16+
pgt_console.workspace = true
17+
pgt_diagnostics.workspace = true
18+
pgt_query_ext.workspace = true
19+
pgt_schema_cache.workspace = true
20+
rustc-hash = { workspace = true }
2021

2122
biome_deserialize = { workspace = true, optional = true }
2223
biome_deserialize_macros = { workspace = true, optional = true }
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#[derive(Default)]
2+
pub struct AnalysedFileContext {}
3+
4+
impl AnalysedFileContext {
5+
#[allow(unused)]
6+
pub fn update_from(&mut self, stmt_root: &pgt_query_ext::NodeEnum) {}
7+
}

crates/pgt_analyse/src/context.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,35 @@
1+
use pgt_schema_cache::SchemaCache;
2+
13
use crate::{
4+
AnalysedFileContext,
25
categories::RuleCategory,
36
rule::{GroupCategory, Rule, RuleGroup, RuleMetadata},
47
};
58

69
pub struct RuleContext<'a, R: Rule> {
710
stmt: &'a pgt_query_ext::NodeEnum,
811
options: &'a R::Options,
12+
schema_cache: Option<&'a SchemaCache>,
13+
file_context: &'a AnalysedFileContext,
914
}
1015

1116
impl<'a, R> RuleContext<'a, R>
1217
where
1318
R: Rule + Sized + 'static,
1419
{
1520
#[allow(clippy::too_many_arguments)]
16-
pub fn new(stmt: &'a pgt_query_ext::NodeEnum, options: &'a R::Options) -> Self {
17-
Self { stmt, options }
21+
pub fn new(
22+
stmt: &'a pgt_query_ext::NodeEnum,
23+
options: &'a R::Options,
24+
schema_cache: Option<&'a SchemaCache>,
25+
file_context: &'a AnalysedFileContext,
26+
) -> Self {
27+
Self {
28+
stmt,
29+
options,
30+
schema_cache,
31+
file_context,
32+
}
1833
}
1934

2035
/// Returns the group that belongs to the current rule
@@ -32,6 +47,14 @@ where
3247
self.stmt
3348
}
3449

50+
pub fn file_context(&self) -> &AnalysedFileContext {
51+
self.file_context
52+
}
53+
54+
pub fn schema_cache(&self) -> Option<&SchemaCache> {
55+
self.schema_cache
56+
}
57+
3558
/// Returns the metadata of the rule
3659
///
3760
/// The metadata contains information about the rule, such as the name, version, language, and whether it is recommended.

crates/pgt_analyse/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod analysed_file_context;
12
mod categories;
23
pub mod context;
34
mod filter;
@@ -9,6 +10,7 @@ mod rule;
910
// Re-exported for use in the `declare_group` macro
1011
pub use pgt_diagnostics::category_concat;
1112

13+
pub use crate::analysed_file_context::AnalysedFileContext;
1214
pub use crate::categories::{
1315
ActionCategory, RefactorKind, RuleCategories, RuleCategoriesBuilder, RuleCategory,
1416
SUPPRESSION_ACTION_CATEGORY, SourceActionKind,

crates/pgt_analyse/src/registry.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::{borrow, collections::BTreeSet};
22

33
use crate::{
44
AnalyserOptions,
5+
analysed_file_context::AnalysedFileContext,
56
context::RuleContext,
67
filter::{AnalysisFilter, GroupKey, RuleKey},
78
rule::{GroupCategory, Rule, RuleDiagnostic, RuleGroup},
@@ -158,6 +159,8 @@ impl RuleRegistry {
158159
pub struct RegistryRuleParams<'a> {
159160
pub root: &'a pgt_query_ext::NodeEnum,
160161
pub options: &'a AnalyserOptions,
162+
pub analysed_file_context: &'a AnalysedFileContext,
163+
pub schema_cache: Option<&'a pgt_schema_cache::SchemaCache>,
161164
}
162165

163166
/// Executor for rule as a generic function pointer
@@ -174,7 +177,14 @@ impl RegistryRule {
174177
R: Rule<Options: Default> + 'static,
175178
{
176179
let options = params.options.rule_options::<R>().unwrap_or_default();
177-
let ctx = RuleContext::new(params.root, &options);
180+
181+
let ctx = RuleContext::new(
182+
params.root,
183+
&options,
184+
params.schema_cache,
185+
params.analysed_file_context,
186+
);
187+
178188
R::run(&ctx)
179189
}
180190

crates/pgt_analyse/src/rule.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ pub trait GroupCategory {
102102
pub trait Rule: RuleMeta + Sized {
103103
type Options: Default + Clone + Debug;
104104

105-
fn run(ctx: &RuleContext<Self>) -> Vec<RuleDiagnostic>;
105+
/// `schema_cache` will only be available if the user has a working database connection.
106+
fn run(rule_context: &RuleContext<Self>) -> Vec<RuleDiagnostic>;
106107
}
107108

108109
/// Diagnostic object returned by a single analysis rule
@@ -208,6 +209,12 @@ impl RuleDiagnostic {
208209
self
209210
}
210211

212+
/// Sets the span of this diagnostic.
213+
pub fn span(mut self, span: TextRange) -> Self {
214+
self.span = Some(span);
215+
self
216+
}
217+
211218
/// Marks this diagnostic as unnecessary code, which will
212219
/// be displayed in the language server.
213220
///

crates/pgt_analyser/Cargo.toml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ repository.workspace = true
1212
version = "0.0.0"
1313

1414
[dependencies]
15-
pgt_analyse = { workspace = true }
16-
pgt_console = { workspace = true }
17-
pgt_diagnostics = { workspace = true }
18-
pgt_query_ext = { workspace = true }
19-
serde = { workspace = true }
15+
pgt_analyse = { workspace = true }
16+
pgt_console = { workspace = true }
17+
pgt_diagnostics = { workspace = true }
18+
pgt_query_ext = { workspace = true }
19+
pgt_schema_cache = { workspace = true }
20+
pgt_text_size = { workspace = true }
21+
serde = { workspace = true }
2022

2123
[dev-dependencies]
2224
insta = { version = "1.42.1" }

crates/pgt_analyser/src/lib.rs

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use std::{ops::Deref, sync::LazyLock};
22

33
use pgt_analyse::{
4-
AnalyserOptions, AnalysisFilter, MetadataRegistry, RegistryRuleParams, RuleDiagnostic,
5-
RuleRegistry,
4+
AnalysedFileContext, AnalyserOptions, AnalysisFilter, MetadataRegistry, RegistryRuleParams,
5+
RuleDiagnostic, RuleRegistry,
66
};
77
pub use registry::visit_registry;
88

@@ -30,8 +30,15 @@ pub struct Analyser<'a> {
3030
registry: RuleRegistry,
3131
}
3232

33-
pub struct AnalyserContext<'a> {
34-
pub root: &'a pgt_query_ext::NodeEnum,
33+
#[derive(Debug)]
34+
pub struct AnalysableStatement {
35+
pub root: pgt_query_ext::NodeEnum,
36+
pub range: pgt_text_size::TextRange,
37+
}
38+
39+
pub struct AnalyserParams<'a> {
40+
pub stmts: Vec<AnalysableStatement>,
41+
pub schema_cache: Option<&'a pgt_schema_cache::SchemaCache>,
3542
}
3643

3744
pub struct AnalyserConfig<'a> {
@@ -52,17 +59,31 @@ impl<'a> Analyser<'a> {
5259
}
5360
}
5461

55-
pub fn run(&self, ctx: AnalyserContext) -> Vec<RuleDiagnostic> {
56-
let params = RegistryRuleParams {
57-
root: ctx.root,
58-
options: self.options,
59-
};
62+
pub fn run(&self, params: AnalyserParams) -> Vec<RuleDiagnostic> {
63+
let mut diagnostics = vec![];
64+
65+
let mut file_context = AnalysedFileContext::default();
66+
67+
for stmt in params.stmts {
68+
let rule_params = RegistryRuleParams {
69+
root: &stmt.root,
70+
options: self.options,
71+
analysed_file_context: &file_context,
72+
schema_cache: params.schema_cache,
73+
};
6074

61-
self.registry
62-
.rules
63-
.iter()
64-
.flat_map(|rule| (rule.run)(&params))
65-
.collect::<Vec<_>>()
75+
diagnostics.extend(
76+
self.registry
77+
.rules
78+
.iter()
79+
.flat_map(|rule| (rule.run)(&rule_params))
80+
.map(|r| r.span(stmt.range)),
81+
);
82+
83+
file_context.update_from(&stmt.root);
84+
}
85+
86+
diagnostics
6687
}
6788
}
6889

@@ -77,9 +98,10 @@ mod tests {
7798
markup,
7899
};
79100
use pgt_diagnostics::PrintDiagnostic;
101+
use pgt_text_size::TextRange;
80102
use termcolor::NoColor;
81103

82-
use crate::Analyser;
104+
use crate::{AnalysableStatement, Analyser};
83105

84106
#[ignore]
85107
#[test]
@@ -102,6 +124,7 @@ mod tests {
102124
};
103125

104126
let ast = pgt_query_ext::parse(SQL).expect("failed to parse SQL");
127+
let range = TextRange::new(0.into(), u32::try_from(SQL.len()).unwrap().into());
105128

106129
let options = AnalyserOptions::default();
107130

@@ -110,7 +133,10 @@ mod tests {
110133
filter,
111134
});
112135

113-
let results = analyser.run(crate::AnalyserContext { root: &ast });
136+
let results = analyser.run(crate::AnalyserParams {
137+
stmts: vec![AnalysableStatement { root: ast, range }],
138+
schema_cache: None,
139+
});
114140

115141
println!("*******************");
116142
for result in &results {

crates/pgt_analyser/tests/rules_tests.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use core::slice;
22
use std::{fmt::Write, fs::read_to_string, path::Path};
33

44
use pgt_analyse::{AnalyserOptions, AnalysisFilter, RuleDiagnostic, RuleFilter};
5-
use pgt_analyser::{Analyser, AnalyserConfig, AnalyserContext};
5+
use pgt_analyser::{AnalysableStatement, Analyser, AnalyserConfig, AnalyserParams};
66
use pgt_console::StdDisplay;
77
use pgt_diagnostics::PrintDiagnostic;
88

@@ -32,7 +32,15 @@ fn rule_test(full_path: &'static str, _: &str, _: &str) {
3232
filter,
3333
});
3434

35-
let results = analyser.run(AnalyserContext { root: &ast });
35+
let stmt = AnalysableStatement {
36+
root: ast,
37+
range: pgt_text_size::TextRange::new(0.into(), u32::try_from(query.len()).unwrap().into()),
38+
};
39+
40+
let results = analyser.run(AnalyserParams {
41+
stmts: vec![stmt],
42+
schema_cache: None,
43+
});
3644

3745
let mut snapshot = String::new();
3846
write_snapshot(&mut snapshot, query.as_str(), results.as_slice());

0 commit comments

Comments
 (0)