Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: less cloning and caching #235

Merged
merged 4 commits into from
Apr 27, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
chore: less cloning and caching
  • Loading branch information
gvozdvmozgu committed Apr 27, 2024
commit efc24bac6eede0a40345263c0cc67dbf0d51e12a
17 changes: 7 additions & 10 deletions crates/lib/src/core/config.rs
Original file line number Diff line number Diff line change
@@ -125,7 +125,7 @@ pub struct FluffConfig {
pub(crate) raw: AHashMap<String, Value>,
extra_config_path: Option<String>,
_configs: AHashMap<String, AHashMap<String, String>>,
dialect: String,
pub(crate) dialect: Dialect,
sql_file_exts: Vec<String>,
}

@@ -168,7 +168,7 @@ impl FluffConfig {
a
}

let dialect = match configs.get("dialect") {
let _dialect = match configs.get("dialect") {
None => get_default_dialect(),
Some(Value::String(std)) => {
dialect_selector(std).unwrap_or_else(|| panic!("Unknown dialect {std}"));
@@ -212,7 +212,7 @@ impl FluffConfig {

Self {
raw: configs,
dialect,
dialect: dialect_selector("ansi").unwrap(),
extra_config_path,
_configs: AHashMap::new(),
indentation: indentation.unwrap_or_default(),
@@ -255,7 +255,7 @@ impl FluffConfig {
}

/// Process a full raw file for inline config and update self.
pub fn process_raw_file_for_config(&mut self, raw_str: &str) {
pub fn process_raw_file_for_config(&self, raw_str: &str) {
// Scan the raw file for config commands
for raw_line in raw_str.lines() {
if raw_line.to_string().starts_with("-- sqlfluff") {
@@ -266,7 +266,7 @@ impl FluffConfig {
}

/// Process an inline config command and update self.
pub fn process_inline_config(&mut self, _config_line: &str) {
pub fn process_inline_config(&self, _config_line: &str) {
panic!("Not implemented")
}

@@ -286,11 +286,8 @@ command. Available dialects: {}",
)))
}

pub fn get_dialect(&self) -> Dialect {
match dialect_selector(self.dialect.as_str()) {
None => panic!("dialect not found"),
Some(d) => d,
}
pub fn get_dialect(&self) -> &Dialect {
&self.dialect
}

pub fn sql_file_exts(&self) -> &[String] {
13 changes: 10 additions & 3 deletions crates/lib/src/core/dialects/base.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::borrow::Cow;
use std::collections::hash_map::Entry;
use std::fmt::Debug;
use std::rc::Rc;

use ahash::{AHashMap, AHashSet};
use itertools::Itertools;
@@ -22,6 +23,12 @@ pub struct Dialect {
bracket_collections: AHashMap<String, AHashSet<BracketPair>>,
}

impl PartialEq for Dialect {
fn eq(&self, other: &Self) -> bool {
self.root_segment_name == other.root_segment_name
}
}

impl Dialect {
pub fn new(root_segment_name: &'static str) -> Self {
Dialect { root_segment_name, ..Default::default() }
@@ -106,7 +113,7 @@ impl Dialect {
}
}

pub fn r#ref(&self, name: &str) -> Box<dyn Matchable> {
pub fn r#ref(&self, name: &str) -> Rc<dyn Matchable> {
// TODO:
// if !self.expanded {
// panic!("Dialect must be expanded before use.");
@@ -168,7 +175,7 @@ impl Dialect {
);

self.library
.insert(n.into(), DialectElementType::Matchable(Box::new(parser)));
.insert(n.into(), DialectElementType::Matchable(Rc::new(parser)));
}
}
}
@@ -179,7 +186,7 @@ impl Dialect {
self.root_segment_name
}

pub fn get_root_segment(&self) -> Box<dyn Matchable> {
pub fn get_root_segment(&self) -> Rc<dyn Matchable> {
self.r#ref(self.root_segment_name())
}
}
63 changes: 19 additions & 44 deletions crates/lib/src/core/linter/linter.rs
Original file line number Diff line number Diff line change
@@ -13,7 +13,6 @@ use super::linted_dir::LintedDir;
use super::runner::RunnerContext;
use crate::cli::formatters::OutputStreamFormatter;
use crate::core::config::FluffConfig;
use crate::core::dialects::init::dialect_selector;
use crate::core::errors::{SQLFluffUserError, SQLLexError, SQLLintError, SQLParseError, SqlError};
use crate::core::linter::common::{ParsedString, RenderedFile};
use crate::core::linter::linted_file::LintedFile;
@@ -84,7 +83,6 @@ impl Linter {
&self,
in_str: String,
f_name: Option<String>,
config: Option<&FluffConfig>,
encoding: Option<String>,
parse_statistics: Option<bool>,
) -> Result<ParsedString, SQLFluffUserError> {
@@ -93,25 +91,10 @@ impl Linter {
let parse_statistics = parse_statistics.unwrap_or(false);

let mut violations: Vec<Box<dyn SqlError>> = vec![];
// Dispatch the output for the template header (including the config diff)
if let Some(formatter) = &self.formatter {
if let Some(unwrapped_config) = config {
formatter.dispatch_template_header(
/*f_name.clone(),
self.config.clone(),
unwrapped_config.clone()*/
)
} else {
panic!("config cannot be Option in this case")
}
}

// Just use the local config from here
let binding = self.config.clone();
let mut config = config.unwrap_or(&binding).clone();
// Scan the raw file for config commands.
config.process_raw_file_for_config(&in_str);
let rendered = self.render_string(in_str, f_name.clone(), config, Some(encoding))?;
self.config.process_raw_file_for_config(&in_str);
let rendered = self.render_string(in_str, f_name.clone(), &self.config, Some(encoding))?;

for violation in &rendered.templater_violations {
violations.push(Box::new(violation.clone()));
@@ -138,17 +121,10 @@ impl Linter {
fix: bool,
) -> LintedFile {
// Sort out config, defaulting to the built in config if no override
let defaulted_config = config.unwrap_or(&self.config);
let _defaulted_config = config.unwrap_or(&self.config);
// Parse the string.
let parsed = self
.parse_string(
in_str.unwrap_or("".to_string()),
f_name,
Some(defaulted_config),
None,
None,
)
.unwrap();
let parsed =
self.parse_string(in_str.unwrap_or("".to_string()), f_name, None, None).unwrap();

// Lint the file and return the LintedFile
self.lint_parsed(parsed, rules, fix)
@@ -195,7 +171,7 @@ impl Linter {

pub fn render_file(&mut self, fname: String) -> RenderedFile {
let in_str = std::fs::read_to_string(&fname).unwrap();
self.render_string(in_str, fname, self.config.clone(), None).unwrap()
self.render_string(in_str, fname, &self.config, None).unwrap()
}

pub fn lint_rendered(
@@ -248,7 +224,6 @@ impl Linter {

let mut initial_linting_errors = Vec::new();
let phases: &[_] = if fix { &["main", "post"] } else { &["main"] };
let dialect = dialect_selector("ansi").unwrap();

// If we are fixing then we want to loop up to the runaway_limit, otherwise just
// once for linting.
@@ -286,7 +261,7 @@ impl Linter {
}

let (linting_errors, fixes) =
rule.crawl(&dialect, fix, tree.clone(), &self.config);
rule.crawl(&self.config.dialect, fix, tree.clone(), &self.config);
let anchor_info = compute_anchor_edit_info(fixes.clone());

if is_first_linter_pass {
@@ -301,7 +276,7 @@ impl Linter {
let _last_fixes = fixes;

let (new_tree, _, _, valid) =
tree.apply_fixes(dialect_selector("ansi").unwrap(), anchor_info);
tree.apply_fixes(&self.config.dialect, anchor_info);

if false {
println!(
@@ -330,7 +305,7 @@ impl Linter {
&self,
in_str: String,
f_name: String,
config: FluffConfig,
config: &FluffConfig,
encoding: Option<String>,
) -> Result<RenderedFile, SQLFluffUserError> {
// TODO Implement loggers eventually
@@ -371,7 +346,7 @@ impl Linter {
match self.templater.process(
in_str.as_str(),
f_name.as_str(),
Some(&config),
Some(config),
self.formatter.as_ref(),
) {
Ok(file) => {
@@ -402,7 +377,7 @@ impl Linter {
Ok(RenderedFile {
templated_file: templated_file.unwrap(),
templater_violations,
config,
config: config.clone(),
time_dict: AHashMap::new(),
f_name: f_name.to_owned(),
encoding: encoding.to_owned().unwrap_or_else(|| "UTF-8".into()),
@@ -426,7 +401,7 @@ impl Linter {
let mut tokens: Option<Vec<ErasedSegment>> = None;

if rendered.templated_file.is_templated() {
let (t, lvs, _config) =
let (t, lvs) =
Self::lex_templated_file(rendered.templated_file.clone(), &rendered.config);
tokens = t;
if !lvs.is_empty() {
@@ -478,7 +453,7 @@ impl Linter {
f_name: Option<String>,
parse_statistics: bool,
) -> (Option<ErasedSegment>, Vec<SQLParseError>) {
let mut parser = Parser::new(Some(config.clone()), None);
let mut parser = Parser::new(config, None);
let mut violations: Vec<SQLParseError> = Vec::new();

let parsed = match parser.parse(tokens, f_name, parse_statistics) {
@@ -499,11 +474,11 @@ impl Linter {
fn lex_templated_file(
templated_file: TemplatedFile,
config: &FluffConfig,
) -> (Option<Vec<ErasedSegment>>, Vec<SQLLexError>, FluffConfig) {
) -> (Option<Vec<ErasedSegment>>, Vec<SQLLexError>) {
let mut violations: Vec<SQLLexError> = vec![];
// linter_logger.info("LEXING RAW ({})", templated_file.fname);
// Get the lexer
let lexer = Lexer::new(config.clone(), None);
let lexer = Lexer::new(config, None);
// Lex the file and log any problems
let result = lexer.lex(StringOrTemplate::Template(templated_file));
match result {
@@ -515,10 +490,10 @@ impl Linter {
violations.extend(lex_vs);

if tokens.is_empty() {
return (None, violations, config.clone());
return (None, violations);
}

(tokens.into(), violations, config.clone())
(tokens.into(), violations)
}
}
}
@@ -755,7 +730,7 @@ mod tests {
#[test]
fn test__linter__empty_file() {
let linter = Linter::new(FluffConfig::new(<_>::default(), None, None), None, None);
let parsed = linter.parse_string("".into(), None, None, None, None).unwrap();
let parsed = linter.parse_string("".into(), None, None, None).unwrap();

assert!(parsed.violations.is_empty());
}
@@ -781,7 +756,7 @@ mod tests {
.to_string();

let linter = Linter::new(FluffConfig::new(<_>::default(), None, None), None, None);
let _parsed = linter.parse_string(sql, None, None, None, None).unwrap();
let _parsed = linter.parse_string(sql, None, None, None).unwrap();
}

#[test]
27 changes: 14 additions & 13 deletions crates/lib/src/core/parser/context.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
use std::rc::Rc;

use ahash::AHashMap;

use super::match_result::MatchResult;
use super::matchable::Matchable;
use crate::core::config::FluffConfig;
use crate::core::dialects::base::Dialect;
use crate::core::dialects::init::dialect_selector;

#[derive(Debug)]
pub struct ParseContext {
dialect: Dialect,
pub struct ParseContext<'a> {
dialect: &'a Dialect,
tqdm: Option<()>,
match_segment: String,
match_stack: Vec<String>,
match_depth: usize,
track_progress: bool,
pub(crate) terminators: Vec<Box<dyn Matchable>>,
pub(crate) terminators: Vec<Rc<dyn Matchable>>,
parse_cache: AHashMap<((String, (usize, usize), &'static str, usize), String), MatchResult>,
pub(crate) indentation_config: AHashMap<String, bool>,
}

impl ParseContext {
pub fn new(dialect: Dialect, indentation_config: AHashMap<String, bool>) -> Self {
impl<'a> ParseContext<'a> {
pub fn new(dialect: &'a Dialect, indentation_config: AHashMap<String, bool>) -> Self {
Self {
dialect,
tqdm: None,
@@ -35,11 +36,11 @@ impl ParseContext {
}

pub fn dialect(&self) -> &Dialect {
&self.dialect
self.dialect
}

pub fn from_config(config: FluffConfig) -> Self {
let dialect = dialect_selector("ansi").unwrap();
pub fn from_config(config: &'a FluffConfig) -> Self {
let dialect = &config.dialect;
let indentation_config = config.raw["indentation"].as_map().unwrap();
let indentation_config: AHashMap<_, _> =
indentation_config.iter().map(|(key, value)| (key.clone(), value.to_bool())).collect();
@@ -60,7 +61,7 @@ impl ParseContext {
&mut self,
name: impl ToString,
clear_terminators: bool,
push_terminators: &[Box<dyn Matchable>],
push_terminators: &[Rc<dyn Matchable>],
track_progress: Option<bool>,
f: impl FnOnce(&mut Self) -> T,
) -> T {
@@ -99,8 +100,8 @@ impl ParseContext {
fn set_terminators(
&mut self,
clear_terminators: bool,
push_terminators: &[Box<dyn Matchable>],
) -> (usize, Vec<Box<dyn Matchable>>) {
push_terminators: &[Rc<dyn Matchable>],
) -> (usize, Vec<Rc<dyn Matchable>>) {
let mut appended = 0;
let terminators = self.terminators.clone();

@@ -125,7 +126,7 @@ impl ParseContext {
fn reset_terminators(
&mut self,
appended: usize,
terminators: Vec<Box<dyn Matchable>>,
terminators: Vec<Rc<dyn Matchable>>,
clear_terminators: bool,
) {
if clear_terminators {
Loading