From 0bc598a4598d21d57d2aa1473d04823b4d7f183d Mon Sep 17 00:00:00 2001 From: quardbreak <44920739+quardbreak@users.noreply.github.com> Date: Mon, 27 Dec 2021 23:34:40 +0300 Subject: [PATCH 001/197] Fix homepage links for dmdoc and interval-tree (#301) --- crates/dmdoc/Cargo.toml | 2 +- crates/interval-tree/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index c9864c2d..3523bacb 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -2,7 +2,7 @@ name = "dmdoc" version = "1.4.1" authors = ["Tad Hardesty "] -homepage = "https://github.com/SpaceManiac/SpacemanDMM/blob/master/src/dmdoc/README.md" +homepage = "https://github.com/SpaceManiac/SpacemanDMM/blob/master/crates/dmdoc/README.md" edition = "2018" [dependencies] diff --git a/crates/interval-tree/Cargo.toml b/crates/interval-tree/Cargo.toml index 66b430eb..df7aa8e8 100644 --- a/crates/interval-tree/Cargo.toml +++ b/crates/interval-tree/Cargo.toml @@ -3,7 +3,7 @@ name = "interval-tree" version = "0.8.0" authors = ["coco ", "Tad Hardesty "] description = "A simple Interval Tree implementation" -repository = "https://github.com/SpaceManiac/SpacemanDMM/tree/master/src/interval_tree" +repository = "https://github.com/SpaceManiac/SpacemanDMM/tree/master/crates/interval-tree" keywords = ["datastructure", "interval", "tree", "map"] license-file = "LICENSE" edition = "2018" From 4756f31219db7676b058a2d5952d0efd503fe9a7 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 3 Jan 2022 17:59:25 -0800 Subject: [PATCH 002/197] Improve error locations in DMM parser Fixes a case where parse errors could refer to LocatedTokens with locations starting at 0,0 instead of at where the input string was actually taken from. --- crates/dmm-tools/src/dmm/read.rs | 41 ++++++++++++++++++++------ crates/dreammaker/src/constants.rs | 4 +-- crates/dreammaker/src/error.rs | 17 ++++++++++- crates/dreammaker/src/lexer.rs | 46 ++++++++++++++++++++---------- 4 files changed, 82 insertions(+), 26 deletions(-) diff --git a/crates/dmm-tools/src/dmm/read.rs b/crates/dmm-tools/src/dmm/read.rs index 771c7c51..617ebe71 100644 --- a/crates/dmm-tools/src/dmm/read.rs +++ b/crates/dmm-tools/src/dmm/read.rs @@ -37,6 +37,27 @@ pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { let mut escaping = false; let mut skip_whitespace = false; + let mut curr_key_start_location = Location::default(); + + let mut curr_datum_start_location = Location::default(); + macro_rules! set_curr_datum_start_location { + () => { + if curr_datum.is_empty() { + curr_datum_start_location = chars.location(); + } + } + } + + macro_rules! insert_current_var { + () => { + curr_prefab.vars.insert( + from_utf8_or_latin1(take(&mut curr_var)), + dm::constants::evaluate_str(curr_datum_start_location, &take(&mut curr_datum)) + .map_err(|e| e.with_note(curr_key_start_location, format!("within key: \"{}\"", super::FormatKey(curr_key_length, super::Key(curr_key)))))? + ); + } + } + while let Some(ch) = chars.next() { if ch == b'\n' || ch == b'\r' { in_comment_line = false; @@ -63,15 +84,19 @@ pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { if in_varedit_block { if in_quote_block { if ch == b'\\' { + set_curr_datum_start_location!(); curr_datum.push(ch); escaping = true; } else if escaping { + set_curr_datum_start_location!(); curr_datum.push(ch); escaping = false; } else if ch == b'"' { + set_curr_datum_start_location!(); curr_datum.push(ch); in_quote_block = false; } else { + set_curr_datum_start_location!(); curr_datum.push(ch); } } else { // in_quote_block @@ -82,6 +107,7 @@ pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { skip_whitespace = false; if ch == b'"' { + set_curr_datum_start_location!(); curr_datum.push(ch); in_quote_block = true; } else if ch == b'=' && curr_var.is_empty() { @@ -93,20 +119,15 @@ pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { curr_var.truncate(length); skip_whitespace = true; } else if ch == b';' { - curr_prefab.vars.insert( - from_utf8_or_latin1(take(&mut curr_var)), - dm::constants::evaluate_str(chars.location(), &take(&mut curr_datum))?, - ); + insert_current_var!(); skip_whitespace = true; } else if ch == b'}' { if !curr_var.is_empty() { - curr_prefab.vars.insert( - from_utf8_or_latin1(take(&mut curr_var)), - dm::constants::evaluate_str(chars.location(), &take(&mut curr_datum))?, - ); + insert_current_var!(); } in_varedit_block = false; } else { + set_curr_datum_start_location!(); curr_datum.push(ch); } } @@ -130,6 +151,7 @@ pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { in_data_block = false; after_data_block = true; } else { + set_curr_datum_start_location!(); curr_datum.push(ch); } } else if in_key_block { @@ -138,6 +160,9 @@ pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { assert!(map.key_length == 0 || map.key_length == curr_key_length); map.key_length = curr_key_length; } else { + if curr_key == 0 { + curr_key_start_location = chars.location(); + } curr_key = advance_key(chars.location(), curr_key, ch)?; curr_key_length += 1; } diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index bd9959c9..9cb6a0d9 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -400,10 +400,10 @@ impl fmt::Display for ConstFn { // The constant evaluator pub fn evaluate_str(location: Location, input: &[u8]) -> Result { - use super::lexer::{Lexer, from_utf8_or_latin1_borrowed}; + use super::lexer::{Lexer, LocationTracker, from_utf8_or_latin1_borrowed}; let ctx = Context::default(); - let mut lexer = Lexer::new(&ctx, location.file, input); + let mut lexer = Lexer::from_input(&ctx, LocationTracker::from_location(location, input.into())); let expr = crate::parser::parse_expression(&ctx, location, &mut lexer)?; let leftover = lexer.remaining(); if !leftover.is_empty() { diff --git a/crates/dreammaker/src/error.rs b/crates/dreammaker/src/error.rs index 8620a298..f1a1feac 100644 --- a/crates/dreammaker/src/error.rs +++ b/crates/dreammaker/src/error.rs @@ -519,7 +519,22 @@ impl DMError { impl fmt::Display for DMError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}:{}:{}", self.location.line, self.location.column, self.description) + // Like `pretty_print_error` above, but without filename information. + write!(f, "{}:{}: {}: {}", self.location.line, self.location.column, self.severity, self.description)?; + for note in self.notes.iter() { + if note.location == self.location { + write!(f, "\n- {}", note.description, )?; + } else { + write!( + f, + "\n- {}:{}: {}", + note.location.line, + note.location.column, + note.description, + )?; + } + } + Ok(()) } } diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index 9e708b03..ef943fcf 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -482,10 +482,6 @@ enum Directive { Stringy, } -fn has_bom(slice: &[u8]) -> bool { - slice.starts_with(b"\xEF\xBB\xBF") -} - fn buffer_read(file: FileId, mut read: R) -> Result, DMError> { let mut buffer = Vec::new(); @@ -537,6 +533,18 @@ pub struct LocationTracker<'a> { } impl<'a> LocationTracker<'a> { + pub fn skip_utf8_bom(input: Cow<'a, [u8]>) -> Cow<'a, [u8]> { + const BOM: &[u8] = b"\xEF\xBB\xBF"; + if input.starts_with(BOM) { + match input { + Cow::Borrowed(b) => Cow::Borrowed(&b[BOM.len()..]), + Cow::Owned(mut o) => { o.drain(..BOM.len()); Cow::Owned(o) } + } + } else { + input + } + } + pub fn new(file: FileId, inner: Cow<'a, [u8]>) -> LocationTracker<'a> { LocationTracker { inner, @@ -550,6 +558,17 @@ impl<'a> LocationTracker<'a> { } } + /// `location` will be taken as the location of the first character of `inner`. + pub fn from_location(location: Location, inner: Cow<'a, [u8]>) -> LocationTracker<'a> { + let location = location.pred(); + LocationTracker { + inner, + offset: 0, + location, + at_line_end: location.column == !0, + } + } + pub fn location(&self) -> Location { self.location } @@ -634,19 +653,10 @@ impl<'ctx> HasLocation for Lexer<'ctx> { } impl<'ctx> Lexer<'ctx> { - /// Create a new lexer from a byte stream. - pub fn new>>(context: &'ctx Context, file_number: FileId, input: I) -> Self { - let mut cow = input.into(); - if has_bom(&cow) { - cow = match cow { - Cow::Borrowed(b) => Cow::from(&b[3..]), - Cow::Owned(mut o) => { o.drain(..3); Cow::Owned(o) } - }; - } - + pub fn from_input(context: &'ctx Context, input: LocationTracker<'ctx>) -> Self { Lexer { context, - input: LocationTracker::new(file_number, cow), + input, next: None, final_newline: false, at_line_head: true, @@ -656,6 +666,12 @@ impl<'ctx> Lexer<'ctx> { } } + /// Create a new lexer from a byte stream. + pub fn new>>(context: &'ctx Context, file_number: FileId, input: I) -> Self { + let inner = LocationTracker::skip_utf8_bom(input.into()); + Lexer::from_input(context, LocationTracker::new(file_number, inner)) + } + /// Create a new lexer from a reader. pub fn from_read(context: &'ctx Context, file: FileId, read: R) -> Result { let start_time = std::time::Instant::now(); From 4c24fcb883ef116d3d4a14921cc2ce1a8abc3061 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Tue, 4 Jan 2022 17:37:47 -0800 Subject: [PATCH 003/197] Fix tests failing due to subtraction followed by overflow --- crates/dreammaker/src/error.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/dreammaker/src/error.rs b/crates/dreammaker/src/error.rs index f1a1feac..74d999f7 100644 --- a/crates/dreammaker/src/error.rs +++ b/crates/dreammaker/src/error.rs @@ -300,6 +300,10 @@ impl Location { } else if self.line != 0 { self.column = !0; self.line -= 1; + } else if self.file == FILEID_BAD { + // This file ID generally comes from using Location::default(). + // In that case hopefully it's a test or something, so just let it + // stay 0:0. } else if self.file.0 != 0 { self.column = !0; self.line = !0; From 0a121f6ae5a0fddb2c57ed17085a214e5d156d9c Mon Sep 17 00:00:00 2001 From: pali <6pali6@gmail.com> Date: Tue, 8 Feb 2022 02:09:44 +0100 Subject: [PATCH 004/197] Add lints for the switch(rand(L, H)) pattern (#302) A pattern such as ```dm switch(rand(1, 3)) if(1) foo() if(2) bar() if(3) baz() ``` is not uncommon in SS13 code. Sadly, it is also not uncommon for people to add new cases to a longer switch of this form and forget to change the `rand` arguments at the top. This PR adds a linter warning for when the `rand` range is not fully covered by the cases and for when a case lies completely outside of the `rand` range. This currently generates 7 warnings on tgstation master. Sadly, it is (at least to me) not quite clear if the omissions of a part of the `rand` range are intentional there or not. However, I believe that even if they are intentional it is worth adding the missing part of the range as a case with empty body explicitly to make the intent clear to future developers. As a less related (but perhaps more important) addition this PR now also adds a warning for switch branches of the form `if(X || Y)` which is pretty much always a mistake and should instead be `if(X, Y)`. This lint generates 5 warnings on current tg code, seemingly all being actual mistakes. --- crates/dreamchecker/src/lib.rs | 8 ++ crates/dreamchecker/src/switch_rand_range.rs | 117 ++++++++++++++++++ .../tests/switch_rand_range_tests.rs | 108 ++++++++++++++++ 3 files changed, 233 insertions(+) create mode 100644 crates/dreamchecker/src/switch_rand_range.rs create mode 100644 crates/dreamchecker/tests/switch_rand_range_tests.rs diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 86f52ffa..d187a411 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -15,6 +15,8 @@ use ahash::RandomState; mod type_expr; use type_expr::TypeExpr; +mod switch_rand_range; +use switch_rand_range::check_switch_rand_range; #[doc(hidden)] // Intended for the tests only. pub mod test_helpers; @@ -1475,11 +1477,17 @@ impl<'o, 's> AnalyzeProc<'o, 's> { self.inside_newcontext = self.inside_newcontext.wrapping_sub(1); }, Statement::Switch { input, cases, default } => { + check_switch_rand_range(input, cases, default, location, self.context); let mut allterm = ControlFlow::alltrue(); self.visit_control_condition(location, input); self.visit_expression(location, input, None, local_vars); for (case, ref block) in cases.iter() { let mut scoped_locals = local_vars.clone(); + if let [dm::ast::Case::Exact(Expression::BinaryOp{op: BinaryOp::Or, ..})] = case.elem[..] { + error(case.location, "Elements in a switch-case branch separated by ||, this is likely in error and should be replaced by a comma") + .set_severity(Severity::Warning) + .register(self.context); + } for case_part in case.elem.iter() { match case_part { dm::ast::Case::Exact(expr) => { self.visit_expression(case.location, expr, None, &mut scoped_locals); }, diff --git a/crates/dreamchecker/src/switch_rand_range.rs b/crates/dreamchecker/src/switch_rand_range.rs new file mode 100644 index 00000000..4a71b23c --- /dev/null +++ b/crates/dreamchecker/src/switch_rand_range.rs @@ -0,0 +1,117 @@ +use std::borrow::Borrow; + +use dm::ast::*; +use dm::{Context, DMError, Location, Severity}; + +/** + * Checks for mistakes in switches of the form `switch(rand(L, H))`. + * If some cases lie outside of the [L, H] range or the whole [L, H] range is not covered by all the cases a warning is issued. + */ +pub fn check_switch_rand_range( + input: &Box, + cases: &Box<[(Spanned>, Block)]>, + default: &Option, + location: Location, + context: &Context, +) { + let (rand_start, rand_end) = if let Some(range) = get_rand_range(input) { + range + } else { + return; + }; + + let mut case_ranges = vec![]; + case_ranges.reserve(cases.len()); + for case_block in cases.iter() { + let location = case_block.0.location; + for case in case_block.0.elem.iter() { + if let Some((start, end)) = get_case_range(&case, location) { + let start = start.ceil() as i32; + let end = end.floor() as i32; + if start <= rand_end && end >= rand_start { + case_ranges.push((start, end)); + } else { + DMError::new(location, format!("Case range '{} to {}' will never trigger as it is outside the rand() range {} to {}", start, end, rand_start, rand_end)) + .with_component(dm::Component::DreamChecker) + .set_severity(Severity::Warning) + .register(context); + } + } + } + } + + if default.is_some() { + // covers the whole range directly so no need to check for gaps + return; + } + + case_ranges.sort_by(|a, b| a.0.cmp(&b.0)); + let mut first_uncovered = rand_start; + for (start, end) in case_ranges.iter() { + if *start > first_uncovered { + break; + } else { + first_uncovered = std::cmp::max(first_uncovered, end + 1); + } + } + + if first_uncovered <= rand_end { + DMError::new( + location, + format!( + "Switch branches on rand() with range {} to {} but no case branch triggers for {}", + rand_start, rand_end, first_uncovered + ), + ) + .with_component(dm::Component::DreamChecker) + .set_severity(Severity::Warning) + .register(context); + } +} + +fn get_case_range(case: &Case, location: Location) -> Option<(f32, f32)> { + match case { + Case::Exact(ref value) => { + let value = value + .to_owned() + .simple_evaluate(location) + .ok()? + .to_float()?; + Some((value, value)) + } + Case::Range(ref min, ref max) => { + let min = min.to_owned().simple_evaluate(location).ok()?.to_float()?; + let max = max.to_owned().simple_evaluate(location).ok()?.to_float()?; + Some((min, max)) + } + } +} + +fn get_rand_range(maybe_rand: &Expression) -> Option<(i32, i32)> { + let (term, location) = match maybe_rand { + &Expression::Base { + ref term, + ref follow, + } if follow.is_empty() => (&term.elem, term.location), + _ => return None, + }; + + let rand_args: &[Expression] = match term { + Term::Call(proc_name, args) if proc_name.as_str() == "rand" => args.borrow(), + _ => return None, + }; + + let (min, max) = match rand_args { + [min, max] => ( + min.to_owned().simple_evaluate(location).ok()?.to_float()?, + max.to_owned().simple_evaluate(location).ok()?.to_float()?, + ), + [max] => ( + 0., + max.to_owned().simple_evaluate(location).ok()?.to_float()?, + ), + _ => return None, + }; + + Some((min.ceil() as i32, max.floor() as i32)) +} diff --git a/crates/dreamchecker/tests/switch_rand_range_tests.rs b/crates/dreamchecker/tests/switch_rand_range_tests.rs new file mode 100644 index 00000000..acc32c0c --- /dev/null +++ b/crates/dreamchecker/tests/switch_rand_range_tests.rs @@ -0,0 +1,108 @@ + +extern crate dreamchecker as dc; + +use dc::test_helpers::*; + +pub const SWITCH_RAND_INCOMPLETE_ERRORS: &[(u32, u16, &str)] = &[ + (5, 9, "Case range '0 to 0' will never trigger as it is outside the rand() range 1 to 3"), + (2, 5, "Switch branches on rand() with range 1 to 3 but no case branch triggers for 3"), +]; + +#[test] +fn switch_rand_incomplete() { + let code = r##" +/proc/test() + switch(rand(1, 3)) + if(0) + return + if(1) + return + if(2) + return +"##.trim(); + check_errors_match(code, SWITCH_RAND_INCOMPLETE_ERRORS); +} + + +pub const SWITCH_RAND_WITH_EVALUATION_ERRORS: &[(u32, u16, &str)] = &[ + (2, 5, "Switch branches on rand() with range 2 to 3 but no case branch triggers for 3"), +]; + +#[test] +fn switch_rand_with_evaluation() { + let code = r##" +/proc/test() + switch(rand(1 + 1, 4 - 1)) + if(3 - 1) + return +"##.trim(); + check_errors_match(code, SWITCH_RAND_WITH_EVALUATION_ERRORS); +} + + +#[test] +fn switch_rand_case_ranges() { + let code = r##" +/proc/test() + switch(rand(1, 4)) + if(1 to 2) + return + if(3, 4) + return +"##.trim(); + check_errors_match(code, &[]); +} + + +pub const SWITCH_RAND_DEFAULT_ERRORS: &[(u32, u16, &str)] = &[ + (5, 9, "Case range '5 to 5' will never trigger as it is outside the rand() range 1 to 4"), +]; + +#[test] +fn switch_rand_default() { + let code = r##" +/proc/test() + switch(rand(1, 4)) + if(5) + return + if(2) + return + else + return +"##.trim(); + check_errors_match(code, SWITCH_RAND_DEFAULT_ERRORS); +} + + + +#[test] +fn switch_rand_floats() { + let code = r##" +/proc/test() + switch(rand(1, 4)) + if(0.5 to 1.5) + return + if(2) + return + if(2.5 to 400) + return +"##.trim(); + check_errors_match(code, &[]); +} + + + +#[test] +fn switch_rand_out_of_order() { + let code = r##" +/proc/test() + switch(rand(1, 4)) + if(3 to 4) + return + if(2) + return + if(1) + return +"##.trim(); + check_errors_match(code, &[]); +} From 963c2c0792ef44750933e5dfaab686def7ee6c9b Mon Sep 17 00:00:00 2001 From: KIBORG04 Date: Thu, 10 Feb 2022 03:38:23 +0300 Subject: [PATCH 005/197] Update dockerfile (#303) I made it work --- dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dockerfile b/dockerfile index 56597d06..9547bf27 100644 --- a/dockerfile +++ b/dockerfile @@ -3,7 +3,7 @@ FROM rust:1.54 WORKDIR /usr/src/myapp COPY . . -RUN cargo build -p cli --release +RUN cargo build -p dmm-tools-cli --release RUN ln -s /usr/src/myapp/target/release/dmm-tools /usr/src/myapp/dmm-tools ENTRYPOINT ["./dmm-tools"] CMD ["help"] From 7e5335e78d94d5e6d40bc5ef03b6df0e6ef4b287 Mon Sep 17 00:00:00 2001 From: fira Date: Fri, 15 Apr 2022 13:05:11 +0200 Subject: [PATCH 006/197] Fix Sleep/Purity checks being skipped under certain overrides (#311) * bugfix: fix part of the proc tree not being traversed for sleeps/purity when overrides are present * add unit test * copypasting whitespace be like Co-authored-by: Fira --- crates/dreamchecker/src/lib.rs | 6 +++-- crates/dreamchecker/tests/sleep_pure_tests.rs | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index d187a411..196e7889 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -695,7 +695,8 @@ impl<'o> AnalyzeObjectTree<'o> { .with_blocking_builtins(self.sleeping_procs.get_violators(*child_violator).unwrap()) .register(self.context) } - } else if let Some(calledvec) = self.call_tree.get(&nextproc) { + } + if let Some(calledvec) = self.call_tree.get(&nextproc) { for (proccalled, location, new_context) in calledvec.iter() { let mut newstack = callstack.clone(); newstack.add_step(*proccalled, *location, *new_context); @@ -745,7 +746,8 @@ impl<'o> AnalyzeObjectTree<'o> { .with_blocking_builtins(self.impure_procs.get_violators(*child_violator).unwrap()) .register(self.context) } - } else if let Some(calledvec) = self.call_tree.get(&nextproc) { + } + if let Some(calledvec) = self.call_tree.get(&nextproc) { for (proccalled, location, new_context) in calledvec.iter() { let mut newstack = callstack.clone(); newstack.add_step(*proccalled, *location, *new_context); diff --git a/crates/dreamchecker/tests/sleep_pure_tests.rs b/crates/dreamchecker/tests/sleep_pure_tests.rs index 9a023b6b..1f62b56a 100644 --- a/crates/dreamchecker/tests/sleep_pure_tests.rs +++ b/crates/dreamchecker/tests/sleep_pure_tests.rs @@ -149,6 +149,32 @@ fn sleep4() { check_errors_match(code, SLEEP_ERROR4); } +// Test overrides and for regression of issue #267 +pub const SLEEP_ERROR5: &[(u32, u16, &str)] = &[ + (7, 19, "/datum/sub/proc/checker sets SpacemanDMM_should_not_sleep but calls blocking proc /proc/sleeper"), +]; + +#[test] +fn sleep5() { + let code = r##" +/datum/proc/checker() + set SpacemanDMM_should_not_sleep = 1 + +/datum/proc/proxy() + sleeper() + +/datum/sub/checker() + proxy() + +/proc/sleeper() + sleep(1) + +/datum/hijack/proxy() + sleep(1) +"##.trim(); + check_errors_match(code, SLEEP_ERROR5); +} + pub const PURE_ERRORS: &[(u32, u16, &str)] = &[ (12, 16, "/mob/proc/test2 sets SpacemanDMM_should_be_pure but calls a /proc/impure that does impure operations"), ]; From a0430d44e3f0c95df3e7768e632fdea2c69372f2 Mon Sep 17 00:00:00 2001 From: tigercat2000 Date: Sat, 30 Apr 2022 11:02:50 -0700 Subject: [PATCH 007/197] Fix Clippy lints (#315) This resolves every single error raised by [Clippy](https://github.com/rust-lang/rust-clippy) for every active crate. Most are formatting or redundant code, there's only a few things that are functionally better. * Implement PartialEq manually on Prefab and Pop to ensure consistency with Hash * Disable clippy::if_same_then_else for simple elif chains * Add a standard path for the unit test codebase so I don't have to worry about git add * Collapse nested if within smart cables loop * mem::replace(x, X::default()) -> mem::take(x) * Single character strings -> chars * Use a const fn for Constant::null, unwrap_or -> unwrap_or_else calls to it * writeln! always uses \n alone * Address complex type signatures with type aliases * PickArgs shouldn't have Box in it's type alias * Random unnecessary variable access * Add and remove closures where appropriate * No more redundant field names in struct initialization * Remove unnecessary references * Use strip_prefix instead of starts_with -> [..] * Use Range.contains instead of >= && <= comparisons * Group hex literals by 4 * Elide lifetimes wherever possible * Replace match with matches! wherever possible * Remove needless borrows * Control flow cleanup * Misc signature & redundancy fixes * Rename functions or move them to the correct std Trait * Just ignore the too many arguments lint on the big ugly functions * require! wasn't doing anything in tree_block. tree_entries returns a Status<()>, thus passing () to self.require. Macro expansion: ```rust fn tree_block( &mut self, current: NodeIndex, proc_kind: Option, var_type: Option, ) -> Status<()> { match self.exact(Token::Punct(Punctuation::LBrace))? { Some(x) => x, None => return Ok(None), }; Ok(Some({ let v = self.tree_entries( current, proc_kind, var_type, Token::Punct(Punctuation::RBrace), ); self.require(v)? })) } fn tree_entries( &mut self, current: NodeIndex, proc_kind: Option, var_type: Option, terminator: Token, ) -> Status<()> { ``` * Fix large enum variants Co-authored-by: Tad Hardesty * Clarify intent on some of the linted code --- .gitignore | 1 + crates/builtins-proc-macro/src/lib.rs | 10 +-- crates/dm-langserver/src/color.rs | 2 +- crates/dm-langserver/src/completion.rs | 4 +- crates/dm-langserver/src/debugger/auxtools.rs | 14 ++-- crates/dm-langserver/src/debugger/evaluate.rs | 2 + crates/dm-langserver/src/debugger/extools.rs | 11 ++-- crates/dm-langserver/src/debugger/mod.rs | 24 ++++--- crates/dm-langserver/src/document.rs | 3 +- crates/dm-langserver/src/find_references.rs | 2 +- crates/dm-langserver/src/jrpc_io.rs | 2 +- crates/dm-langserver/src/main.rs | 65 +++++++++---------- crates/dm-langserver/src/symbol_search.rs | 19 ++---- crates/dmdoc/src/main.rs | 61 +++++++++-------- crates/dmdoc/src/markdown.rs | 2 +- crates/dmm-tools-cli/src/main.rs | 16 ++--- crates/dmm-tools/src/dmi.rs | 7 +- crates/dmm-tools/src/dmm.rs | 20 ++++-- crates/dmm-tools/src/dmm/read.rs | 8 +-- crates/dmm-tools/src/dmm/save_tgm.rs | 18 ++--- crates/dmm-tools/src/icon_cache.rs | 2 +- crates/dmm-tools/src/minimap.rs | 34 +++++----- .../src/render_passes/icon_smoothing.rs | 7 +- .../src/render_passes/icon_smoothing_2020.rs | 2 + crates/dmm-tools/src/render_passes/mod.rs | 12 ++-- crates/dmm-tools/src/render_passes/random.rs | 4 +- .../src/render_passes/smart_cables.rs | 16 +++-- .../dmm-tools/src/render_passes/structures.rs | 6 +- .../src/render_passes/transit_tube.rs | 2 +- crates/dreamchecker/src/lib.rs | 63 +++++++++--------- crates/dreamchecker/src/switch_rand_range.rs | 6 +- crates/dreammaker/src/ast.rs | 35 +++++----- crates/dreammaker/src/config.rs | 12 ++-- crates/dreammaker/src/constants.rs | 63 ++++++++++-------- crates/dreammaker/src/dmi.rs | 12 ++-- crates/dreammaker/src/error.rs | 2 +- crates/dreammaker/src/lexer.rs | 6 +- crates/dreammaker/src/lib.rs | 22 +++---- crates/dreammaker/src/objtree.rs | 8 ++- crates/dreammaker/src/parser.rs | 52 ++++++++------- crates/dreammaker/src/preprocessor.rs | 13 ++-- crates/interval-tree/src/tree.rs | 22 ++++--- 42 files changed, 365 insertions(+), 327 deletions(-) diff --git a/.gitignore b/.gitignore index a221ac10..5b894527 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ target/ .vscode/ +test_codebase/ diff --git a/crates/builtins-proc-macro/src/lib.rs b/crates/builtins-proc-macro/src/lib.rs index 0dcec30b..22757591 100644 --- a/crates/builtins-proc-macro/src/lib.rs +++ b/crates/builtins-proc-macro/src/lib.rs @@ -56,7 +56,7 @@ impl Parse for ProcArgument { enum EntryBody { None, - Variable(Option), + Variable(Option>), Proc(Punctuated), } @@ -64,7 +64,7 @@ impl EntryBody { fn parse_with_path(path: &[Ident], input: ParseStream) -> Result { if input.peek(Token![=]) { input.parse::()?; - Ok(EntryBody::Variable(Some(input.parse::()?))) + Ok(EntryBody::Variable(Some(Box::new(input.parse::()?)))) } else if input.peek(syn::token::Paren) { let content; parenthesized!(content in input); @@ -87,7 +87,7 @@ impl Parse for BuiltinEntry { let header: Header = input.parse()?; let body = EntryBody::parse_with_path(&header.path, input)?; - input.parse::()?.span; + input.parse::()?; Ok(BuiltinEntry { header, body, @@ -159,7 +159,7 @@ pub fn builtins_table(input: TokenStream) -> TokenStream { if ident == "doc" { markdown_span = Some(attr_span); markdown.push_str(&syn::parse2::(attr.tokens).unwrap().0.value()); - markdown.push_str("\n"); + markdown.push('\n'); } else { attr_calls.extend(quote_spanned! { attr_span => .docs.#path }); attr_calls.extend(attr.tokens); @@ -197,5 +197,5 @@ pub fn builtins_table(input: TokenStream) -> TokenStream { output.push(line); } - output.into_iter().flat_map(|x| TokenStream::from(x)).collect() + output.into_iter().flat_map(TokenStream::from).collect() } diff --git a/crates/dm-langserver/src/color.rs b/crates/dm-langserver/src/color.rs index 5872190c..1634b86b 100644 --- a/crates/dm-langserver/src/color.rs +++ b/crates/dm-langserver/src/color.rs @@ -7,7 +7,7 @@ use regex::Regex; /// Extract ranges and colors from an input string. -pub fn extract_colors<'a>(input: &'a str) -> impl Iterator + 'a { +pub fn extract_colors(input: &str) -> impl Iterator + '_ { COLOR_REGEX.captures_iter(input).flat_map(|capture| { parse_capture(&capture).map(|rgba| { let totality = capture.get(0).unwrap(); diff --git a/crates/dm-langserver/src/completion.rs b/crates/dm-langserver/src/completion.rs index 71f4add8..00cef839 100644 --- a/crates/dm-langserver/src/completion.rs +++ b/crates/dm-langserver/src/completion.rs @@ -200,7 +200,7 @@ impl<'a> Engine<'a> { // follow the path ops until we hit 'proc' or 'verb' let mut iter = parts.iter(); let mut decl = None; - while let Some(&(op, ref name)) = iter.next() { + for &(op, ref name) in iter.by_ref() { if name == "proc" { decl = Some("proc"); break; @@ -409,7 +409,7 @@ impl<'a> Engine<'a> { } // proc parameters - let ty = ty.unwrap_or(self.objtree.root()); + let ty = ty.unwrap_or_else(|| self.objtree.root()); if let Some((proc_name, idx)) = proc_name { if let Some(proc) = ty.get().procs.get(proc_name) { if let Some(value) = proc.value.get(idx) { diff --git a/crates/dm-langserver/src/debugger/auxtools.rs b/crates/dm-langserver/src/debugger/auxtools.rs index 18486318..31791f37 100644 --- a/crates/dm-langserver/src/debugger/auxtools.rs +++ b/crates/dm-langserver/src/debugger/auxtools.rs @@ -36,6 +36,12 @@ pub struct AuxtoolsThread { last_error: Arc>, } +pub struct AuxtoolsScopes { + pub arguments: Option, + pub locals: Option, + pub globals: Option, +} + impl Auxtools { pub fn connect(seq: Arc, port: Option) -> std::io::Result { let addr: SocketAddr = (Ipv4Addr::LOCALHOST, port.unwrap_or(DEFAULT_PORT)).into(); @@ -51,7 +57,7 @@ impl Auxtools { AuxtoolsThread { seq, responses: responses_sender, - last_error: last_error, + last_error, }.run(stream); }) }; @@ -79,7 +85,7 @@ impl Auxtools { AuxtoolsThread { seq, responses: responses_sender, - last_error: last_error, + last_error, }.spawn_listener(listener, connection_sender) }; @@ -323,7 +329,7 @@ impl Auxtools { } // TODO: return all the scopes - pub fn get_scopes(&mut self, frame_id: u32) -> Result<(Option, Option, Option), Box> { + pub fn get_scopes(&mut self, frame_id: u32) -> Result> { self.send_or_disconnect(Request::Scopes { frame_id })?; @@ -333,7 +339,7 @@ impl Auxtools { arguments, locals, globals, - } => Ok((arguments, locals, globals)), + } => Ok(AuxtoolsScopes { arguments, locals, globals }), response => Err(Box::new(UnexpectedResponse::new("Scopes", response))), } } diff --git a/crates/dm-langserver/src/debugger/evaluate.rs b/crates/dm-langserver/src/debugger/evaluate.rs index ccd2a084..244b5c33 100644 --- a/crates/dm-langserver/src/debugger/evaluate.rs +++ b/crates/dm-langserver/src/debugger/evaluate.rs @@ -33,6 +33,8 @@ impl Debugger { let bytecode = extools.bytecode(&frame.proc, frame.override_id); return Ok(EvaluateResponse::from(Self::format_disassembly(bytecode))); + } else { + return Err(Box::new(GenericError("Unknown #command"))); } } } diff --git a/crates/dm-langserver/src/debugger/extools.rs b/crates/dm-langserver/src/debugger/extools.rs index 968ad703..cde71385 100644 --- a/crates/dm-langserver/src/debugger/extools.rs +++ b/crates/dm-langserver/src/debugger/extools.rs @@ -41,7 +41,7 @@ enum ExtoolsHolderInner { cancel_tx: mpsc::Sender<()>, conn_rx: mpsc::Receiver, }, - Active(Extools), + Active(Box), } impl Default for ExtoolsHolder { @@ -114,7 +114,7 @@ impl ExtoolsHolder { ExtoolsHolderInner::Listening { conn_rx, .. } | ExtoolsHolderInner::Attaching { conn_rx, .. } => { if let Ok(conn) = conn_rx.try_recv() { - self.0 = ExtoolsHolderInner::Active(conn); + self.0 = ExtoolsHolderInner::Active(Box::new(conn)); } } _ => {} @@ -126,6 +126,8 @@ impl ExtoolsHolder { } pub fn disconnect(&mut self) { + // This part of code is not complete, we don't want to use matches! + #[allow(clippy::single_match)] match std::mem::replace(&mut self.0, ExtoolsHolderInner::None) { ExtoolsHolderInner::Attaching { cancel_tx, .. } => { let _ = cancel_tx.send(()); }, // TODO: ExtoolsHolderInner::Listening @@ -337,9 +339,8 @@ impl Drop for Extools { } fn parse_lineno(comment: &str) -> Option { - let prefix = "Line number: "; - if comment.starts_with(prefix) { - comment[prefix.len()..].parse::().ok() + if let Some(rest) = comment.strip_prefix("Line number: ") { + rest.parse::().ok() } else { None } diff --git a/crates/dm-langserver/src/debugger/mod.rs b/crates/dm-langserver/src/debugger/mod.rs index f990a108..da2fee80 100644 --- a/crates/dm-langserver/src/debugger/mod.rs +++ b/crates/dm-langserver/src/debugger/mod.rs @@ -2,6 +2,8 @@ //! //! * https://microsoft.github.io/debug-adapter-protocol/ #![allow(dead_code)] +// In BYOND references 0xAA_BBBBBB, A is the the type and B is the instance ID. +#![allow(clippy::unusual_byte_groupings)] macro_rules! output { (in $seq:expr, $fmt:expr) => { @@ -49,10 +51,14 @@ use auxtools::Auxtools; use ahash::RandomState; use dap_types::*; +use self::auxtools::AuxtoolsScopes; use self::extools::ExtoolsHolder; use self::launched::{Launched, EngineParams}; use crate::jrpc_io; +/// line, path, name, override_id +pub type LineNumber = (i64, String, String, usize); + pub fn start_server( engine: DebugEngine, dreamseeker_exe: String, @@ -138,7 +144,7 @@ impl DebugDatabaseBuilder { extools_dll: _, debug_server_dll: _, } = self; - let mut line_numbers: HashMap, RandomState> = + let mut line_numbers: HashMap, RandomState> = HashMap::with_hasher(RandomState::default()); objtree.root().recurse(&mut |ty| { @@ -179,7 +185,7 @@ pub struct DebugDatabase { root_dir: std::path::PathBuf, files: dm::FileList, objtree: Arc, - line_numbers: HashMap, RandomState>, + line_numbers: HashMap, RandomState>, } fn get_proc<'o>( @@ -363,7 +369,7 @@ impl Debugger { } } - DebugClient::Auxtools(auxtools) => for stack in auxtools.get_stacks().unwrap_or(vec![]) { + DebugClient::Auxtools(auxtools) => for stack in auxtools.get_stacks().unwrap_or_default() { if stack.id == 0 { continue; } @@ -528,7 +534,7 @@ handle_request! { } DebugClient::Auxtools(auxtools) => { - self.stddef_dm_info = auxtools.get_stddef()?.map(|x| StddefDmInfo::new(x)); + self.stddef_dm_info = auxtools.get_stddef()?.map(StddefDmInfo::new); auxtools.configured()?; } } @@ -657,7 +663,7 @@ handle_request! { } saved.retain(|k| { - if !keep.contains(&k) { + if !keep.contains(k) { extools.unset_breakpoint(&k.0, k.1, k.2); false } else { @@ -728,7 +734,7 @@ handle_request! { } saved.retain(|k| { - if !keep.contains(&k) { + if !keep.contains(k) { let _ = auxtools.unset_breakpoint(&auxtools_types::InstructionRef { proc: auxtools_types::ProcRef { path: k.0.clone(), @@ -800,7 +806,7 @@ handle_request! { } saved.retain(|k| { - if !keep.contains(&k) { + if !keep.contains(k) { extools.unset_breakpoint(&k.0, k.1, k.2); false } else { @@ -857,7 +863,7 @@ handle_request! { } saved.retain(|k| { - if !keep.contains(&k) { + if !keep.contains(k) { let _ = auxtools.unset_breakpoint(&auxtools_types::InstructionRef { proc: auxtools_types::ProcRef { path: k.0.clone(), @@ -1050,7 +1056,7 @@ handle_request! { } DebugClient::Auxtools(auxtools) => { - let (arguments, locals, globals) = auxtools.get_scopes(frameId as u32)?; + let AuxtoolsScopes { arguments, locals, globals } = auxtools.get_scopes(frameId as u32)?; let mut scopes = Vec::with_capacity(locals.is_some() as usize + arguments.is_some() as usize + globals.is_some() as usize); if let Some(locals) = locals { diff --git a/crates/dm-langserver/src/document.rs b/crates/dm-langserver/src/document.rs index 02816d2b..168bb2df 100644 --- a/crates/dm-langserver/src/document.rs +++ b/crates/dm-langserver/src/document.rs @@ -8,7 +8,6 @@ use std::collections::HashMap; use std::rc::Rc; use url::Url; -use jsonrpc; use lsp_types::{TextDocumentItem, TextDocumentIdentifier, VersionedTextDocumentIdentifier, TextDocumentContentChangeEvent}; @@ -229,7 +228,7 @@ pub fn find_word(text: &str, offset: usize) -> &str { } fn is_ident(ch: char) -> bool { - (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_' + ('0'..='9').contains(&ch) || ('a'..='z').contains(&ch) || ('A'..='Z').contains(&ch) || ch == '_' } /// An adaptation of `std::io::Cursor` which works on an `Rc`, which diff --git a/crates/dm-langserver/src/find_references.rs b/crates/dm-langserver/src/find_references.rs index e138f8a5..242b73a8 100644 --- a/crates/dm-langserver/src/find_references.rs +++ b/crates/dm-langserver/src/find_references.rs @@ -338,7 +338,7 @@ impl<'o> WalkProc<'o> { fn visit_var(&mut self, location: Location, var_type: &VarType, name: &str, value: Option<&'o Expression>) { let ty = self.static_type(location, &var_type.type_path); self.use_type(location, &ty); - if let Some(ref expr) = value { + if let Some(expr) = value { self.visit_expression(location, expr, ty.basic_type()); } self.local_vars.insert(name.to_owned(), Local { diff --git a/crates/dm-langserver/src/jrpc_io.rs b/crates/dm-langserver/src/jrpc_io.rs index 8cd378d2..d3ff6a42 100644 --- a/crates/dm-langserver/src/jrpc_io.rs +++ b/crates/dm-langserver/src/jrpc_io.rs @@ -35,7 +35,7 @@ fn read(input: &mut R) -> Result, Box()? }; // skip blank line diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index 3c133f80..1dd93f38 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -133,8 +133,8 @@ impl ClientCaps { } } if let Some(ref experimental) = caps.experimental { - if let Some(ref dreammaker) = experimental.get("dreammaker") { - if let Some(ref object_tree) = dreammaker.get("objectTree") { + if let Some(dreammaker) = experimental.get("dreammaker") { + if let Some(object_tree) = dreammaker.get("objectTree") { if let Some(value) = object_tree.as_bool() { this.object_tree = value; } @@ -153,7 +153,7 @@ struct DiagnosticsTracker { impl DiagnosticsTracker { fn file_url(root: Option<&Url>, file_list: &dm::FileList, file: dm::FileId) -> Option { let fname_string = file_list.get_path(file).display().to_string(); - if let Some(ref root) = root { + if let Some(root) = root { root.join(&fname_string).ok() } else { Url::parse(&fname_string).ok() @@ -580,17 +580,17 @@ impl<'a> Engine<'a> { Ok(path) => path, Err(_) => "".as_ref(), }; - let (real_file_id, mut preprocessor) = match self.context.get_file(&stripped) { - Some(id) => (id, defines.branch_at_file(id, &self.context)), - None => (FileId::default(), defines.branch_at_end(&self.context)), + let (real_file_id, mut preprocessor) = match self.context.get_file(stripped) { + Some(id) => (id, defines.branch_at_file(id, self.context)), + None => (FileId::default(), defines.branch_at_end(self.context)), }; let contents = self.docs.read(url).map_err(invalid_request)?; let file_id = preprocessor.push_file(stripped.to_owned(), contents).map_err(invalid_request)?; preprocessor.enable_annotations(); let mut annotations = AnnotationTree::default(); { - let indent = dm::indents::IndentProcessor::new(&self.context, &mut preprocessor); - let parser = dm::parser::Parser::new(&self.context, indent); + let indent = dm::indents::IndentProcessor::new(self.context, &mut preprocessor); + let parser = dm::parser::Parser::new(self.context, indent); parser.parse_annotations_only(&mut annotations); } annotations.merge(preprocessor.take_annotations().unwrap()); @@ -601,7 +601,7 @@ impl<'a> Engine<'a> { let filename = url.to_string(); let contents = self.docs.get_contents(url).map_err(invalid_request)?.into_owned(); - let mut pp = dm::preprocessor::Preprocessor::from_buffer(&self.context, filename.clone().into(), contents); + let mut pp = dm::preprocessor::Preprocessor::from_buffer(self.context, filename.clone().into(), contents); let file_id = self.context.get_file(filename.as_ref()).expect("file didn't exist?"); // Clear old errors for this file. Hacky, but it will work for now. self.context.errors_mut().retain(|error| error.location().file != file_id); @@ -609,8 +609,8 @@ impl<'a> Engine<'a> { pp.enable_annotations(); let mut annotations = AnnotationTree::default(); { - let indent = dm::indents::IndentProcessor::new(&self.context, &mut pp); - let mut parser = dm::parser::Parser::new(&self.context, indent); + let indent = dm::indents::IndentProcessor::new(self.context, &mut pp); + let mut parser = dm::parser::Parser::new(self.context, indent); parser.annotate_to(&mut annotations); // Every time anyone types anything the object tree is replaced. // This is probably really inefficient, but it will do until @@ -618,7 +618,7 @@ impl<'a> Engine<'a> { self.objtree = Arc::new(parser.parse_object_tree()); } pp.finalize(); - dreamchecker::run(&self.context, &self.objtree); + dreamchecker::run(self.context, &self.objtree); // Perform a diagnostics pump on this file only. // Assume all errors are in this file. @@ -694,13 +694,11 @@ impl<'a> Engine<'a> { // chop off proc name and 'proc/' or 'verb/' if it's there // TODO: factor this logic somewhere let mut proc_path = &proc_path[..]; - match proc_path.split_last() { - Some((name, rest)) => { - proc_name = Some((name.as_str(), *idx)); - proc_path = rest; - } - _ => {} + if let Some((name, rest)) = proc_path.split_last() { + proc_name = Some((name.as_str(), *idx)); + proc_path = rest; } + match proc_path.split_last() { Some((kwd, rest)) if kwd == "proc" || kwd == "verb" => proc_path = rest, _ => {} @@ -744,7 +742,7 @@ impl<'a> Engine<'a> { } // proc parameters - let ty = ty.unwrap_or(self.objtree.root()); + let ty = ty.unwrap_or_else(|| self.objtree.root()); if let Some((proc_name, idx)) = proc_name { if let Some(proc) = ty.get().procs.get(proc_name) { if let Some(value) = proc.value.get(idx) { @@ -877,7 +875,7 @@ impl<'a> Engine<'a> { }, Annotation::UnscopedCall(proc_name) => { let (ty, _) = self.find_type_context(&iter); - let mut next = ty.or(Some(self.objtree.root())); + let mut next = ty.or_else(|| Some(self.objtree.root())); while let Some(ty) = next { if let Some(proc) = ty.procs.get(proc_name) { if let Some(ref decl) = proc.declaration { @@ -959,7 +957,7 @@ impl<'a> Engine<'a> { } let _ = write!(message, "{}", each); } - message.push_str(")"); + message.push(')'); defstring = message.clone(); } @@ -1238,7 +1236,7 @@ handle_method_call! { } for (var_name, tv) in ty.vars.iter() { if let Some(decl) = tv.declaration.as_ref() { - if query.matches_var(&var_name) { + if query.matches_var(var_name) { results.push(SymbolInformation { name: var_name.clone(), kind: SymbolKind::Field, @@ -1252,7 +1250,7 @@ handle_method_call! { for (proc_name, pv) in ty.procs.iter() { if let Some(decl) = pv.declaration.as_ref() { - if query.matches_proc(&proc_name, decl.kind) { + if query.matches_proc(proc_name, decl.kind) { results.push(SymbolInformation { name: proc_name.clone(), kind: if ty.is_root() { @@ -1383,18 +1381,15 @@ handle_method_call! { } Annotation::UnscopedVar(var_name) if symbol_id.is_some() => { let (ty, proc_name) = self.find_type_context(&iter); - match self.find_unscoped_var(&iter, ty, proc_name, var_name) { - UnscopedVar::Variable { ty, .. } => { - if let Some(_decl) = ty.get_var_declaration(var_name) { - results.append(&mut self.construct_var_hover(var_name, Some(ty), false)?); - } - }, - _ => {} + if let UnscopedVar::Variable { ty, .. } = self.find_unscoped_var(&iter, ty, proc_name, var_name) { + if let Some(_decl) = ty.get_var_declaration(var_name) { + results.append(&mut self.construct_var_hover(var_name, Some(ty), false)?); + } } } Annotation::UnscopedCall(proc_name) if symbol_id.is_some() => { let (ty, _) = self.find_type_context(&iter); - let next = ty.or(Some(self.objtree.root())); + let next = ty.or_else(|| Some(self.objtree.root())); results.append(&mut self.construct_proc_hover(proc_name, next, false)?); } Annotation::ScopedCall(priors, proc_name) if symbol_id.is_some() => { @@ -1468,7 +1463,7 @@ handle_method_call! { }, Annotation::UnscopedCall(proc_name) => { let (ty, _) = self.find_type_context(&iter); - let mut next = ty.or(Some(self.objtree.root())); + let mut next = ty.or_else(|| Some(self.objtree.root())); while let Some(ty) = next { if let Some(proc) = ty.procs.get(proc_name) { results.push(self.convert_location(proc.main_value().location, &proc.main_value().docs, &[&ty.path, "/proc/", proc_name])?); @@ -1713,7 +1708,7 @@ handle_method_call! { // TODO: unscoped_completions calls find_type_context again self.unscoped_completions(&mut results, &iter, ""); } else { - self.tree_completions(&mut results, true, ty.unwrap_or(self.objtree.root()), ""); + self.tree_completions(&mut results, true, ty.unwrap_or_else(|| self.objtree.root()), ""); } } @@ -1778,7 +1773,7 @@ handle_method_call! { active_signature: Some(0), active_parameter: Some(idx as i64), signatures: vec![SignatureInformation { - label: label, + label, parameters: Some(params), documentation: None, }], @@ -1936,7 +1931,7 @@ handle_method_call! { on ColorPresentationRequest(&mut self, params) { let content = self.docs.get_contents(¶ms.text_document.uri).map_err(invalid_request)?; let chunk = document::get_range(&content, params.range)?; - let color_format = color::ColorFormat::parse(&chunk).unwrap_or_default(); + let color_format = color::ColorFormat::parse(chunk).unwrap_or_default(); // TODO: return compatible alternate presentations for converting // between "#..." and rgb(). vec![ diff --git a/crates/dm-langserver/src/symbol_search.rs b/crates/dm-langserver/src/symbol_search.rs index 2835b365..624b4701 100644 --- a/crates/dm-langserver/src/symbol_search.rs +++ b/crates/dm-langserver/src/symbol_search.rs @@ -16,16 +16,14 @@ impl Query { if !any_alphanumeric(query) { return None; } - Some(if query.starts_with('#') { - Query::Define(query[1..].to_lowercase()) - } else if query.starts_with("var/") { - let query = &query["var/".len()..]; + Some(if let Some(query) = query.strip_prefix('#') { + Query::Define(query.to_lowercase()) + } else if let Some(query) = query.strip_prefix("var/") { if !any_alphanumeric(query) { return None; } Query::Var(query.to_lowercase()) - } else if query.starts_with("proc/") { - let query = &query["proc/".len()..]; + } else if let Some(query) = query.strip_prefix("proc/") { if !any_alphanumeric(query) { return None; } @@ -55,12 +53,9 @@ impl Query { } pub fn matches_on_type(&self, _path: &str) -> bool { - match *self { - Query::Anything(_) | + matches!(*self, Query::Anything(_) | Query::Proc(_) | - Query::Var(_) => true, - _ => false, - } + Query::Var(_)) } pub fn matches_var(&self, name: &str) -> bool { @@ -80,7 +75,7 @@ impl Query { } } -fn simplify<'a>(s: &'a str) -> impl Iterator + Clone + 'a { +fn simplify(s: &str) -> impl Iterator + Clone + '_ { s.chars().flat_map(|c| c.to_lowercase()).filter(|c| c.is_alphanumeric()) } diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 51ee2a0b..5f71c851 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -232,7 +232,7 @@ fn main2() -> Result<(), Box> { if let Some(ty) = objtree.find(ty_path) { entity_exists = ty.vars.contains_key(name); } - } else if let Some(_) = objtree.find(reference) { + } else if objtree.find(reference).is_some() { entity_exists = true; } else if let Some(idx) = reference.rfind('/') { let (parent, rest) = (&reference[..idx], &reference[idx + 1..]); @@ -286,13 +286,11 @@ fn main2() -> Result<(), Box> { }) } } - } else { - if ty.location.is_builtins() { - external_url = Some(match ty.docs.builtin_docs { - BuiltinDocs::None => format!("{}{}", DM_REFERENCE_BASE, ty.path), - BuiltinDocs::ReferenceHash(hash) => format!("{}{}", DM_REFERENCE_BASE, hash), - }) - } + } else if ty.location.is_builtins() { + external_url = Some(match ty.docs.builtin_docs { + BuiltinDocs::None => format!("{}{}", DM_REFERENCE_BASE, ty.path), + BuiltinDocs::ReferenceHash(hash) => format!("{}{}", DM_REFERENCE_BASE, hash), + }) } } } @@ -317,7 +315,7 @@ fn main2() -> Result<(), Box> { } } else { for bit in ty_path.trim_start_matches('/').split('/') { - progress.push_str("/"); + progress.push('/'); progress.push_str(bit); if let Some(info) = types_with_docs.get(progress.as_str()) { if let Some(proc_name) = proc_name { @@ -431,7 +429,7 @@ fn main2() -> Result<(), Box> { if let Some(buf) = read_as_markdown(path)? { if Some(path) != index_path.as_ref().map(Path::new) { - let module = module_entry(&mut modules1, &path); + let module = module_entry(&mut modules1, path); module.items_wip.push((0, ModuleItem::DocComment(DocComment { kind: CommentKind::Block, target: DocTarget::EnclosingItem, @@ -446,7 +444,7 @@ fn main2() -> Result<(), Box> { let mut index_docs = None; if let Some(index_path) = index_path { let buf = read_as_markdown(index_path.as_ref())?.expect("file for --index must be .md or .txt"); - error_entity_put(index_path.to_owned()); + error_entity_put(index_path); index_docs = Some(DocBlock::parse_with_title(&buf, Some(broken_link_callback))); } @@ -609,7 +607,7 @@ fn main2() -> Result<(), Box> { ModuleItem::Type { path: ty.get().pretty_path(), teaser: block.teaser().to_owned(), - substance: substance, + substance, }, )); } @@ -661,7 +659,7 @@ fn main2() -> Result<(), Box> { let mut _first = true; macro_rules! push_docs { () => { // oof if !docs.is_empty() { - let doc = std::mem::replace(&mut docs, Default::default()); + let doc = std::mem::take(&mut docs); if _first { _first = false; let (title, block) = DocBlock::parse_with_title(&doc.text(), Some(broken_link_callback)); @@ -732,10 +730,10 @@ fn main2() -> Result<(), Box> { let mut tera = template::builtin()?; // register tera extensions - let linkify_typenames = all_type_names.clone(); + let linkify_typenames = all_type_names; tera.register_filter("linkify_type", move |value: &Value, _: &HashMap| { match *value { - tera::Value::String(ref s) => Ok(linkify_type(&linkify_typenames, s.split("/").skip_while(|b| b.is_empty())).into()), + tera::Value::String(ref s) => Ok(linkify_type(&linkify_typenames, s.split('/').skip_while(|b| b.is_empty())).into()), tera::Value::Array(ref a) => Ok(linkify_type(&linkify_typenames, a.iter().filter_map(|v| v.as_str())).into()), _ => Err("linkify_type() input must be string".into()), } @@ -833,7 +831,7 @@ fn main2() -> Result<(), Box> { children: Vec::new(), })), types: build_index_tree(type_docs.iter().map(|(path, ty)| IndexTree { - htmlname: &ty.htmlname, + htmlname: ty.htmlname, full_name: path, self_name: if ty.name.is_empty() { last_element(path) @@ -914,22 +912,21 @@ fn module_path(path: &Path) -> String { if path.file_name().map_or(false, |x| x.to_string_lossy().eq_ignore_ascii_case("README")) { path.pop(); } - path.display().to_string().replace("\\", "/") + path.display().to_string().replace('\\', "/") } fn module_entry<'a, 'b>(modules: &'a mut BTreeMap>, path: &Path) -> &'a mut Module1<'b> { - modules.entry(module_path(path)).or_insert_with(|| { - let mut module = Module1::default(); - module.htmlname = module_path(path); - module.orig_filename = path.display().to_string().replace("\\", "/"); - module + modules.entry(module_path(path)).or_insert_with(|| Module1 { + htmlname: module_path(path), + orig_filename: path.display().to_string().replace('\\', "/"), + .. Default::default() }) } fn is_visible(entry: &walkdir::DirEntry) -> bool { entry.file_name() .to_str() - .map(|s| !s.starts_with(".")) + .map(|s| !s.starts_with('.')) .unwrap_or(true) } @@ -946,9 +943,9 @@ fn linkify_type<'a, I: Iterator>(all_type_names: &BTreeSet let mut all_progress = String::new(); let mut progress = String::new(); for bit in iter { - all_progress.push_str("/"); + all_progress.push('/'); all_progress.push_str(bit); - progress.push_str("/"); + progress.push('/'); progress.push_str(bit); if all_type_names.contains(&all_progress) { use std::fmt::Write; @@ -1011,7 +1008,7 @@ fn git_info(git: &mut Git) -> Result<(), git2::Error> { } // figure out the remote URL, convert from SSH to HTTPS - let mut iter = upstream_name.splitn(2, "/"); + let mut iter = upstream_name.splitn(2, '/'); let remote_name = req!(iter.next()); if let Some(name) = iter.next() { git.remote_branch = name.to_owned(); @@ -1019,12 +1016,12 @@ fn git_info(git: &mut Git) -> Result<(), git2::Error> { let remote = repo.find_remote(remote_name)?; let mut url = req!(remote.url()); - if url.ends_with("/") { + if url.ends_with('/') { url = &url[..url.len() - 1]; } if url.ends_with(".git") { url = &url[..url.len() - 4]; - if url.ends_with("/") { + if url.ends_with('/') { url = &url[..url.len() - 1]; } } @@ -1033,8 +1030,8 @@ fn git_info(git: &mut Git) -> Result<(), git2::Error> { } else if url.starts_with("ssh://") { git.web_url = url.replace("ssh://", "https://"); } else { - let at = req!(url.find("@")); - let colon = req!(url.find(":")); + let at = req!(url.find('@')); + let colon = req!(url.find(':')); if colon >= at { git.web_url = format!("https://{}/{}", &url[at + 1..colon], &url[colon + 1..]); } else { @@ -1102,7 +1099,7 @@ where { let mut i = 1; let mut len = 0; - let mut bits = each.full_name.split("/").peekable(); + let mut bits = each.full_name.split('/').peekable(); if bits.peek() == Some(&"") { bits.next(); len += 1; @@ -1157,7 +1154,7 @@ fn combine(stack: &mut Vec, to: usize) { } fn last_element(path: &str) -> &str { - path.split("/").last().unwrap_or("") + path.split('/').last().unwrap_or("") } // ---------------------------------------------------------------------------- diff --git a/crates/dmdoc/src/markdown.rs b/crates/dmdoc/src/markdown.rs index 96a1fd28..574ddbf1 100644 --- a/crates/dmdoc/src/markdown.rs +++ b/crates/dmdoc/src/markdown.rs @@ -119,7 +119,7 @@ impl<'a, I: Iterator>> Iterator for HeadingLinker<'a, I> { if let Some(Event::Start(Tag::Heading(heading))) = original { let mut text_buf = String::new(); - while let Some(event) = self.inner.next() { + for event in self.inner.by_ref() { if let Event::Text(ref text) = event { text_buf.push_str(text.as_ref()); } diff --git a/crates/dmm-tools-cli/src/main.rs b/crates/dmm-tools-cli/src/main.rs index ac8e9142..f2949d00 100644 --- a/crates/dmm-tools-cli/src/main.rs +++ b/crates/dmm-tools-cli/src/main.rs @@ -73,7 +73,7 @@ impl Context { eprintln!("parsing {}", environment.display()); if let Some(parent) = environment.parent() { - self.icon_cache.set_icons_root(&parent); + self.icon_cache.set_icons_root(parent); } self.dm_context.autodetect_config(&environment); @@ -227,9 +227,7 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { .dm_context .errors() .iter() - .filter(|e| e.severity() <= dm::Severity::Error) - .next() - .is_some() + .any(|e| e.severity() <= dm::Severity::Error) { println!("there were some parsing errors; render may be inaccurate") } @@ -285,12 +283,12 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { println!("{}generating z={}", prefix, 1 + z); let bump = Default::default(); let minimap_context = minimap::Context { - objtree: &objtree, + objtree, map: &map, level: map.z_level(z), min: (min.x - 1, min.y - 1), max: (max.x - 1, max.y - 1), - render_passes: &render_passes, + render_passes, errors: &errors, bump: &bump, }; @@ -443,7 +441,7 @@ impl std::str::FromStr for CoordArg { fn from_str(s: &str) -> Result { match s - .split(",") + .split(',') .map(|x| x.parse()) .collect::, std::num::ParseIntError>>() { @@ -551,9 +549,7 @@ fn render_many(context: &Context, command: RenderManyCommand) -> RenderManyComma .dm_context .errors() .iter() - .filter(|e| e.severity() <= dm::Severity::Error) - .next() - .is_some() + .any(|e| e.severity() <= dm::Severity::Error) { eprintln!("there were some parsing errors; render may be inaccurate") } diff --git a/crates/dmm-tools/src/dmi.rs b/crates/dmm-tools/src/dmi.rs index af8916bd..93cd2719 100644 --- a/crates/dmm-tools/src/dmi.rs +++ b/crates/dmm-tools/src/dmi.rs @@ -12,7 +12,10 @@ use ndarray::Array2; pub use dm::dmi::*; use std::ops::{Index, IndexMut}; -type Rect = (u32, u32, u32, u32); +/// Absolute x and y. +pub type Coordinate = (u32, u32); +/// Start x, Start y, End x, End y - relative to Coordinate. +pub type Rect = (u32, u32, u32, u32); // ---------------------------------------------------------------------------- // Icon file and metadata handling @@ -156,7 +159,7 @@ impl Image { Ok(()) } - pub fn composite(&mut self, other: &Image, pos: (u32, u32), crop: Rect, color: [u8; 4]) { + pub fn composite(&mut self, other: &Image, pos: Coordinate, crop: Rect, color: [u8; 4]) { let other_dat = other.data.as_slice().unwrap(); let self_dat = self.data.as_slice_mut().unwrap(); let mut sy = crop.1; diff --git a/crates/dmm-tools/src/dmm.rs b/crates/dmm-tools/src/dmm.rs index b69c0cf1..58dadf60 100644 --- a/crates/dmm-tools/src/dmm.rs +++ b/crates/dmm-tools/src/dmm.rs @@ -119,13 +119,21 @@ pub struct ZLevel<'a> { } // TODO: port to ast::Prefab -#[derive(Debug, Default, Eq, PartialEq, Clone)] +#[derive(Debug, Default, Clone)] pub struct Prefab { pub path: String, // insertion order, sort of most of the time alphabetical but not quite pub vars: IndexMap, } +impl PartialEq for Prefab { + fn eq(&self, other: &Self) -> bool { + self.path == other.path && self.vars.keys().eq(other.vars.keys()) + } +} + +impl Eq for Prefab {} + impl std::hash::Hash for Prefab { fn hash(&self, state: &mut H) { self.path.hash(state); @@ -205,7 +213,7 @@ impl Map { ZLevel { grid: self.grid.index_axis(Axis(0), z) } } - pub fn iter_levels<'a>(&'a self) -> impl Iterator)> + 'a { + pub fn iter_levels(&self) -> impl Iterator)> + '_ { self.grid.axis_iter(Axis(0)).enumerate().map(|(i, grid)| (i as i32 + 1, ZLevel { grid })) } @@ -226,7 +234,7 @@ impl std::ops::Index for Map { impl<'a> ZLevel<'a> { /// Iterate over the z-level in row-major order starting at the top-left. - pub fn iter_top_down<'b>(&'b self) -> impl Iterator + 'b { + pub fn iter_top_down(&self) -> impl Iterator + '_ { let dim = self.grid.dim(); self.grid.indexed_iter().map(move |(c, k)| (Coord2::from_raw(c, dim), *k)) } @@ -322,9 +330,9 @@ impl fmt::Display for FormatKey { const BASE_52: &[u8] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; fn base_52_reverse(ch: u8) -> Result { - if ch >= b'a' && ch <= b'z' { + if (b'a'..=b'z').contains(&ch) { Ok(ch as KeyType - b'a' as KeyType) - } else if ch >= b'A' && ch <= b'Z' { + } else if (b'A'..=b'Z').contains(&ch) { Ok(26 + ch as KeyType - b'A' as KeyType) } else { Err(format!("Not a base-52 character: {:?}", ch as char)) @@ -332,7 +340,7 @@ fn base_52_reverse(ch: u8) -> Result { } fn advance_key(current: KeyType, next_digit: KeyType) -> Result { - current.checked_mul(52).and_then(|b| b.checked_add(next_digit)).ok_or_else(|| { + current.checked_mul(52).and_then(|b| b.checked_add(next_digit)).ok_or({ // https://secure.byond.com/forum/?post=2340796#comment23770802 "Key overflow, max is 'ymo'" }) diff --git a/crates/dmm-tools/src/dmm/read.rs b/crates/dmm-tools/src/dmm/read.rs index 617ebe71..a07452f2 100644 --- a/crates/dmm-tools/src/dmm/read.rs +++ b/crates/dmm-tools/src/dmm/read.rs @@ -1,6 +1,7 @@ //! Map parser, supporting standard DMM or TGM-format files. use std::collections::BTreeMap; use std::cmp::max; +use std::mem::take; use ndarray::Array3; @@ -9,11 +10,6 @@ use dm::lexer::{LocationTracker, from_utf8_or_latin1}; use super::{Map, Key, KeyType, Prefab}; -#[inline] -fn take(t: &mut T) -> T { - std::mem::replace(t, T::default()) -} - pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { let file_id = Default::default(); let mut chars = LocationTracker::new(file_id, dm::lexer::buffer_file(file_id, path)?.into()); @@ -59,6 +55,8 @@ pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { } while let Some(ch) = chars.next() { + // Readability, simple elif chain isn't duplicate code + #[allow(clippy::if_same_then_else)] if ch == b'\n' || ch == b'\r' { in_comment_line = false; comment_trigger = false; diff --git a/crates/dmm-tools/src/dmm/save_tgm.rs b/crates/dmm-tools/src/dmm/save_tgm.rs index 46677048..b37418cb 100644 --- a/crates/dmm-tools/src/dmm/save_tgm.rs +++ b/crates/dmm-tools/src/dmm/save_tgm.rs @@ -8,13 +8,15 @@ use super::Map; const TGM_HEADER: &str = "//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE"; +// Note: writeln! currently (2022-04-30) writes the \n character alone on all platforms +// If that changes, this will break. pub fn save_tgm(map: &Map, f: File) -> io::Result<()> { let mut f = BufWriter::new(f); - write!(f, "{}\n", TGM_HEADER)?; + writeln!(f, "{}", TGM_HEADER)?; // dictionary for (&key, prefabs) in map.dictionary.iter() { - write!(f, "\"{}\" = (\n", map.format_key(key))?; + writeln!(f, "\"{}\" = (", map.format_key(key))?; for (i, fab) in prefabs.iter().enumerate() { write!(f, "{}", fab.path)?; if !fab.vars.is_empty() { @@ -28,21 +30,21 @@ pub fn save_tgm(map: &Map, f: File) -> io::Result<()> { write!(f, "\n\t}}")?; } if i + 1 != prefabs.len() { - write!(f, ",\n")?; + writeln!(f, ",")?; } } - write!(f, ")\n")?; + writeln!(f, ")")?; } // grid in Y-major for (z, z_grid) in map.grid.axis_iter(Axis(0)).enumerate() { - write!(f, "\n")?; + writeln!(f)?; for (x, x_col) in z_grid.axis_iter(Axis(1)).enumerate() { - write!(f, "({},1,{}) = {{\"\n", x + 1, z + 1)?; + writeln!(f, "({},1,{}) = {{\"", x + 1, z + 1)?; for &elem in x_col.iter() { - write!(f, "{}\n", map.format_key(elem))?; + writeln!(f, "{}", map.format_key(elem))?; } - write!(f, "\"}}\n")?; + writeln!(f, "\"}}")?; } } diff --git a/crates/dmm-tools/src/icon_cache.rs b/crates/dmm-tools/src/icon_cache.rs index ec4fdde2..57fd8a8f 100644 --- a/crates/dmm-tools/src/icon_cache.rs +++ b/crates/dmm-tools/src/icon_cache.rs @@ -31,7 +31,7 @@ impl IconCache { None => { let arc = match &self.icons_root { Some(root) => load(&root.join(path)), - None => load(&path), + None => load(path), }.map(Arc::new); self.lock.write().unwrap().insert(path.to_owned(), arc.clone()); arc diff --git a/crates/dmm-tools/src/minimap.rs b/crates/dmm-tools/src/minimap.rs index e64e043b..8e992d06 100644 --- a/crates/dmm-tools/src/minimap.rs +++ b/crates/dmm-tools/src/minimap.rs @@ -6,7 +6,7 @@ use ndarray::Axis; use dm::objtree::*; use dm::constants::Constant; use crate::dmm::{Map, ZLevel, Prefab}; -use crate::dmi::{Dir, Image}; +use crate::dmi::{self, Dir, Image}; use crate::render_passes::RenderPass; use crate::icon_cache::IconCache; @@ -29,6 +29,8 @@ pub struct Context<'a> { pub bump: &'a bumpalo::Bump, } +// This should eventually be faliable and not just shrug it's shoulders at errors and log them. +#[allow(clippy::result_unit_err)] pub fn generate(ctx: Context, icon_cache: &IconCache) -> Result { let Context { objtree, @@ -70,13 +72,13 @@ pub fn generate(ctx: Context, icon_cache: &IconCache) -> Result { 'atom: for atom in atoms.get(e).expect("bad key").iter() { for pass in render_passes.iter() { // Note that late_filter is NOT called during smoothing lookups. - if !pass.late_filter(&atom, objtree) { + if !pass.late_filter(atom, objtree) { continue 'atom; } } let mut sprite = Sprite::from_vars(objtree, atom); for pass in render_passes { - pass.adjust_sprite(&atom, &mut sprite, objtree, bump); + pass.adjust_sprite(atom, &mut sprite, objtree, bump); } if sprite.icon.is_empty() { println!("no icon: {}", atom.type_.path); @@ -163,7 +165,7 @@ pub fn generate(ctx: Context, icon_cache: &IconCache) -> Result { } // OOB handling -fn clip(bounds: (u32, u32), mut loc: (i32, i32), mut rect: (u32, u32, u32, u32)) -> Option<((u32, u32), (u32, u32, u32, u32))> { +fn clip(bounds: dmi::Coordinate, mut loc: (i32, i32), mut rect: dmi::Rect) -> Option<(dmi::Coordinate, dmi::Rect)> { if loc.0 < 0 { rect.0 += (-loc.0) as u32; match rect.2.checked_sub((-loc.0) as u32) { @@ -268,7 +270,7 @@ impl<'a> Atom<'a> { impl<'a> From<&'a Type> for Atom<'a> { fn from(type_: &'a Type) -> Self { Atom { - type_: type_, + type_, prefab: None, sprite: Sprite::default(), } @@ -318,7 +320,7 @@ pub trait GetVar<'a> { fn get_path(&self) -> &str; fn get_var(&self, key: &str, objtree: &'a ObjectTree) -> &'a Constant { - self.get_var_inner(key, objtree).unwrap_or(Constant::null()) + self.get_var_inner(key, objtree).unwrap_or_else(Constant::null) } fn get_var_notnull(&self, key: &str, objtree: &'a ObjectTree) -> Option<&'a Constant> { @@ -337,7 +339,7 @@ impl<'a> GetVar<'a> for Atom<'a> { } fn get_var_inner(&self, key: &str, objtree: &'a ObjectTree) -> Option<&'a Constant> { - if let Some(ref prefab) = self.prefab { + if let Some(prefab) = self.prefab { if let Some(v) = prefab.get(key) { return Some(v); } @@ -345,7 +347,7 @@ impl<'a> GetVar<'a> for Atom<'a> { let mut current = Some(self.type_); while let Some(t) = current.take() { if let Some(v) = t.vars.get(key) { - return Some(v.value.constant.as_ref().unwrap_or(Constant::null())); + return Some(v.value.constant.as_ref().unwrap_or_else(Constant::null)); } current = objtree.parent_of(t); } @@ -365,7 +367,7 @@ impl<'a> GetVar<'a> for &'a Prefab { let mut current = objtree.find(&self.path); while let Some(t) = current.take() { if let Some(v) = t.get().vars.get(key) { - return Some(v.value.constant.as_ref().unwrap_or(Constant::null())); + return Some(v.value.constant.as_ref().unwrap_or_else(Constant::null)); } current = t.parent_type(); } @@ -382,7 +384,7 @@ impl<'a> GetVar<'a> for &'a Type { let mut current = Some(*self); while let Some(t) = current.take() { if let Some(v) = t.vars.get(key) { - return Some(v.value.constant.as_ref().unwrap_or(Constant::null())); + return Some(v.value.constant.as_ref().unwrap_or_else(Constant::null)); } current = objtree.parent_of(t); } @@ -399,7 +401,7 @@ impl<'a> GetVar<'a> for TypeRef<'a> { let mut current = Some(*self); while let Some(t) = current.take() { if let Some(v) = t.get().vars.get(key) { - return Some(v.value.constant.as_ref().unwrap_or(Constant::null())); + return Some(v.value.constant.as_ref().unwrap_or_else(Constant::null)); } current = t.parent_type(); } @@ -520,7 +522,7 @@ impl<'s> Sprite<'s> { category: Category::from_path(vars.get_path()), icon: vars.get_var("icon", objtree).as_path_str().unwrap_or(""), icon_state: vars.get_var("icon_state", objtree).as_str().unwrap_or(""), - dir: vars.get_var("dir", objtree).to_int().and_then(Dir::from_int).unwrap_or(Dir::default()), + dir: vars.get_var("dir", objtree).to_int().and_then(Dir::from_int).unwrap_or_default(), color: color_of(objtree, vars), ofs_x: pixel_x + pixel_w + step_x, ofs_y: pixel_y + pixel_z + step_y, @@ -568,12 +570,12 @@ pub(crate) fn layer_of<'s, T: GetVar<'s> + ?Sized>(objtree: &'s ObjectTree, atom pub fn color_of<'s, T: GetVar<'s> + ?Sized>(objtree: &'s ObjectTree, atom: &T) -> [u8; 4] { let alpha = match atom.get_var("alpha", objtree) { - &Constant::Float(i) if i >= 0. && i <= 255. => i as u8, + &Constant::Float(i) if (0. ..=255.).contains(&i) => i as u8, _ => 255, }; - match atom.get_var("color", objtree) { - &Constant::String(ref color) if color.starts_with("#") => { + match *atom.get_var("color", objtree) { + Constant::String(ref color) if color.starts_with('#') => { let mut sum = 0; for ch in color[1..color.len()].chars() { sum = 16 * sum + ch.to_digit(16).unwrap_or(0); @@ -591,7 +593,7 @@ pub fn color_of<'s, T: GetVar<'s> + ?Sized>(objtree: &'s ObjectTree, atom: &T) - [255, 255, 255, alpha] // invalid } } - &Constant::String(ref color) => match html_color(color) { + Constant::String(ref color) => match html_color(color) { Some([r, g, b]) => [r, g, b, alpha], None => [255, 255, 255, alpha], } diff --git a/crates/dmm-tools/src/render_passes/icon_smoothing.rs b/crates/dmm-tools/src/render_passes/icon_smoothing.rs index c0d2b51a..623a6c8f 100644 --- a/crates/dmm-tools/src/render_passes/icon_smoothing.rs +++ b/crates/dmm-tools/src/render_passes/icon_smoothing.rs @@ -118,7 +118,7 @@ fn find_type_in_direction(objtree: &ObjectTree, adjacency: &Neighborhood, source if smoothlist_contains(elements, path) { return true; } - path = &path[..path.rfind("/").unwrap()]; + path = &path[..path.rfind('/').unwrap()]; } } } else { @@ -142,9 +142,8 @@ fn find_type_in_direction(objtree: &ObjectTree, adjacency: &Neighborhood, source } fn smoothlist_contains(list: &[(Constant, Option)], desired: &str) -> bool { - for &(ref key, _) in list { - // TODO: be more specific than to_string - if key.to_string() == desired { + for (key, _) in list { + if key == desired { return true; } } diff --git a/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs b/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs index 0c74fa30..3ef0570b 100644 --- a/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs +++ b/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs @@ -81,6 +81,8 @@ impl RenderPass for IconSmoothing { // Older cardinal smoothing system fn calculate_adjacencies(objtree: &ObjectTree, neighborhood: &Neighborhood, atom: &Atom, smooth_flags: i32) -> i32 { + // Easier to read as a nested conditional + #[allow(clippy::collapsible_if)] if atom.istype("/atom/movable/") { if atom.get_var("can_be_unanchored", objtree).to_bool() && !atom.get_var("anchored", objtree).to_bool() { return 0; diff --git a/crates/dmm-tools/src/render_passes/mod.rs b/crates/dmm-tools/src/render_passes/mod.rs index 116746b3..0a20eb62 100644 --- a/crates/dmm-tools/src/render_passes/mod.rs +++ b/crates/dmm-tools/src/render_passes/mod.rs @@ -119,8 +119,8 @@ pub const RENDER_PASSES: &[RenderPassInfo] = &[ ]; pub fn configure(renderer_config: &dm::config::MapRenderer, include: &str, exclude: &str) -> Vec> { - let include: Vec<&str> = include.split(",").collect(); - let exclude: Vec<&str> = exclude.split(",").collect(); + let include: Vec<&str> = include.split(',').collect(); + let exclude: Vec<&str> = exclude.split(',').collect(); configure_list(renderer_config, &include, &exclude) } @@ -454,10 +454,10 @@ impl RenderPass for FancyLayers { self.apply_fancy_layer(atom.get_path(), sprite); // dual layering of vents 1: hide original sprite underfloor - if atom.istype("/obj/machinery/atmospherics/components/unary/") { - if unary_aboveground(atom, objtree).is_some() { - sprite.layer = Layer::from(-5); - } + if atom.istype("/obj/machinery/atmospherics/components/unary/") + && unary_aboveground(atom, objtree).is_some() + { + sprite.layer = Layer::from(-5); } } diff --git a/crates/dmm-tools/src/render_passes/random.rs b/crates/dmm-tools/src/render_passes/random.rs index bd34282f..25c0921b 100644 --- a/crates/dmm-tools/src/render_passes/random.rs +++ b/crates/dmm-tools/src/render_passes/random.rs @@ -169,10 +169,10 @@ impl RenderPass for Random { } fn pickweight<'a>(list: &[&'a (Constant, Option)]) -> &'a Constant { - let mut total: i32 = list.iter().map(|(_, v)| v.as_ref().unwrap_or(Constant::null()).to_int().unwrap_or(1)).sum(); + let mut total: i32 = list.iter().map(|(_, v)| v.as_ref().unwrap_or_else(Constant::null).to_int().unwrap_or(1)).sum(); total = rand::thread_rng().gen_range(1..=total); for (k, v) in list.iter() { - total -= v.as_ref().unwrap_or(Constant::null()).to_int().unwrap_or(1); + total -= v.as_ref().unwrap_or_else(Constant::null).to_int().unwrap_or(1); if total <= 0 { return k; } diff --git a/crates/dmm-tools/src/render_passes/smart_cables.rs b/crates/dmm-tools/src/render_passes/smart_cables.rs index b1ee0e9e..8cae1a0c 100644 --- a/crates/dmm-tools/src/render_passes/smart_cables.rs +++ b/crates/dmm-tools/src/render_passes/smart_cables.rs @@ -50,11 +50,15 @@ impl RenderPass for SmartCables { } for atom in turf { - if atom.istype("/obj/structure/cable/") { - if atom.get_var("cable_layer", objtree).as_str().unwrap_or("l2") == cable_layer { - linked_dirs |= check_dir.to_int(); - break; - } + if atom.istype("/obj/structure/cable/") + && atom + .get_var("cable_layer", objtree) + .as_str() + .unwrap_or("l2") + == cable_layer + { + linked_dirs |= check_dir.to_int(); + break; } } } @@ -87,6 +91,8 @@ impl RenderPass for SmartCables { fn should_have_node(turf: &[Atom]) -> bool { for atom in turf { + // Readability, simple elif chain isn't duplicate code + #[allow(clippy::if_same_then_else)] if atom.istype("/obj/structure/grille/") || atom.istype("/obj/structure/cable_bridge/") { return true; } else if atom.istype("/obj/machinery/power/") { diff --git a/crates/dmm-tools/src/render_passes/structures.rs b/crates/dmm-tools/src/render_passes/structures.rs index b7cf08e3..fb879c5f 100644 --- a/crates/dmm-tools/src/render_passes/structures.rs +++ b/crates/dmm-tools/src/render_passes/structures.rs @@ -16,9 +16,9 @@ impl RenderPass for Spawners { for &(ref key, _) in elements.iter() { // TODO: use a more civilized lookup method let type_key; - let reference = match key { - &Constant::String(ref s) => s, - &Constant::Prefab(ref fab) => { + let reference = match *key { + Constant::String(ref s) => s, + Constant::Prefab(ref fab) => { type_key = dm::ast::FormatTreePath(&fab.path).to_string(); type_key.as_str() }, diff --git a/crates/dmm-tools/src/render_passes/transit_tube.rs b/crates/dmm-tools/src/render_passes/transit_tube.rs index b52a1950..c79009c1 100644 --- a/crates/dmm-tools/src/render_passes/transit_tube.rs +++ b/crates/dmm-tools/src/render_passes/transit_tube.rs @@ -34,7 +34,7 @@ impl RenderPass for TransitTube { } }; - let dir = atom.get_var("dir", objtree).to_int().and_then(Dir::from_int).unwrap_or(Dir::default()); + let dir = atom.get_var("dir", objtree).to_int().and_then(Dir::from_int).unwrap_or_default(); if atom.istype("/obj/structure/transit_tube/station/reverse/") { fulfill(&match dir { North => [East], diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 196e7889..6173615c 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -37,10 +37,7 @@ pub enum StaticType<'o> { impl<'o> StaticType<'o> { fn is_truthy(&self) -> bool { - match *self { - StaticType::None => false, - _ => true, - } + !matches!(*self, StaticType::None) } fn basic_type(&self) -> Option> { @@ -226,7 +223,7 @@ impl<'o> Analysis<'o> { fn from_static_type_impure(ty: TypeRef<'o>) -> Analysis<'o> { let mut analysis = Analysis::from(StaticType::Type(ty)); analysis.is_impure = Some(true); - return analysis + analysis } fn from_value(objtree: &'o ObjectTree, value: Constant, type_hint: Option>) -> Analysis<'o> { @@ -297,7 +294,7 @@ impl<'o> From> for Analysis<'o> { Analysis { aset, - static_ty: static_ty, + static_ty, fix_hint: None, value: None, is_impure: None, @@ -328,7 +325,7 @@ fn run_inner(context: &Context, objtree: &ObjectTree, cli: bool) { cli_println!("============================================================"); cli_println!("Analyzing variables...\n"); - check_var_defs(&objtree, &context); + check_var_defs(objtree, context); let mut analyzer = AnalyzeObjectTree::new(context, objtree); @@ -485,8 +482,8 @@ impl<'o> CallStack<'o> { trait DMErrorExt { fn with_callstack(self, stack: &CallStack) -> Self; - fn with_blocking_builtins(self, blockers: &Vec<(String, Location)>) -> Self; - fn with_impure_operations(self, impures: &Vec<(String, Location)>) -> Self; + fn with_blocking_builtins(self, blockers: &[(String, Location)]) -> Self; + fn with_impure_operations(self, impures: &[(String, Location)]) -> Self; } impl DMErrorExt for DMError { @@ -497,14 +494,14 @@ impl DMErrorExt for DMError { self } - fn with_blocking_builtins(mut self, blockers: &Vec<(String, Location)>) -> DMError { + fn with_blocking_builtins(mut self, blockers: &[(String, Location)]) -> DMError { for (procname, location) in blockers.iter() { self.add_note(*location, format!("{}() called here", procname)); } self } - fn with_impure_operations(mut self, impures: &Vec<(String, Location)>) -> DMError { + fn with_impure_operations(mut self, impures: &[(String, Location)]) -> DMError { for (impure, location) in impures.iter() { self.add_note(*location, format!("{} happens here", impure)); } @@ -667,10 +664,10 @@ impl<'o> AnalyzeObjectTree<'o> { if !visited.insert(nextproc) { continue } - if let Some(_) = self.waitfor_procs.get(&nextproc) { + if self.waitfor_procs.get(&nextproc).is_some() { continue } - if let Some(_) = self.sleep_exempt.get(nextproc) { + if self.sleep_exempt.get(nextproc).is_some() { continue } if new_context { @@ -776,7 +773,7 @@ impl<'o> AnalyzeObjectTree<'o> { } } } else if name.starts_with("SpacemanDMM_") { - self.add_directive_or_error(proc, &name.as_str(), value, statement.location); + self.add_directive_or_error(proc, name.as_str(), value, statement.location); } else if !KNOWN_SETTING_NAMES.contains(&name.as_str()) { error(statement.location, format!("unknown setting {:?}", name)) .set_severity(Severity::Warning) @@ -784,7 +781,7 @@ impl<'o> AnalyzeObjectTree<'o> { } else { match name.as_str() { "background" | "waitfor" | "hidden" | "instant" | "popup_menu" => { - if let Err(_) = directive_value_to_truthy(value, statement.location) { + if directive_value_to_truthy(value, statement.location).is_err() { error(statement.location, format!("set {} must be 0/1/TRUE/FALSE", name.as_str())) .set_severity(Severity::Warning) .with_errortype("invalid_set_value") @@ -1037,11 +1034,11 @@ impl ControlFlow { } } pub fn terminates(&self) -> bool { - return !self.fuzzy && ( self.returns || self.continues || self.breaks ) + !self.fuzzy && ( self.returns || self.continues || self.breaks ) } pub fn terminates_loop(&self) -> bool { - return !self.fuzzy && ( self.returns || self.breaks ) + !self.fuzzy && ( self.returns || self.breaks ) } pub fn no_else(&mut self) { @@ -1212,7 +1209,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { let state = self.visit_statement(stmt.location, &stmt.elem, local_vars); term.merge(state); } - return term + term } fn loop_condition_check(&mut self, location: Location, expression: &'o Expression) { @@ -1252,7 +1249,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { match expr { Expression::Base { term, follow } => { if let Term::Call(call, vec) = &term.elem { - if !follow.iter().any(|f| match f.elem { Follow::Call(..) => true, _ => false }) { + if !follow.iter().any(|f| matches!(f.elem, Follow::Call(..))) { if let Some(proc) = self.ty.get_proc(call) { if let Some((_, _, loc)) = self.env.must_be_pure.get_self_or_parent(proc) { error(location, format!("call to pure proc {} discards return value", call)) @@ -1540,7 +1537,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Statement::Label { name: _, block } => { self.visit_block(block, &mut local_vars.clone()); }, Statement::Del(expr) => { self.visit_expression(location, expr, None, local_vars); }, } - return ControlFlow::allfalse() + ControlFlow::allfalse() } fn visit_var_stmt(&mut self, location: Location, var: &'o VarStatement, local_vars: &mut HashMap, RandomState>) { @@ -1552,7 +1549,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { let static_type = self.env.static_type(location, &var_type.type_path); // Visit the expression if it's there let mut analysis = match value { - Some(ref expr) => self.visit_expression(location, expr, static_type.basic_type(), local_vars), + Some(expr) => self.visit_expression(location, expr, static_type.basic_type(), local_vars), None => Analysis::null(), }; analysis.static_ty = static_type; @@ -1622,7 +1619,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { .register(self.context); }, Expression::TernaryOp { cond, if_, else_ } => { - error(location, format!("ambiguous ternary on left side of an `in`")) + error(location, "ambiguous ternary on left side of an `in`".to_string()) .set_severity(Severity::Warning) .with_errortype("ambiguous_in_lhs") .with_note(location, "add parentheses to fix: `a ? b : (c in d)`") @@ -1689,7 +1686,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { let mut ana = self.static_type(location, &decl.var_type.type_path) .with_fix_hint(decl.location, "add additional type info here"); ana.is_impure = Some(true); - return ana + ana } else { error(location, format!("undefined var: {:?}", unscoped_name)) .register(self.context); @@ -1701,10 +1698,10 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Term::Prefab(prefab) => { if let Some(nav) = self.ty.navigate_path(&prefab.path) { let ty = nav.ty(); // TODO: handle proc/verb paths here - let pop = dm::constants::Pop::from(ty.path.split("/").skip(1).map(ToOwned::to_owned).collect::>().into_boxed_slice()); + let pop = dm::constants::Pop::from(ty.path.split('/').skip(1).map(ToOwned::to_owned).collect::>().into_boxed_slice()); Analysis { static_ty: StaticType::None, - aset: assumption_set![Assumption::IsPath(true, nav.ty())].into(), + aset: assumption_set![Assumption::IsPath(true, nav.ty())], value: Some(Constant::Prefab(Box::new(pop))), fix_hint: None, is_impure: None, @@ -2039,7 +2036,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { }; error(location, format!("Attempting {} on a {} which does not overload {}", operator, typeerror, operator)) .register(self.context); - return Analysis::empty() + Analysis::empty() } fn visit_unary(&mut self, rhs: Analysis<'o>, op: &UnaryOp, location: Location, local_vars: &mut HashMap, RandomState>) -> Analysis<'o> { @@ -2091,6 +2088,8 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Analysis::empty() } + // It's fine. + #[allow(clippy::too_many_arguments)] fn check_filter_flag(&mut self, expr: &'o Expression, can_be_zero: bool, location: Location, typevalue: &str, valid_flags: &[&str], flagfieldname: &str, exclusive: bool) { match expr { Expression::BinaryOp{ op: BinaryOp::BitOr, lhs, rhs } => { @@ -2112,7 +2111,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } match &term.elem { Term::Ident(flagname) => { - if valid_flags.iter().position(|&x| x == flagname).is_none() { + if !valid_flags.iter().any(|&x| x == flagname) { error(location, format!("filter(type=\"{}\") called with invalid '{}' flag '{}'", typevalue, flagfieldname, flagname)) .with_filter_args(location, typevalue) .register(self.context); @@ -2195,7 +2194,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { .entry(name.clone()) .and_modify(|ca| ca.others += 1) .or_insert(CalledAt { - location: location, + location, others: 0, }); } @@ -2206,7 +2205,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { expr => { if let Some(Term::Call(callname, _)) = expr.as_term() { // only interested in the first expression being arglist - if callname.as_str() == "arglist" && param_name_map.len() == 0 && param_idx == 0 { + if callname.as_str() == "arglist" && param_name_map.is_empty() && param_idx == 0 { arglist_used = true; } } @@ -2245,19 +2244,19 @@ impl<'o, 's> AnalyzeProc<'o, 's> { .register(self.context); return Analysis::empty() }); - guard!(let Some(arglist) = VALID_FILTER_TYPES.get(&typevalue) else { + guard!(let Some(arglist) = VALID_FILTER_TYPES.get(typevalue) else { error(location, format!("filter() called with invalid type keyword parameter value '{}'", typevalue)) .register(self.context); return Analysis::empty() }); for arg in param_name_map.keys() { - if *arg != "type" && arglist.iter().position(|&x| x == *arg).is_none() { + if *arg != "type" && !arglist.iter().any(|&x| x == *arg) { error(location, format!("filter(type=\"{}\") called with invalid keyword parameter '{}'", typevalue, arg)) .with_filter_args(location, typevalue) .register(self.context); } } - if let Some((flagfieldname, exclusive, can_be_zero, valid_flags)) = VALID_FILTER_FLAGS.get(&typevalue) { + if let Some((flagfieldname, exclusive, can_be_zero, valid_flags)) = VALID_FILTER_FLAGS.get(typevalue) { if let Some(flagsvalue) = param_expr_map.get(flagfieldname) { self.check_filter_flag(flagsvalue, *can_be_zero, location, typevalue, valid_flags, flagfieldname, *exclusive); } diff --git a/crates/dreamchecker/src/switch_rand_range.rs b/crates/dreamchecker/src/switch_rand_range.rs index 4a71b23c..aecf2b53 100644 --- a/crates/dreamchecker/src/switch_rand_range.rs +++ b/crates/dreamchecker/src/switch_rand_range.rs @@ -8,8 +8,8 @@ use dm::{Context, DMError, Location, Severity}; * If some cases lie outside of the [L, H] range or the whole [L, H] range is not covered by all the cases a warning is issued. */ pub fn check_switch_rand_range( - input: &Box, - cases: &Box<[(Spanned>, Block)]>, + input: &Expression, + cases: &SwitchCases, default: &Option, location: Location, context: &Context, @@ -25,7 +25,7 @@ pub fn check_switch_rand_range( for case_block in cases.iter() { let location = case_block.0.location; for case in case_block.0.elem.iter() { - if let Some((start, end)) = get_case_range(&case, location) { + if let Some((start, end)) = get_case_range(case, location) { let start = start.ceil() as i32; let end = end.floor() as i32; if start <= rand_end && end >= rand_start { diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 91de444a..23a589e5 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -7,6 +7,12 @@ use phf::phf_map; use crate::error::Location; +/// Arguments for [`Term::Pick`] +pub type PickArgs = [(Option, Expression)]; + +/// Cases for [`Term::Switch`] +pub type SwitchCases = [(Spanned>, Block)]; + // ---------------------------------------------------------------------------- // Simple enums @@ -25,7 +31,7 @@ pub enum UnaryOp { impl UnaryOp { /// Prepare to display this unary operator around (to the left or right of) /// its operand. - pub fn around<'a, T: fmt::Display + ?Sized>(self, expr: &'a T) -> impl fmt::Display + 'a { + pub fn around(self, expr: &'_ T) -> impl fmt::Display + '_ { /// A formatting wrapper created by `UnaryOp::around`. struct Around<'a, T: 'a + ?Sized> { op: UnaryOp, @@ -353,13 +359,15 @@ macro_rules! type_table { } } - impl $name { - pub fn from_str(text: &str) -> Option { - match text { + impl std::str::FromStr for $name { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { $( - $txt => Some($name::$i), + $txt => Ok($name::$i), )* - _ => None, + _ => Err(()), } } } @@ -743,17 +751,14 @@ impl Expression { if !rhterm.is_static() { return false } - match op { - BinaryOp::Eq | + matches!(op, BinaryOp::Eq | BinaryOp::NotEq | BinaryOp::Less | BinaryOp::Greater | BinaryOp::LessEq | BinaryOp::GreaterEq | BinaryOp::And | - BinaryOp::Or => true, - _ => false, - } + BinaryOp::Or) }, _ => false, } @@ -793,7 +798,7 @@ impl Expression { _ => None, } } else { - return None + None } }, Expression::TernaryOp { cond, if_, else_ } => { @@ -889,7 +894,7 @@ pub enum Term { in_list: Option>, // in }, /// A `pick` call, possibly with weights. - Pick(Box<[(Option, Expression)]>), + Pick(Box), /// A use of the `call()()` primitive. DynamicCall(Box<[Expression]>, Box<[Expression]>), } @@ -1124,7 +1129,7 @@ impl VarSuffix { pub fn into_initializer(self) -> Option { // `var/L[10]` is equivalent to `var/list/L = new /list(10)` // `var/L[2][][3]` is equivalent to `var/list/list/list = new /list(2, 3)` - let args: Vec<_> = self.list.into_iter().filter_map(|x| x).collect(); + let args: Vec<_> = self.list.into_iter().flatten().collect(); if args.is_empty() { None } else { @@ -1184,7 +1189,7 @@ pub enum Statement { }, Switch { input: Box, - cases: Box<[(Spanned>, Block)]>, + cases: Box, default: Option, }, TryCatch { diff --git a/crates/dreammaker/src/config.rs b/crates/dreammaker/src/config.rs index 1f129c50..4adcb258 100644 --- a/crates/dreammaker/src/config.rs +++ b/crates/dreammaker/src/config.rs @@ -180,13 +180,11 @@ impl From for WarningLevel { impl PartialEq for WarningLevel { fn eq(&self, other: &Severity) -> bool { - match (self, other) { - (WarningLevel::Error, Severity::Error) => true, - (WarningLevel::Warning, Severity::Warning) => true, - (WarningLevel::Info, Severity::Info) => true, - (WarningLevel::Hint, Severity::Hint) => true, - _ => false, - } + matches!((self, other), + (WarningLevel::Error, Severity::Error) + | (WarningLevel::Warning, Severity::Warning) + | (WarningLevel::Info, Severity::Info) + | (WarningLevel::Hint, Severity::Hint)) } } diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index 9cb6a0d9..bfd7c30f 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -13,15 +13,24 @@ use super::objtree::*; use super::preprocessor::DefineMap; use super::{Context, DMError, HasLocation, Location, Severity}; +pub type Arguments = [(Constant, Option)]; + /// An absolute typepath and optional variables. /// /// The path may involve `/proc` or `/verb` references. -#[derive(Clone, Eq, PartialEq, Debug)] +#[derive(Clone, Debug)] pub struct Pop { pub path: TreePath, pub vars: IndexMap, } +impl PartialEq for Pop { + fn eq(&self, other: &Self) -> bool { + self.path == other.path && self.vars.keys().eq(other.vars.keys()) + } +} + +impl Eq for Pop {} impl std::hash::Hash for Pop { fn hash(&self, state: &mut H) { @@ -58,12 +67,12 @@ pub enum Constant { /// The type to be instantiated. type_: Option>, /// The list of arugments to pass to the `New()` proc. - args: Option)]>>, + args: Option>, }, /// A `list` literal. Elements have optional associations. - List(Box<[(Constant, Option)]>), + List(Box), /// A call to a constant type constructor. - Call(ConstFn, Box<[(Constant, Option)]>), + Call(ConstFn, Box), /// A prefab literal. Prefab(Box), /// A string literal. @@ -144,8 +153,8 @@ impl Constant { // ------------------------------------------------------------------------ // Constructors - pub fn null() -> &'static Constant { - static NULL: Constant = Constant::Null(None); + pub const fn null<'a>() -> &'a Constant { + const NULL: Constant = Constant::Null(None); &NULL } @@ -407,7 +416,7 @@ pub fn evaluate_str(location: Location, input: &[u8]) -> Result return Ok(ConstLookup::Continue(parent)), Some(var) => match var.value.constant.clone() { - Some(constant) => return Ok(ConstLookup::Found(decl.var_type.type_path.clone(), constant)), + Some(constant) => return Ok(ConstLookup::Found(decl.var_type.type_path, constant)), None => match var.value.expression.clone() { Some(expr) => { if var.value.being_evaluated { @@ -591,7 +600,7 @@ impl<'a> ConstantFolder<'a> { } /// arguments or keyword arguments - fn arguments(&mut self, v: Box<[Expression]>) -> Result)]>, DMError> { + fn arguments(&mut self, v: Box<[Expression]>) -> Result, DMError> { let mut out = Vec::with_capacity(v.len()); for each in Vec::from(v).into_iter() { out.push(match each { @@ -822,7 +831,7 @@ impl<'a> ConstantFolder<'a> { return Err(self.error(format!("cannot reference variable {:?} in this context", ident))); } let tree = self.tree.as_mut().unwrap(); - match constant_ident_lookup(tree, ty, &ident, must_be_const) + match constant_ident_lookup(tree, ty, ident, must_be_const) .map_err(|e| e.with_location(location))? { ConstLookup::Found(_, v) => return Ok(v), @@ -900,27 +909,25 @@ impl<'a> ConstantFolder<'a> { // Only set space if it wasn't set manually by the space arg let space = if let Some(space) = space { space - } else { - if color_args.r || color_args.g || color_args.b { - // TODO: Add hint here for useless r/g/b kwarg - ColorSpace::Rgb - } else if color_args.h { - if color_args.c && color_args.y { - ColorSpace::Hcy - } else if color_args.s { - if color_args.v { - ColorSpace::Hsv - } else if color_args.l { - ColorSpace::Hsl - } else { - return Err(self.error("malformed rgb() call, could not determine space: only h & s specified")); - } + } else if color_args.r || color_args.g || color_args.b { + // TODO: Add hint here for useless r/g/b kwarg + ColorSpace::Rgb + } else if color_args.h { + if color_args.c && color_args.y { + ColorSpace::Hcy + } else if color_args.s { + if color_args.v { + ColorSpace::Hsv + } else if color_args.l { + ColorSpace::Hsl } else { - return Err(self.error("malformed rgb() call, could not determine space: only h specified")); + return Err(self.error("malformed rgb() call, could not determine space: only h & s specified")); } } else { - ColorSpace::Rgb // Default + return Err(self.error("malformed rgb() call, could not determine space: only h specified")); } + } else { + ColorSpace::Rgb // Default }; let mut value_vec: Vec = vec![]; @@ -999,7 +1006,7 @@ impl<'a> ConstantFolder<'a> { }; // Extract the raw 4th alpha positional argument if it wasn't a kwarg - let alpha = color_args.a.or(value_vec.get(3).map(|&x| x as i32)); + let alpha = color_args.a.or_else(|| value_vec.get(3).map(|&x| x as i32)); // APPARENTLY the author thinks fractional rgb is a thing, hence the rounding if let Some(alpha) = alpha { diff --git a/crates/dreammaker/src/dmi.rs b/crates/dreammaker/src/dmi.rs index a031d8e3..4e30c786 100644 --- a/crates/dreammaker/src/dmi.rs +++ b/crates/dreammaker/src/dmi.rs @@ -266,7 +266,7 @@ impl Metadata { } let state_index = match self.state_names.get(icon_state) { Some(&i) => i, - None if icon_state == "" => 0, + None if icon_state.is_empty() => 0, None => return None, }; let state = &self.states[state_index]; @@ -285,7 +285,7 @@ impl Metadata { impl State { pub fn num_sprites(&self) -> usize { - self.dirs.len() * self.frames.len() + self.dirs.count() * self.frames.count() } pub fn index_of_dir(&self, dir: Dir) -> u32 { @@ -306,12 +306,12 @@ impl State { #[inline] pub fn index_of_frame(&self, dir: Dir, frame: u32) -> u32 { - self.index_of_dir(dir) + frame * self.dirs.len() as u32 + self.index_of_dir(dir) + frame * self.dirs.count() as u32 } } impl Dirs { - pub fn len(self) -> usize { + pub fn count(self) -> usize { match self { Dirs::One => 1, Dirs::Four => 4, @@ -321,7 +321,7 @@ impl Dirs { } impl Frames { - pub fn len(&self) -> usize { + pub fn count(&self) -> usize { match *self { Frames::One => 1, Frames::Count(n) => n, @@ -371,7 +371,7 @@ fn parse_metadata(data: &str) -> Metadata { "height" => metadata.height = value.parse().unwrap(), "state" => { if let Some(state) = state.take() { - frames_so_far += state.frames.len() * state.dirs.len(); + frames_so_far += state.frames.count() * state.dirs.count(); metadata.states.push(state); } let unquoted = value[1..value.len() - 1].to_owned(); // TODO: unquote diff --git a/crates/dreammaker/src/error.rs b/crates/dreammaker/src/error.rs index 74d999f7..05c7aa29 100644 --- a/crates/dreammaker/src/error.rs +++ b/crates/dreammaker/src/error.rs @@ -253,7 +253,7 @@ impl Context { let mut printed = false; for err in errors.iter() { if err.severity <= min_severity { - self.pretty_print_error(stderr, &err).expect("error writing to stderr"); + self.pretty_print_error(stderr, err).expect("error writing to stderr"); printed = true; } } diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index ef943fcf..df29b73c 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -434,11 +434,11 @@ impl LocatedToken { } fn is_digit(ch: u8) -> bool { - ch >= b'0' && ch <= b'9' + (b'0'..=b'9').contains(&ch) } fn is_ident(ch: u8) -> bool { - (ch >= b'a' && ch <= b'z') || (ch >= b'A' && ch <= b'Z') || ch == b'_' + (b'a'..=b'z').contains(&ch) || (b'A'..=b'Z').contains(&ch) || ch == b'_' } fn from_latin1(bytes: &[u8]) -> String { @@ -1261,7 +1261,7 @@ impl<'ctx> Iterator for Lexer<'ctx> { _ => { if !found_illegal { let mut msg = format!("illegal byte 0x{:x}", first); - if first >= b' ' && first <= b'~' { + if (b' '..=b'~').contains(&first) { use std::fmt::Write; let _ = write!(msg, " ({:?})", first as char); } diff --git a/crates/dreammaker/src/lib.rs b/crates/dreammaker/src/lib.rs index 2c9b4c6e..02473825 100644 --- a/crates/dreammaker/src/lib.rs +++ b/crates/dreammaker/src/lib.rs @@ -173,18 +173,16 @@ pub const DEFAULT_ENV: &str = "tgstation.dme"; /// If multiple environments exist, the first non-default is preferred. pub fn detect_environment(root: &Path, default: &str) -> std::io::Result> { let mut result = None; - for entry in std::fs::read_dir(root)? { - if let Ok(entry) = entry { - let name = entry.file_name(); - let (dme, default) = { - let utf8_name = name.to_string_lossy(); - (utf8_name.ends_with(".dme"), utf8_name == default) - }; - if dme { - result = Some(entry.path()); - if !default { - break; - } + for entry in std::fs::read_dir(root)?.flatten() { + let name = entry.file_name(); + let (dme, default) = { + let utf8_name = name.to_string_lossy(); + (utf8_name.ends_with(".dme"), utf8_name == default) + }; + if dme { + result = Some(entry.path()); + if !default { + break; } } } diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index 277853f6..46169776 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -644,7 +644,7 @@ impl ObjectTree { (0..self.graph.len()).map(NodeIndex::new) } - pub fn iter_types<'a>(&'a self) -> impl Iterator> + 'a { + pub fn iter_types(&self) -> impl Iterator> + '_ { self.node_indices().map(move |idx| TypeRef::new(self, idx)) } @@ -877,7 +877,7 @@ impl ObjectTreeBuilder { parent_type_buf = String::new(); for piece in pop.path.iter() { parent_type_buf.push('/'); - parent_type_buf.push_str(&piece); + parent_type_buf.push_str(piece); } parent_type = &parent_type_buf; } @@ -892,7 +892,7 @@ impl ObjectTreeBuilder { parent_type }; - if path == "/client" && parent_type == "" { + if path == "/client" && parent_type.is_empty() { // client has no parent by default, but can be safely reparented to /datum NodeIndex::new(0) } else if let Some(&idx) = self.inner.types.get(parent_type) { @@ -1100,6 +1100,8 @@ impl ObjectTreeBuilder { }))) } + // It's fine. + #[allow(clippy::too_many_arguments)] pub(crate) fn register_proc( &mut self, context: &Context, diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index e32ac05a..f6807db9 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -3,6 +3,9 @@ use std::borrow::Cow; use std::collections::BTreeMap; use std::ops::Range; +use std::str::FromStr; + +use crate::ast; use super::{DMError, Location, HasLocation, Context, Severity, FileId}; use super::lexer::{LocatedToken, Token, Punctuation}; @@ -90,6 +93,8 @@ impl OpInfo { } #[derive(Debug, Clone, Copy)] +// Too much effort to change now, and it matches the ast naming, so whatever +#[allow(clippy::enum_variant_names)] enum Op { BinaryOp(BinaryOp), AssignOp(AssignOp), @@ -251,12 +256,11 @@ impl TTKind { } fn is_end(self, token: &Token) -> bool { - match (self, token) { - (TTKind::Paren, &Token::Punct(Punctuation::RParen)) => true, - (TTKind::Brace, &Token::Punct(Punctuation::RBrace)) => true, - (TTKind::Bracket, &Token::Punct(Punctuation::RBracket)) => true, - _ => false, - } + matches!((self, token), + (TTKind::Paren, &Token::Punct(Punctuation::RParen)) + | (TTKind::Brace, &Token::Punct(Punctuation::RBrace)) + | (TTKind::Bracket, &Token::Punct(Punctuation::RBracket)) + ) } } @@ -586,9 +590,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { fn tree_block(&mut self, current: NodeIndex, proc_kind: Option, var_type: Option) -> Status<()> { leading!(self.exact(Token::Punct(Punctuation::LBrace))); - Ok(Some(require!( - self.tree_entries(current, proc_kind, var_type, Token::Punct(Punctuation::RBrace)) - ))) + require!(self.tree_entries(current, proc_kind, var_type, Token::Punct(Punctuation::RBrace))); + SUCCESS } fn tree_entries(&mut self, current: NodeIndex, proc_kind: Option, var_type: Option, terminator: Token) -> Status<()> { @@ -981,7 +984,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let result = { let mut subparser: Parser<'ctx, '_, '_> = Parser::new(self.context, body_tt); if let Some(a) = self.annotations.as_mut() { - subparser.annotations = Some(&mut *a); + subparser.annotations = Some(*a); } let block = subparser.block(&LoopContext::None); subparser.require(block) @@ -1009,7 +1012,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { proc.docs.extend(comment); // manually performed for borrowck reasons if let Some(dest) = self.annotations.as_mut() { - let new_stack = reconstruct_path(&self.tree.get_path(current), proc_kind, None, name); + let new_stack = reconstruct_path(self.tree.get_path(current), proc_kind, None, name); dest.insert(entry_start..body_start, Annotation::ProcHeader(new_stack.to_vec(), idx)); dest.insert(body_start..self.location, Annotation::ProcBody(new_stack.to_vec(), idx)); } @@ -1142,8 +1145,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let ident = leading!(self.ident()); let mut as_what = match InputType::from_str(&ident) { - Some(what) => what, - None => { + Ok(what) => what, + Err(()) => { self.context.register_error(self.error(format!("bad input type: '{}'", ident))); InputType::empty() } @@ -1151,8 +1154,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { while let Some(()) = self.exact(Token::Punct(Punctuation::BitOr))? { let ident = require!(self.ident()); match InputType::from_str(&ident) { - Some(what) => as_what |= what, - None => { + Ok(what) => as_what |= what, + Err(()) => { self.context.register_error(self.error(format!("bad input type: '{}'", ident))); } } @@ -1397,15 +1400,14 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let try_block = require!(self.block(loop_ctx)); self.skip_phantom_semicolons()?; require!(self.exact_ident("catch")); - let catch_params; - if let Some(()) = self.exact(Token::Punct(Punctuation::LParen))? { - catch_params = require!(self.separated(Punctuation::Comma, Punctuation::RParen, None, |this| { + let catch_params = if let Some(()) = self.exact(Token::Punct(Punctuation::LParen))? { + require!(self.separated(Punctuation::Comma, Punctuation::RParen, None, |this| { // TODO: improve upon this cheap approximation success(leading!(this.tree_path(true)).1.into_boxed_slice()) - })); + })) } else { - catch_params = Vec::new(); - } + Vec::new() + }; let catch_block = require!(self.block(loop_ctx)); spanned(Statement::TryCatch { try_block, @@ -1591,6 +1593,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // for(var/a = 1 to 20 // for(var/a in 1 to 20 + // This... isn't a boxed local, it's method arguments. Clippy?? + #[allow(clippy::boxed_local)] fn for_range( &mut self, var_type: Option, @@ -2183,10 +2187,10 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let follow = match self.arguments(belongs_to, &ident)? { Some(args) => { if !belongs_to.is_empty() { - let past = std::mem::replace(belongs_to, Vec::new()); + let past = std::mem::take(belongs_to); self.annotate_precise(start..end, || Annotation::ScopedCall(past, ident.clone())); } - Follow::Call(kind, ident.into(), args.into()) + Follow::Call(kind, ident.into(), args) }, None => { if !belongs_to.is_empty() { @@ -2267,7 +2271,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } } - fn pick_arguments(&mut self) -> Status, Expression)]>> { + fn pick_arguments(&mut self) -> Status> { leading!(self.exact(Token::Punct(Punctuation::LParen))); success(require!(self.separated( Punctuation::Comma, diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index a681eadc..771f1fab 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -641,7 +641,7 @@ impl<'ctx> Preprocessor<'ctx> { // Make sure the file hasn't already been included. // All DM source is effectively `#pragma once`. - let file_id = self.context.register_file(®ister); + let file_id = self.context.register_file(register); if let Some(&loc) = self.include_locations.get(&file_id) { Err(DMError::new(self.last_input_loc, format!("duplicate #include {:?}", path)) .set_severity(Severity::Warning) @@ -652,7 +652,7 @@ impl<'ctx> Preprocessor<'ctx> { Ok(Include::File { path, //file: file_id, - lexer: Lexer::from_read(&self.context, file_id, read)?, + lexer: Lexer::from_read(self.context, file_id, read)?, }) } } @@ -744,7 +744,7 @@ impl<'ctx> Preprocessor<'ctx> { expect_token!((path_str) = Token::String(path_str)); let include_loc = _last_expected_loc; expect_token!(() = Token::Punct(Punctuation::Newline)); - let path = PathBuf::from(path_str.replace("\\", "/")); + let path = PathBuf::from(path_str.replace('\\', "/")); for candidate in vec![ // 1. relative to file in which `#include` appears. @@ -757,6 +757,8 @@ impl<'ctx> Preprocessor<'ctx> { } // Double-match is used to let go of the borrow of // `candidate` so it can be used in the second half. + // This is how BYOND refers to it's file formats, this is how we should refer to them. + #[allow(clippy::upper_case_acronyms)] enum FileType { DMM, DMF, @@ -815,9 +817,8 @@ impl<'ctx> Preprocessor<'ctx> { // Skip to the end of the line, or else we'll catch // stringify operators `#X` as unknown directives. loop { - match next!() { - Token::Punct(Punctuation::Newline) => break, - _ => {} + if let Token::Punct(Punctuation::Newline) = next!() { + break } } } diff --git a/crates/interval-tree/src/tree.rs b/crates/interval-tree/src/tree.rs index 7e6b399d..5e1eafb6 100644 --- a/crates/interval-tree/src/tree.rs +++ b/crates/interval-tree/src/tree.rs @@ -94,7 +94,7 @@ impl IntervalTree { pub fn remove(&mut self, key: RangeInclusive) { match self.root.take() { Some(box_to_node) => self.root = box_to_node.delete(key), - None => return + None => () } } @@ -161,7 +161,7 @@ impl IntervalTree { /// assert_eq!(t.min().unwrap().1, &[25]); /// /// ``` - pub fn min<'a>(&'a self) -> Option<(&'a RangeInclusive, &'a [V])> { + pub fn min(&self) -> Option<(&'_ RangeInclusive, &'_ [V])> { self.root.as_ref().map(|n| n.min_pair()) } @@ -178,15 +178,10 @@ impl IntervalTree { /// assert_eq!(t.max().unwrap().1, &[50]); /// /// ``` - pub fn max<'a>(&'a self) -> Option<(&'a RangeInclusive, &'a [V])> { + pub fn max(&self) -> Option<(&'_ RangeInclusive, &'_ [V])> { self.root.as_ref().map(|n| n.max_pair()) } -/// Return an iterator for all (key,value) pairs in the tree, consuming the tree in the process. - pub fn into_iter(self) -> IntoIter { - IntoIter::new(self) - } - /// Merge all (key, value) pairs from another tree into this one, consuming it. pub fn merge(&mut self, other: IntervalTree) { for (k, v) in other.into_iter() { @@ -195,6 +190,17 @@ impl IntervalTree { } } +impl IntoIterator for IntervalTree { + type Item = as Iterator>::Item; + + type IntoIter = IntoIter; + + /// Return an iterator for all (key,value) pairs in the tree, consuming the tree in the process. + fn into_iter(self) -> Self::IntoIter { + Self::IntoIter::new(self) + } +} + impl IntervalTree { /// This function will return a read only iterator for all (key,value) pairs between the two /// bounds. From 8d57ddf399c4637af493b770dd903f3285d16ced Mon Sep 17 00:00:00 2001 From: LatteKat <56778689+jupyterkat@users.noreply.github.com> Date: Thu, 12 May 2022 12:42:55 +1000 Subject: [PATCH 008/197] Update all dependencies (#314) notable changes: - dmdoc: changes in brokenlink callback, no longer takes &str directly, borrows instead, so the closure must not outlive the doc its parsing - langserver: some structs's member names are changed to uppercase, doc-id version is not an option<> anymore, some u64s are changed to be u32 instead, oneof enum uses in some cases Co-authored-by: Tad Hardesty --- Cargo.lock | 428 +++++++++++++------------ crates/builtins-proc-macro/Cargo.toml | 2 +- crates/dap-types/Cargo.toml | 6 +- crates/dm-langserver/Cargo.toml | 24 +- crates/dm-langserver/src/completion.rs | 24 +- crates/dm-langserver/src/document.rs | 22 +- crates/dm-langserver/src/main.rs | 85 ++--- crates/dmdoc/Cargo.toml | 18 +- crates/dmdoc/src/main.rs | 424 +++++++++++++----------- crates/dmdoc/src/markdown.rs | 20 +- crates/dmm-tools-cli/Cargo.toml | 16 +- crates/dmm-tools/Cargo.toml | 18 +- crates/dreamchecker/Cargo.toml | 6 +- crates/dreammaker/Cargo.toml | 22 +- crates/interval-tree/Cargo.toml | 2 +- crates/spaceman-dmm/Cargo.toml | 28 +- 16 files changed, 601 insertions(+), 544 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c935f37..358ef1ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,15 +56,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "base64" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bincode" @@ -122,9 +116,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.8.0" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "byte-tools" @@ -134,18 +128,18 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytemuck" -version = "1.7.3" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f" +checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e215f8c2f9f79cb53c8335e687ffd07d5bfcb6fe5fc80723762d0be46e7cc54" +checksum = "562e382481975bc61d11275ac5e62a19abd00b0547d99516a415336f183dcd0e" dependencies = [ "proc-macro2", "quote", @@ -160,9 +154,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cc" -version = "1.0.72" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" dependencies = [ "jobserver", ] @@ -231,18 +225,18 @@ checksum = "3776b2bcc4e914db501bb9be9572dd706e344b9eb8f882894f3daa651d281381" [[package]] name = "crc32fast" -version = "1.3.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" dependencies = [ "cfg-if", "crossbeam-utils", @@ -261,10 +255,11 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.5" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" +checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" dependencies = [ + "autocfg", "cfg-if", "crossbeam-utils", "lazy_static", @@ -274,9 +269,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" dependencies = [ "cfg-if", "lazy_static", @@ -294,9 +289,9 @@ dependencies = [ [[package]] name = "deflate" -version = "0.9.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f95bf05dffba6e6cce8dfbb30def788154949ccd9aed761b472119c21e01c70" +checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f" dependencies = [ "adler32", ] @@ -437,70 +432,6 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" -[[package]] -name = "encoding" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" -dependencies = [ - "encoding-index-japanese", - "encoding-index-korean", - "encoding-index-simpchinese", - "encoding-index-singlebyte", - "encoding-index-tradchinese", -] - -[[package]] -name = "encoding-index-japanese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-korean" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-simpchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-singlebyte" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-tradchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding_index_tests" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" - [[package]] name = "fake-simd" version = "0.1.2" @@ -518,9 +449,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af" dependencies = [ "cfg-if", "crc32fast", @@ -546,9 +477,92 @@ dependencies = [ [[package]] name = "futures" -version = "0.1.31" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-executor" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" + +[[package]] +name = "futures-macro" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] [[package]] name = "generic-array" @@ -570,9 +584,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if", "libc", @@ -592,9 +606,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.13.25" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29229cc1b24c0e6062f6e742aa3e256492a5323365e5ed3413599f8a5eff7d6" +checksum = "d0155506aab710a86160ddb504a480d2964d7ab5b9e62419be69e0032bc5931c" dependencies = [ "bitflags", "libc", @@ -697,9 +711,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" dependencies = [ "autocfg", "hashbrown", @@ -738,11 +752,13 @@ dependencies = [ [[package]] name = "jsonrpc-core" -version = "14.2.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0747307121ffb9703afd93afbd0fb4f854c38fb873f2c8b90e0e902f27c7b62" +checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ "futures", + "futures-executor", + "futures-util", "log", "serde", "serde_derive", @@ -757,15 +773,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.112" +version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" [[package]] name = "libgit2-sys" -version = "0.12.26+1.3.0" +version = "0.13.4+1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e1c899248e606fbfe68dcb31d8b0176ebab833b103824af31bddf4b7457494" +checksum = "d0fa6563431ede25f5cc7f6d803c6afbc1c5d3ad3d4925d12c882bf2b526f5d1" dependencies = [ "cc", "libc", @@ -775,9 +791,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.3" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" +checksum = "92e7e15d7610cce1d9752e137625f14e61a28cd45929b6e12e47b50fe154ee2e" dependencies = [ "cc", "libc", @@ -787,10 +803,11 @@ dependencies = [ [[package]] name = "lodepng" -version = "3.4.7" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24844d5c0b922ddd52fb5bf0964a4c7f8e799a946ec01bb463771eb04fc1a323" +checksum = "7f84e1fdcdbe8b3f0f9caaadb6b86d0e0647786e993f6ea70686f6837b989ec7" dependencies = [ + "crc32fast", "fallible_collections", "flate2", "libc", @@ -799,20 +816,19 @@ dependencies = [ [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] [[package]] name = "lsp-types" -version = "0.80.0" +version = "0.93.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4265e2715bdacbb4dad029fce525e420cd66dc0af24ff9cb996a8ab48ac92ef" +checksum = "70c74e2173b2b31f8655d33724b4b45ac13f439386f66290f539c22b144c2212" dependencies = [ - "base64", "bitflags", "serde", "serde_json", @@ -843,9 +859,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" @@ -858,12 +874,11 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.4.4" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" dependencies = [ "adler", - "autocfg", ] [[package]] @@ -881,18 +896,18 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085" +checksum = "97fbc387afefefd5e9e39493299f3069e14a140dd34dc19b4c1c1a8fddb6a790" dependencies = [ "num-traits", ] [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", "num-traits", @@ -900,18 +915,18 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", @@ -919,9 +934,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" [[package]] name = "opaque-debug" @@ -931,9 +946,9 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "ordered-float" -version = "2.8.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97c9d06878b3a851e8026ef94bf7fef9ba93062cd412601da4d9cf369b1cc62d" +checksum = "96bcbab4bfea7a59c2c0fe47211a1ac4e3e96bea6eb446d704f310bc5c732ae2" dependencies = [ "num-traits", ] @@ -1052,29 +1067,40 @@ dependencies = [ ] [[package]] -name = "pkg-config" -version = "0.3.24" +name = "pin-project-lite" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "png" -version = "0.17.2" +version = "0.17.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c845088517daa61e8a57eee40309347cea13f273694d1385c553e7a57127763b" +checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba" dependencies = [ "bitflags", "crc32fast", "deflate", - "encoding", "miniz_oxide", ] [[package]] name = "ppv-lite86" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro-error" @@ -1108,18 +1134,18 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.34" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" +checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" dependencies = [ "unicode-xid", ] [[package]] name = "pulldown-cmark" -version = "0.7.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca36dea94d187597e104a5c8e4b07576a8a45aa5db48a65e12940d3eb7461f55" +checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6" dependencies = [ "bitflags", "getopts", @@ -1129,23 +1155,22 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.10" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ "proc-macro2", ] [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -1167,15 +1192,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - [[package]] name = "rawpointer" version = "0.2.1" @@ -1184,9 +1200,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" +checksum = "fd249e82c21598a9a426a4e00dd7adc1d640b22445ec8545feef801d1a74c221" dependencies = [ "autocfg", "crossbeam-deque", @@ -1196,22 +1212,21 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" +checksum = "9f51245e1e62e1f1629cbfec37b5793bbabcaeb90f30e94d2ba03564687353e4" dependencies = [ "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "lazy_static", "num_cpus", ] [[package]] name = "regex" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" dependencies = [ "aho-corasick", "memchr", @@ -1226,9 +1241,9 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "rgb" -version = "0.8.31" +version = "0.8.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a374af9a0e5fdcdd98c1c7b64f05004f9ea2555b6c75f211daa81268a3c50f1" +checksum = "e74fdc210d8f24a7dbfedc13b04ba5764f5232754ccebfdf5fff1bad791ccbc6" dependencies = [ "bytemuck", ] @@ -1256,18 +1271,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.132" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.132" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ "proc-macro2", "quote", @@ -1276,9 +1291,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.73" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ "itoa", "ryu", @@ -1287,9 +1302,9 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5" +checksum = "a2ad84e47328a31223de7fed7a4f5087f2d6ddfe586cf3ca25b7a165bc0a5aed" dependencies = [ "proc-macro2", "quote", @@ -1310,9 +1325,15 @@ dependencies = [ [[package]] name = "siphasher" -version = "0.3.7" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + +[[package]] +name = "slab" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" [[package]] name = "slug" @@ -1331,9 +1352,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" dependencies = [ "clap", "lazy_static", @@ -1355,9 +1376,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.82" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +checksum = "04066589568b72ec65f42d65a1a52436e954b168773148893c020269563decf2" dependencies = [ "proc-macro2", "quote", @@ -1388,9 +1409,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] @@ -1406,28 +1427,29 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ "once_cell", ] [[package]] name = "time" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", + "wasi", "winapi", ] [[package]] name = "tinyvec" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -1440,18 +1462,18 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "toml" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "serde", ] [[package]] name = "typenum" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "ucd-trie" @@ -1529,9 +1551,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-normalization" @@ -1544,9 +1566,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" [[package]] name = "unicode-width" @@ -1556,9 +1578,9 @@ checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "unicode-xid" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" [[package]] name = "url" @@ -1587,9 +1609,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" @@ -1604,9 +1626,9 @@ dependencies = [ [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "winapi" diff --git a/crates/builtins-proc-macro/Cargo.toml b/crates/builtins-proc-macro/Cargo.toml index 1c17dcfa..7c715111 100644 --- a/crates/builtins-proc-macro/Cargo.toml +++ b/crates/builtins-proc-macro/Cargo.toml @@ -10,4 +10,4 @@ proc-macro = true [dependencies] syn = "1.0" quote = "1.0" -proc-macro2 = "1.0.24" +proc-macro2 = "1.0.37" diff --git a/crates/dap-types/Cargo.toml b/crates/dap-types/Cargo.toml index 67f0e7ae..aa3d2b6d 100644 --- a/crates/dap-types/Cargo.toml +++ b/crates/dap-types/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Tad Hardesty "] edition = "2018" [dependencies] -serde = "1.0.27" -serde_json = "1.0.10" -serde_derive = "1.0.27" +serde = "1.0.136" +serde_json = "1.0.79" +serde_derive = "1.0.136" ahash = "0.7.6" diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index 2336c4e1..20f2d0ab 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -5,23 +5,23 @@ authors = ["Tad Hardesty "] edition = "2018" [dependencies] -url = "2.1.0" -serde = "1.0.27" -serde_json = "1.0.10" -serde_derive = "1.0.27" -bincode = "1.3.1" -jsonrpc-core = "14.0.3" -lsp-types = "0.80.0" +url = "2.2.2" +serde = "1.0.136" +serde_json = "1.0.79" +serde_derive = "1.0.136" +bincode = "1.3.3" +jsonrpc-core = "18.0.0" +lsp-types = "0.93.0" dap-types = { path = "../dap-types" } dreammaker = { path = "../dreammaker" } dreamchecker = { path = "../dreamchecker" } interval-tree = { path = "../interval-tree" } -libc = "0.2.65" -guard = "0.5.0" -regex = "1.3" +libc = "0.2.124" +guard = "0.5.1" +regex = "1.5.5" lazy_static = "1.4" ahash = "0.7.6" [build-dependencies] -chrono = "0.4.0" -git2 = { version = "0.13", default-features = false } +chrono = "0.4.19" +git2 = { version = "0.14.2", default-features = false } diff --git a/crates/dm-langserver/src/completion.rs b/crates/dm-langserver/src/completion.rs index 00cef839..18356796 100644 --- a/crates/dm-langserver/src/completion.rs +++ b/crates/dm-langserver/src/completion.rs @@ -66,7 +66,7 @@ fn item_var(ty: TypeRef, name: &str, var: &TypeVar) -> CompletionItem { CompletionItem { label: name.to_owned(), - kind: Some(CompletionItemKind::Field), + kind: Some(CompletionItemKind::FIELD), detail: Some(detail), documentation: item_documentation(&var.value.docs), .. Default::default() @@ -77,11 +77,11 @@ fn item_proc(ty: TypeRef, name: &str, proc: &TypeProc) -> CompletionItem { CompletionItem { label: name.to_owned(), kind: Some(if ty.is_root() { - CompletionItemKind::Function + CompletionItemKind::FUNCTION } else if is_constructor_name(name) { - CompletionItemKind::Constructor + CompletionItemKind::CONSTRUCTOR } else { - CompletionItemKind::Method + CompletionItemKind::METHOD }), detail: Some(format!("on {}", ty.pretty_path())), documentation: item_documentation(&proc.main_value().docs), @@ -234,7 +234,7 @@ impl<'a> Engine<'a> { if contains(name, query) { results.push(CompletionItem { label: name.to_owned(), - kind: Some(CompletionItemKind::Keyword), + kind: Some(CompletionItemKind::KEYWORD), .. Default::default() }) } @@ -246,7 +246,7 @@ impl<'a> Engine<'a> { if contains(child.name(), query) { results.push(CompletionItem { label: child.name().to_owned(), - kind: Some(CompletionItemKind::Class), + kind: Some(CompletionItemKind::CLASS), documentation: item_documentation(&child.docs), .. Default::default() }); @@ -323,7 +323,7 @@ impl<'a> Engine<'a> { if contains(name, query) { results.push(CompletionItem { label: name.to_owned(), - kind: Some(CompletionItemKind::Keyword), + kind: Some(CompletionItemKind::KEYWORD), .. Default::default() }) } @@ -334,7 +334,7 @@ impl<'a> Engine<'a> { if contains(child.name(), query) { results.push(CompletionItem { label: child.name().to_owned(), - kind: Some(CompletionItemKind::Class), + kind: Some(CompletionItemKind::CLASS), documentation: item_documentation(&child.docs), .. Default::default() }); @@ -387,7 +387,7 @@ impl<'a> Engine<'a> { if contains(name, query) { results.push(CompletionItem { label: name.to_owned(), - kind: Some(CompletionItemKind::Keyword), + kind: Some(CompletionItemKind::KEYWORD), .. Default::default() }); } @@ -400,7 +400,7 @@ impl<'a> Engine<'a> { if contains(name, query) { results.push(CompletionItem { label: name.clone(), - kind: Some(CompletionItemKind::Variable), + kind: Some(CompletionItemKind::VARIABLE), detail: Some("(local)".to_owned()), .. Default::default() }); @@ -417,7 +417,7 @@ impl<'a> Engine<'a> { if contains(¶m.name, query) { results.push(CompletionItem { label: param.name.clone(), - kind: Some(CompletionItemKind::Variable), + kind: Some(CompletionItemKind::VARIABLE), detail: Some("(parameter)".to_owned()), .. Default::default() }); @@ -434,7 +434,7 @@ impl<'a> Engine<'a> { if contains(name, query) { results.push(CompletionItem { label: name.to_owned(), - kind: Some(CompletionItemKind::Constant), + kind: Some(CompletionItemKind::CONSTANT), detail: Some(define.display_with_name(name).to_string()), documentation: item_documentation(define.docs()), .. Default::default() diff --git a/crates/dm-langserver/src/document.rs b/crates/dm-langserver/src/document.rs index 168bb2df..33b1fc6f 100644 --- a/crates/dm-langserver/src/document.rs +++ b/crates/dm-langserver/src/document.rs @@ -42,15 +42,7 @@ impl DocumentStore { doc_id: VersionedTextDocumentIdentifier, changes: Vec, ) -> Result { - // "If a versioned text document identifier is sent from the server to - // the client and the file is not open in the editor (the server has - // not received an open notification before) the server can send `null` - // to indicate that the version is known and the content on disk is the - // truth (as speced with document content ownership)." - let new_version = match doc_id.version { - Some(version) => version, - None => return Err(invalid_request("document version is missing")), - }; + let new_version = doc_id.version; let document = match self.map.get_mut(&doc_id.uri) { Some(doc) => doc, @@ -106,12 +98,12 @@ impl DocumentStore { /// The internal representation of document contents received from the client. struct Document { - version: i64, + version: i32, text: Rc, } impl Document { - fn new(version: i64, text: String) -> Document { + fn new(version: i32, text: String) -> Document { Document { version, text: Rc::new(text), @@ -139,7 +131,7 @@ impl Document { /// Find the offset into the given text at which the given zero-indexed line /// number begins. -fn line_offset(text: &str, line_number: u64) -> Result { +fn line_offset(text: &str, line_number: u32) -> Result { // Hopefully this logic isn't too far off. let mut start_pos = 0; for _ in 0..line_number { @@ -151,14 +143,14 @@ fn line_offset(text: &str, line_number: u64) -> Result { Ok(start_pos) } -fn total_offset(text: &str, line: u64, mut character: u64) -> Result { +fn total_offset(text: &str, line: u32, mut character: u32) -> Result { let start = line_offset(text, line)?; // column is measured in UTF-16 code units, which is really inconvenient. let mut chars = text[start..].chars(); while character > 0 { if let Some(ch) = chars.next() { - character = character.saturating_sub(ch.len_utf16() as u64); + character = character.saturating_sub(ch.len_utf16() as u32); } else { break } @@ -180,7 +172,7 @@ pub fn offset_to_position(text: &str, offset: usize) -> lsp_types::Position { let mut character = 0; for ch in text[line_start..offset].chars() { - character += ch.len_utf16() as u64; + character += ch.len_utf16() as u32; } lsp_types::Position { line, character } diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index 1dd93f38..46aaec6a 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -199,7 +199,7 @@ impl DiagnosticsTracker { for note in error.notes().iter() { let diag = lsp_types::Diagnostic { message: note.description().to_owned(), - severity: Some(lsp_types::DiagnosticSeverity::Information), + severity: Some(lsp_types::DiagnosticSeverity::INFORMATION), range: location_to_range(note.location()), source: component_to_source(error.component()), .. Default::default() @@ -245,7 +245,7 @@ struct Engine<'a> { docs: document::DocumentStore, status: InitStatus, - parent_pid: u64, + parent_pid: u32, threads: Vec>, root: Option, @@ -381,7 +381,7 @@ impl<'a> Engine<'a> { fn recurse_objtree(&self, ty: TypeRef) -> extras::ObjectTreeType { let mut entry = extras::ObjectTreeType { name: ty.name().to_owned(), - kind: lsp_types::SymbolKind::Class, + kind: lsp_types::SymbolKind::CLASS, location: self.convert_location(ty.location, &ty.docs, &[&ty.path]).ok(), vars: Vec::new(), procs: Vec::new(), @@ -393,7 +393,7 @@ impl<'a> Engine<'a> { let is_declaration = var.declaration.is_some(); entry.vars.push(extras::ObjectTreeVar { name: name.to_owned(), - kind: lsp_types::SymbolKind::Field, + kind: lsp_types::SymbolKind::FIELD, location: self.convert_location(var.value.location, &var.value.docs, &[&ty.path, "/var/", name]).ok(), is_declaration, }); @@ -406,7 +406,7 @@ impl<'a> Engine<'a> { for value in proc.value.iter() { entry.procs.push(extras::ObjectTreeProc { name: name.to_owned(), - kind: lsp_types::SymbolKind::Method, + kind: lsp_types::SymbolKind::METHOD, location: self.convert_location(value.location, &value.docs, &[&ty.path, "/proc/", name]).ok(), is_verb, }); @@ -660,7 +660,7 @@ impl<'a> Engine<'a> { for note in error.notes().iter() { let diag = lsp_types::Diagnostic { message: note.description().to_owned(), - severity: Some(lsp_types::DiagnosticSeverity::Information), + severity: Some(lsp_types::DiagnosticSeverity::INFORMATION), range: location_to_range(note.location()), source: component_to_source(error.component()), .. Default::default() @@ -1054,7 +1054,7 @@ impl<'a> Engine<'a> { }, Call::Notification(notification) => { if let Err(e) = self.handle_notification(notification) { - self.show_message(MessageType::Error, e.message); + self.show_message(MessageType::ERROR, e.message); } None }, @@ -1154,20 +1154,21 @@ handle_method_call! { InitializeResult { capabilities: ServerCapabilities { - definition_provider: Some(true), - workspace_symbol_provider: Some(true), + definition_provider: Some(OneOf::Left(true)), + workspace_symbol_provider: Some(OneOf::Left(true)), hover_provider: Some(HoverProviderCapability::Simple(true)), - document_symbol_provider: Some(true), - references_provider: Some(true), + document_symbol_provider: Some(OneOf::Left(true)), + references_provider: Some(OneOf::Left(true)), implementation_provider: Some(ImplementationProviderCapability::Simple(true)), type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)), text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { open_close: Some(true), - change: Some(TextDocumentSyncKind::Incremental), + change: Some(TextDocumentSyncKind::INCREMENTAL), .. Default::default() })), completion_provider: Some(CompletionOptions { trigger_characters: Some(vec![".".to_owned(), ":".to_owned(), "/".to_owned()]), + all_commit_characters: None, resolve_provider: None, work_done_progress_options: Default::default(), }), @@ -1211,9 +1212,10 @@ handle_method_call! { if query.matches_define(name) { results.push(SymbolInformation { name: name.to_owned(), - kind: SymbolKind::Constant, + kind: SymbolKind::CONSTANT, location: self.convert_location(range.start, define.docs(), &["/DM/preprocessor/", name])?, container_name: None, + tags: None, deprecated: None, }); } @@ -1224,9 +1226,10 @@ handle_method_call! { if query.matches_type(ty.name(), &ty.path) && !ty.is_root() { results.push(SymbolInformation { name: ty.name().to_owned(), - kind: SymbolKind::Class, + kind: SymbolKind::CLASS, location: self.convert_location(ty.location, &ty.docs, &[&ty.path])?, container_name: Some(ty.parent_path_str().to_owned()), + tags: None, deprecated: None, }); } @@ -1239,9 +1242,10 @@ handle_method_call! { if query.matches_var(var_name) { results.push(SymbolInformation { name: var_name.clone(), - kind: SymbolKind::Field, + kind: SymbolKind::FIELD, location: self.convert_location(decl.location, &tv.value.docs, &[&ty.path, "/var/", var_name])?, container_name: Some(ty.path.clone()), + tags: None, deprecated: None, }); } @@ -1254,14 +1258,15 @@ handle_method_call! { results.push(SymbolInformation { name: proc_name.clone(), kind: if ty.is_root() { - SymbolKind::Function + SymbolKind::FUNCTION } else if is_constructor_name(proc_name.as_str()) { - SymbolKind::Constructor + SymbolKind::CONSTRUCTOR } else { - SymbolKind::Method + SymbolKind::METHOD }, location: self.convert_location(decl.location, &pv.main_value().docs, &[&ty.path, "/proc/", proc_name])?, container_name: Some(ty.path.clone()), + tags: None, deprecated: None, }); } @@ -1757,7 +1762,7 @@ handle_method_call! { if self.client_caps.label_offset_support { params.push(ParameterInformation { - label: ParameterLabel::LabelOffsets([start as u64, end as u64]), + label: ParameterLabel::LabelOffsets([start as u32, end as u32]), documentation: None, }); } else { @@ -1771,11 +1776,12 @@ handle_method_call! { result = Some(SignatureHelp { active_signature: Some(0), - active_parameter: Some(idx as i64), + active_parameter: Some(idx as u32), signatures: vec![SignatureInformation { label, parameters: Some(params), documentation: None, + active_parameter: None, }], }); break; @@ -1829,7 +1835,8 @@ handle_method_call! { result.push(DocumentSymbol { name, detail, - kind: SymbolKind::Class, + kind: SymbolKind::CLASS, + tags: None, deprecated: None, range, selection_range, @@ -1840,7 +1847,8 @@ handle_method_call! { result.push(DocumentSymbol { name: path.last().unwrap().to_owned(), detail: None, - kind: SymbolKind::Field, + kind: SymbolKind::FIELD, + tags: None, deprecated: None, range, selection_range, @@ -1851,17 +1859,18 @@ handle_method_call! { if path.is_empty() { continue } let (name, detail) = name_and_detail(path); let kind = if path.len() == 1 || (path.len() == 2 && path[0] == "proc") { - SymbolKind::Function + SymbolKind::FUNCTION } else if is_constructor_name(&name) { - SymbolKind::Constructor + SymbolKind::CONSTRUCTOR } else { - SymbolKind::Method + SymbolKind::METHOD }; result.push(DocumentSymbol { name, detail, kind, deprecated: None, + tags: None, range, selection_range, children: Some(find_document_symbols(iter, end)), @@ -1871,7 +1880,8 @@ handle_method_call! { result.push(DocumentSymbol { name: name.to_owned(), detail: None, - kind: SymbolKind::Variable, + kind: SymbolKind::VARIABLE, + tags: None, deprecated: None, range, selection_range, @@ -1882,7 +1892,8 @@ handle_method_call! { result.push(DocumentSymbol { name: name.to_owned(), detail: None, - kind: SymbolKind::Constant, + kind: SymbolKind::CONSTANT, + tags: None, deprecated: None, range, selection_range, @@ -1918,10 +1929,10 @@ handle_method_call! { end: document::offset_to_position(&content, end), }, color: Color { - red: (r as f64) / 255., - green: (g as f64) / 255., - blue: (b as f64) / 255., - alpha: (a as f64) / 255., + red: (r as f32) / 255., + green: (g as f32) / 255., + blue: (b as f32) / 255., + alpha: (a as f32) / 255., }, }); } @@ -2104,10 +2115,10 @@ fn path_to_url(path: PathBuf) -> Result { fn convert_severity(severity: dm::Severity) -> lsp_types::DiagnosticSeverity { match severity { - dm::Severity::Error => lsp_types::DiagnosticSeverity::Error, - dm::Severity::Warning => lsp_types::DiagnosticSeverity::Warning, - dm::Severity::Info => lsp_types::DiagnosticSeverity::Information, - dm::Severity::Hint => lsp_types::DiagnosticSeverity::Hint, + dm::Severity::Error => lsp_types::DiagnosticSeverity::ERROR, + dm::Severity::Warning => lsp_types::DiagnosticSeverity::WARNING, + dm::Severity::Info => lsp_types::DiagnosticSeverity::INFORMATION, + dm::Severity::Hint => lsp_types::DiagnosticSeverity::HINT, } } @@ -2138,8 +2149,8 @@ fn is_constructor_name(name: &str) -> bool { fn location_to_position(loc: dm::Location) -> lsp_types::Position { lsp_types::Position { - line: loc.line.saturating_sub(1) as u64, - character: loc.column.saturating_sub(1) as u64, + line: loc.line.saturating_sub(1) as u32, + character: loc.column.saturating_sub(1) as u32, } } diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index 3523bacb..f5dd91ef 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -7,16 +7,16 @@ edition = "2018" [dependencies] dreammaker = { path = "../dreammaker" } -pulldown-cmark = "0.7.0" -tera = "1.0.2" -serde = "1.0.71" -serde_derive = "1.0.27" -walkdir = "2.2.0" -git2 = { version = "0.13", default-features = false } +pulldown-cmark = "0.9.1" +tera = "1.15.0" +serde = "1.0.136" +serde_derive = "1.0.136" +walkdir = "2.3.2" +git2 = { version = "0.14.2", default-features = false } [dev-dependencies] -walkdir = "2.2.0" +walkdir = "2.3.2" [build-dependencies] -chrono = "0.4.0" -git2 = { version = "0.13", default-features = false } +chrono = "0.4.19" +git2 = { version = "0.14.2", default-features = false } diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 5f71c851..9a80a5e6 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -15,6 +15,8 @@ use std::io::{self, Write}; use std::fs::{self, File}; use std::path::{Path, PathBuf}; use std::sync::Arc; +use dm::objtree::ObjectTree; +use pulldown_cmark::{BrokenLink, CowStr}; use tera::Value; @@ -176,201 +178,6 @@ fn main2() -> Result<(), Box> { let diagnostic_count: std::cell::Cell = Default::default(); let error_entity: std::cell::Cell> = Default::default(); let error_entity_put = |string: String| error_entity.set(Some(string)); - let error_entity_print = || { - diagnostic_count.set(diagnostic_count.get() + 1); - if let Some(name) = error_entity.take() { - eprintln!("{}:", name); - } - }; - - // (normalized, reference) -> (href, tooltip) - let broken_link_callback = &|_: &str, reference: &str| -> Option<(String, String)> { - // macros - if let Some(module) = macro_to_module_map.get(reference) { - return Some((format!("{}.html#define/{}", module, reference), reference.to_owned())); - } else if macro_exists.contains(reference) { - error_entity_print(); - eprintln!(" [{}]: macro not documented", reference); - return None; - } else if reference.ends_with(".dm") || reference.ends_with(".txt") || reference.ends_with(".md") { - let mod_path = module_path(reference.as_ref()); - if modules_which_exist.contains(&mod_path) { - return Some((format!("{}.html", mod_path), reference.to_owned())); - } - error_entity_print(); - eprintln!(" [{}]: module {}", reference, if Path::new(reference).exists() { "not documented" } else { "does not exist" }); - return None; - } - - // parse "proc" or "var" reference out - let mut ty_path = reference; - let mut proc_name = None; - let mut var_name = None; - let mut entity_exists = false; - if let Some(idx) = reference.find("/proc/") { - // `[/ty/proc/procname]` - let name = &reference[idx + "/proc/".len()..]; - proc_name = Some(name); - ty_path = &reference[..idx]; - if let Some(ty) = objtree.find(ty_path) { - entity_exists = ty.procs.contains_key(name); - } - } else if let Some(idx) = reference.find("/verb/") { - // `[/ty/verb/procname]` - let name = &reference[idx + "/verb/".len()..]; - proc_name = Some(name); - ty_path = &reference[..idx]; - if let Some(ty) = objtree.find(ty_path) { - // there are no builtin verbs - entity_exists = ty.procs.contains_key(name); - } - } else if let Some(idx) = reference.find("/var/") { - // `[/ty/var/varname]` - let name = &reference[idx + "/var/".len()..]; - var_name = Some(name); - ty_path = &reference[..idx]; - if let Some(ty) = objtree.find(ty_path) { - entity_exists = ty.vars.contains_key(name); - } - } else if objtree.find(reference).is_some() { - entity_exists = true; - } else if let Some(idx) = reference.rfind('/') { - let (parent, rest) = (&reference[..idx], &reference[idx + 1..]); - if let Some(ty) = objtree.find(parent) { - if ty.procs.contains_key(rest) && !ty.vars.contains_key(rest) { - // correct `[/ty/procname]` to `[/ty/proc/procname]` - proc_name = Some(rest); - ty_path = parent; - error_entity_print(); - eprintln!(" [{}]: correcting to [{}/proc/{}]", reference, parent, rest); - entity_exists = true; - } else if ty.vars.contains_key(rest) { - // correct `[/ty/varname]` to `[/ty/var/varname]` - var_name = Some(rest); - ty_path = parent; - error_entity_print(); - eprintln!(" [{}]: correcting to [{}/var/{}]", reference, parent, rest); - entity_exists = true; - } - } - } else if objtree.root().vars.contains_key(reference) { - ty_path = ""; - var_name = Some(reference); - error_entity_print(); - eprintln!(" [{0}]: correcting to [/var/{0}]", reference); - entity_exists = true; - } - // else `[/ty]` - - // Determine external doc URL - let mut external_url = None; - if entity_exists { - // TODO: .location.is_builtins() is not the best way to find this out, - // for example if it's overridden in the DM code but not re-documented. - if let Some(ty) = objtree.find(ty_path) { - if let Some(var_name) = var_name { - if let Some(var) = ty.get_value(var_name) { - if var.location.is_builtins() { - external_url = Some(match var.docs.builtin_docs { - BuiltinDocs::None => format!("{}{}/var/{}", DM_REFERENCE_BASE, ty.path, var_name), - BuiltinDocs::ReferenceHash(hash) => format!("{}{}", DM_REFERENCE_BASE, hash), - }) - } - } - } else if let Some(proc_name) = proc_name { - if let Some(proc) = ty.get_proc(proc_name) { - if proc.location.is_builtins() { - external_url = Some(match proc.docs.builtin_docs { - BuiltinDocs::None => format!("{}{}/proc/{}", DM_REFERENCE_BASE, ty.path, proc_name), - BuiltinDocs::ReferenceHash(hash) => format!("{}{}", DM_REFERENCE_BASE, hash), - }) - } - } - } else if ty.location.is_builtins() { - external_url = Some(match ty.docs.builtin_docs { - BuiltinDocs::None => format!("{}{}", DM_REFERENCE_BASE, ty.path), - BuiltinDocs::ReferenceHash(hash) => format!("{}{}", DM_REFERENCE_BASE, hash), - }) - } - } - } - - let mut progress = String::new(); - let mut best = 0; - - if ty_path.is_empty() { - progress.push_str("/global"); - if let Some(info) = types_with_docs.get("") { - if let Some(proc_name) = proc_name { - if info.proc_docs.contains(proc_name) { - best = progress.len(); - } - } else if let Some(var_name) = var_name { - if info.var_docs.contains(var_name) { - best = progress.len(); - } - } else { - best = progress.len(); - } - } - } else { - for bit in ty_path.trim_start_matches('/').split('/') { - progress.push('/'); - progress.push_str(bit); - if let Some(info) = types_with_docs.get(progress.as_str()) { - if let Some(proc_name) = proc_name { - if info.proc_docs.contains(proc_name) { - best = progress.len(); - } - } else if let Some(var_name) = var_name { - if info.var_docs.contains(var_name) { - best = progress.len(); - } - } else { - best = progress.len(); - } - } - } - } - - if best > 0 { - use std::fmt::Write; - - if best < progress.len() { - error_entity_print(); - if entity_exists { - eprint!(" [{}]: not documented, guessing [{}", reference, &progress[..best]); - } else { - eprint!(" [{}]: unknown crosslink, guessing [{}", reference, &progress[..best]); - } - if let Some(proc_name) = proc_name { - let _ = eprint!("/proc/{}", proc_name); - } else if let Some(var_name) = var_name { - let _ = eprint!("/var/{}", var_name); - } - eprintln!("]"); - progress.truncate(best); - } - - let mut href = format!("{}.html", &progress[1..]); - if let Some(proc_name) = proc_name { - let _ = write!(href, "#proc/{}", proc_name); - } else if let Some(var_name) = var_name { - let _ = write!(href, "#var/{}", var_name); - } - Some((href, progress)) - } else if let Some(external) = external_url { - Some((external, reference.to_owned())) - } else { - error_entity_print(); - if entity_exists { - eprintln!(" [{}]: not documented", reference); - } else { - eprintln!(" [{}]: unknown crosslink", reference); - } - None - } - }; // if macros have docs, that counts as a module too for (range, (name, define)) in define_history.iter() { @@ -399,6 +206,9 @@ fn main2() -> Result<(), Box> { continue; } error_entity_put(format!("#define {}", name)); + let broken_link_callback = &mut |link: BrokenLink| -> Option<(CowStr, CowStr)> { + broken_link_fixer(link, ¯o_to_module_map, ¯o_exists, &diagnostic_count, &error_entity, &modules_which_exist, &objtree, &types_with_docs) + }; let docs = DocBlock::parse(&docs.text(), Some(broken_link_callback)); let module = module_entry(&mut modules1, &context.file_path(range.start.file)); module.items_wip.push(( @@ -445,6 +255,9 @@ fn main2() -> Result<(), Box> { if let Some(index_path) = index_path { let buf = read_as_markdown(index_path.as_ref())?.expect("file for --index must be .md or .txt"); error_entity_put(index_path); + let broken_link_callback = &mut |link: BrokenLink| -> Option<(CowStr, CowStr)> { + broken_link_fixer(link, ¯o_to_module_map, ¯o_exists, &diagnostic_count, &error_entity, &modules_which_exist, &objtree, &types_with_docs) + }; index_docs = Some(DocBlock::parse_with_title(&buf, Some(broken_link_callback))); } @@ -477,6 +290,9 @@ fn main2() -> Result<(), Box> { let mut substance = false; if !ty.docs.is_empty() { error_entity_put(ty.path.to_owned()); + let broken_link_callback = &mut |link: BrokenLink| -> Option<(CowStr, CowStr)> { + broken_link_fixer(link, ¯o_to_module_map, ¯o_exists, &diagnostic_count, &error_entity, &modules_which_exist, &objtree, &types_with_docs) + }; let (title, block) = DocBlock::parse_with_title(&ty.docs.text(), Some(broken_link_callback)); if let Some(title) = title { parsed_type.name = title.into(); @@ -509,6 +325,9 @@ fn main2() -> Result<(), Box> { } error_entity_put(format!("{}/var/{}", ty.path, name)); + let broken_link_callback = &mut |link: BrokenLink| -> Option<(CowStr, CowStr)> { + broken_link_fixer(link, ¯o_to_module_map, ¯o_exists, &diagnostic_count, &error_entity, &modules_which_exist, &objtree, &types_with_docs) + }; let block = DocBlock::parse(&var.value.docs.text(), Some(broken_link_callback)); // if the var is global, add it to the module tree @@ -565,6 +384,9 @@ fn main2() -> Result<(), Box> { } error_entity_put(format!("{}/proc/{}", ty.path, name)); + let broken_link_callback = &mut |link: BrokenLink| -> Option<(CowStr, CowStr)> { + broken_link_fixer(link, ¯o_to_module_map, ¯o_exists, &diagnostic_count, &error_entity, &modules_which_exist, &objtree, &types_with_docs) + }; let block = DocBlock::parse(&proc_value.docs.text(), Some(broken_link_callback)); // if the proc is global, add it to the module tree @@ -660,6 +482,9 @@ fn main2() -> Result<(), Box> { macro_rules! push_docs { () => { // oof if !docs.is_empty() { let doc = std::mem::take(&mut docs); + let broken_link_callback = &mut |link: BrokenLink| -> Option<(CowStr, CowStr)> { + broken_link_fixer(link, ¯o_to_module_map, ¯o_exists, &diagnostic_count, &error_entity, &modules_which_exist, &objtree, &types_with_docs) + }; if _first { _first = false; let (title, block) = DocBlock::parse_with_title(&doc.text(), Some(broken_link_callback)); @@ -904,6 +729,215 @@ fn main2() -> Result<(), Box> { Ok(()) } +// reference & other captures -> (href, tooltip) +// this function's purpose is to prevent code copying in above closures +#[allow(clippy::too_many_arguments)] +fn broken_link_fixer<'str>( + link: BrokenLink, + macro_to_module_map: &BTreeMap<&str, String>, + macro_exists: &BTreeSet<&str>, + diagnostic_count: &std::cell::Cell, + error_entity: &std::cell::Cell>, + modules_which_exist: &BTreeSet, + objtree: &ObjectTree, + types_with_docs: &BTreeMap<&str, TypeHasDocs>, +) -> Option<(CowStr<'str>, CowStr<'str>)> + { + let referie = link.reference.into_string(); + let reference = referie.as_str(); + let error_entity_print = || { + diagnostic_count.set(diagnostic_count.get() + 1); + if let Some(name) = error_entity.take() { + eprintln!("{}:", name); + } + }; + // macros + if let Some(module) = macro_to_module_map.get(reference) { + return Some((format!("{}.html#define/{}", module, reference).into(), reference.to_owned().into())); + } else if macro_exists.contains(reference) { + error_entity_print(); + eprintln!(" [{}]: macro not documented", reference); + return None; + } else if reference.ends_with(".dm") || reference.ends_with(".txt") || reference.ends_with(".md") { + let mod_path = module_path(reference.as_ref()); + if modules_which_exist.contains(&mod_path) { + return Some((format!("{}.html", mod_path).into(), reference.to_owned().into())); + } + error_entity_print(); + eprintln!(" [{}]: module {}", reference, if Path::new(reference).exists() { "not documented" } else { "does not exist" }); + return None; + } + + // parse "proc" or "var" reference out + let mut ty_path = reference; + let mut proc_name = None; + let mut var_name = None; + let mut entity_exists = false; + if let Some(idx) = reference.find("/proc/") { + // `[/ty/proc/procname]` + let name = &reference[idx + "/proc/".len()..]; + proc_name = Some(name); + ty_path = &reference[..idx]; + if let Some(ty) = objtree.find(ty_path) { + entity_exists = ty.procs.contains_key(name); + } + } else if let Some(idx) = reference.find("/verb/") { + // `[/ty/verb/procname]` + let name = &reference[idx + "/verb/".len()..]; + proc_name = Some(name); + ty_path = &reference[..idx]; + if let Some(ty) = objtree.find(ty_path) { + // there are no builtin verbs + entity_exists = ty.procs.contains_key(name); + } + } else if let Some(idx) = reference.find("/var/") { + // `[/ty/var/varname]` + let name = &reference[idx + "/var/".len()..]; + var_name = Some(name); + ty_path = &reference[..idx]; + if let Some(ty) = objtree.find(ty_path) { + entity_exists = ty.vars.contains_key(name); + } + } else if objtree.find(reference).is_some() { + entity_exists = true; + } else if let Some(idx) = reference.rfind('/') { + let (parent, rest) = (&reference[..idx], &reference[idx + 1..]); + if let Some(ty) = objtree.find(parent) { + if ty.procs.contains_key(rest) && !ty.vars.contains_key(rest) { + // correct `[/ty/procname]` to `[/ty/proc/procname]` + proc_name = Some(rest); + ty_path = parent; + error_entity_print(); + eprintln!(" [{}]: correcting to [{}/proc/{}]", reference, parent, rest); + entity_exists = true; + } else if ty.vars.contains_key(rest) { + // correct `[/ty/varname]` to `[/ty/var/varname]` + var_name = Some(rest); + ty_path = parent; + error_entity_print(); + eprintln!(" [{}]: correcting to [{}/var/{}]", reference, parent, rest); + entity_exists = true; + } + } + } else if objtree.root().vars.contains_key(reference) { + ty_path = ""; + var_name = Some(reference); + error_entity_print(); + eprintln!(" [{0}]: correcting to [/var/{0}]", reference); + entity_exists = true; + } + // else `[/ty]` + + // Determine external doc URL + let mut external_url = None; + if entity_exists { + // TODO: .location.is_builtins() is not the best way to find this out, + // for example if it's overridden in the DM code but not re-documented. + if let Some(ty) = objtree.find(ty_path) { + if let Some(var_name) = var_name { + if let Some(var) = ty.get_value(var_name) { + if var.location.is_builtins() { + external_url = Some(match var.docs.builtin_docs { + BuiltinDocs::None => format!("{}{}/var/{}", DM_REFERENCE_BASE, ty.path, var_name), + BuiltinDocs::ReferenceHash(hash) => format!("{}{}", DM_REFERENCE_BASE, hash), + }) + } + } + } else if let Some(proc_name) = proc_name { + if let Some(proc) = ty.get_proc(proc_name) { + if proc.location.is_builtins() { + external_url = Some(match proc.docs.builtin_docs { + BuiltinDocs::None => format!("{}{}/proc/{}", DM_REFERENCE_BASE, ty.path, proc_name), + BuiltinDocs::ReferenceHash(hash) => format!("{}{}", DM_REFERENCE_BASE, hash), + }) + } + } + } else if ty.location.is_builtins() { + external_url = Some(match ty.docs.builtin_docs { + BuiltinDocs::None => format!("{}{}", DM_REFERENCE_BASE, ty.path), + BuiltinDocs::ReferenceHash(hash) => format!("{}{}", DM_REFERENCE_BASE, hash), + }) + } + } + } + + let mut progress = String::new(); + let mut best = 0; + + if ty_path.is_empty() { + progress.push_str("/global"); + if let Some(info) = types_with_docs.get("") { + if let Some(proc_name) = proc_name { + if info.proc_docs.contains(proc_name) { + best = progress.len(); + } + } else if let Some(var_name) = var_name { + if info.var_docs.contains(var_name) { + best = progress.len(); + } + } else { + best = progress.len(); + } + } + } else { + for bit in ty_path.trim_start_matches('/').split('/') { + progress.push('/'); + progress.push_str(bit); + if let Some(info) = types_with_docs.get(progress.as_str()) { + if let Some(proc_name) = proc_name { + if info.proc_docs.contains(proc_name) { + best = progress.len(); + } + } else if let Some(var_name) = var_name { + if info.var_docs.contains(var_name) { + best = progress.len(); + } + } else { + best = progress.len(); + } + } + } + } + + if best > 0 { + use std::fmt::Write; + + if best < progress.len() { + error_entity_print(); + if entity_exists { + eprint!(" [{}]: not documented, guessing [{}", reference, &progress[..best]); + } else { + eprint!(" [{}]: unknown crosslink, guessing [{}", reference, &progress[..best]); + } + if let Some(proc_name) = proc_name { + let _ = eprint!("/proc/{}", proc_name); + } else if let Some(var_name) = var_name { + let _ = eprint!("/var/{}", var_name); + } + eprintln!("]"); + progress.truncate(best); + } + + let mut href = format!("{}.html", &progress[1..]); + if let Some(proc_name) = proc_name { + let _ = write!(href, "#proc/{}", proc_name); + } else if let Some(var_name) = var_name { + let _ = write!(href, "#var/{}", var_name); + } + Some((href.into(), progress.into())) + } else if let Some(external) = external_url { + Some((external.into(), reference.to_owned().into())) + } else { + error_entity_print(); + if entity_exists { + eprintln!(" [{}]: not documented", reference); + } else { + eprintln!(" [{}]: unknown crosslink", reference); + } + None + } +} + // ---------------------------------------------------------------------------- // Helpers diff --git a/crates/dmdoc/src/markdown.rs b/crates/dmdoc/src/markdown.rs index 574ddbf1..12c72e2c 100644 --- a/crates/dmdoc/src/markdown.rs +++ b/crates/dmdoc/src/markdown.rs @@ -3,11 +3,9 @@ use std::ops::Range; use std::collections::VecDeque; -use pulldown_cmark::{self, Parser, Tag, Event}; +use pulldown_cmark::{self, Parser, Tag, Event, BrokenLinkCallback, HeadingLevel}; -pub type BrokenLinkCallback<'a> = Option<&'a dyn Fn(&str, &str) -> Option<(String, String)>>; - -pub fn render(markdown: &str, broken_link_callback: BrokenLinkCallback) -> String { +pub fn render<'string, 'func>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, 'func>) -> String { let mut buf = String::new(); push_html(&mut buf, parser(markdown, broken_link_callback)); buf @@ -22,19 +20,19 @@ pub struct DocBlock { } impl DocBlock { - pub fn parse(markdown: &str, broken_link_callback: BrokenLinkCallback) -> Self { + pub fn parse<'string, 'func>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, 'func>) -> Self { parse_main(parser(markdown, broken_link_callback).peekable()) } - pub fn parse_with_title(markdown: &str, broken_link_callback: BrokenLinkCallback) -> (Option, Self) { + pub fn parse_with_title<'string, 'func>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, 'func>) -> (Option, Self) { let mut parser = parser(markdown, broken_link_callback).peekable(); ( - if let Some(&Event::Start(Tag::Heading(1))) = parser.peek() { + if let Some(&Event::Start(Tag::Heading(HeadingLevel::H1, _, _))) = parser.peek() { parser.next(); let mut pieces = Vec::new(); loop { match parser.next() { - None | Some(Event::End(Tag::Heading(1))) => break, + None | Some(Event::End(Tag::Heading(HeadingLevel::H1, _, _))) => break, Some(other) => pieces.push(other), } } @@ -54,7 +52,7 @@ impl DocBlock { } } -fn parser<'a>(markdown: &'a str, broken_link_callback: BrokenLinkCallback<'a>) -> Parser<'a> { +fn parser<'string, 'func>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, 'func>) -> Parser<'string, 'func> { Parser::new_with_broken_link_callback( markdown, pulldown_cmark::Options::ENABLE_TABLES | pulldown_cmark::Options::ENABLE_STRIKETHROUGH, @@ -116,7 +114,7 @@ impl<'a, I: Iterator>> Iterator for HeadingLinker<'a, I> { } let original = self.inner.next(); - if let Some(Event::Start(Tag::Heading(heading))) = original { + if let Some(Event::Start(Tag::Heading(heading, _, _))) = original { let mut text_buf = String::new(); for event in self.inner.by_ref() { @@ -124,7 +122,7 @@ impl<'a, I: Iterator>> Iterator for HeadingLinker<'a, I> { text_buf.push_str(text.as_ref()); } - if let Event::End(Tag::Heading(_)) = event { + if let Event::End(Tag::Heading(_, _, _)) = event { break; } diff --git a/crates/dmm-tools-cli/Cargo.toml b/crates/dmm-tools-cli/Cargo.toml index 08ae49a3..c6a8802d 100644 --- a/crates/dmm-tools-cli/Cargo.toml +++ b/crates/dmm-tools-cli/Cargo.toml @@ -10,16 +10,16 @@ name = "dmm-tools" path = "src/main.rs" [dependencies] -structopt = "0.3.3" -structopt-derive = "0.4.0" -serde = "1.0.27" -serde_derive = "1.0.27" -serde_json = "1.0.9" -rayon = "1.0.0" +structopt = "0.3.26" +structopt-derive = "0.4.18" +serde = "1.0.136" +serde_derive = "1.0.136" +serde_json = "1.0.79" +rayon = "1.5.2" dreammaker = { path = "../dreammaker" } dmm-tools = { path = "../dmm-tools", features = ["png"] } ahash = "0.7.6" [build-dependencies] -chrono = "0.4.0" -git2 = { version = "0.13", default-features = false } +chrono = "0.4.19" +git2 = { version = "0.14.2", default-features = false } diff --git a/crates/dmm-tools/Cargo.toml b/crates/dmm-tools/Cargo.toml index b7dfde5c..38d80068 100644 --- a/crates/dmm-tools/Cargo.toml +++ b/crates/dmm-tools/Cargo.toml @@ -5,24 +5,24 @@ authors = ["Tad Hardesty "] edition = "2018" [dependencies] -inflate = "0.4.1" -ndarray = "0.15.3" -rand = "0.8.4" +inflate = "0.4.5" +ndarray = "0.15.4" +rand = "0.8.5" dreammaker = { path = "../dreammaker" } -lodepng = "3.0.0" -indexmap = "1.7.0" +lodepng = "3.6.1" +indexmap = "1.8.1" ahash = "0.7.6" [dependencies.bytemuck] -version = "1.5" +version = "1.9.1" features = ["derive"] [dependencies.bumpalo] -version = "3.0.0" +version = "3.9.1" features = ["collections"] [dependencies.png] -version = "0.17.2" +version = "0.17.5" optional = true [dependencies.gfx_core] @@ -30,4 +30,4 @@ version = "0.9.2" optional = true [dev-dependencies] -walkdir = "2.0.1" +walkdir = "2.3.2" diff --git a/crates/dreamchecker/Cargo.toml b/crates/dreamchecker/Cargo.toml index 04bd65fc..be910add 100644 --- a/crates/dreamchecker/Cargo.toml +++ b/crates/dreamchecker/Cargo.toml @@ -6,10 +6,10 @@ edition = "2018" [dependencies] dreammaker = { path = "../dreammaker" } -guard = "0.5.0" +guard = "0.5.1" serde_json = "1.0" ahash = "0.7.6" [build-dependencies] -chrono = "0.4.0" -git2 = { version = "0.13", default-features = false } +chrono = "0.4.19" +git2 = { version = "0.14.2", default-features = false } diff --git a/crates/dreammaker/Cargo.toml b/crates/dreammaker/Cargo.toml index 822a38bc..688efd42 100644 --- a/crates/dreammaker/Cargo.toml +++ b/crates/dreammaker/Cargo.toml @@ -7,18 +7,18 @@ edition = "2018" [dependencies] interval-tree = { path = "../interval-tree" } builtins-proc-macro = { path = "../builtins-proc-macro" } -lodepng = "3.1.0" -bitflags = "1.0.3" -termcolor = "1.0.4" -ordered-float = "2.0.0" -serde = { version = "1.0.103", features = ["derive"] } -serde_derive = "1.0.103" -toml = "0.5.5" -guard = "0.5.0" -phf = { version = "0.10.0", features = ["macros"] } +lodepng = "3.6.1" +bitflags = "1.3.2" +termcolor = "1.1.3" +ordered-float = "3.0.0" +serde = { version = "1.0.136", features = ["derive"] } +serde_derive = "1.0.136" +toml = "0.5.9" +guard = "0.5.1" +phf = { version = "0.10.1", features = ["macros"] } color_space = "0.5.3" ahash = "0.7.6" -indexmap = "1.7.0" +indexmap = "1.8.1" [dev-dependencies] -walkdir = "2.0.1" +walkdir = "2.3.2" diff --git a/crates/interval-tree/Cargo.toml b/crates/interval-tree/Cargo.toml index df7aa8e8..b6b08922 100644 --- a/crates/interval-tree/Cargo.toml +++ b/crates/interval-tree/Cargo.toml @@ -9,4 +9,4 @@ license-file = "LICENSE" edition = "2018" [dev-dependencies] -rand = "0.8.4" +rand = "0.8.5" diff --git a/crates/spaceman-dmm/Cargo.toml b/crates/spaceman-dmm/Cargo.toml index 6763ab79..7d471fb0 100644 --- a/crates/spaceman-dmm/Cargo.toml +++ b/crates/spaceman-dmm/Cargo.toml @@ -11,28 +11,28 @@ path = "src/main.rs" [dependencies] dreammaker = { path = "../dreammaker" } dmm-tools = { path = "../tools", features = ["gfx_core"] } -glutin = "0.21.1" -gfx_gl = "0.6.0" +glutin = "0.28.0" +gfx_gl = "0.6.1" gfx = "0.18" gfx_core = "0.9.2" gfx_window_glutin = "0.31.0" gfx_device_gl = "0.16.2" -imgui = "0.2.1" -imgui-gfx-renderer = "0.2.0" +imgui = "0.8.2" +imgui-gfx-renderer = "0.8.2" lodepng = "3.0.0" -ndarray = "0.13.0" -divrem = "0.1.0" -serde = "1.0.76" -serde_derive = "1.0.76" -toml = "0.5.5" -petgraph = { version = "0.5.0", default-features = false } -weak-table = "0.2.3" -slice-of-array = "0.2.0" +ndarray = "0.15.4" +divrem = "1.0.0" +serde = "1.0.136" +serde_derive = "1.0.136" +toml = "0.5.9" +petgraph = { version = "0.6.0", default-features = false } +weak-table = "0.3.2" +slice-of-array = "0.3.2" [dependencies.nfd] git = "https://github.com/SpaceManiac/nfd-rs" branch = "zenity" [build-dependencies] -chrono = "0.4.0" -git2 = { version = "0.13", default-features = false } +chrono = "0.4.19" +git2 = { version = "0.14.2", default-features = false } From 4302562211ff283e614d99797c83c43322f1f157 Mon Sep 17 00:00:00 2001 From: tigercat2000 Date: Wed, 11 May 2022 19:51:34 -0700 Subject: [PATCH 009/197] Add [u8] read/write functions to Image/IconFile/Metadata (#316) This is so IconDiffBot2 can operate purely in memory. Metadata::from_bytes and IconFile::from_bytes take an &[u8] as the sequence of bytes of a valid PNG+DMI file to produce their types. Image::to_bytes gives a Vec which is just the output from png::Encoder. There is no Image::from_bytes because there's no reason not to use IconFile::from_bytes, and there is no to_bytes for Metadata or IconFile because they don't support to_file either. IconFile could, but it's unnecessary. Co-authored-by: Tad Hardesty --- crates/dmm-tools/src/dmi.rs | 54 ++++++++++++++++++++++++++---------- crates/dreammaker/src/dmi.rs | 7 ++++- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/crates/dmm-tools/src/dmi.rs b/crates/dmm-tools/src/dmi.rs index 93cd2719..dcdbc194 100644 --- a/crates/dmm-tools/src/dmi.rs +++ b/crates/dmm-tools/src/dmi.rs @@ -30,7 +30,11 @@ pub struct IconFile { impl IconFile { pub fn from_file(path: &Path) -> io::Result { - let (bitmap, metadata) = Metadata::from_file(path)?; + Self::from_bytes(&std::fs::read(path)?) + } + + pub fn from_bytes(data: &[u8]) -> io::Result { + let (bitmap, metadata) = Metadata::from_bytes(data)?; Ok(IconFile { metadata, image: Image::from_rgba(bitmap), @@ -125,18 +129,17 @@ impl Image { } } - /// Read an `Image` from a file. + /// Read an `Image` from a `&[u8]` slice. /// - /// Prefer to call `IconFile::from_file`, which can read both metadata and + /// Prefer to call `IconFile::from_bytes`, which can read both metadata and /// image contents at one time. - pub fn from_file(path: &Path) -> io::Result { - let path = &::dm::fix_case(path); + pub fn from_bytes(data: &[u8]) -> io::Result { let mut decoder = Decoder::new(); decoder.info_raw_mut().colortype = ColorType::RGBA; decoder.info_raw_mut().set_bitdepth(8); decoder.read_text_chunks(false); decoder.remember_unknown_chunks(false); - let bitmap = match decoder.decode_file(path) { + let bitmap = match decoder.decode(data) { Ok(::lodepng::Image::RGBA(bitmap)) => bitmap, Ok(_) => return Err(io::Error::new(io::ErrorKind::InvalidData, "not RGBA")), Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, e)), @@ -145,18 +148,39 @@ impl Image { Ok(Image::from_rgba(bitmap)) } + /// Read an `Image` from a file. + /// + /// Prefer to call `IconFile::from_file`, which can read both metadata and + /// image contents at one time. + pub fn from_file(path: &Path) -> io::Result { + let path = &::dm::fix_case(path); + Self::from_bytes(&std::fs::read(path)?) + } + + #[cfg(feature = "png")] + pub fn to_write(&self, writer: W) -> io::Result<()> { + { + let mut encoder = png::Encoder::new(writer, self.width, self.height); + encoder.set_color(::png::ColorType::Rgba); + encoder.set_depth(::png::BitDepth::Eight); + let mut writer = encoder.write_header()?; + // TODO: metadata with write_chunk() + + writer.write_image_data(bytemuck::cast_slice(self.data.as_slice().unwrap()))?; + } + Ok(()) + } + #[cfg(feature = "png")] pub fn to_file(&self, path: &Path) -> io::Result<()> { - use std::fs::File; + self.to_write(std::fs::File::create(path)?) + } - let mut encoder = png::Encoder::new(File::create(path)?, self.width, self.height); - encoder.set_color(::png::ColorType::Rgba); - encoder.set_depth(::png::BitDepth::Eight); - let mut writer = encoder.write_header()?; - // TODO: metadata with write_chunk() - - writer.write_image_data(bytemuck::cast_slice(self.data.as_slice().unwrap()))?; - Ok(()) + #[cfg(feature = "png")] + pub fn to_bytes(&self) -> io::Result> { + let mut vector = Vec::new(); + self.to_write(&mut vector)?; + Ok(vector) } pub fn composite(&mut self, other: &Image, pos: Coordinate, crop: Rect, color: [u8; 4]) { diff --git a/crates/dreammaker/src/dmi.rs b/crates/dreammaker/src/dmi.rs index 4e30c786..ee087e86 100644 --- a/crates/dreammaker/src/dmi.rs +++ b/crates/dreammaker/src/dmi.rs @@ -223,11 +223,16 @@ impl Metadata { /// Read the bitmap and DMI metadata from a given file in a single pass. pub fn from_file(path: &Path) -> io::Result<(lodepng::Bitmap, Metadata)> { let path = &crate::fix_case(path); + Self::from_bytes(&std::fs::read(path)?) + } + + /// Read a u8 array (raw data of a file) as a DMI into a bitmap and metadata + pub fn from_bytes(data: &[u8]) -> io::Result<(lodepng::Bitmap, Metadata)> { let mut decoder = Decoder::new(); decoder.info_raw_mut().colortype = lodepng::ColorType::RGBA; decoder.info_raw_mut().set_bitdepth(8); decoder.remember_unknown_chunks(false); - let bitmap = match decoder.decode_file(path) { + let bitmap = match decoder.decode(data) { Ok(::lodepng::Image::RGBA(bitmap)) => bitmap, Ok(_) => return Err(io::Error::new(io::ErrorKind::InvalidData, "not RGBA")), Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, e)), From 59e161b02f991d507bfd54642559840f79c1915e Mon Sep 17 00:00:00 2001 From: Spookerton Date: Thu, 12 May 2022 03:52:50 +0100 Subject: [PATCH 010/197] Add /dm_filter hidden type to builtins (#312) reference to this type - After some cursory poking, /dm_filter is a hidden type that can be used to manipulate filter instances without using the runtime search operator (:). There is no official reference material for it. It does not descend from datum, cannot be subtyped, and can only be created *successfully* by a valid call to proc/filter(...). All filter types create the same kind of /dm_filter but with different properties, of which I believe type is the only const. A contributor on Bay tried to use it but checker doesn't know about it. I'm not familiar with the guts of suite, but I think this is all that's necessary? --- crates/dreammaker/src/builtins.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/crates/dreammaker/src/builtins.rs b/crates/dreammaker/src/builtins.rs index c17c164d..4c301541 100644 --- a/crates/dreammaker/src/builtins.rs +++ b/crates/dreammaker/src/builtins.rs @@ -590,7 +590,7 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { savefile yes yes yes yes yes yes client yes yes yes yes yes yes yes - All other root types have an implicit `parent_type = /datum`. + Most other root types have an implicit `parent_type = /datum`. */ datum; datum/var/const/type; // not editable @@ -1064,6 +1064,34 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { savefile/proc/Lock(timeout); savefile/proc/Unlock(); + //512 stuff + + // /dm_filter is a hidden type that can be used to manipulate filter + // instances without using the runtime search operator (:). It does + // not descend from datum, cannot be subtyped, and can only be created + // successfully by a valid call to proc/filter(...). All filter types + // create the same kind of /dm_filter, but with different properties. + dm_filter; + dm_filter/var/const/type; + dm_filter/var/x; + dm_filter/var/y; + dm_filter/var/icon; + dm_filter/var/render_source; + dm_filter/var/flags; + dm_filter/var/size; + dm_filter/var/threshold; + dm_filter/var/offset; + dm_filter/var/alpha; + dm_filter/var/color; + dm_filter/var/space; + dm_filter/var/transform; + dm_filter/var/blend_mode; + dm_filter/var/density; + dm_filter/var/factor; + dm_filter/var/repeat; + dm_filter/var/radius; + dm_filter/var/falloff; + // 513 stuff proc/arctan(A,B); proc/clamp(NumberOrList,Low,High); From a2eaf42f9ea82faf2db6ed5403164ef695c32e9a Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 19 Feb 2022 17:21:55 -0800 Subject: [PATCH 011/197] Fix panic in langserver in case of disk I/O time rounding errors --- crates/dm-langserver/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index 46aaec6a..de096199 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -485,7 +485,7 @@ impl<'a> Engine<'a> { let elapsed = start.elapsed(); start += elapsed; { let disk = ctx.get_io_time(); - let parse = elapsed - disk; + let parse = elapsed.saturating_sub(disk); eprint!("disk {}.{:03}s - parse {}.{:03}s", disk.as_secs(), disk.subsec_millis(), parse.as_secs(), parse.subsec_millis()); } From e979b2e69af0173f1e13d52926ab3dece84f8e1d Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 30 Apr 2022 11:15:17 -0700 Subject: [PATCH 012/197] Include values of Prefab and Pop in their Hash and Eq impls --- crates/dmm-tools/src/dmm.rs | 9 ++++++--- crates/dreammaker/src/constants.rs | 8 ++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/crates/dmm-tools/src/dmm.rs b/crates/dmm-tools/src/dmm.rs index 58dadf60..5f2ab6c1 100644 --- a/crates/dmm-tools/src/dmm.rs +++ b/crates/dmm-tools/src/dmm.rs @@ -118,7 +118,6 @@ pub struct ZLevel<'a> { pub grid: ndarray::ArrayView<'a, Key, ndarray::Dim<[usize; 2]>>, } -// TODO: port to ast::Prefab #[derive(Debug, Default, Clone)] pub struct Prefab { pub path: String, @@ -128,7 +127,7 @@ pub struct Prefab { impl PartialEq for Prefab { fn eq(&self, other: &Self) -> bool { - self.path == other.path && self.vars.keys().eq(other.vars.keys()) + self.path == other.path && self.vars == other.vars } } @@ -137,7 +136,11 @@ impl Eq for Prefab {} impl std::hash::Hash for Prefab { fn hash(&self, state: &mut H) { self.path.hash(state); - self.vars.keys().for_each(|key| {key.hash(state)}); + let mut items: Vec<_> = self.vars.iter().collect(); + items.sort_by_key(|&(k, _)| k); + for kvp in items { + kvp.hash(state); + } } } diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index bfd7c30f..d4bb17bb 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -26,7 +26,7 @@ pub struct Pop { impl PartialEq for Pop { fn eq(&self, other: &Self) -> bool { - self.path == other.path && self.vars.keys().eq(other.vars.keys()) + self.path == other.path && self.vars == other.vars } } @@ -35,7 +35,11 @@ impl Eq for Pop {} impl std::hash::Hash for Pop { fn hash(&self, state: &mut H) { self.path.hash(state); - self.vars.keys().for_each(|key| {key.hash(state)}); + let mut items: Vec<_> = self.vars.iter().collect(); + items.sort_by_key(|&(k, _)| k); + for kvp in items { + kvp.hash(state); + } } } From 860d6c48a6141755f139456ad48852e16e766cf3 Mon Sep 17 00:00:00 2001 From: moxian Date: Wed, 18 May 2022 02:27:40 +0000 Subject: [PATCH 013/197] Change panics when parsing a malformed dmi to return a Result instead (#319) Currently parsing a malformed - but also well-formed, yet ancient - .dmi files results in a panic deep within the guts of SpacemanDMM. That's undesirable, since `.dmi`'s which SpacemanDMM does not understand (yet BYOND dreammaker handles fine) do exist in the wild (see https://github.com/ParadiseSS13/Paradise/pull/17800 for a couple of examples). I don't think teaching SpacemanDMM of the legacy file formats is worth it, but making it return a Result instead of outright panicking definitely is (and it's much less work than the former). This is technically a breaking change since it changes the signature of the public `dreammaker::dmi::Metadata::meta_from_str()`. (But it's probably rarely used, and definitely easy to fix at the call site?..) Co-authored-by: Tad Hardesty --- crates/dreammaker/src/dmi.rs | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/crates/dreammaker/src/dmi.rs b/crates/dreammaker/src/dmi.rs index ee087e86..19fb9422 100644 --- a/crates/dreammaker/src/dmi.rs +++ b/crates/dreammaker/src/dmi.rs @@ -6,7 +6,7 @@ use std::collections::BTreeMap; use lodepng::Decoder; -const VERSION: &str = "4.0"; +const EXPECTED_VERSION_LINE: &str = "version = 4.0"; /// The two-dimensional facing subset of BYOND's direction type. #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] @@ -238,11 +238,11 @@ impl Metadata { Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, e)), }; - let metadata = Metadata::from_decoder(bitmap.width as u32, bitmap.height as u32, &decoder); + let metadata = Metadata::from_decoder(bitmap.width as u32, bitmap.height as u32, &decoder)?; Ok((bitmap, metadata)) } - fn from_decoder(width: u32, height: u32, decoder: &Decoder) -> Metadata { + fn from_decoder(width: u32, height: u32, decoder: &Decoder) -> io::Result { for (key, value) in decoder.info_png().text_keys() { if key == b"Description" { if let Ok(value) = std::str::from_utf8(value) { @@ -251,17 +251,17 @@ impl Metadata { break; } } - Metadata { + Ok(Metadata { width, height, states: Default::default(), state_names: Default::default(), - } + }) } /// Parse metadata from a `Description` string. #[inline] - pub fn meta_from_str(data: &str) -> Metadata { + pub fn meta_from_str(data: &str) -> io::Result { parse_metadata(data) } @@ -346,7 +346,7 @@ impl Frames { // ---------------------------------------------------------------------------- // Metadata parser -fn parse_metadata(data: &str) -> Metadata { +fn parse_metadata(data: &str) -> io::Result { let mut metadata = Metadata { width: 32, height: 32, @@ -354,12 +354,20 @@ fn parse_metadata(data: &str) -> Metadata { state_names: BTreeMap::new(), }; if data.is_empty() { - return metadata; + return Ok(metadata); } let mut lines = data.lines(); - assert_eq!(lines.next().unwrap(), "# BEGIN DMI"); - assert_eq!(lines.next().unwrap(), &format!("version = {}", VERSION)); + let header = (lines.next(), lines.next()); + let expected_header = (Some("# BEGIN DMI"), Some(EXPECTED_VERSION_LINE)); + if header != expected_header { + return Err( + io::Error::new( + io::ErrorKind::InvalidData, + format!("Wrong dmi metadata header. Expected {:?}, got {:?}", expected_header, header ) + ) + ); + } let mut state: Option = None; let mut frames_so_far = 0; @@ -438,5 +446,5 @@ fn parse_metadata(data: &str) -> Metadata { } metadata.states.extend(state); - metadata + Ok(metadata) } From 6f26e074de887da5bbf70bbdea4ef2395250b206 Mon Sep 17 00:00:00 2001 From: moxian Date: Wed, 18 May 2022 02:28:10 +0000 Subject: [PATCH 014/197] Add a few simple derives to dmi-related structs (#320) Specifically, add `#[derive(Clone, PartialEq)]` to `dmi::{Metadata, State, Frames}` As per (very weakly authoritative) one should derive all the std's traits whenever feasible. Currently for my own project I only need `State::Clone`. The `PartialEq` is being added for consistency with it being present on other structs already, and the rest of the `std`'s traits feel a bit like an overkill presently (despite what the guidelines might say) --- crates/dreammaker/src/dmi.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/dreammaker/src/dmi.rs b/crates/dreammaker/src/dmi.rs index 19fb9422..491029d4 100644 --- a/crates/dreammaker/src/dmi.rs +++ b/crates/dreammaker/src/dmi.rs @@ -171,7 +171,7 @@ impl Default for Dir { } /// Embedded metadata describing a DMI spritesheet's layout. -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq)] pub struct Metadata { /// The width of the icon in pixels. pub width: u32, @@ -184,7 +184,7 @@ pub struct Metadata { } /// The metadata belonging to a single icon state. -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq)] pub struct State { /// The state's name, corresponding to the `icon_state` var. pub name: String, @@ -208,7 +208,7 @@ pub enum Dirs { } /// How many frames of animation a state has, and their durations. -#[derive(Debug, PartialEq)] +#[derive(Debug, Clone, PartialEq)] pub enum Frames { /// Without an explicit setting, only one frame. One, From 2be4bc87e3facbe04826b2dfc7f23dfd54c5330a Mon Sep 17 00:00:00 2001 From: Jordan Dominion Date: Wed, 15 Jun 2022 21:07:15 -0400 Subject: [PATCH 015/197] Add some missing vars to database builtins (#326) See stddef.dm https://www.byond.com/forum/post/2371109 Fixes #325 --- crates/dreammaker/src/builtins.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/dreammaker/src/builtins.rs b/crates/dreammaker/src/builtins.rs index 4c301541..42f746ab 100644 --- a/crates/dreammaker/src/builtins.rs +++ b/crates/dreammaker/src/builtins.rs @@ -960,12 +960,14 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { regex/proc/Replace(text, rep, start, end); database; + database/var/_binobj; database/proc/Close(); database/proc/Error(); database/proc/ErrorMsg(); database/proc/Open(filename); database/proc/New(filename); + database/query/var/database/database; database/query/proc/Add(text, item1, item2 /*...*/); database/query/proc/Close(); database/query/proc/Columns(column); From f80d6373e7fcfb809ddc1f88f152dcc1cce67623 Mon Sep 17 00:00:00 2001 From: Mothblocks <35135081+Mothblocks@users.noreply.github.com> Date: Fri, 17 Jun 2022 16:54:02 -0700 Subject: [PATCH 016/197] Check for empty docs_in in flush_docs (#327) Might speed things up a little. --- crates/dreammaker/src/preprocessor.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index 771f1fab..75ea4f74 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -624,7 +624,9 @@ impl<'ctx> Preprocessor<'ctx> { /// Something other than a `#define` was encountered, docs are not for us. fn flush_docs(&mut self) { - self.docs_out.extend(self.docs_in.drain(..)); + if !self.docs_in.is_empty() { + self.docs_out.extend(self.docs_in.drain(..)); + } } // ------------------------------------------------------------------------ From 4a7d19401e42f31566a8b26f9eda8710c147ebde Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 27 Jun 2022 17:10:00 -0700 Subject: [PATCH 017/197] Update to auxtools debug server v2.2.3 --- scripts/download-auxtools.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/download-auxtools.sh b/scripts/download-auxtools.sh index afb16a98..aa0d2907 100755 --- a/scripts/download-auxtools.sh +++ b/scripts/download-auxtools.sh @@ -2,9 +2,9 @@ set -euo pipefail # Settings -DEBUG_SERVER_TAG=v2.2.2 -DEBUG_SERVER_DLL_URL=https://github.com/willox/auxtools/releases/download/v2.2.2/debug_server.dll -DEBUG_SERVER_DLL_SHA256=847c3bfbd35f2eb57f43d0ba08df323c0f0beb1f7d518e7e54791a1aff13a56f +DEBUG_SERVER_TAG=v2.2.3 +DEBUG_SERVER_DLL_URL=https://github.com/willox/auxtools/releases/download/v2.2.3/debug_server.dll +DEBUG_SERVER_DLL_SHA256=dd10daa07607b278536152bf5c79906180958c4b765b486c18a021418103893e # ----------------------------------------------------------------------------- cd "$(dirname "${BASH_SOURCE[0]}")" From 4420bb5d60c83cd3a274bb9abce91a6d31a64249 Mon Sep 17 00:00:00 2001 From: tigercat2000 Date: Sat, 9 Jul 2022 15:30:19 -0700 Subject: [PATCH 018/197] Add an IconFile to gif/png renderer (#318) This is finally something I'm comfortable with having added upstream, the API is stabilized and functions well for IDB2's use-case, but should be able to be used by other projects as well. New dependencies: - Added the `either` crate to get around an annoying type issue with chained iterators. - Added the `derivative` crate to make `State` realistically comparable across different icon files (important for diffing in IDB2) - `offset` is ignored for PartialEq. Notes on public API changes: - Most of the new stuff is in the inline module `dmm_tools::dmi::render`. - `IconFile`, `Rgba8`, and `Image` are now `Debug` - `from_bytes` on `Image`, `IconFile`, and `State` no longer takes an explicit &[u8] array, instead it takes the trait bound `>` for ease of "eat my ownership because I don't care" - `IconFile` has a new function `pub fn get_icon_state>(&self, icon_state: S) -> io::Result<&State>` for looking up states by name. - `Image` has a `clear()` method which fills the data array with defaults. - `State` has a new member, `pub duplicate: Option`, which is used for correctly supporting duplicate icon states by enumerating how many times the state name has been seen before this particular `State` was read. - `State` has a `get_icon_state` method which backs `IconFile`'s `get_icon_state`. - `State` has a `is_animated(&self) -> bool` method which is used in IDB2 for precalculating the file extension - `State` also has `get_state_name_index`, which is used by `parse_metadata` to give duplicate states a unique entry into the `state_names` `BTreeMap`. - `parse_metadata` now keeps track of duplicate states and puts them in `state_names` according to the above. --- Cargo.lock | 36 ++++ crates/dmm-tools/Cargo.toml | 5 + crates/dmm-tools/src/dmi.rs | 25 ++- crates/dmm-tools/src/dmi/render.rs | 223 +++++++++++++++++++++++ crates/dmm-tools/src/minimap.rs | 2 +- crates/dmm-tools/tests/parse_codebase.rs | 1 + crates/dreammaker/Cargo.toml | 1 + crates/dreammaker/src/dmi.rs | 141 ++++++++++++-- 8 files changed, 411 insertions(+), 23 deletions(-) create mode 100644 crates/dmm-tools/src/dmi/render.rs diff --git a/Cargo.lock b/Cargo.lock index 358ef1ea..b8ce6692 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -217,6 +217,12 @@ dependencies = [ "vec_map", ] +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "color_space" version = "0.5.3" @@ -296,6 +302,17 @@ dependencies = [ "adler32", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "deunicode" version = "0.4.3" @@ -357,7 +374,9 @@ dependencies = [ "bumpalo", "bytemuck", "dreammaker", + "either", "gfx_core", + "gif", "indexmap", "inflate", "lodepng", @@ -413,6 +432,7 @@ dependencies = [ "bitflags", "builtins-proc-macro", "color_space", + "derivative", "guard", "indexmap", "interval-tree", @@ -604,6 +624,16 @@ dependencies = [ "log", ] +[[package]] +name = "gif" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "git2" version = "0.14.4" @@ -1630,6 +1660,12 @@ version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +[[package]] +name = "weezl" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c97e489d8f836838d497091de568cf16b117486d529ec5579233521065bd5e4" + [[package]] name = "winapi" version = "0.3.9" diff --git a/crates/dmm-tools/Cargo.toml b/crates/dmm-tools/Cargo.toml index 38d80068..7c056cac 100644 --- a/crates/dmm-tools/Cargo.toml +++ b/crates/dmm-tools/Cargo.toml @@ -12,6 +12,7 @@ dreammaker = { path = "../dreammaker" } lodepng = "3.6.1" indexmap = "1.8.1" ahash = "0.7.6" +either = "1.6.1" [dependencies.bytemuck] version = "1.9.1" @@ -29,5 +30,9 @@ optional = true version = "0.9.2" optional = true +[dependencies.gif] +version = "0.11.3" +optional = true + [dev-dependencies] walkdir = "2.3.2" diff --git a/crates/dmm-tools/src/dmi.rs b/crates/dmm-tools/src/dmi.rs index dcdbc194..d8f4bbbf 100644 --- a/crates/dmm-tools/src/dmi.rs +++ b/crates/dmm-tools/src/dmi.rs @@ -20,7 +20,11 @@ pub type Rect = (u32, u32, u32, u32); // ---------------------------------------------------------------------------- // Icon file and metadata handling +#[cfg(all(feature = "png", feature = "gif"))] +pub mod render; + /// An image with associated DMI metadata. +#[derive(Debug)] pub struct IconFile { /// The icon's metadata. pub metadata: Metadata, @@ -42,7 +46,7 @@ impl IconFile { } #[inline] - pub fn rect_of(&self, icon_state: &str, dir: Dir) -> Option { + pub fn rect_of(&self, icon_state: &StateIndex, dir: Dir) -> Option { self.metadata.rect_of(self.image.width, icon_state, dir, 0) } @@ -56,9 +60,18 @@ impl IconFile { self.metadata.height, ) } + + pub fn get_icon_state(&self, icon_state: &StateIndex) -> io::Result<&State> { + self.metadata.get_icon_state(icon_state).ok_or_else(|| { + io::Error::new( + io::ErrorKind::NotFound, + format!("icon_state {} not found", icon_state), + ) + }) + } } -#[derive(Default, Clone, Copy, Pod, Zeroable, Eq, PartialEq)] +#[derive(Default, Debug, Clone, Copy, Pod, Zeroable, Eq, PartialEq)] #[repr(C)] pub struct Rgba8 { pub r: u8, @@ -99,6 +112,7 @@ impl IndexMut for Rgba8 { // Image manipulation /// A two-dimensional RGBA image. +#[derive(Clone, Debug, PartialEq, Eq)] pub struct Image { pub width: u32, pub height: u32, @@ -129,7 +143,7 @@ impl Image { } } - /// Read an `Image` from a `&[u8]` slice. + /// Read an `Image` from a [u8] array. /// /// Prefer to call `IconFile::from_bytes`, which can read both metadata and /// image contents at one time. @@ -157,6 +171,10 @@ impl Image { Self::from_bytes(&std::fs::read(path)?) } + pub fn clear(&mut self) { + self.data.fill(Default::default()) + } + #[cfg(feature = "png")] pub fn to_write(&self, writer: W) -> io::Result<()> { { @@ -165,7 +183,6 @@ impl Image { encoder.set_depth(::png::BitDepth::Eight); let mut writer = encoder.write_header()?; // TODO: metadata with write_chunk() - writer.write_image_data(bytemuck::cast_slice(self.data.as_slice().unwrap()))?; } Ok(()) diff --git a/crates/dmm-tools/src/dmi/render.rs b/crates/dmm-tools/src/dmi/render.rs new file mode 100644 index 00000000..55e61c04 --- /dev/null +++ b/crates/dmm-tools/src/dmi/render.rs @@ -0,0 +1,223 @@ +use super::*; +use either::Either; +use gif::DisposalMethod; + +static NO_TINT: [u8; 4] = [0xff, 0xff, 0xff, 0xff]; + +/// Used to render an IconFile to a .gif/.png easily. +#[derive(Debug)] +pub struct IconRenderer<'a> { + /// The IconFile we render from. + source: &'a IconFile, +} + +/// [`IconRenderer::render`] will return this to indicate if it wrote to the stream using +/// [`gif::Encoder`] or `[`png::Encoder`]. +#[derive(Debug, Clone, Copy)] +pub enum RenderType { + Png, + Gif +} + +#[derive(Debug)] +pub struct RenderStateGuard<'a> { + pub render_type: RenderType, + renderer: &'a IconRenderer<'a>, + state: &'a State, +} + +impl<'a> RenderStateGuard<'a> { + pub fn render(self, target: W) -> io::Result<()> { + match self.render_type { + RenderType::Png => { + self.renderer.render_to_png(self.state, target) + }, + RenderType::Gif => { + self.renderer.render_gif(self.state, target) + }, + } + } +} + +/// Public API +impl<'a> IconRenderer<'a> { + pub fn new(source: &'a IconFile) -> Self { + Self { + source, + } + } + + /// Renders with either [`gif::Encoder`] or [`png::Encoder`] depending on whether the icon state is animated + /// or not. + /// Returns a [`RenderType`] to help you determine how to treat the written data. + pub fn prepare_render(&self, icon_state: &StateIndex) -> io::Result { + self.prepare_render_state(self.source.get_icon_state(icon_state)?) + } + + /// This is here so that duplicate icon states can be handled by not relying on the btreemap + /// of state names in [`Metadata`]. + pub fn prepare_render_state(&'a self, icon_state: &'a State) -> io::Result { + match icon_state.is_animated() { + false => Ok(RenderStateGuard { + renderer: self, + state: icon_state, + render_type: RenderType::Png, + }), + true => Ok(RenderStateGuard { + renderer: self, + state: icon_state, + render_type: RenderType::Gif, + }), + } + } + + /// Instead of writing to a file, this gives a Vec of each frame/dir as it would be composited + /// for a file. + pub fn render_to_images(&self, icon_state: &StateIndex) -> io::Result> { + let state = self.source.get_icon_state(icon_state)?; + Ok(self.render_frames(state)) + } +} + +/// Private helpers +impl<'a> IconRenderer<'a> { + /// Helper for render_to_images- not used for render_gif because it's less efficient. + fn render_frames(&self, icon_state: &State) -> Vec { + let frames = match &icon_state.frames { + Frames::One => 1, + Frames::Count(count) => *count, + Frames::Delays(delays) => delays.len(), + }; + let mut canvas = self.get_canvas(icon_state.dirs); + let mut vec = Vec::new(); + let range = if icon_state.rewind { + Either::Left((0..frames).chain((0..frames).rev())) + } else { + Either::Right(0..frames) + }; + for frame in range { + self.render_dirs(icon_state, &mut canvas, frame as u32); + vec.push(canvas.clone()); + canvas.clear(); + } + vec + } + + /// Returns a new canvas of the appropriate size + fn get_canvas(&self, dirs: Dirs) -> Image { + match dirs { + Dirs::One => Image::new_rgba(self.source.metadata.width, self.source.metadata.height), + Dirs::Four => Image::new_rgba(self.source.metadata.width * 4, self.source.metadata.height), + Dirs::Eight => Image::new_rgba(self.source.metadata.width * 8, self.source.metadata.height), + } + } + + /// Gives a [`Vec`] of each [`Dir`] matching our [`Dirs`] setting, + /// in the same order BYOND uses. + fn ordered_dirs(dirs: Dirs) -> Vec { + match dirs { + Dirs::One => { [Dir::South].to_vec() }, + Dirs::Four => { + [ + Dir::South, + Dir::North, + Dir::East, + Dir::West, + ].to_vec() + }, + Dirs::Eight => { + [ + Dir::South, + Dir::North, + Dir::East, + Dir::West, + Dir::Southeast, + Dir::Southwest, + Dir::Northeast, + Dir::Northwest, + ].to_vec() + }, + } + } + + /// Renders each direction to the same canvas, offsetting them to the right + fn render_dirs(&self, icon_state: &State, canvas: &mut Image, frame: u32) { + for (dir_no, dir) in Self::ordered_dirs(icon_state.dirs).iter().enumerate() { + let frame_idx = icon_state.index_of_frame(*dir, frame as u32); + let frame_rect = self.source.rect_of_index(frame_idx); + canvas.composite( + &self.source.image, + (self.source.metadata.width * (dir_no as u32), 0), + frame_rect, + NO_TINT, + ); + } + } + + /// Renders the whole file to a gif, animated states becoming frames + fn render_gif( + &self, + icon_state: &State, + target: W, + ) -> io::Result<()> { + + if !icon_state.is_animated() { + return Err(io::Error::new(io::ErrorKind::InvalidData, "Tried to render gif with one frame")); + } + + let (frames, delays) = match &icon_state.frames { + Frames::Count(frames) => (*frames, None), + Frames::Delays(delays) => (delays.len(), Some(delays)), + _ => unreachable!(), + }; + + let mut canvas = self.get_canvas(icon_state.dirs); + + let mut encoder = + gif::Encoder::new(target, canvas.width as u16, canvas.height as u16, &[]) + .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("{e}")))?; + + encoder + .set_repeat(gif::Repeat::Infinite) + .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("{e}")))?; + + let range = if icon_state.rewind { + Either::Left((0..frames).chain((0..frames).rev())) + } else { + Either::Right(0..frames) + }; + + for frame in range { + self.render_dirs(icon_state, &mut canvas, frame as u32); + + let mut pixels = bytemuck::cast_slice(canvas.data.as_slice().unwrap()).to_owned(); + let mut gif_frame = + gif::Frame::from_rgba(canvas.width as u16, canvas.height as u16, &mut pixels); + // gif::Frame delays are measured in "Frame delay in units of 10 ms." + // aka centiseconds. We're measuring in BYOND ticks, aka deciseconds. + // And it's a u16 for some reason so we just SHRUG and floor it. + gif_frame.delay = + (delays.map_or_else(|| 1.0, |f| *f.get(frame).unwrap_or(&1.0)) * 10.0) as u16; + // the disposal method by default is "keep the previous frame under the alpha mask" + // wtf + gif_frame.dispose = DisposalMethod::Background; + encoder.write_frame(&gif_frame).unwrap(); + // Clear the canvas. + canvas.clear(); + } + + Ok(()) + } + + /// Renders the whole file to a png, discarding all but the first frame of animations + fn render_to_png(&self, icon_state: &State, target: W) -> io::Result<()> { + let mut canvas = self.get_canvas(icon_state.dirs); + + self.render_dirs(icon_state, &mut canvas, 0); + + canvas.to_write(target)?; + // Always remember to clear the canvas for the next guy! + canvas.clear(); + Ok(()) + } +} \ No newline at end of file diff --git a/crates/dmm-tools/src/minimap.rs b/crates/dmm-tools/src/minimap.rs index 8e992d06..92c5d1c7 100644 --- a/crates/dmm-tools/src/minimap.rs +++ b/crates/dmm-tools/src/minimap.rs @@ -141,7 +141,7 @@ pub fn generate(ctx: Context, icon_cache: &IconCache) -> Result { None => continue, }; - if let Some(rect) = icon_file.rect_of(sprite.icon_state, sprite.dir) { + if let Some(rect) = icon_file.rect_of(&sprite.icon_state.into(), sprite.dir) { let pixel_x = sprite.ofs_x; let pixel_y = sprite.ofs_y + icon_file.metadata.height as i32; let loc = ( diff --git a/crates/dmm-tools/tests/parse_codebase.rs b/crates/dmm-tools/tests/parse_codebase.rs index da30e0c7..3bc01f2c 100644 --- a/crates/dmm-tools/tests/parse_codebase.rs +++ b/crates/dmm-tools/tests/parse_codebase.rs @@ -46,3 +46,4 @@ fn parse_all_dmi() { dmi::Metadata::from_file(path).unwrap(); }); } + diff --git a/crates/dreammaker/Cargo.toml b/crates/dreammaker/Cargo.toml index 688efd42..ac99ca86 100644 --- a/crates/dreammaker/Cargo.toml +++ b/crates/dreammaker/Cargo.toml @@ -19,6 +19,7 @@ phf = { version = "0.10.1", features = ["macros"] } color_space = "0.5.3" ahash = "0.7.6" indexmap = "1.8.1" +derivative = "2.2.0" [dev-dependencies] walkdir = "2.3.2" diff --git a/crates/dreammaker/src/dmi.rs b/crates/dreammaker/src/dmi.rs index 491029d4..844d0ab8 100644 --- a/crates/dreammaker/src/dmi.rs +++ b/crates/dreammaker/src/dmi.rs @@ -1,13 +1,41 @@ //! DMI metadata parsing and representation. +use std::fmt::Display; use std::io; use std::path::Path; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashMap}; +use derivative::Derivative; use lodepng::Decoder; const EXPECTED_VERSION_LINE: &str = "version = 4.0"; +/// Index into the state name table +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)] +pub struct StateIndex(String, u32); + +impl Display for StateIndex { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if self.1 == 0 { + write!(f, "{}", self.0) + } else { + write!(f, "{} ({})", self.0, self.1) + } + } +} + +impl From for StateIndex { + fn from(s: String) -> Self { + StateIndex(s, 0) + } +} + +impl From<&str> for StateIndex { + fn from(s: &str) -> Self { + StateIndex(s.to_owned(), 0) + } +} + /// The two-dimensional facing subset of BYOND's direction type. #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] pub enum Dir { @@ -180,20 +208,24 @@ pub struct Metadata { /// The list of states in the order they appear in the spritesheet. pub states: Vec, /// A lookup table from state name to its position in `states`. - pub state_names: BTreeMap, + pub state_names: BTreeMap, } /// The metadata belonging to a single icon state. -#[derive(Debug, Clone, PartialEq)] +#[derive(Derivative, Debug, Clone)] +#[derivative(PartialEq)] pub struct State { /// The state's name, corresponding to the `icon_state` var. pub name: String, /// Whether this is a movement state (shown during gliding). pub movement: bool, /// The number of frames in the spritesheet before this state's first frame. + #[derivative(PartialEq="ignore")] pub offset: usize, /// 0 for infinite, 1+ for finite. pub loop_: u32, + /// The number of `State`s before this with the same name. + pub duplicate_index: u32, pub rewind: bool, pub dirs: Dirs, pub frames: Frames, @@ -265,16 +297,11 @@ impl Metadata { parse_metadata(data) } - pub fn rect_of(&self, bitmap_width: u32, icon_state: &str, dir: Dir, frame: u32) -> Option<(u32, u32, u32, u32)> { + pub fn rect_of(&self, bitmap_width: u32, icon_state: &StateIndex, dir: Dir, frame: u32) -> Option<(u32, u32, u32, u32)> { if self.states.is_empty() { return Some((0, 0, self.width, self.height)); } - let state_index = match self.state_names.get(icon_state) { - Some(&i) => i, - None if icon_state.is_empty() => 0, - None => return None, - }; - let state = &self.states[state_index]; + let state = self.get_icon_state(icon_state)?; let icon_index = state.index_of_frame(dir, frame); let icon_count = bitmap_width / self.width; @@ -286,9 +313,25 @@ impl Metadata { self.height, )) } + + pub fn get_icon_state(&self, icon_state: &StateIndex) -> Option<&State> { + let state_index = match self.state_names.get(icon_state) { + Some(&i) => i, + None => return None, + }; + Some(&self.states[state_index]) + } } impl State { + pub fn is_animated(&self) -> bool { + match self.frames { + Frames::One | Frames::Count(1) => false, + Frames::Count(_) => true, + Frames::Delays(_) => true, + } + } + pub fn num_sprites(&self) -> usize { self.dirs.count() * self.frames.count() } @@ -313,6 +356,10 @@ impl State { pub fn index_of_frame(&self, dir: Dir, frame: u32) -> u32 { self.index_of_dir(dir) + frame * self.dirs.count() as u32 } + + pub fn get_state_name_index(&self) -> StateIndex { + StateIndex(self.name.clone(), self.duplicate_index) + } } impl Dirs { @@ -372,13 +419,13 @@ fn parse_metadata(data: &str) -> io::Result { let mut state: Option = None; let mut frames_so_far = 0; + let mut duplicate_map: HashMap = HashMap::new(); + for line in lines { if line.starts_with("# END DMI") { break; } - let mut split = line.trim().splitn(2, " = "); - let key = split.next().unwrap(); - let value = split.next().unwrap(); + let (key, value) = line.trim().split_once(" = ").unwrap(); match key { "width" => metadata.width = value.parse().unwrap(), "height" => metadata.height = value.parse().unwrap(), @@ -389,19 +436,29 @@ fn parse_metadata(data: &str) -> io::Result { } let unquoted = value[1..value.len() - 1].to_owned(); // TODO: unquote assert!(!unquoted.contains('\\') && !unquoted.contains('"')); - if !metadata.state_names.contains_key(&unquoted) { - metadata.state_names.insert(unquoted.clone(), metadata.states.len()); - } - state = Some(State { + let count = duplicate_map.entry(unquoted.clone()).or_insert(0); + + let new_state = State { offset: frames_so_far, name: unquoted, loop_: 0, + duplicate_index: *count, rewind: false, movement: false, dirs: Dirs::One, frames: Frames::One, - }); + }; + + let key = new_state.get_state_name_index(); + + if let std::collections::btree_map::Entry::Vacant(e) = metadata.state_names.entry(key) { + e.insert(metadata.states.len()); + } + + state = Some(new_state); + + *count += 1; } "dirs" => { let state = state.as_mut().unwrap(); @@ -448,3 +505,51 @@ fn parse_metadata(data: &str) -> io::Result { Ok(metadata) } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn duplicate_states() { + let description = r##" +# BEGIN DMI +version = 4.0 + width = 32 + height = 32 +state = "duplicate" + dirs = 1 + frames = 1 +state = "duplicate" + dirs = 1 + frames = 1 +state = "duplicate" + dirs = 1 + frames = 1 +# END DMI +"##.trim(); + + let metadata = parse_metadata(description).unwrap(); + assert_eq!(metadata.state_names.len(), 3); + assert_eq!( + metadata.state_names, + BTreeMap::from([ + (StateIndex("duplicate".to_owned(), 0), 0), + (StateIndex("duplicate".to_owned(), 1), 1), + (StateIndex("duplicate".to_owned(), 2), 2) + ]) + ); + assert_eq!(metadata.states.len(), 3); + + for (no, state) in metadata.states.iter().enumerate() { + if no == 0 { + assert_eq!(state.duplicate_index, 0) + } else { + assert_eq!(state.duplicate_index, no as u32); + } + + // Note: using `no` here only works by virtue of the test data being only composed of duplicates + assert_eq!(no, *metadata.state_names.get(&state.get_state_name_index()).unwrap()) + } + } +} \ No newline at end of file From 8641274b25d6e978617e80b53b068905f575197e Mon Sep 17 00:00:00 2001 From: tigercat2000 Date: Mon, 11 Jul 2022 22:57:15 -0700 Subject: [PATCH 019/197] Fix edge case where delay has non-1 overflow (#331) Sometimes, Dream Maker just doesn't get rid of extra delay information when a state has the number of frames edited. This means we need to truncate our delay list to the number of frames specified by the frames key. This always worked fine- however, we also simplify `delays = 1,1,...` to `Frames::Count(delays.len())`. The bug in our code was that we checked if our `delays = 1,1,...` *before* truncating the array in the truncation case, so we would output `Frames::Delays([1,1])` for this metadata. Caused a PartialEq failure in IDB here: https://github.com/tigercat2000/IconDiffBot2-test/pull/20 https://github.com/ParadiseSS13/Paradise/pull/18326 --- crates/dreammaker/src/dmi.rs | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/crates/dreammaker/src/dmi.rs b/crates/dreammaker/src/dmi.rs index 844d0ab8..4fdaacf3 100644 --- a/crates/dreammaker/src/dmi.rs +++ b/crates/dreammaker/src/dmi.rs @@ -487,9 +487,11 @@ fn parse_metadata(data: &str) -> io::Result { } else { state.frames = Frames::Delays(vector); }, - Frames::Count(n) => if !vector.iter().all(|&n| n == 1.) { + Frames::Count(n) => { vector.truncate(n); - state.frames = Frames::Delays(vector); + if !vector.iter().all(|&n| n == 1.) { + state.frames = Frames::Delays(vector); + } }, Frames::Delays(_) => panic!(), } @@ -529,7 +531,7 @@ state = "duplicate" # END DMI "##.trim(); - let metadata = parse_metadata(description).unwrap(); + let metadata = parse_metadata(description).expect("Metadata is valid"); assert_eq!(metadata.state_names.len(), 3); assert_eq!( metadata.state_names, @@ -552,4 +554,32 @@ state = "duplicate" assert_eq!(no, *metadata.state_names.get(&state.get_state_name_index()).unwrap()) } } + + #[test] + /// Sometimes, Dream Maker just doesn't get rid of extra delay + /// information when a state has the number of frames edited. + /// + /// This means we need to truncate our delay list to the number of frames specified by the frames key. + /// + /// This always worked fine- however, we also simplify `delays = 1,1,...` to `Frames::Count(delays.len())`. + /// + /// The bug in our code was that we checked if our `delays = 1,1,...` *before* truncating the array + /// in the truncation case, so we would output `Frames::Delays([1,1])` for this metadata. + fn delay_overflow_edge_case() { + let description = r##" +# BEGIN DMI +version = 4.0 + width = 32 + height = 32 +state = "one" + dirs = 1 + frames = 2 + delay = 1,1,0.5,0.5 +# END DMI +"##.trim(); + + let metadata = parse_metadata(description).expect("Metadata is valid"); + let state = metadata.get_icon_state(&StateIndex("one".to_owned(), 0)).expect("Only one state, named one, should be found"); + assert_eq!(state.frames, Frames::Count(2)); + } } \ No newline at end of file From 5c07083706d3a6fe0dd1b7e2585084e04d9aa939 Mon Sep 17 00:00:00 2001 From: LatteKat <56778689+jupyterkat@users.noreply.github.com> Date: Thu, 15 Sep 2022 10:43:23 +1000 Subject: [PATCH 020/197] Bump up all dependencies (#336) --- Cargo.lock | 606 +++++++++++++++----------- crates/builtins-proc-macro/Cargo.toml | 2 +- crates/dap-types/Cargo.toml | 8 +- crates/dm-langserver/Cargo.toml | 20 +- crates/dmdoc/Cargo.toml | 14 +- crates/dmm-tools-cli/Cargo.toml | 14 +- crates/dmm-tools/Cargo.toml | 18 +- crates/dreamchecker/Cargo.toml | 6 +- crates/dreammaker/Cargo.toml | 12 +- 9 files changed, 393 insertions(+), 307 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b8ce6692..cbcdb8d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,14 +26,35 @@ dependencies = [ ] [[package]] -name = "aho-corasick" -version = "0.7.18" +name = "ahash" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "57e6e951cfbb2db8de1828d49073a113a29fd7117b1596caa781a258c7e38d72" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -77,25 +98,13 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "block-buffer" -version = "0.7.3" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ - "block-padding", - "byte-tools", - "byteorder", "generic-array", ] -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", -] - [[package]] name = "bstr" version = "0.2.17" @@ -116,42 +125,30 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.9.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "bytemuck" -version = "1.9.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" +checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562e382481975bc61d11275ac5e62a19abd00b0547d99516a415336f183dcd0e" +checksum = "1b9e1f5fa78f69496407a27ae9ed989e3c3b072310286f5ef385525e4cbc24a9" dependencies = [ "proc-macro2", "quote", "syn", ] -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - [[package]] name = "cc" version = "1.0.73" @@ -169,22 +166,24 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" dependencies = [ - "libc", + "iana-time-zone", + "js-sys", "num-integer", "num-traits", "time", + "wasm-bindgen", "winapi", ] [[package]] name = "chrono-tz" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58549f1842da3080ce63002102d5bc954c7bc843d4f47818e642abdc36253552" +checksum = "29c39203181991a7dd4343b8005bd804e7a9a37afb8ac070e43771e8c820bbde" dependencies = [ "chrono", "chrono-tz-build", @@ -193,9 +192,9 @@ dependencies = [ [[package]] name = "chrono-tz-build" -version = "0.0.2" +version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db058d493fb2f65f41861bfed7e3fe6335264a9f0f92710cab5bdf01fef09069" +checksum = "6f509c3a87b33437b05e2458750a0700e5bdd6956176773e6c7d6dd15a283a0c" dependencies = [ "parse-zoneinfo", "phf", @@ -229,6 +228,21 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3776b2bcc4e914db501bb9be9572dd706e344b9eb8f882894f3daa651d281381" +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.3.2" @@ -240,9 +254,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if", "crossbeam-utils", @@ -250,9 +264,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -261,47 +275,48 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "lazy_static", "memoffset", + "once_cell", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" dependencies = [ "cfg-if", - "lazy_static", + "once_cell", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", ] [[package]] name = "dap-types" version = "0.0.0" dependencies = [ - "ahash", + "ahash 0.8.0", "serde", "serde_derive", "serde_json", ] -[[package]] -name = "deflate" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f" -dependencies = [ - "adler32", -] - [[package]] name = "derivative" version = "2.2.0" @@ -321,18 +336,19 @@ checksum = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690" [[package]] name = "digest" -version = "0.8.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ - "generic-array", + "block-buffer", + "crypto-common", ] [[package]] name = "dm-langserver" version = "1.5.1" dependencies = [ - "ahash", + "ahash 0.8.0", "bincode", "chrono", "dap-types", @@ -370,7 +386,7 @@ dependencies = [ name = "dmm-tools" version = "0.1.0" dependencies = [ - "ahash", + "ahash 0.8.0", "bumpalo", "bytemuck", "dreammaker", @@ -390,7 +406,7 @@ dependencies = [ name = "dmm-tools-cli" version = "1.3.1" dependencies = [ - "ahash", + "ahash 0.8.0", "chrono", "dmm-tools", "dreammaker", @@ -416,7 +432,7 @@ dependencies = [ name = "dreamchecker" version = "1.7.1" dependencies = [ - "ahash", + "ahash 0.8.0", "chrono", "dreammaker", "git2", @@ -428,7 +444,7 @@ dependencies = [ name = "dreammaker" version = "0.1.0" dependencies = [ - "ahash", + "ahash 0.8.0", "bitflags", "builtins-proc-macro", "color_space", @@ -448,34 +464,26 @@ dependencies = [ [[package]] name = "either" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "fallible_collections" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52db5973b6a19247baf19b30f41c23a1bfffc2e9ce0a5db2f60e3cd5dc8895f7" +checksum = "c195cf4b2285d3c993eb887b4dc56b0d5728bbe1d0f9a99c0ac6bec2da3e4d85" dependencies = [ "hashbrown", ] [[package]] name = "flate2" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" dependencies = [ - "cfg-if", "crc32fast", - "libc", "miniz_oxide", ] @@ -487,19 +495,18 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] [[package]] name = "futures" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" dependencies = [ "futures-channel", "futures-core", @@ -512,9 +519,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" dependencies = [ "futures-core", "futures-sink", @@ -522,15 +529,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" [[package]] name = "futures-executor" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab" dependencies = [ "futures-core", "futures-task", @@ -539,15 +546,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" [[package]] name = "futures-macro" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" dependencies = [ "proc-macro2", "quote", @@ -556,21 +563,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" dependencies = [ "futures-channel", "futures-core", @@ -586,11 +593,12 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.12.4" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", + "version_check", ] [[package]] @@ -604,13 +612,13 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -626,9 +634,9 @@ dependencies = [ [[package]] name = "gif" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b" +checksum = "3edd93c6756b4dfaf2709eafcc345ba2636565295c198a9cfbf75fa5e3e00b06" dependencies = [ "color_quant", "weezl", @@ -636,9 +644,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.14.4" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0155506aab710a86160ddb504a480d2964d7ab5b9e62419be69e0032bc5931c" +checksum = "2994bee4a3a6a51eb90c218523be382fd7ea09b16380b9312e9dbe955ff7c7d1" dependencies = [ "bitflags", "libc", @@ -649,9 +657,9 @@ dependencies = [ [[package]] name = "globset" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd" +checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" dependencies = [ "aho-corasick", "bstr", @@ -679,11 +687,11 @@ checksum = "ff893cc51ea04f8a3b73fbaf4376c06ebc5a0ccbe86d460896f805d9417c93ea" [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash", + "ahash 0.7.6", ] [[package]] @@ -711,12 +719,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026" [[package]] -name = "idna" -version = "0.2.3" +name = "iana-time-zone" +version = "0.1.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "237a0714f28b1ee39ccec0770ccb544eb02c9ef2c82bb096230eefcffa6468b0" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "js-sys", + "once_cell", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] @@ -741,9 +762,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", "hashbrown", @@ -767,9 +788,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" [[package]] name = "jobserver" @@ -780,6 +801,15 @@ dependencies = [ "libc", ] +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "jsonrpc-core" version = "18.0.0" @@ -803,15 +833,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.125" +version = "0.2.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" [[package]] name = "libgit2-sys" -version = "0.13.4+1.4.2" +version = "0.14.0+1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0fa6563431ede25f5cc7f6d803c6afbc1c5d3ad3d4925d12c882bf2b526f5d1" +checksum = "47a00859c70c8a4f7218e6d1cc32875c4b55f6799445b842b0d8ed5e4c3d959b" dependencies = [ "cc", "libc", @@ -821,9 +851,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.6" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e7e15d7610cce1d9752e137625f14e61a28cd45929b6e12e47b50fe154ee2e" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" dependencies = [ "cc", "libc", @@ -833,9 +863,9 @@ dependencies = [ [[package]] name = "lodepng" -version = "3.6.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f84e1fdcdbe8b3f0f9caaadb6b86d0e0647786e993f6ea70686f6837b989ec7" +checksum = "ff45534ec797452c044fcd47861059eddb501e30a8fd9fdadea7957cdff3ebc7" dependencies = [ "crc32fast", "fallible_collections", @@ -855,9 +885,9 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.93.0" +version = "0.93.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70c74e2173b2b31f8655d33724b4b45ac13f439386f66290f539c22b144c2212" +checksum = "a3bcfee315dde785ba887edb540b08765fd7df75a7d948844be6bf5712246734" dependencies = [ "bitflags", "serde", @@ -866,18 +896,6 @@ dependencies = [ "url", ] -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - [[package]] name = "matrixmultiply" version = "0.3.2" @@ -904,18 +922,18 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.5.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" dependencies = [ "adler", ] [[package]] name = "ndarray" -version = "0.15.4" +version = "0.15.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec23e6762830658d2b3d385a75aa212af2f67a4586d4442907144f3bb6a1ca8" +checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32" dependencies = [ "matrixmultiply", "num-complex", @@ -926,9 +944,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fbc387afefefd5e9e39493299f3069e14a140dd34dc19b4c1c1a8fddb6a790" +checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" dependencies = [ "num-traits", ] @@ -964,15 +982,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.10.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" - -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" [[package]] name = "ordered-float" @@ -994,24 +1006,25 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.1.3" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +checksum = "cb779fcf4bb850fbbb0edc96ff6cf34fd90c4b1a112ce042653280d9a7364048" dependencies = [ + "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.1.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +checksum = "502b62a6d0245378b04ffe0a7fb4f4419a4815fce813bd8a0ec89a56e07d67b1" dependencies = [ "pest", "pest_generator", @@ -1019,9 +1032,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.1.3" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" +checksum = "451e629bf49b750254da26132f1a5a9d11fd8a95a3df51d15c4abd1ba154cb6c" dependencies = [ "pest", "pest_meta", @@ -1032,31 +1045,30 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.1.3" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +checksum = "bcec162c71c45e269dfc3fc2916eaeb97feab22993a21bcce4721d08cd7801a6" dependencies = [ - "maplit", + "once_cell", "pest", - "sha-1", + "sha1", ] [[package]] name = "phf" -version = "0.10.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" dependencies = [ "phf_macros", "phf_shared", - "proc-macro-hack", ] [[package]] name = "phf_codegen" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770" dependencies = [ "phf_generator", "phf_shared", @@ -1064,9 +1076,9 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" dependencies = [ "phf_shared", "rand", @@ -1074,13 +1086,12 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +checksum = "92aacdc5f16768709a569e913f7451034034178b05bdc8acda226659a3dccc66" dependencies = [ "phf_generator", "phf_shared", - "proc-macro-hack", "proc-macro2", "quote", "syn", @@ -1088,9 +1099,9 @@ dependencies = [ [[package]] name = "phf_shared" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" dependencies = [ "siphasher", "uncased", @@ -1116,13 +1127,13 @@ checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "png" -version = "0.17.5" +version = "0.17.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba" +checksum = "8f0e7f4c94ec26ff209cee506314212639d6c91b80afb82984819fafce9df01c" dependencies = [ "bitflags", "crc32fast", - "deflate", + "flate2", "miniz_oxide", ] @@ -1156,26 +1167,20 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - [[package]] name = "proc-macro2" -version = "1.0.38" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "pulldown-cmark" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6" +checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63" dependencies = [ "bitflags", "getopts", @@ -1185,9 +1190,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -1230,9 +1235,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd249e82c21598a9a426a4e00dd7adc1d640b22445ec8545feef801d1a74c221" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" dependencies = [ "autocfg", "crossbeam-deque", @@ -1242,9 +1247,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f51245e1e62e1f1629cbfec37b5793bbabcaeb90f30e94d2ba03564687353e4" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -1254,9 +1259,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.5" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", @@ -1265,24 +1270,24 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "rgb" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e74fdc210d8f24a7dbfedc13b04ba5764f5232754ccebfdf5fff1bad791ccbc6" +checksum = "c3b221de559e4a29df3b957eec92bc0de6bc8eaf6ca9cfed43e5e1d67ff65a34" dependencies = [ "bytemuck", ] [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "same-file" @@ -1301,18 +1306,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.137" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" dependencies = [ "proc-macro2", "quote", @@ -1321,9 +1326,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.81" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "itoa", "ryu", @@ -1332,9 +1337,9 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ad84e47328a31223de7fed7a4f5087f2d6ddfe586cf3ca25b7a165bc0a5aed" +checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca" dependencies = [ "proc-macro2", "quote", @@ -1342,15 +1347,14 @@ dependencies = [ ] [[package]] -name = "sha-1" -version = "0.8.2" +name = "sha1" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +checksum = "006769ba83e921b3085caa8334186b00cf92b4cb1a6cf4632fbccc8eff5c7549" dependencies = [ - "block-buffer", + "cfg-if", + "cpufeatures", "digest", - "fake-simd", - "opaque-debug", ] [[package]] @@ -1361,9 +1365,12 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "slab" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] [[package]] name = "slug" @@ -1406,20 +1413,20 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.93" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04066589568b72ec65f42d65a1a52436e954b168773148893c020269563decf2" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] name = "tera" -version = "1.15.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3cac831b615c25bcef632d1cabf864fa05813baad3d526829db18eb70e8b58d" +checksum = "1d4685e72cb35f0eb74319c8fe2d3b61e93da5609841cde2cb87fcc3bea56d20" dependencies = [ "chrono", "chrono-tz", @@ -1455,6 +1462,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.4" @@ -1471,7 +1498,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", - "wasi", + "wasi 0.10.0+wasi-snapshot-preview1", "winapi", ] @@ -1507,15 +1534,15 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "ucd-trie" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "uncased" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baeed7327e25054889b9bd4f975f32e5f4c5d434042d59ab6cd4142c0a76ed0" +checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" dependencies = [ "version_check", ] @@ -1586,41 +1613,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] -name = "unicode-normalization" -version = "0.1.19" +name = "unicode-ident" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" + +[[package]] +name = "unicode-normalization" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - -[[package]] -name = "unicode-xid" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", "serde", ] @@ -1661,10 +1687,70 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] -name = "weezl" -version = "0.1.6" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c97e489d8f836838d497091de568cf16b117486d529ec5579233521065bd5e4" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + +[[package]] +name = "weezl" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" [[package]] name = "winapi" diff --git a/crates/builtins-proc-macro/Cargo.toml b/crates/builtins-proc-macro/Cargo.toml index 7c715111..f4a85396 100644 --- a/crates/builtins-proc-macro/Cargo.toml +++ b/crates/builtins-proc-macro/Cargo.toml @@ -10,4 +10,4 @@ proc-macro = true [dependencies] syn = "1.0" quote = "1.0" -proc-macro2 = "1.0.37" +proc-macro2 = "1.0.43" diff --git a/crates/dap-types/Cargo.toml b/crates/dap-types/Cargo.toml index aa3d2b6d..72f995c4 100644 --- a/crates/dap-types/Cargo.toml +++ b/crates/dap-types/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Tad Hardesty "] edition = "2018" [dependencies] -serde = "1.0.136" -serde_json = "1.0.79" -serde_derive = "1.0.136" -ahash = "0.7.6" +serde = "1.0.144" +serde_json = "1.0.85" +serde_derive = "1.0.144" +ahash = "0.8.0" diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index 20f2d0ab..4785c395 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -5,23 +5,23 @@ authors = ["Tad Hardesty "] edition = "2018" [dependencies] -url = "2.2.2" -serde = "1.0.136" -serde_json = "1.0.79" -serde_derive = "1.0.136" +url = "2.3.1" +serde = "1.0.144" +serde_json = "1.0.85" +serde_derive = "1.0.144" bincode = "1.3.3" jsonrpc-core = "18.0.0" -lsp-types = "0.93.0" +lsp-types = "0.93.1" dap-types = { path = "../dap-types" } dreammaker = { path = "../dreammaker" } dreamchecker = { path = "../dreamchecker" } interval-tree = { path = "../interval-tree" } -libc = "0.2.124" +libc = "0.2.132" guard = "0.5.1" -regex = "1.5.5" +regex = "1.6.0" lazy_static = "1.4" -ahash = "0.7.6" +ahash = "0.8.0" [build-dependencies] -chrono = "0.4.19" -git2 = { version = "0.14.2", default-features = false } +chrono = "0.4.22" +git2 = { version = "0.15.0", default-features = false } diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index f5dd91ef..a525e6f0 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -7,16 +7,16 @@ edition = "2018" [dependencies] dreammaker = { path = "../dreammaker" } -pulldown-cmark = "0.9.1" -tera = "1.15.0" -serde = "1.0.136" -serde_derive = "1.0.136" +pulldown-cmark = "0.9.2" +tera = "1.17.0" +serde = "1.0.144" +serde_derive = "1.0.144" walkdir = "2.3.2" -git2 = { version = "0.14.2", default-features = false } +git2 = { version = "0.15.0", default-features = false } [dev-dependencies] walkdir = "2.3.2" [build-dependencies] -chrono = "0.4.19" -git2 = { version = "0.14.2", default-features = false } +chrono = "0.4.22" +git2 = { version = "0.15.0", default-features = false } diff --git a/crates/dmm-tools-cli/Cargo.toml b/crates/dmm-tools-cli/Cargo.toml index c6a8802d..a1b55340 100644 --- a/crates/dmm-tools-cli/Cargo.toml +++ b/crates/dmm-tools-cli/Cargo.toml @@ -12,14 +12,14 @@ path = "src/main.rs" [dependencies] structopt = "0.3.26" structopt-derive = "0.4.18" -serde = "1.0.136" -serde_derive = "1.0.136" -serde_json = "1.0.79" -rayon = "1.5.2" +serde = "1.0.144" +serde_derive = "1.0.144" +serde_json = "1.0.85" +rayon = "1.5.3" dreammaker = { path = "../dreammaker" } dmm-tools = { path = "../dmm-tools", features = ["png"] } -ahash = "0.7.6" +ahash = "0.8.0" [build-dependencies] -chrono = "0.4.19" -git2 = { version = "0.14.2", default-features = false } +chrono = "0.4.22" +git2 = { version = "0.15.0", default-features = false } diff --git a/crates/dmm-tools/Cargo.toml b/crates/dmm-tools/Cargo.toml index 7c056cac..0141d7be 100644 --- a/crates/dmm-tools/Cargo.toml +++ b/crates/dmm-tools/Cargo.toml @@ -6,24 +6,24 @@ edition = "2018" [dependencies] inflate = "0.4.5" -ndarray = "0.15.4" +ndarray = "0.15.6" rand = "0.8.5" dreammaker = { path = "../dreammaker" } -lodepng = "3.6.1" -indexmap = "1.8.1" -ahash = "0.7.6" -either = "1.6.1" +lodepng = "3.7.0" +indexmap = "1.9.1" +ahash = "0.8.0" +either = "1.8.0" [dependencies.bytemuck] -version = "1.9.1" +version = "1.12.1" features = ["derive"] [dependencies.bumpalo] -version = "3.9.1" +version = "3.11.0" features = ["collections"] [dependencies.png] -version = "0.17.5" +version = "0.17.6" optional = true [dependencies.gfx_core] @@ -31,7 +31,7 @@ version = "0.9.2" optional = true [dependencies.gif] -version = "0.11.3" +version = "0.11.4" optional = true [dev-dependencies] diff --git a/crates/dreamchecker/Cargo.toml b/crates/dreamchecker/Cargo.toml index be910add..f3a72851 100644 --- a/crates/dreamchecker/Cargo.toml +++ b/crates/dreamchecker/Cargo.toml @@ -8,8 +8,8 @@ edition = "2018" dreammaker = { path = "../dreammaker" } guard = "0.5.1" serde_json = "1.0" -ahash = "0.7.6" +ahash = "0.8.0" [build-dependencies] -chrono = "0.4.19" -git2 = { version = "0.14.2", default-features = false } +chrono = "0.4.22" +git2 = { version = "0.15.0", default-features = false } diff --git a/crates/dreammaker/Cargo.toml b/crates/dreammaker/Cargo.toml index ac99ca86..64b790a6 100644 --- a/crates/dreammaker/Cargo.toml +++ b/crates/dreammaker/Cargo.toml @@ -7,18 +7,18 @@ edition = "2018" [dependencies] interval-tree = { path = "../interval-tree" } builtins-proc-macro = { path = "../builtins-proc-macro" } -lodepng = "3.6.1" +lodepng = "3.7.0" bitflags = "1.3.2" termcolor = "1.1.3" ordered-float = "3.0.0" -serde = { version = "1.0.136", features = ["derive"] } -serde_derive = "1.0.136" +serde = { version = "1.0.144", features = ["derive"] } +serde_derive = "1.0.144" toml = "0.5.9" guard = "0.5.1" -phf = { version = "0.10.1", features = ["macros"] } +phf = { version = "0.11.1", features = ["macros"] } color_space = "0.5.3" -ahash = "0.7.6" -indexmap = "1.8.1" +ahash = "0.8.0" +indexmap = "1.9.1" derivative = "2.2.0" [dev-dependencies] From 10d9575f9e188832770543c5c25f705fbe8df9bf Mon Sep 17 00:00:00 2001 From: TiviPlus <57223640+TiviPlus@users.noreply.github.com> Date: Sun, 30 Oct 2022 09:45:33 +0100 Subject: [PATCH 021/197] Add missing _binobj var for generators (#342) Similar to the database binobj, it's a internal object whose string representation is useful for reading the generator's arguments. --- crates/dreammaker/src/builtins.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/dreammaker/src/builtins.rs b/crates/dreammaker/src/builtins.rs index 42f746ab..d62b79e2 100644 --- a/crates/dreammaker/src/builtins.rs +++ b/crates/dreammaker/src/builtins.rs @@ -1130,6 +1130,7 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { // 514 stuff generator; + generator/var/_binobj; generator/proc/Rand(); generator/proc/Turn(a); From 9d278dcd8e60dd6fe632e2fa79bf0fd1ea3ab68f Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 15 Jan 2023 22:20:03 -0800 Subject: [PATCH 022/197] Fix parsing heredocs with multiple quotes in a row Previously misparsed {"foo""bar"} as String("foo\"\"\"bar"). --- crates/dreammaker/src/lexer.rs | 9 +++-- crates/dreammaker/tests/lexer_tests.rs | 56 ++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index df29b73c..803516fb 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -976,10 +976,11 @@ impl<'ctx> Lexer<'ctx> { break; } continue; - } else if ch == end[0] && !backslash { - // TODO: this is a hack to fix the '""}' situation - buf.extend_from_slice(&end[..idx]); - idx = 1; + } else if idx > 0 && ch == end[idx - 1] && end[..idx - 1] == end[1..idx] && !backslash { + // Handle `""}` and similar situations by holding `idx` steady + // and shifting the first character of `end` into `buf`. + buf.extend_from_slice(&end[..1]); + continue; } else { buf.extend_from_slice(&end[..idx]); idx = 0; diff --git a/crates/dreammaker/tests/lexer_tests.rs b/crates/dreammaker/tests/lexer_tests.rs index 59232298..817f5dee 100644 --- a/crates/dreammaker/tests/lexer_tests.rs +++ b/crates/dreammaker/tests/lexer_tests.rs @@ -83,3 +83,59 @@ fn raw_strings() { assert_eq!(each, &desired); } } + +#[test] +fn heredoc_with_quotes() { + // 1-3 quotes in the middle of ordinary characters + assert_eq!( + lex(r#"{"foo"bar"}"#), + vec![ + Token::String(r#"foo"bar"#.to_owned()), + Token::Punct(Punctuation::Newline), + ] + ); + assert_eq!( + lex(r#"{"foo""bar"}"#), + vec![ + Token::String(r#"foo""bar"#.to_owned()), + Token::Punct(Punctuation::Newline), + ] + ); + assert_eq!( + lex(r#"{"foo"""bar"}"#), + vec![ + Token::String(r#"foo"""bar"#.to_owned()), + Token::Punct(Punctuation::Newline), + ] + ); + + // 0-5 quotes at the start/end + assert_eq!( + lex(r#"{""}"#), + vec![ + Token::String(r#""#.to_owned()), + Token::Punct(Punctuation::Newline), + ] + ); + assert_eq!( + lex(r#"{"""}"#), + vec![ + Token::String(r#"""#.to_owned()), + Token::Punct(Punctuation::Newline), + ] + ); + assert_eq!( + lex(r#"{""""}"#), + vec![ + Token::String(r#""""#.to_owned()), + Token::Punct(Punctuation::Newline), + ] + ); + assert_eq!( + lex(r#"{"""""}"#), + vec![ + Token::String(r#"""""#.to_owned()), + Token::Punct(Punctuation::Newline), + ] + ); +} From c40fa46644c19b82817deef9bb1ef96b33f547b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jan 2023 15:38:07 -0800 Subject: [PATCH 023/197] Bump bumpalo from 3.11.0 to 3.11.1 (#346) Bumps [bumpalo](https://github.com/fitzgen/bumpalo) from 3.11.0 to 3.11.1. - [Release notes](https://github.com/fitzgen/bumpalo/releases) - [Changelog](https://github.com/fitzgen/bumpalo/blob/main/CHANGELOG.md) - [Commits](https://github.com/fitzgen/bumpalo/compare/3.11.0...3.11.1) --- updated-dependencies: - dependency-name: bumpalo dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/dmm-tools/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cbcdb8d3..9ff7e6cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,9 +125,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.11.0" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "bytemuck" diff --git a/crates/dmm-tools/Cargo.toml b/crates/dmm-tools/Cargo.toml index 0141d7be..77a65471 100644 --- a/crates/dmm-tools/Cargo.toml +++ b/crates/dmm-tools/Cargo.toml @@ -19,7 +19,7 @@ version = "1.12.1" features = ["derive"] [dependencies.bumpalo] -version = "3.11.0" +version = "3.11.1" features = ["collections"] [dependencies.png] From 7a2f3b00dab2d89e79421c55080dc9594c8b0ef1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jan 2023 17:51:24 -0800 Subject: [PATCH 024/197] Bump git2 from 0.15.0 to 0.16.1 (#348) Bumps [git2](https://github.com/rust-lang/git2-rs) from 0.15.0 to 0.16.1. - [Release notes](https://github.com/rust-lang/git2-rs/releases) - [Commits](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.15.0...0.16.1) --- updated-dependencies: - dependency-name: git2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- crates/dm-langserver/Cargo.toml | 2 +- crates/dmdoc/Cargo.toml | 4 ++-- crates/dmm-tools-cli/Cargo.toml | 2 +- crates/dreamchecker/Cargo.toml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9ff7e6cd..32be9b7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -644,9 +644,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.15.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2994bee4a3a6a51eb90c218523be382fd7ea09b16380b9312e9dbe955ff7c7d1" +checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc" dependencies = [ "bitflags", "libc", @@ -839,9 +839,9 @@ checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" [[package]] name = "libgit2-sys" -version = "0.14.0+1.5.0" +version = "0.14.2+1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a00859c70c8a4f7218e6d1cc32875c4b55f6799445b842b0d8ed5e4c3d959b" +checksum = "7f3d95f6b51075fe9810a7ae22c7095f12b98005ab364d8544797a825ce946a4" dependencies = [ "cc", "libc", diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index 4785c395..fc91c987 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -24,4 +24,4 @@ ahash = "0.8.0" [build-dependencies] chrono = "0.4.22" -git2 = { version = "0.15.0", default-features = false } +git2 = { version = "0.16.1", default-features = false } diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index a525e6f0..b2186f4e 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -12,11 +12,11 @@ tera = "1.17.0" serde = "1.0.144" serde_derive = "1.0.144" walkdir = "2.3.2" -git2 = { version = "0.15.0", default-features = false } +git2 = { version = "0.16.1", default-features = false } [dev-dependencies] walkdir = "2.3.2" [build-dependencies] chrono = "0.4.22" -git2 = { version = "0.15.0", default-features = false } +git2 = { version = "0.16.1", default-features = false } diff --git a/crates/dmm-tools-cli/Cargo.toml b/crates/dmm-tools-cli/Cargo.toml index a1b55340..55a1471d 100644 --- a/crates/dmm-tools-cli/Cargo.toml +++ b/crates/dmm-tools-cli/Cargo.toml @@ -22,4 +22,4 @@ ahash = "0.8.0" [build-dependencies] chrono = "0.4.22" -git2 = { version = "0.15.0", default-features = false } +git2 = { version = "0.16.1", default-features = false } diff --git a/crates/dreamchecker/Cargo.toml b/crates/dreamchecker/Cargo.toml index f3a72851..a439a13d 100644 --- a/crates/dreamchecker/Cargo.toml +++ b/crates/dreamchecker/Cargo.toml @@ -12,4 +12,4 @@ ahash = "0.8.0" [build-dependencies] chrono = "0.4.22" -git2 = { version = "0.15.0", default-features = false } +git2 = { version = "0.16.1", default-features = false } From 75c989bf14d444adb656960fc06de9193b3a833a Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 30 Jan 2023 19:05:21 -0800 Subject: [PATCH 025/197] Add hover for macro documentation --- crates/dm-langserver/src/main.rs | 12 ++++++++--- crates/dreammaker/src/annotation.rs | 10 ++++++++- crates/dreammaker/src/preprocessor.rs | 30 ++++++++++++++++----------- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index de096199..fc3e654c 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -1405,6 +1405,13 @@ handle_method_call! { let next = self.find_scoped_type(&iter, priors); results.append(&mut self.construct_var_hover(var_name, next, true)?); } + Annotation::MacroUse { docs, .. } => { + if let Some(dc) = docs { + if !dc.is_empty() { + results.push(dc.text()); + } + } + } _ => {} } } @@ -1536,9 +1543,8 @@ handle_method_call! { } } }, - Annotation::MacroUse(name, location) => { - // TODO: get docs for this macro - results.push(self.convert_location(*location, &Default::default(), &["/DM/preprocessor/", name])?); + Annotation::MacroUse { name, definition_location, .. } => { + results.push(self.convert_location(*definition_location, &Default::default(), &["/DM/preprocessor/", name])?); }, } diff --git a/crates/dreammaker/src/annotation.rs b/crates/dreammaker/src/annotation.rs index df19cc2c..cd79fd2f 100644 --- a/crates/dreammaker/src/annotation.rs +++ b/crates/dreammaker/src/annotation.rs @@ -1,7 +1,11 @@ //! Data structures for the parser to output mappings from input ranges to AST //! elements at those positions. +use std::rc::Rc; + use interval_tree::{IntervalTree, RangePairIter, RangeInclusive, range}; +use crate::docs::DocCollection; + use super::Location; use super::ast::*; @@ -29,7 +33,11 @@ pub enum Annotation { // a macro is called here, which is defined at this location MacroDefinition(Ident), - MacroUse(String, Location), + MacroUse { + name: String, + definition_location: Location, + docs: Option>, + }, Include(std::path::PathBuf), Resource(std::path::PathBuf), diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index 75ea4f74..0cdfa11a 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -1,5 +1,6 @@ //! The preprocessor. use std::collections::{HashMap, VecDeque}; +use std::rc::Rc; use std::{io, fmt}; use std::fs::File; use std::path::{Path, PathBuf}; @@ -25,13 +26,13 @@ const MAX_RECURSION_DEPTH: usize = 32; pub enum Define { Constant { subst: Vec, - docs: DocCollection, + docs: Rc, }, Function { params: Vec, subst: Vec, variadic: bool, - docs: DocCollection, + docs: Rc, }, } @@ -532,7 +533,7 @@ impl<'ctx> Preprocessor<'ctx> { // ------------------------------------------------------------------------ // Macro definition handling - fn annotate_macro(&mut self, ident: &str, def_loc: Location) { + fn annotate_macro(&mut self, ident: &str, definition_location: Location, docs: Option>) { if self.include_stack.in_expansion() { return; } @@ -540,7 +541,12 @@ impl<'ctx> Preprocessor<'ctx> { if let Some(annotations) = self.annotations.as_mut() { annotations.insert( self.last_input_loc .. self.last_input_loc.add_columns(ident.len() as u16), - Annotation::MacroUse(ident.to_owned(), def_loc)); + Annotation::MacroUse { + name: ident.to_owned(), + definition_location, + docs, + } + ); } } @@ -897,9 +903,9 @@ impl<'ctx> Preprocessor<'ctx> { } } let define = if params.is_empty() { - Define::Constant { subst, docs } + Define::Constant { subst, docs: Rc::new(docs) } } else { - Define::Function { params, subst, variadic, docs } + Define::Function { params, subst, variadic, docs: Rc::new(docs) } }; // DEBUG can only be defined in the root .dme file if define_name != "DEBUG" || self.in_environment() { @@ -972,7 +978,7 @@ impl<'ctx> Preprocessor<'ctx> { // substitute special macros if ident == "__FILE__" { - self.annotate_macro(ident, Location::builtins()); + self.annotate_macro(ident, Location::builtins(), None); for include in self.include_stack.stack.iter().rev() { if let Include::File { ref path, .. } = *include { self.output.push_back(Token::String(path.display().to_string())); @@ -982,7 +988,7 @@ impl<'ctx> Preprocessor<'ctx> { self.output.push_back(Token::String(String::new())); return Ok(()); } else if ident == "__LINE__" { - self.annotate_macro(ident, Location::builtins()); + self.annotate_macro(ident, Location::builtins(), None); self.output.push_back(Token::Int(self.last_input_loc.line as i32)); return Ok(()); } @@ -1008,8 +1014,8 @@ impl<'ctx> Preprocessor<'ctx> { } match expansion { - Some((location, Define::Constant { subst, docs: _ })) => { - self.annotate_macro(ident, location); + Some((location, Define::Constant { subst, docs })) => { + self.annotate_macro(ident, location, Some(docs.clone())); self.include_stack.stack.push(Include::Expansion { //name: ident.to_owned(), tokens: subst.into_iter().collect(), @@ -1017,7 +1023,7 @@ impl<'ctx> Preprocessor<'ctx> { }); return Ok(()); } - Some((location, Define::Function { ref params, ref subst, variadic, docs: _ })) => { + Some((location, Define::Function { ref params, ref subst, variadic, docs })) => { // if it's not followed by an LParen, it isn't really a function call match next!() { Token::Punct(Punctuation::LParen) => {} @@ -1033,7 +1039,7 @@ impl<'ctx> Preprocessor<'ctx> { } } - self.annotate_macro(ident, location); + self.annotate_macro(ident, location, Some(docs.clone())); // read arguments let mut args = Vec::new(); From b02afe77867872ee5c780235c243b5a61229dead Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 30 Jan 2023 19:06:38 -0800 Subject: [PATCH 026/197] Indent match_annotation! bodies --- crates/dm-langserver/src/main.rs | 454 +++++++++++++++---------------- 1 file changed, 227 insertions(+), 227 deletions(-) diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index fc3e654c..c4747de6 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -821,113 +821,113 @@ impl<'a> Engine<'a> { let iter = annotations.get_location(location); match_annotation! { iter; - Annotation::Variable(path) => { - let mut current = self.objtree.root(); - let (var_name, most) = path.split_last().unwrap(); - for part in most { - if part == "var" { break } - if let Some(child) = current.child(part) { - current = child; - } else { - break; - } - } - - if let Some(decl) = current.get_var_declaration(var_name) { - symbol_id = Some(decl.id); - } - }, - Annotation::ProcHeader(parts, _) => { - let mut current = self.objtree.root(); - let (proc_name, most) = parts.split_last().unwrap(); - for part in most { - if part == "proc" || part == "verb" { break } - if let Some(child) = current.child(part) { - current = child; - } else { - break; - } - } - - if let Some(decl) = current.get_proc_declaration(proc_name) { - symbol_id = Some(decl.id); - } - }, - Annotation::TreePath(absolute, parts) => { - if let Some(ty) = self.objtree.type_by_path(completion::combine_tree_path(&iter, *absolute, parts)) { - symbol_id = Some(ty.id); - } - }, - Annotation::TypePath(parts) => { - match self.follow_type_path(&iter, parts) { - // '/datum/proc/foo' - Some(completion::TypePathResult { ty, decl: _, proc: Some((proc_name, _)) }) => { - if let Some(decl) = ty.get_proc_declaration(proc_name) { - symbol_id = Some(decl.id); + Annotation::Variable(path) => { + let mut current = self.objtree.root(); + let (var_name, most) = path.split_last().unwrap(); + for part in most { + if part == "var" { break } + if let Some(child) = current.child(part) { + current = child; + } else { + break; } - }, - // 'datum/bar' - Some(completion::TypePathResult { ty, decl: None, proc: None }) => { + } + + if let Some(decl) = current.get_var_declaration(var_name) { + symbol_id = Some(decl.id); + } + }, + Annotation::ProcHeader(parts, _) => { + let mut current = self.objtree.root(); + let (proc_name, most) = parts.split_last().unwrap(); + for part in most { + if part == "proc" || part == "verb" { break } + if let Some(child) = current.child(part) { + current = child; + } else { + break; + } + } + + if let Some(decl) = current.get_proc_declaration(proc_name) { + symbol_id = Some(decl.id); + } + }, + Annotation::TreePath(absolute, parts) => { + if let Some(ty) = self.objtree.type_by_path(completion::combine_tree_path(&iter, *absolute, parts)) { symbol_id = Some(ty.id); - }, - _ => {} - } - }, - Annotation::UnscopedCall(proc_name) => { - let (ty, _) = self.find_type_context(&iter); - let mut next = ty.or_else(|| Some(self.objtree.root())); - while let Some(ty) = next { - if let Some(proc) = ty.procs.get(proc_name) { - if let Some(ref decl) = proc.declaration { - symbol_id = Some(decl.id); - break; - } } - next = ty.parent_type(); - } - }, - Annotation::UnscopedVar(var_name) => { - let (ty, proc_name) = self.find_type_context(&iter); - match self.find_unscoped_var(&iter, ty, proc_name, var_name) { - UnscopedVar::Parameter { .. } => { - // TODO - }, - UnscopedVar::Variable { ty, .. } => { - if let Some(decl) = ty.get_var_declaration(var_name) { - symbol_id = Some(decl.id); - } - }, - UnscopedVar::Local { .. } => { - // TODO - }, - UnscopedVar::None => {} - } - }, - Annotation::ScopedCall(priors, proc_name) => { - let mut next = self.find_scoped_type(&iter, priors); - while let Some(ty) = next { - if let Some(proc) = ty.procs.get(proc_name) { - if let Some(ref decl) = proc.declaration { - symbol_id = Some(decl.id); - break; - } + }, + Annotation::TypePath(parts) => { + match self.follow_type_path(&iter, parts) { + // '/datum/proc/foo' + Some(completion::TypePathResult { ty, decl: _, proc: Some((proc_name, _)) }) => { + if let Some(decl) = ty.get_proc_declaration(proc_name) { + symbol_id = Some(decl.id); + } + }, + // 'datum/bar' + Some(completion::TypePathResult { ty, decl: None, proc: None }) => { + symbol_id = Some(ty.id); + }, + _ => {} } - next = ty.parent_type_without_root(); - } - }, - Annotation::ScopedVar(priors, var_name) => { - let mut next = self.find_scoped_type(&iter, priors); - while let Some(ty) = next { - if let Some(var) = ty.vars.get(var_name) { - if let Some(ref decl) = var.declaration { - symbol_id = Some(decl.id); - break; + }, + Annotation::UnscopedCall(proc_name) => { + let (ty, _) = self.find_type_context(&iter); + let mut next = ty.or_else(|| Some(self.objtree.root())); + while let Some(ty) = next { + if let Some(proc) = ty.procs.get(proc_name) { + if let Some(ref decl) = proc.declaration { + symbol_id = Some(decl.id); + break; + } } + next = ty.parent_type(); } - next = ty.parent_type_without_root(); - } - }, - // TODO: macros + }, + Annotation::UnscopedVar(var_name) => { + let (ty, proc_name) = self.find_type_context(&iter); + match self.find_unscoped_var(&iter, ty, proc_name, var_name) { + UnscopedVar::Parameter { .. } => { + // TODO + }, + UnscopedVar::Variable { ty, .. } => { + if let Some(decl) = ty.get_var_declaration(var_name) { + symbol_id = Some(decl.id); + } + }, + UnscopedVar::Local { .. } => { + // TODO + }, + UnscopedVar::None => {} + } + }, + Annotation::ScopedCall(priors, proc_name) => { + let mut next = self.find_scoped_type(&iter, priors); + while let Some(ty) = next { + if let Some(proc) = ty.procs.get(proc_name) { + if let Some(ref decl) = proc.declaration { + symbol_id = Some(decl.id); + break; + } + } + next = ty.parent_type_without_root(); + } + }, + Annotation::ScopedVar(priors, var_name) => { + let mut next = self.find_scoped_type(&iter, priors); + while let Some(ty) = next { + if let Some(var) = ty.vars.get(var_name) { + if let Some(ref decl) = var.declaration { + symbol_id = Some(decl.id); + break; + } + } + next = ty.parent_type_without_root(); + } + }, + // TODO: macros } Ok(symbol_id) @@ -1437,97 +1437,20 @@ handle_method_call! { let iter = annotations.get_location(location); match_annotation! { iter; - Annotation::TreePath(absolute, parts) => { - let full_path: Vec<&str> = completion::combine_tree_path(&iter, *absolute, parts).collect(); + Annotation::TreePath(absolute, parts) => { + let full_path: Vec<&str> = completion::combine_tree_path(&iter, *absolute, parts).collect(); - if let Some(ty) = self.objtree.type_by_path(full_path.iter().cloned()) { - results.push(self.convert_location(ty.location, &ty.docs, &[&ty.path])?); - } else if let Some((&proc_name, prefix)) = full_path.split_last() { - // If it's not a type, try to find the proc equivalent. Start - // at the parent type so that this is a decent shortcut for - // going to the parent proc. - // TODO: only do this if we're in a ProcHeader. - let mut next = self.objtree.type_by_path(prefix); - if let Some(ty) = next { - next = ty.parent_type(); - } - while let Some(ty) = next { - if let Some(proc) = ty.procs.get(proc_name) { - results.push(self.convert_location(proc.main_value().location, &proc.main_value().docs, &[&ty.path, "/proc/", proc_name])?); - break; - } - next = ty.parent_type(); - } - } - }, - Annotation::TypePath(parts) => { - match self.follow_type_path(&iter, parts) { - // '/datum/proc/foo' - Some(completion::TypePathResult { ty, decl: _, proc: Some((proc_name, proc)) }) => { - results.push(self.convert_location(proc.location, &proc.docs, &[&ty.path, "/proc/", proc_name])?); - }, - // 'datum/bar' - Some(completion::TypePathResult { ty, decl: None, proc: None }) => { + if let Some(ty) = self.objtree.type_by_path(full_path.iter().cloned()) { results.push(self.convert_location(ty.location, &ty.docs, &[&ty.path])?); - }, - _ => {} - } - }, - Annotation::UnscopedCall(proc_name) => { - let (ty, _) = self.find_type_context(&iter); - let mut next = ty.or_else(|| Some(self.objtree.root())); - while let Some(ty) = next { - if let Some(proc) = ty.procs.get(proc_name) { - results.push(self.convert_location(proc.main_value().location, &proc.main_value().docs, &[&ty.path, "/proc/", proc_name])?); - break; - } - next = ty.parent_type(); - } - }, - Annotation::UnscopedVar(var_name) => { - let (ty, proc_name) = self.find_type_context(&iter); - match self.find_unscoped_var(&iter, ty, proc_name, var_name) { - UnscopedVar::Parameter { ty, proc, param } => { - results.push(self.convert_location(param.location, &Default::default(), &[&ty.path, "/proc/", proc])?); - }, - UnscopedVar::Variable { ty, var } => { - results.push(self.convert_location(var.value.location, &var.value.docs, &[&ty.path, "/var/", var_name])?); - }, - UnscopedVar::Local { loc, .. } => { - results.push(self.convert_location(dm::Location { file: real_file_id, ..loc }, &Default::default(), &[])?); - }, - UnscopedVar::None => {} - } - }, - Annotation::ScopedCall(priors, proc_name) => { - let mut next = self.find_scoped_type(&iter, priors); - while let Some(ty) = next { - if let Some(proc) = ty.procs.get(proc_name) { - results.push(self.convert_location(proc.main_value().location, &proc.main_value().docs, &[&ty.path, "/proc/", proc_name])?); - break; - } - next = ty.parent_type_without_root(); - } - }, - Annotation::ScopedVar(priors, var_name) => { - let mut next = self.find_scoped_type(&iter, priors); - while let Some(ty) = next { - if let Some(var) = ty.vars.get(var_name) { - results.push(self.convert_location(var.value.location, &var.value.docs, &[&ty.path, "/var/", var_name])?); - break; - } - next = ty.parent_type_without_root(); - } - }, - Annotation::ParentCall => { - if let (Some(ty), Some((proc_name, idx))) = self.find_type_context(&iter) { - // TODO: idx is always 0 unless there are multiple overrides in - // the same .dm file, due to annotations operating against a - // dummy ObjectTree which does not contain any definitions from - // other files. - if idx == 0 { - // first proc on the type, go to the REAL parent - let mut next = ty.parent_type(); + } else if let Some((&proc_name, prefix)) = full_path.split_last() { + // If it's not a type, try to find the proc equivalent. Start + // at the parent type so that this is a decent shortcut for + // going to the parent proc. + // TODO: only do this if we're in a ProcHeader. + let mut next = self.objtree.type_by_path(prefix); + if let Some(ty) = next { + next = ty.parent_type(); + } while let Some(ty) = next { if let Some(proc) = ty.procs.get(proc_name) { results.push(self.convert_location(proc.main_value().location, &proc.main_value().docs, &[&ty.path, "/proc/", proc_name])?); @@ -1535,17 +1458,94 @@ handle_method_call! { } next = ty.parent_type(); } - } else if let Some(proc) = ty.procs.get(proc_name) { - // override, go to the previous version of the proc - if let Some(parent) = proc.value.get(idx - 1) { - results.push(self.convert_location(parent.location, &parent.docs, &[&ty.path, "/proc/", proc_name])?); + } + }, + Annotation::TypePath(parts) => { + match self.follow_type_path(&iter, parts) { + // '/datum/proc/foo' + Some(completion::TypePathResult { ty, decl: _, proc: Some((proc_name, proc)) }) => { + results.push(self.convert_location(proc.location, &proc.docs, &[&ty.path, "/proc/", proc_name])?); + }, + // 'datum/bar' + Some(completion::TypePathResult { ty, decl: None, proc: None }) => { + results.push(self.convert_location(ty.location, &ty.docs, &[&ty.path])?); + }, + _ => {} + } + }, + Annotation::UnscopedCall(proc_name) => { + let (ty, _) = self.find_type_context(&iter); + let mut next = ty.or_else(|| Some(self.objtree.root())); + while let Some(ty) = next { + if let Some(proc) = ty.procs.get(proc_name) { + results.push(self.convert_location(proc.main_value().location, &proc.main_value().docs, &[&ty.path, "/proc/", proc_name])?); + break; + } + next = ty.parent_type(); + } + }, + Annotation::UnscopedVar(var_name) => { + let (ty, proc_name) = self.find_type_context(&iter); + match self.find_unscoped_var(&iter, ty, proc_name, var_name) { + UnscopedVar::Parameter { ty, proc, param } => { + results.push(self.convert_location(param.location, &Default::default(), &[&ty.path, "/proc/", proc])?); + }, + UnscopedVar::Variable { ty, var } => { + results.push(self.convert_location(var.value.location, &var.value.docs, &[&ty.path, "/var/", var_name])?); + }, + UnscopedVar::Local { loc, .. } => { + results.push(self.convert_location(dm::Location { file: real_file_id, ..loc }, &Default::default(), &[])?); + }, + UnscopedVar::None => {} + } + }, + Annotation::ScopedCall(priors, proc_name) => { + let mut next = self.find_scoped_type(&iter, priors); + while let Some(ty) = next { + if let Some(proc) = ty.procs.get(proc_name) { + results.push(self.convert_location(proc.main_value().location, &proc.main_value().docs, &[&ty.path, "/proc/", proc_name])?); + break; + } + next = ty.parent_type_without_root(); + } + }, + Annotation::ScopedVar(priors, var_name) => { + let mut next = self.find_scoped_type(&iter, priors); + while let Some(ty) = next { + if let Some(var) = ty.vars.get(var_name) { + results.push(self.convert_location(var.value.location, &var.value.docs, &[&ty.path, "/var/", var_name])?); + break; + } + next = ty.parent_type_without_root(); + } + }, + Annotation::ParentCall => { + if let (Some(ty), Some((proc_name, idx))) = self.find_type_context(&iter) { + // TODO: idx is always 0 unless there are multiple overrides in + // the same .dm file, due to annotations operating against a + // dummy ObjectTree which does not contain any definitions from + // other files. + if idx == 0 { + // first proc on the type, go to the REAL parent + let mut next = ty.parent_type(); + while let Some(ty) = next { + if let Some(proc) = ty.procs.get(proc_name) { + results.push(self.convert_location(proc.main_value().location, &proc.main_value().docs, &[&ty.path, "/proc/", proc_name])?); + break; + } + next = ty.parent_type(); + } + } else if let Some(proc) = ty.procs.get(proc_name) { + // override, go to the previous version of the proc + if let Some(parent) = proc.value.get(idx - 1) { + results.push(self.convert_location(parent.location, &parent.docs, &[&ty.path, "/proc/", proc_name])?); + } } } - } - }, - Annotation::MacroUse { name, definition_location, .. } => { - results.push(self.convert_location(*definition_location, &Default::default(), &["/DM/preprocessor/", name])?); - }, + }, + Annotation::MacroUse { name, definition_location, .. } => { + results.push(self.convert_location(*definition_location, &Default::default(), &["/DM/preprocessor/", name])?); + }, } if results.is_empty() { @@ -1569,35 +1569,35 @@ handle_method_call! { let iter = annotations.get_location(location); match_annotation! { iter; - Annotation::UnscopedVar(var_name) => { - let (ty, proc_name) = self.find_type_context(&iter); - match self.find_unscoped_var(&iter, ty, proc_name, var_name) { - UnscopedVar::Parameter { param, .. } => { - type_path = ¶m.var_type.type_path; - }, - UnscopedVar::Variable { ty, .. } => { - if let Some(decl) = ty.get_var_declaration(var_name) { - type_path = &decl.var_type.type_path; - } - }, - UnscopedVar::Local { var_type, .. } => { - type_path = &var_type.type_path; - }, - UnscopedVar::None => {} - } - }, - Annotation::ScopedVar(priors, var_name) => { - let mut next = self.find_scoped_type(&iter, priors); - while let Some(ty) = next { - if let Some(var) = ty.get().vars.get(var_name) { - if let Some(ref decl) = var.declaration { - type_path = &decl.var_type.type_path; - break; - } + Annotation::UnscopedVar(var_name) => { + let (ty, proc_name) = self.find_type_context(&iter); + match self.find_unscoped_var(&iter, ty, proc_name, var_name) { + UnscopedVar::Parameter { param, .. } => { + type_path = ¶m.var_type.type_path; + }, + UnscopedVar::Variable { ty, .. } => { + if let Some(decl) = ty.get_var_declaration(var_name) { + type_path = &decl.var_type.type_path; + } + }, + UnscopedVar::Local { var_type, .. } => { + type_path = &var_type.type_path; + }, + UnscopedVar::None => {} } - next = ty.parent_type_without_root(); - } - }, + }, + Annotation::ScopedVar(priors, var_name) => { + let mut next = self.find_scoped_type(&iter, priors); + while let Some(ty) = next { + if let Some(var) = ty.get().vars.get(var_name) { + if let Some(ref decl) = var.declaration { + type_path = &decl.var_type.type_path; + break; + } + } + next = ty.parent_type_without_root(); + } + }, } if type_path.is_empty() { From 00df33a0937ada6949c64b2c2de71755e93d47db Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Wed, 1 Feb 2023 19:05:09 -0800 Subject: [PATCH 027/197] Bump versions for suite 1.7.3 --- Cargo.lock | 8 ++++---- crates/dm-langserver/Cargo.toml | 2 +- crates/dmdoc/Cargo.toml | 2 +- crates/dmm-tools-cli/Cargo.toml | 2 +- crates/dreamchecker/Cargo.toml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 32be9b7c..a27a95ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -346,7 +346,7 @@ dependencies = [ [[package]] name = "dm-langserver" -version = "1.5.1" +version = "1.7.3" dependencies = [ "ahash 0.8.0", "bincode", @@ -370,7 +370,7 @@ dependencies = [ [[package]] name = "dmdoc" -version = "1.4.1" +version = "1.7.3" dependencies = [ "chrono", "dreammaker", @@ -404,7 +404,7 @@ dependencies = [ [[package]] name = "dmm-tools-cli" -version = "1.3.1" +version = "1.7.3" dependencies = [ "ahash 0.8.0", "chrono", @@ -430,7 +430,7 @@ dependencies = [ [[package]] name = "dreamchecker" -version = "1.7.1" +version = "1.7.3" dependencies = [ "ahash 0.8.0", "chrono", diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index fc91c987..56fb6e64 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dm-langserver" -version = "1.5.1" +version = "1.7.3" authors = ["Tad Hardesty "] edition = "2018" diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index b2186f4e..e1b3775d 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dmdoc" -version = "1.4.1" +version = "1.7.3" authors = ["Tad Hardesty "] homepage = "https://github.com/SpaceManiac/SpacemanDMM/blob/master/crates/dmdoc/README.md" edition = "2018" diff --git a/crates/dmm-tools-cli/Cargo.toml b/crates/dmm-tools-cli/Cargo.toml index 55a1471d..e560c042 100644 --- a/crates/dmm-tools-cli/Cargo.toml +++ b/crates/dmm-tools-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dmm-tools-cli" -version = "1.3.1" +version = "1.7.3" authors = ["Tad Hardesty "] description = "BYOND map rendering and analysis tools powered by SpacemanDMM" edition = "2018" diff --git a/crates/dreamchecker/Cargo.toml b/crates/dreamchecker/Cargo.toml index a439a13d..ca3649cd 100644 --- a/crates/dreamchecker/Cargo.toml +++ b/crates/dreamchecker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dreamchecker" -version = "1.7.1" +version = "1.7.3" authors = ["Tad Hardesty "] edition = "2018" From d37df4c7c2519647419e80892fe23aa9a1121995 Mon Sep 17 00:00:00 2001 From: Penelope Haze Date: Sat, 8 Apr 2023 01:10:55 -0500 Subject: [PATCH 028/197] Update dreammaker crate readme to use proper subdomain (#352) Lummox says you shouldn't use the `secure` subdomain for the BYOND forums. --- crates/dreammaker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/dreammaker/README.md b/crates/dreammaker/README.md index 93ddb33b..b11fae37 100644 --- a/crates/dreammaker/README.md +++ b/crates/dreammaker/README.md @@ -15,4 +15,4 @@ core component of SpacemanDMM and powers the rest of the tooling. * Non-constant initial values for object variables. * Integer constants which are outside of range. -[2072419]: https://secure.byond.com/forum/?post=2072419 \ No newline at end of file +[2072419]: https://www.byond.com/forum/?post=2072419 From 56cd51d04ce132cb4f273106788f03cb94ea5743 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Fri, 7 Apr 2023 23:12:25 -0700 Subject: [PATCH 029/197] Swap secure.byond.com URLs to www.byond.com --- README.md | 2 +- crates/dmdoc/README.md | 2 +- crates/dmdoc/src/main.rs | 2 +- crates/dmm-tools/src/dmm.rs | 4 ++-- crates/dreamchecker/README.md | 2 +- crates/dreammaker/src/preprocessor.rs | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7bb5208a..890f8bb3 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ integration build; see [/tg/station's CI suite][ci] for an example. Support is currently provided in /tg/station13's coderbus (ping `SpaceManiac`) and on the [issue tracker]. Pull requests are welcome. -[DreamMaker]: https://secure.byond.com/ +[DreamMaker]: https://www.byond.com/ [language server]: https://langserver.org/ [releases]: https://github.com/SpaceManiac/SpacemanDMM/releases [ci]: https://github.com/tgstation/tgstation/blob/master/.github/workflows/ci_suite.yml#L45 diff --git a/crates/dmdoc/README.md b/crates/dmdoc/README.md index a89e62d6..2342d348 100644 --- a/crates/dmdoc/README.md +++ b/crates/dmdoc/README.md @@ -4,7 +4,7 @@ of the [BYOND] game engine. It produces simple static HTML files based on documented files, macros, types, procs, and vars. -[BYOND]: https://secure.byond.com/ +[BYOND]: https://www.byond.com/ If dmdoc is run in a Git repository, web links to source code are placed next to item headings in the generated output; otherwise, file and line numbers are diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 9a80a5e6..04a17652 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -32,7 +32,7 @@ const BUILD_INFO: &str = concat!( "General Public License version 3.", ); -const DM_REFERENCE_BASE: &str = "https://secure.byond.com/docs/ref/#"; +const DM_REFERENCE_BASE: &str = "https://www.byond.com/docs/ref/#"; // ---------------------------------------------------------------------------- // Driver diff --git a/crates/dmm-tools/src/dmm.rs b/crates/dmm-tools/src/dmm.rs index 5f2ab6c1..3519d393 100644 --- a/crates/dmm-tools/src/dmm.rs +++ b/crates/dmm-tools/src/dmm.rs @@ -18,7 +18,7 @@ mod save_tgm; const MAX_KEY_LENGTH: u8 = 3; /// BYOND is currently limited to 65534 keys. -/// https://secure.byond.com/forum/?post=2340796#comment23770802 +/// https://www.byond.com/forum/?post=2340796#comment23770802 type KeyType = u16; /// An opaque map key. @@ -344,7 +344,7 @@ fn base_52_reverse(ch: u8) -> Result { fn advance_key(current: KeyType, next_digit: KeyType) -> Result { current.checked_mul(52).and_then(|b| b.checked_add(next_digit)).ok_or({ - // https://secure.byond.com/forum/?post=2340796#comment23770802 + // https://www.byond.com/forum/?post=2340796#comment23770802 "Key overflow, max is 'ymo'" }) } diff --git a/crates/dreamchecker/README.md b/crates/dreamchecker/README.md index 7af0d2e6..0e945142 100644 --- a/crates/dreamchecker/README.md +++ b/crates/dreamchecker/README.md @@ -3,7 +3,7 @@ **DreamChecker** is a robust whole-program static analysis and type checking engine for DreamMaker, the scripting language of the [BYOND] game engine. -[BYOND]: https://secure.byond.com/ +[BYOND]: https://www.byond.com/ ## Running DreamChecker diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index 0cdfa11a..a12a3bd5 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -669,7 +669,7 @@ impl<'ctx> Preprocessor<'ctx> { if let Some(loc) = self.danger_idents.get(name) { self.context.register_error(DMError::new(*loc, format!( "macro {:?} used immediately before being {}:\n\ - https://secure.byond.com/forum/?post=2072419", name, kind + https://www.byond.com/forum/?post=2072419", name, kind )).set_severity(Severity::Warning)); } } @@ -1211,7 +1211,7 @@ impl<'ctx> Iterator for Preprocessor<'ctx> { } if let Some(tok) = self.inner_next() { - // linting for https://secure.byond.com/forum/?post=2072419 + // linting for https://www.byond.com/forum/?post=2072419 if !tok.token.is_whitespace() && tok.token != Token::Punct(Punctuation::Hash) { if tok.location.file != self.last_printable_input_loc.file || tok.location.line > self.last_printable_input_loc.line From 20dec28f21bcdb7ad81a057009e0e96fc2e2cf87 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 20 Apr 2023 17:00:28 -0700 Subject: [PATCH 030/197] Fix a missed secure.byond.com reference --- crates/dm-langserver/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/dm-langserver/README.md b/crates/dm-langserver/README.md index 52ba590b..9835e38e 100644 --- a/crates/dm-langserver/README.md +++ b/crates/dm-langserver/README.md @@ -12,7 +12,7 @@ client support. compatible. [language server]: https://langserver.org/ -[BYOND]: https://secure.byond.com/ +[BYOND]: https://www.byond.com/ ## Code completion From 7a23489a3bacb82694ff425a376444448aa2e219 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 20 Apr 2023 17:11:21 -0700 Subject: [PATCH 031/197] Run cargo update --- Cargo.lock | 720 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 474 insertions(+), 246 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a27a95ce..5781e9e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,20 +16,9 @@ checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] name = "ahash" -version = "0.7.6" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "ahash" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57e6e951cfbb2db8de1828d49073a113a29fd7117b1596caa781a258c7e38d72" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if", "getrandom", @@ -39,9 +28,18 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.19" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "aho-corasick" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bce8d450891e3b36f85a2230cec441fddd60e0c455b61b15bb3ffba955ca85" dependencies = [ "memchr", ] @@ -70,7 +68,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -98,20 +96,21 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "block-buffer" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "bstr" -version = "0.2.17" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" dependencies = [ "memchr", + "serde", ] [[package]] @@ -120,40 +119,40 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "bytemuck" -version = "1.12.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.2.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9e1f5fa78f69496407a27ae9ed989e3c3b072310286f5ef385525e4cbc24a9" +checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] name = "cc" -version = "1.0.73" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", ] @@ -166,9 +165,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.22" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" dependencies = [ "iana-time-zone", "js-sys", @@ -181,23 +180,23 @@ dependencies = [ [[package]] name = "chrono-tz" -version = "0.6.3" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c39203181991a7dd4343b8005bd804e7a9a37afb8ac070e43771e8c820bbde" +checksum = "58549f1842da3080ce63002102d5bc954c7bc843d4f47818e642abdc36253552" dependencies = [ "chrono", "chrono-tz-build", - "phf", + "phf 0.10.1", ] [[package]] name = "chrono-tz-build" -version = "0.0.3" +version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f509c3a87b33437b05e2458750a0700e5bdd6956176773e6c7d6dd15a283a0c" +checksum = "db058d493fb2f65f41861bfed7e3fe6335264a9f0f92710cab5bdf01fef09069" dependencies = [ "parse-zoneinfo", - "phf", + "phf 0.10.1", "phf_codegen", ] @@ -216,6 +215,16 @@ dependencies = [ "vec_map", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -230,15 +239,15 @@ checksum = "3776b2bcc4e914db501bb9be9572dd706e344b9eb8f882894f3daa651d281381" [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" dependencies = [ "libc", ] @@ -254,9 +263,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" dependencies = [ "cfg-if", "crossbeam-utils", @@ -264,9 +273,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -275,26 +284,24 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.10" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", "memoffset", - "once_cell", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.11" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" dependencies = [ "cfg-if", - "once_cell", ] [[package]] @@ -307,11 +314,55 @@ dependencies = [ "typenum", ] +[[package]] +name = "cxx" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn 2.0.15", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.15", +] + [[package]] name = "dap-types" version = "0.0.0" dependencies = [ - "ahash 0.8.0", + "ahash", "serde", "serde_derive", "serde_json", @@ -325,7 +376,7 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -336,9 +387,9 @@ checksum = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690" [[package]] name = "digest" -version = "0.10.3" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer", "crypto-common", @@ -348,7 +399,7 @@ dependencies = [ name = "dm-langserver" version = "1.7.3" dependencies = [ - "ahash 0.8.0", + "ahash", "bincode", "chrono", "dap-types", @@ -386,7 +437,7 @@ dependencies = [ name = "dmm-tools" version = "0.1.0" dependencies = [ - "ahash 0.8.0", + "ahash", "bumpalo", "bytemuck", "dreammaker", @@ -406,7 +457,7 @@ dependencies = [ name = "dmm-tools-cli" version = "1.7.3" dependencies = [ - "ahash 0.8.0", + "ahash", "chrono", "dmm-tools", "dreammaker", @@ -432,7 +483,7 @@ dependencies = [ name = "dreamchecker" version = "1.7.3" dependencies = [ - "ahash 0.8.0", + "ahash", "chrono", "dreammaker", "git2", @@ -444,7 +495,7 @@ dependencies = [ name = "dreammaker" version = "0.1.0" dependencies = [ - "ahash 0.8.0", + "ahash", "bitflags", "builtins-proc-macro", "color_space", @@ -454,7 +505,7 @@ dependencies = [ "interval-tree", "lodepng", "ordered-float", - "phf", + "phf 0.11.1", "serde", "serde_derive", "termcolor", @@ -464,27 +515,36 @@ dependencies = [ [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "fallible_collections" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c195cf4b2285d3c993eb887b4dc56b0d5728bbe1d0f9a99c0ac6bec2da3e4d85" +checksum = "9acf77205554f3cfeca94a4b910e159ad9824e8c2d164de02b3f12495cc1074d" dependencies = [ - "hashbrown", + "hashbrown 0.13.2", +] + +[[package]] +name = "fdeflate" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +dependencies = [ + "simd-adler32", ] [[package]] name = "flate2" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.6.2", ] [[package]] @@ -504,9 +564,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.24" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", @@ -519,9 +579,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.24" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", "futures-sink", @@ -529,15 +589,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.24" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-executor" -version = "0.3.24" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" dependencies = [ "futures-core", "futures-task", @@ -546,38 +606,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.24" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-macro" -version = "0.3.24" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] name = "futures-sink" -version = "0.3.24" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "futures-task" -version = "0.3.24" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-util" -version = "0.3.24" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-channel", "futures-core", @@ -593,9 +653,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -612,9 +672,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" dependencies = [ "cfg-if", "libc", @@ -657,11 +717,11 @@ dependencies = [ [[package]] name = "globset" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ - "aho-corasick", + "aho-corasick 0.7.20", "bstr", "fnv", "log", @@ -690,8 +750,14 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.7.6", + "ahash", ] [[package]] @@ -713,23 +779,45 @@ dependencies = [ ] [[package]] -name = "humansize" -version = "1.1.1" +name = "hermit-abi" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "humansize" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" +dependencies = [ + "libm", +] [[package]] name = "iana-time-zone" -version = "0.1.48" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237a0714f28b1ee39ccec0770ccb544eb02c9ef2c82bb096230eefcffa6468b0" +checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" dependencies = [ "android_system_properties", "core-foundation-sys", + "iana-time-zone-haiku", "js-sys", - "once_cell", "wasm-bindgen", - "winapi", + "windows", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", ] [[package]] @@ -744,11 +832,10 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.18" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d" +checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" dependencies = [ - "crossbeam-utils", "globset", "lazy_static", "log", @@ -762,12 +849,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", ] [[package]] @@ -788,24 +875,24 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.3" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "jobserver" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] @@ -833,9 +920,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.132" +version = "0.2.142" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" +checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" [[package]] name = "libgit2-sys" @@ -849,6 +936,12 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libm" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" + [[package]] name = "libz-sys" version = "1.1.8" @@ -862,10 +955,19 @@ dependencies = [ ] [[package]] -name = "lodepng" -version = "3.7.0" +name = "link-cplusplus" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff45534ec797452c044fcd47861059eddb501e30a8fd9fdadea7957cdff3ebc7" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + +[[package]] +name = "lodepng" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0ad39f75bbaa4b10bb6f2316543632a8046a5bcf9c785488d79720b21f044f8" dependencies = [ "crc32fast", "fallible_collections", @@ -885,9 +987,9 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.93.1" +version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3bcfee315dde785ba887edb540b08765fd7df75a7d948844be6bf5712246734" +checksum = "9be6e9c7e2d18f651974370d7aff703f9513e0df6e464fd795660edc77e6ca51" dependencies = [ "bitflags", "serde", @@ -898,9 +1000,9 @@ dependencies = [ [[package]] name = "matrixmultiply" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add85d4dd35074e6fedc608f8c8f513a3548619a9024b751949ef0e8e45a4d84" +checksum = "bb99c395ae250e1bf9133673f03ca9f97b7e71b705436bf8f089453445d1e9fe" dependencies = [ "rawpointer", ] @@ -913,22 +1015,32 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" -version = "0.6.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" dependencies = [ "autocfg", ] [[package]] name = "miniz_oxide" -version = "0.5.4" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", + "simd-adler32", +] + [[package]] name = "ndarray" version = "0.15.6" @@ -944,9 +1056,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" +checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" dependencies = [ "num-traits", ] @@ -972,25 +1084,25 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] [[package]] name = "once_cell" -version = "1.14.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "ordered-float" -version = "3.0.0" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bcbab4bfea7a59c2c0fe47211a1ac4e3e96bea6eb446d704f310bc5c732ae2" +checksum = "13a384337e997e6860ffbaa83708b2ef329fd8c54cb67a5f64d421e0f943254f" dependencies = [ "num-traits", ] @@ -1012,9 +1124,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.3.1" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb779fcf4bb850fbbb0edc96ff6cf34fd90c4b1a112ce042653280d9a7364048" +checksum = "7b1403e8401ad5dedea73c626b99758535b342502f8d1e361f4a2dd952749122" dependencies = [ "thiserror", "ucd-trie", @@ -1022,9 +1134,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.3.1" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "502b62a6d0245378b04ffe0a7fb4f4419a4815fce813bd8a0ec89a56e07d67b1" +checksum = "be99c4c1d2fc2769b1d00239431d711d08f6efedcecb8b6e30707160aee99c15" dependencies = [ "pest", "pest_generator", @@ -1032,26 +1144,35 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.3.1" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451e629bf49b750254da26132f1a5a9d11fd8a95a3df51d15c4abd1ba154cb6c" +checksum = "e56094789873daa36164de2e822b3888c6ae4b4f9da555a1103587658c805b1e" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] name = "pest_meta" -version = "2.3.1" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec162c71c45e269dfc3fc2916eaeb97feab22993a21bcce4721d08cd7801a6" +checksum = "6733073c7cff3d8459fda0e42f13a047870242aed8b509fe98000928975f359e" dependencies = [ "once_cell", "pest", - "sha1", + "sha2", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", ] [[package]] @@ -1061,17 +1182,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" dependencies = [ "phf_macros", - "phf_shared", + "phf_shared 0.11.1", ] [[package]] name = "phf_codegen" -version = "0.11.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", ] [[package]] @@ -1080,7 +1211,7 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" dependencies = [ - "phf_shared", + "phf_shared 0.11.1", "rand", ] @@ -1090,11 +1221,21 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92aacdc5f16768709a569e913f7451034034178b05bdc8acda226659a3dccc66" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.11.1", + "phf_shared 0.11.1", "proc-macro2", "quote", - "syn", + "syn 1.0.109", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", + "uncased", ] [[package]] @@ -1104,7 +1245,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" dependencies = [ "siphasher", - "uncased", ] [[package]] @@ -1121,27 +1261,28 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "png" -version = "0.17.6" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f0e7f4c94ec26ff209cee506314212639d6c91b80afb82984819fafce9df01c" +checksum = "aaeebc51f9e7d2c150d3f3bfeb667f2aa985db5ef1e3d212847bdedb488beeaa" dependencies = [ "bitflags", "crc32fast", + "fdeflate", "flate2", - "miniz_oxide", + "miniz_oxide 0.7.1", ] [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro-error" @@ -1152,7 +1293,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "version_check", ] @@ -1169,9 +1310,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.43" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ "unicode-ident", ] @@ -1190,9 +1331,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.21" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] @@ -1220,9 +1361,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] @@ -1235,21 +1376,19 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" -version = "1.5.3" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" dependencies = [ - "autocfg", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -1259,35 +1398,35 @@ dependencies = [ [[package]] name = "regex" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "ac6cf59af1067a3fb53fbe5c88c053764e930f932be1d71d3ffe032cbe147f59" dependencies = [ - "aho-corasick", + "aho-corasick 1.0.0", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "b6868896879ba532248f33598de5181522d8b3d9d724dfd230911e1a7d4822f5" [[package]] name = "rgb" -version = "0.8.33" +version = "0.8.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3b221de559e4a29df3b957eec92bc0de6bc8eaf6ca9cfed43e5e1d67ff65a34" +checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" dependencies = [ "bytemuck", ] [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "same-file" @@ -1305,30 +1444,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] -name = "serde" -version = "1.0.144" +name = "scratch" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" +checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" + +[[package]] +name = "serde" +version = "1.0.160" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.144" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" +checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] name = "serde_json" -version = "1.0.85" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ "itoa", "ryu", @@ -1337,26 +1482,32 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.9" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca" +checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] -name = "sha1" -version = "0.10.4" +name = "sha2" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006769ba83e921b3085caa8334186b00cf92b4cb1a6cf4632fbccc8eff5c7549" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if", "cpufeatures", "digest", ] +[[package]] +name = "simd-adler32" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f" + [[package]] name = "siphasher" version = "0.3.10" @@ -1365,9 +1516,9 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "slab" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg", ] @@ -1408,14 +1559,25 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "syn" -version = "1.0.99" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" dependencies = [ "proc-macro2", "quote", @@ -1424,9 +1586,9 @@ dependencies = [ [[package]] name = "tera" -version = "1.17.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d4685e72cb35f0eb74319c8fe2d3b61e93da5609841cde2cb87fcc3bea56d20" +checksum = "95a665751302f22a03c56721e23094e4dc22b04a80f381e6737a07bf7a7c70c0" dependencies = [ "chrono", "chrono-tz", @@ -1441,14 +1603,15 @@ dependencies = [ "serde", "serde_json", "slug", + "thread_local", "unic-segment", ] [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] @@ -1464,22 +1627,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.35" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.35" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] @@ -1493,9 +1656,9 @@ dependencies = [ [[package]] name = "time" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", @@ -1513,24 +1676,24 @@ dependencies = [ [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "ucd-trie" @@ -1608,30 +1771,30 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.4" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "unicode-normalization" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" @@ -1671,12 +1834,11 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" dependencies = [ "same-file", - "winapi", "winapi-util", ] @@ -1694,9 +1856,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1704,24 +1866,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1729,22 +1891,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "weezl" @@ -1782,3 +1944,69 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" From 3be92a95ae13cfc983618d37d8bc67a8f1159e88 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 20 Apr 2023 17:20:20 -0700 Subject: [PATCH 032/197] Fix deprecation warning for chrono::Utc::today --- crates/dm-langserver/build.rs | 2 +- crates/dmdoc/build.rs | 2 +- crates/dmm-tools-cli/build.rs | 2 +- crates/dreamchecker/build.rs | 2 +- crates/spaceman-dmm/build.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/dm-langserver/build.rs b/crates/dm-langserver/build.rs index 91478f6e..ecc971fb 100644 --- a/crates/dm-langserver/build.rs +++ b/crates/dm-langserver/build.rs @@ -15,7 +15,7 @@ fn main() { Ok(commit) => writeln!(f, "commit: {}", commit).unwrap(), Err(err) => println!("cargo:warning=Failed to fetch commit info: {}", err) } - writeln!(f, "build date: {}", chrono::Utc::today()).unwrap(); + writeln!(f, "build date: {}", chrono::Utc::now().date_naive()).unwrap(); // extools bundling println!("cargo:rerun-if-env-changed=EXTOOLS_BUNDLE_DLL"); diff --git a/crates/dmdoc/build.rs b/crates/dmdoc/build.rs index 71c828bd..cc4979da 100644 --- a/crates/dmdoc/build.rs +++ b/crates/dmdoc/build.rs @@ -13,7 +13,7 @@ fn main() { if let Ok(commit) = read_commit() { writeln!(f, "commit: {}", commit).unwrap(); } - writeln!(f, "build date: {}", chrono::Utc::today()).unwrap(); + writeln!(f, "build date: {}", chrono::Utc::now().date_naive()).unwrap(); } fn read_commit() -> Result { diff --git a/crates/dmm-tools-cli/build.rs b/crates/dmm-tools-cli/build.rs index 71c828bd..cc4979da 100644 --- a/crates/dmm-tools-cli/build.rs +++ b/crates/dmm-tools-cli/build.rs @@ -13,7 +13,7 @@ fn main() { if let Ok(commit) = read_commit() { writeln!(f, "commit: {}", commit).unwrap(); } - writeln!(f, "build date: {}", chrono::Utc::today()).unwrap(); + writeln!(f, "build date: {}", chrono::Utc::now().date_naive()).unwrap(); } fn read_commit() -> Result { diff --git a/crates/dreamchecker/build.rs b/crates/dreamchecker/build.rs index 71c828bd..cc4979da 100644 --- a/crates/dreamchecker/build.rs +++ b/crates/dreamchecker/build.rs @@ -13,7 +13,7 @@ fn main() { if let Ok(commit) = read_commit() { writeln!(f, "commit: {}", commit).unwrap(); } - writeln!(f, "build date: {}", chrono::Utc::today()).unwrap(); + writeln!(f, "build date: {}", chrono::Utc::now().date_naive()).unwrap(); } fn read_commit() -> Result { diff --git a/crates/spaceman-dmm/build.rs b/crates/spaceman-dmm/build.rs index fa2ca3cf..6c6dfba1 100644 --- a/crates/spaceman-dmm/build.rs +++ b/crates/spaceman-dmm/build.rs @@ -15,7 +15,7 @@ fn main() { if let Ok(commit) = read_commit() { writeln!(f, "commit: {}", commit).unwrap(); } - writeln!(f, "build date: {}", chrono::Utc::today()).unwrap(); + writeln!(f, "build date: {}", chrono::Utc::now().date_naive()).unwrap(); // windres icon if cfg!(windows) { From 037f28d766895df6078adfee6d62a75250f4055f Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 20 Apr 2023 17:21:03 -0700 Subject: [PATCH 033/197] Update year in --version messages --- crates/dm-langserver/src/main.rs | 2 +- crates/dmdoc/src/main.rs | 2 +- crates/dmm-tools-cli/src/main.rs | 2 +- crates/dreamchecker/src/main.rs | 2 +- crates/spaceman-dmm/src/main.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index c4747de6..18f1b520 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -53,7 +53,7 @@ fn main() { std::env::set_var("RUST_BACKTRACE", "1"); eprintln!( - "dm-langserver {} Copyright (C) 2017-2021 Tad Hardesty", + "dm-langserver {} Copyright (C) 2017-2023 Tad Hardesty", env!("CARGO_PKG_VERSION") ); eprintln!("This program comes with ABSOLUTELY NO WARRANTY. This is free software,"); diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 04a17652..412aadee 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -25,7 +25,7 @@ use dm::docs::*; use markdown::DocBlock; const BUILD_INFO: &str = concat!( - "dmdoc ", env!("CARGO_PKG_VERSION"), " Copyright (C) 2017-2021 Tad Hardesty\n", + "dmdoc ", env!("CARGO_PKG_VERSION"), " Copyright (C) 2017-2023 Tad Hardesty\n", include_str!(concat!(env!("OUT_DIR"), "/build-info.txt")), "\n", "This program comes with ABSOLUTELY NO WARRANTY. This is free software,\n", "and you are welcome to redistribute it under the conditions of the GNU\n", diff --git a/crates/dmm-tools-cli/src/main.rs b/crates/dmm-tools-cli/src/main.rs index f2949d00..1d686128 100644 --- a/crates/dmm-tools-cli/src/main.rs +++ b/crates/dmm-tools-cli/src/main.rs @@ -92,7 +92,7 @@ impl Context { #[derive(StructOpt, Debug)] #[structopt(name="dmm-tools", -author="Copyright (C) 2017-2021 Tad Hardesty", +author="Copyright (C) 2017-2023 Tad Hardesty", about="This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under the conditions of the GNU General Public License version 3.")] diff --git a/crates/dreamchecker/src/main.rs b/crates/dreamchecker/src/main.rs index 204383a8..3114321b 100644 --- a/crates/dreamchecker/src/main.rs +++ b/crates/dreamchecker/src/main.rs @@ -21,7 +21,7 @@ fn main() { while let Some(arg) = args.next() { if arg == "-V" || arg == "--version" { println!( - "dreamchecker {} Copyright (C) 2017-2021 Tad Hardesty", + "dreamchecker {} Copyright (C) 2017-2023 Tad Hardesty", env!("CARGO_PKG_VERSION") ); println!("{}", include_str!(concat!(env!("OUT_DIR"), "/build-info.txt"))); diff --git a/crates/spaceman-dmm/src/main.rs b/crates/spaceman-dmm/src/main.rs index 47ed799e..1d50829a 100644 --- a/crates/spaceman-dmm/src/main.rs +++ b/crates/spaceman-dmm/src/main.rs @@ -590,7 +590,7 @@ impl EditorScene { ui.menu(im_str!("Help"), true, || { ui.menu(im_str!("About SpacemanDMM"), true, || { ui.text(&im_str!( - "{} {} Copyright (C) 2017-2021 Tad Hardesty", + "{} {} Copyright (C) 2017-2023 Tad Hardesty", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"), )); From e5c7b9fcb5badb6d3622e3c2fbc15ecc75830565 Mon Sep 17 00:00:00 2001 From: willox Date: Fri, 21 Apr 2023 06:42:11 +0100 Subject: [PATCH 034/197] Add call_ext()() support for BYOND 515 (#353) --- crates/dm-langserver/src/find_references.rs | 6 +++++ crates/dreamchecker/src/lib.rs | 10 +++++-- crates/dreamchecker/tests/call_ext_tests.rs | 29 +++++++++++++++++++++ crates/dreammaker/src/ast.rs | 6 +++++ crates/dreammaker/src/parser.rs | 15 +++++++++++ 5 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 crates/dreamchecker/tests/call_ext_tests.rs diff --git a/crates/dm-langserver/src/find_references.rs b/crates/dm-langserver/src/find_references.rs index 242b73a8..44b5f04f 100644 --- a/crates/dm-langserver/src/find_references.rs +++ b/crates/dm-langserver/src/find_references.rs @@ -520,6 +520,12 @@ impl<'o> WalkProc<'o> { self.visit_arguments(location, args_2); StaticType::None }, + Term::ExternalCall { library_name, function_name, args } => { + self.visit_expression(location, library_name, None); + self.visit_expression(location, function_name, None); + self.visit_arguments(location, args); + StaticType::None + }, } } diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 6173615c..061dd709 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -692,7 +692,7 @@ impl<'o> AnalyzeObjectTree<'o> { .with_blocking_builtins(self.sleeping_procs.get_violators(*child_violator).unwrap()) .register(self.context) } - } + } if let Some(calledvec) = self.call_tree.get(&nextproc) { for (proccalled, location, new_context) in calledvec.iter() { let mut newstack = callstack.clone(); @@ -743,7 +743,7 @@ impl<'o> AnalyzeObjectTree<'o> { .with_blocking_builtins(self.impure_procs.get_violators(*child_violator).unwrap()) .register(self.context) } - } + } if let Some(calledvec) = self.call_tree.get(&nextproc) { for (proccalled, location, new_context) in calledvec.iter() { let mut newstack = callstack.clone(); @@ -1863,6 +1863,12 @@ impl<'o, 's> AnalyzeProc<'o, 's> { self.visit_arguments(location, rhs_args, local_vars); Analysis::empty() // TODO }, + Term::ExternalCall { library_name, function_name, args } => { + self.visit_expression(location, library_name, None, local_vars); + self.visit_expression(location, function_name, None, local_vars); + self.visit_arguments(location, args, local_vars); + Analysis::empty() // TODO + }, } } diff --git a/crates/dreamchecker/tests/call_ext_tests.rs b/crates/dreamchecker/tests/call_ext_tests.rs new file mode 100644 index 00000000..2dbf083f --- /dev/null +++ b/crates/dreamchecker/tests/call_ext_tests.rs @@ -0,0 +1,29 @@ +extern crate dreamchecker as dc; + +use dc::test_helpers::*; + +pub const CALL_EXT_MISSING_ARG_ERRORS: &[(u32, u16, &str)] = &[ + (2, 15, "got ')', expected one of: operator, field access, ','"), +]; + +#[test] +fn call_ext_missing_arg() { + let code = r##" +/proc/f() + call_ext(1)(3, 4, 5) +"##.trim(); + check_errors_match(code, CALL_EXT_MISSING_ARG_ERRORS); +} + +pub const CALL_EXT_MISSING_CALL_ERRORS: &[(u32, u16, &str)] = &[ + (2, 19, "got ';', expected one of: '('"), +]; + +#[test] +fn call_ext_missing_call() { + let code = r##" +/proc/f() + call_ext(1, 2) +"##.trim(); + check_errors_match(code, CALL_EXT_MISSING_CALL_ERRORS); +} diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 23a589e5..b2697257 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -897,6 +897,12 @@ pub enum Term { Pick(Box), /// A use of the `call()()` primitive. DynamicCall(Box<[Expression]>, Box<[Expression]>), + /// A use of the `call_ext()()` primitive. + ExternalCall { + library_name: Box, + function_name: Box, + args: Box<[Expression]>, + }, } impl Term { diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index f6807db9..7a3d95ac 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -1984,6 +1984,21 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { require!(self.arguments(&[], "call*")), ), + // term :: 'call_ext' (library_name, function_name) arglist + Token::Ident(ref i, _) if i == "call_ext" => { + require!(self.exact(Token::Punct(Punctuation::LParen))); + let library_name = require!(self.expression()); + require!(self.exact(Token::Punct(Punctuation::Comma))); + let function_name = require!(self.expression()); + require!(self.exact(Token::Punct(Punctuation::RParen))); + + Term::ExternalCall { + library_name: Box::new(library_name), + function_name: Box::new(function_name), + args: require!(self.arguments(&[], "call_ext*")), + } + }, + // term :: 'input' arglist input_specifier Token::Ident(ref i, _) if i == "input" => match self.arguments(&[], "input")? { Some(args) => { From 240d8e02c41e7f8f3f7479354e0dcca362ec511e Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 20 Apr 2023 22:44:29 -0700 Subject: [PATCH 035/197] Add Scope token '::' to lexer --- crates/dreammaker/src/lexer.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index 803516fb..3343e766 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -100,6 +100,7 @@ table! { "//", LineComment; "/=", DivAssign; ":", Colon -> CloseColon; + "::", Scope; ":=", AssignInto; ";", Semicolon; "<", Less; @@ -152,15 +153,15 @@ static SPEEDY_TABLE: [(usize, usize); 127] = [ (2, 3), (3, 5), (5, 6), (6, 8), (0, 0), (8, 10), (10, 14), (14, 15), (15, 16), (16, 17), (17, 20), (20, 23), (23, 24), (24, 27), (27, 30), (30, 34), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (34, 36), (36, 37), (37, 42), (42, 44), (44, 48), (48, 52), + (0, 0), (0, 0), (34, 37), (37, 38), (38, 43), (43, 45), (45, 49), (49, 53), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (52, 53), (0, 0), (53, 54), (54, 56), (0, 0), + (0, 0), (0, 0), (0, 0), (53, 54), (0, 0), (54, 55), (55, 57), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (56, 58), (58, 62), (62, 63), (63, 66)]; + (0, 0), (0, 0), (0, 0), (57, 59), (59, 63), (63, 64), (64, 67)]; #[test] fn make_speedy_table() { From 41297597fb29a565375106189309426b8ef2c3a9 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Fri, 21 Apr 2023 18:40:52 -0700 Subject: [PATCH 036/197] Add final keyword as alias for SpacemanDMM_final --- crates/dm-langserver/src/find_references.rs | 2 +- crates/dreamchecker/src/lib.rs | 2 +- crates/dreamchecker/tests/var_declare_tests.rs | 14 +++++++++++++- crates/dreammaker/src/ast.rs | 5 +++-- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/crates/dm-langserver/src/find_references.rs b/crates/dm-langserver/src/find_references.rs index 44b5f04f..756fc6e0 100644 --- a/crates/dm-langserver/src/find_references.rs +++ b/crates/dm-langserver/src/find_references.rs @@ -679,7 +679,7 @@ impl<'o> WalkProc<'o> { } fn static_type(&mut self, location: Location, mut of: &[String]) -> StaticType<'o> { - while !of.is_empty() && ["static", "global", "const", "tmp"].contains(&&*of[0]) { + while !of.is_empty() && ["static", "global", "const", "tmp", "final", "SpacemanDMM_final", "SpacemanDMM_private", "SpacemanDMM_protected"].contains(&&*of[0]) { of = &of[1..]; } diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 061dd709..ee275de9 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -925,7 +925,7 @@ impl<'o> AnalyzeObjectTree<'o> { } fn static_type<'o>(objtree: &'o ObjectTree, location: Location, mut of: &[String]) -> Result, DMError> { - while !of.is_empty() && ["static", "global", "const", "tmp", "SpacemanDMM_final", "SpacemanDMM_private", "SpacemanDMM_protected"].contains(&&*of[0]) { + while !of.is_empty() && ["static", "global", "const", "tmp", "final", "SpacemanDMM_final", "SpacemanDMM_private", "SpacemanDMM_protected"].contains(&&*of[0]) { of = &of[1..]; } diff --git a/crates/dreamchecker/tests/var_declare_tests.rs b/crates/dreamchecker/tests/var_declare_tests.rs index 0ec546dc..185f3872 100644 --- a/crates/dreamchecker/tests/var_declare_tests.rs +++ b/crates/dreamchecker/tests/var_declare_tests.rs @@ -24,7 +24,7 @@ pub const VAR_FINAL_ERRORS: &[(u32, u16, &str)] = &[ ]; #[test] -fn var_final() { +fn var_spaceman_final() { let code = r##" /mob var/SpacemanDMM_final/foo = 0 @@ -35,6 +35,18 @@ fn var_final() { check_errors_match(code, VAR_FINAL_ERRORS); } +#[test] +fn var_final() { + let code = r##" +/mob + var/final/foo = 0 + +/mob/subtype + foo = 1 +"##.trim(); + check_errors_match(code, VAR_FINAL_ERRORS); +} + pub const VAR_UNDECL_ERRORS: &[(u32, u16, &str)] = &[ (6, 5, "undefined var: \"bar\""), ]; diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index b2697257..5f250118 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -435,6 +435,7 @@ impl VarTypeFlags { "global" | "static" => Some(VarTypeFlags::STATIC), "const" => Some(VarTypeFlags::CONST), "tmp" => Some(VarTypeFlags::TMP), + "final" => Some(VarTypeFlags::FINAL), // SpacemanDMM flags "SpacemanDMM_final" => Some(VarTypeFlags::FINAL), "SpacemanDMM_private" => Some(VarTypeFlags::PRIVATE), @@ -489,7 +490,7 @@ impl VarTypeFlags { if self.is_static() { v.push("static"); } if self.is_const() { v.push("const"); } if self.is_tmp() { v.push("tmp"); } - if self.is_final() { v.push("SpacemanDMM_final"); } + if self.is_final() { v.push("final"); } if self.is_private() { v.push("SpacemanDMM_private"); } if self.is_protected() { v.push("SpacemanDMM_protected"); } v @@ -508,7 +509,7 @@ impl fmt::Display for VarTypeFlags { fmt.write_str("tmp/")?; } if self.is_final() { - fmt.write_str("SpacemanDMM_final/")?; + fmt.write_str("final/")?; } if self.is_private() { fmt.write_str("SpacemanDMM_private/")?; From 32bf1b3b98c3e81e576300ec32bfe357813e4bae Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Fri, 21 Apr 2023 22:17:13 -0700 Subject: [PATCH 037/197] Parse unary reference and dereference operators --- crates/dreammaker/src/ast.rs | 6 ++++++ crates/dreammaker/src/parser.rs | 2 ++ crates/dreammaker/tests/expression_tests.rs | 14 ++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 5f250118..8693035f 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -26,6 +26,8 @@ pub enum UnaryOp { PostIncr, PreDecr, PostDecr, + Reference, + Dereference, } impl UnaryOp { @@ -49,6 +51,8 @@ impl UnaryOp { PostIncr => write!(f, "{}++", self.expr), PreDecr => write!(f, "--{}", self.expr), PostDecr => write!(f, "{}--", self.expr), + Reference => write!(f, "&{}", self.expr), + Dereference => write!(f, "*{}", self.expr), } } } @@ -65,6 +69,8 @@ impl UnaryOp { BitNot => "~", PreIncr | PostIncr => "++", PreDecr | PostDecr => "--", + Reference => "&", + Dereference => "*", } } } diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 7a3d95ac..49b16c0c 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -1858,6 +1858,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { Token::Punct(Punctuation::BitNot) => unary_ops.push(Spanned::new(self.location, Follow::Unary(UnaryOp::BitNot))), Token::Punct(Punctuation::PlusPlus) => unary_ops.push(Spanned::new(self.location, Follow::Unary(UnaryOp::PreIncr))), Token::Punct(Punctuation::MinusMinus) => unary_ops.push(Spanned::new(self.location, Follow::Unary(UnaryOp::PreDecr))), + Token::Punct(Punctuation::BitAnd) => unary_ops.push(Spanned::new(self.location, Follow::Unary(UnaryOp::Reference))), + Token::Punct(Punctuation::Mul) => unary_ops.push(Spanned::new(self.location, Follow::Unary(UnaryOp::Dereference))), other => { self.put_back(other); break; diff --git a/crates/dreammaker/tests/expression_tests.rs b/crates/dreammaker/tests/expression_tests.rs index 727b340d..f8cb4bb7 100644 --- a/crates/dreammaker/tests/expression_tests.rs +++ b/crates/dreammaker/tests/expression_tests.rs @@ -114,3 +114,17 @@ fn bitop_precedence() { } ); } + +#[test] +fn pointer_ops() { + assert_eq!( + parse_expr("*&1"), + Expression::Base { + term: Box::new(Spanned::new(Default::default(), Term::Int(1))), + follow: vec![ + Spanned::new(Default::default(), Follow::Unary(UnaryOp::Reference)), + Spanned::new(Default::default(), Follow::Unary(UnaryOp::Dereference)), + ].into_boxed_slice(), + } + ) +} From 3eddd3204bd419345f00eaab3cecd6617e017313 Mon Sep 17 00:00:00 2001 From: Spookerton Date: Wed, 3 May 2023 04:15:24 +0100 Subject: [PATCH 038/197] Add proc and constant builtins as of 515.1606 (#354) Does not cover: __PROC__ __TYPE__ proc/foo() as hint #pragma %% %%= A.operator%%(B) A.operator%%=(B) A.operator""() --- crates/dreammaker/src/builtins.rs | 39 +++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/crates/dreammaker/src/builtins.rs b/crates/dreammaker/src/builtins.rs index d62b79e2..014fc44f 100644 --- a/crates/dreammaker/src/builtins.rs +++ b/crates/dreammaker/src/builtins.rs @@ -148,7 +148,9 @@ pub fn default_defines(defines: &mut DefineMap) { ANIMATION_END_NOW = Int(1); ANIMATION_LINEAR_TRANSFORM = Int(2); ANIMATION_PARALLEL = Int(4); + ANIMATION_SLICE = Int(8); // 515 ANIMATION_RELATIVE = Int(256); + ANIMATION_CONTINUE = Int(512); // 515 // database DATABASE_OPEN = Int(0); @@ -195,6 +197,14 @@ pub fn default_defines(defines: &mut DefineMap) { NORMAL_RAND = Int(1); LINEAR_RAND = Int(2); SQUARE_RAND = Int(3); + + + // json encode flags (515) + JSON_PRETTY_PRINT = Int(1); + + // json decode flags (515) + JSON_STRICT = Int(1); + JSON_ALLOW_COMMENTS = Int(2); // default } } @@ -1161,6 +1171,35 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { particles/var/rotation; particles/var/spin; particles/var/drift; + + //515 stuff + + proc/ceil(A); + proc/floor(A); + proc/fract(A); + proc/ftime(File, IsCreationTime); + proc/get_steps_to(Ref, Trg, Min=0); + proc/isinf(A); + proc/isnan(A); + proc/ispointer(Value); + proc/nameof(VarPathProcRef); + proc/noise_hash(param1/*, ...*/); + proc/refcount(Object); + proc/trimtext(Text); + proc/trunc(A); + + client/proc/RenderIcon(object); + + savefile/var/byond_build = int!(0); + savefile/var/byond_version = int!(0); + + + sound/var/params; + sound/var/pitch = int!(0); + + list/proc/RemoveAll(Item1/*, ...*/); + + world/proc/Tick(); }; } From 34a656baf699510dc19424af7518023915d69cd3 Mon Sep 17 00:00:00 2001 From: Jordan Dominion Date: Mon, 8 May 2023 23:27:46 -0400 Subject: [PATCH 039/197] Optimize as much as possible in the release build (#357) --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 473daa8a..03658aa4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,4 @@ opt-level = 2 [profile.release] lto = true +codegen-units = 1 From 44a9a2ab3ba210328b2b3086f12b90e3b47d6ab0 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 18 May 2023 18:42:00 -0700 Subject: [PATCH 040/197] Update to auxtools debug server v2.2.4 --- scripts/download-auxtools.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/download-auxtools.sh b/scripts/download-auxtools.sh index aa0d2907..32c3b62c 100755 --- a/scripts/download-auxtools.sh +++ b/scripts/download-auxtools.sh @@ -2,9 +2,9 @@ set -euo pipefail # Settings -DEBUG_SERVER_TAG=v2.2.3 -DEBUG_SERVER_DLL_URL=https://github.com/willox/auxtools/releases/download/v2.2.3/debug_server.dll -DEBUG_SERVER_DLL_SHA256=dd10daa07607b278536152bf5c79906180958c4b765b486c18a021418103893e +DEBUG_SERVER_TAG=v2.2.4 +DEBUG_SERVER_DLL_URL=https://github.com/willox/auxtools/releases/download/v2.2.4/debug_server.dll +DEBUG_SERVER_DLL_SHA256=2a81e64d5cacef372043af476e9b1b2d21e38a6f9f708e0da8ca573bdcfcf0d3 # ----------------------------------------------------------------------------- cd "$(dirname "${BASH_SOURCE[0]}")" From fa608c5c9f5443f5d205d416d9049bbcf2232ca0 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Wed, 17 May 2023 18:03:53 -0700 Subject: [PATCH 041/197] Loosely parse proc return types This is enough to get the parser past them but not enough to make them useful. --- crates/dreammaker/src/parser.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 49b16c0c..813deb34 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -957,6 +957,15 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let location = self.location; let parameters = require!(self.separated(Comma, RParen, None, Parser::proc_parameter)); + // TODO: store this information. + let _return_type = if let Some(()) = self.exact_ident("as")? { + // For now loosely interpret this as an expression, but really it + // should be either an absolute typepath or some |'d input types. + Some(require!(self.expression())) + } else { + None + }; + // split off a subparser so we can keep parsing the objtree // even when the proc body doesn't parse let mut body_start = self.location; From 1f9b4416b38c26acd7a6ff77fdaa6e7693952e47 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 1 Jun 2023 17:18:31 -0700 Subject: [PATCH 042/197] Remove dependency on guard crate - `guard` 0.5.1 was released on 2021-04-11 - `let else` was stabilized in Rust 1.65.0 on 2022-11-03 - `box_syntax` became a hard error in Rust 1.70.0 on 2023-06-01 - `guard` has tests that use box_syntax so it no longer compiles --- Cargo.lock | 9 ------ crates/dm-langserver/Cargo.toml | 1 - crates/dm-langserver/src/debugger/evaluate.rs | 8 ++--- crates/dm-langserver/src/debugger/launched.rs | 2 +- crates/dm-langserver/src/debugger/mod.rs | 30 +++++++++---------- crates/dm-langserver/src/main.rs | 7 ++--- crates/dreamchecker/Cargo.toml | 1 - crates/dreamchecker/src/lib.rs | 21 ++++++------- crates/dreammaker/Cargo.toml | 1 - crates/dreammaker/src/ast.rs | 24 +++++++-------- crates/dreammaker/src/error.rs | 4 +-- crates/dreammaker/src/lib.rs | 1 - 12 files changed, 46 insertions(+), 63 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5781e9e2..668465cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -406,7 +406,6 @@ dependencies = [ "dreamchecker", "dreammaker", "git2", - "guard", "interval-tree", "jsonrpc-core", "lazy_static", @@ -487,7 +486,6 @@ dependencies = [ "chrono", "dreammaker", "git2", - "guard", "serde_json", ] @@ -500,7 +498,6 @@ dependencies = [ "builtins-proc-macro", "color_space", "derivative", - "guard", "indexmap", "interval-tree", "lodepng", @@ -739,12 +736,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "guard" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff893cc51ea04f8a3b73fbaf4376c06ebc5a0ccbe86d460896f805d9417c93ea" - [[package]] name = "hashbrown" version = "0.12.3" diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index 56fb6e64..23b713d8 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -17,7 +17,6 @@ dreammaker = { path = "../dreammaker" } dreamchecker = { path = "../dreamchecker" } interval-tree = { path = "../interval-tree" } libc = "0.2.132" -guard = "0.5.1" regex = "1.6.0" lazy_static = "1.4" ahash = "0.8.0" diff --git a/crates/dm-langserver/src/debugger/evaluate.rs b/crates/dm-langserver/src/debugger/evaluate.rs index 244b5c33..b8570aa0 100644 --- a/crates/dm-langserver/src/debugger/evaluate.rs +++ b/crates/dm-langserver/src/debugger/evaluate.rs @@ -19,17 +19,17 @@ impl Debugger { return Ok(EvaluateResponse::from(EXTOOLS_HELP.trim())); } - guard!(let Some(frame_id) = params.frameId else { + let Some(frame_id) = params.frameId else { return Err(Box::new(GenericError("Must select a stack frame to evaluate in"))); - }); + }; let (thread, frame_no) = extools.get_thread_by_frame_id(frame_id)?; if input.starts_with('#') { if input == "#dis" || input == "#disassemble" { - guard!(let Some(frame) = thread.call_stack.get(frame_no) else { + let Some(frame) = thread.call_stack.get(frame_no) else { return Err(Box::new(GenericError("Stack frame out of range"))); - }); + }; let bytecode = extools.bytecode(&frame.proc, frame.override_id); return Ok(EvaluateResponse::from(Self::format_disassembly(bytecode))); diff --git a/crates/dm-langserver/src/debugger/launched.rs b/crates/dm-langserver/src/debugger/launched.rs index 2a4c8374..7ed6279a 100644 --- a/crates/dm-langserver/src/debugger/launched.rs +++ b/crates/dm-langserver/src/debugger/launched.rs @@ -158,7 +158,7 @@ impl Launched { } fn pipe_output(seq: Arc, keyword: &'static str, stream: Option) -> std::io::Result<()> { - guard!(let Some(stream2) = stream else { return Ok(()); }); + let Some(stream2) = stream else { return Ok(()); }; std::thread::Builder::new() .name(format!("launched debuggee {} relay", keyword)) .spawn(move || { diff --git a/crates/dm-langserver/src/debugger/mod.rs b/crates/dm-langserver/src/debugger/mod.rs index da2fee80..3cee3110 100644 --- a/crates/dm-langserver/src/debugger/mod.rs +++ b/crates/dm-langserver/src/debugger/mod.rs @@ -353,7 +353,7 @@ impl Debugger { match &mut self.client { DebugClient::Extools(extools) => { let keys: Vec<_> = { - guard!(let Ok(extools) = extools.get() else { return }); + let Ok(extools) = extools.get() else { return }; extools .get_all_threads() .keys() @@ -592,12 +592,12 @@ handle_request! { } on SetBreakpoints(&mut self, params) { - guard!(let Some(file_path) = params.source.path else { + let Some(file_path) = params.source.path else { return Err(Box::new(GenericError("missing .source.path"))); - }); - guard!(let Some(file_id) = self.db.file_id(&file_path) else { + }; + let Some(file_id) = self.db.file_id(&file_path) else { return Err(Box::new(GenericError("file is not part of environment"))); - }); + }; if params.sourceModified.unwrap_or(false) { return Err(Box::new(GenericError("cannot update breakpoints in modified source"))); @@ -611,7 +611,7 @@ handle_request! { DebugClient::Extools(extools) => { let mut breakpoints = Vec::new(); - guard!(let Some(extools) = extools.as_ref() else { + let Some(extools) = extools.as_ref() else { for sbp in inputs { breakpoints.push(Breakpoint { message: Some("Debugging hooks not available".to_owned()), @@ -621,7 +621,7 @@ handle_request! { }); } return Ok(SetBreakpointsResponse { breakpoints }); - }); + }; for sbp in inputs { if let Some((typepath, name, override_id)) = self.db.location_to_proc_ref(file_id, sbp.line) { @@ -763,7 +763,7 @@ handle_request! { match &mut self.client { DebugClient::Extools(extools) => { - guard!(let Some(extools) = extools.as_ref() else { + let Some(extools) = extools.as_ref() else { for _ in inputs { breakpoints.push(Breakpoint { message: Some("Debugging hooks not available".to_owned()), @@ -772,7 +772,7 @@ handle_request! { }); } return Ok(SetFunctionBreakpointsResponse { breakpoints }); - }); + }; for sbp in inputs { // parse function reference @@ -1026,9 +1026,9 @@ handle_request! { let thread_id = (frame_id % threads.len()) as i64; let frame_no = frame_id / threads.len(); - guard!(let Some(frame) = threads[&thread_id].call_stack.get(frame_no) else { + let Some(frame) = threads[&thread_id].call_stack.get(frame_no) else { return Err(Box::new(GenericError2(format!("Stack frame out of range: {} (thread {}, depth {})", frameId, thread_id, frame_no)))); - }); + }; ScopesResponse { scopes: vec![ @@ -1152,9 +1152,9 @@ handle_request! { let mod2 = params.variablesReference % 2; let (thread, frame_no) = extools.get_thread_by_frame_id(frame_id)?; - guard!(let Some(frame) = thread.call_stack.get(frame_no) else { + let Some(frame) = thread.call_stack.get(frame_no) else { return Err(Box::new(GenericError("Stack frame out of range"))); - }); + }; if mod2 == 1 { // arguments @@ -1395,9 +1395,9 @@ handle_request! { on Disassemble(&mut self, params) { match &mut self.client { DebugClient::Extools(extools) => { - guard!(let Some(captures) = MEMORY_REFERENCE_REGEX.captures(¶ms.memoryReference) else { + let Some(captures) = MEMORY_REFERENCE_REGEX.captures(¶ms.memoryReference) else { return Err(Box::new(GenericError("Invalid memory reference"))); - }); + }; let proc = &captures[1]; let override_id: usize = captures[2].parse()?; //let offset: i64 = captures[3].parse()?; diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index 18f1b520..e539f3c0 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -17,7 +17,6 @@ extern crate jsonrpc_core as jsonrpc; extern crate dreammaker as dm; extern crate dreamchecker; extern crate libc; -#[macro_use] extern crate guard; extern crate regex; #[macro_use] extern crate lazy_static; @@ -169,7 +168,7 @@ impl DiagnosticsTracker { } else { let mut notes = Vec::with_capacity(error.notes().len()); for note in error.notes().iter() { - guard!(let Some(uri) = DiagnosticsTracker::file_url(root, file_list, note.location().file) else { continue }); + let Some(uri) = DiagnosticsTracker::file_url(root, file_list, note.location().file) else { continue }; notes.push(lsp_types::DiagnosticRelatedInformation { location: lsp_types::Location { uri, @@ -189,7 +188,7 @@ impl DiagnosticsTracker { related_information, .. Default::default() }; - guard!(let Some(uri) = DiagnosticsTracker::file_url(root, file_list, loc.file) else { continue }); + let Some(uri) = DiagnosticsTracker::file_url(root, file_list, loc.file) else { continue }; map.entry(uri) .or_insert_with(Default::default) .push(diag); @@ -204,7 +203,7 @@ impl DiagnosticsTracker { source: component_to_source(error.component()), .. Default::default() }; - guard!(let Some(uri) = DiagnosticsTracker::file_url(root, file_list, note.location().file) else { continue }); + let Some(uri) = DiagnosticsTracker::file_url(root, file_list, note.location().file) else { continue }; map.entry(uri) .or_insert_with(Default::default) .push(diag); diff --git a/crates/dreamchecker/Cargo.toml b/crates/dreamchecker/Cargo.toml index ca3649cd..1bc74326 100644 --- a/crates/dreamchecker/Cargo.toml +++ b/crates/dreamchecker/Cargo.toml @@ -6,7 +6,6 @@ edition = "2018" [dependencies] dreammaker = { path = "../dreammaker" } -guard = "0.5.1" serde_json = "1.0" ahash = "0.8.0" diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index ee275de9..05948d4d 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -1,7 +1,6 @@ //! DreamChecker, a robust static analysis and typechecking engine for //! DreamMaker. #![allow(dead_code, unused_variables)] -#[macro_use] extern crate guard; extern crate dreammaker as dm; use dm::{Context, DMError, Location, Severity}; @@ -973,11 +972,9 @@ pub fn check_var_defs(objtree: &ObjectTree, context: &Context) { continue; } - guard!(let Some(parentvar) = parent.vars.get(varname) - else { continue }); + let Some(parentvar) = parent.vars.get(varname) else { continue }; - guard!(let Some(decl) = &parentvar.declaration - else { continue }); + let Some(decl) = &parentvar.declaration else { continue }; if let Some(mydecl) = &typevar.declaration { if typevar.value.location.is_builtins() { @@ -2065,7 +2062,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { // checks for bitwise operations on a negated LHS fn check_negated_bitwise(&mut self, lhs: &dm::ast::Expression, location: Location, bit_op: BinaryOp, bool_op: BinaryOp) { - guard!(let Expression::Base { follow, .. } = lhs else { return }); + let Expression::Base { follow, .. } = lhs else { return }; let any_not = follow.iter().any(|f| matches!(f.elem, Follow::Unary(UnaryOp::Not))); if any_not { error(location, format!("Ambiguous `!` on left side of bitwise `{}` operator", bit_op)) @@ -2238,23 +2235,23 @@ impl<'o, 's> AnalyzeProc<'o, 's> { // TODO: some filters have limits for their numerical params // eg "rays" type "threshold" param defaults to 0.5, can be 0 to 1 if proc.ty().is_root() && proc.name() == "filter" { - guard!(let Some(typename) = param_name_map.get("type") else { + let Some(typename) = param_name_map.get("type") else { if !arglist_used { error(location, "filter() called without mandatory keyword parameter 'type'") .register(self.context); } // regardless, we're done here return Analysis::empty() - }); - guard!(let Some(Constant::String(typevalue)) = &typename.value else { + }; + let Some(Constant::String(typevalue)) = &typename.value else { error(location, format!("filter() called with non-string type keyword parameter value '{:?}'", typename.value)) .register(self.context); return Analysis::empty() - }); - guard!(let Some(arglist) = VALID_FILTER_TYPES.get(typevalue) else { + }; + let Some(arglist) = VALID_FILTER_TYPES.get(typevalue) else { error(location, format!("filter() called with invalid type keyword parameter value '{}'", typevalue)) .register(self.context); return Analysis::empty() - }); + }; for arg in param_name_map.keys() { if *arg != "type" && !arglist.iter().any(|&x| x == *arg) { error(location, format!("filter(type=\"{}\") called with invalid keyword parameter '{}'", typevalue, arg)) diff --git a/crates/dreammaker/Cargo.toml b/crates/dreammaker/Cargo.toml index 64b790a6..31292905 100644 --- a/crates/dreammaker/Cargo.toml +++ b/crates/dreammaker/Cargo.toml @@ -14,7 +14,6 @@ ordered-float = "3.0.0" serde = { version = "1.0.144", features = ["derive"] } serde_derive = "1.0.144" toml = "0.5.9" -guard = "0.5.1" phf = { version = "0.11.1", features = ["macros"] } color_space = "0.5.3" ahash = "0.8.0" diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 8693035f..6485d47b 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -746,12 +746,12 @@ impl Expression { pub fn is_const_eval(&self) -> bool { match self { Expression::BinaryOp { op, lhs, rhs } => { - guard!(let Some(lhterm) = lhs.as_term() else { + let Some(lhterm) = lhs.as_term() else { return false - }); - guard!(let Some(rhterm) = rhs.as_term() else { + }; + let Some(rhterm) = rhs.as_term() else { return false - }); + }; if !lhterm.is_static() { return false } @@ -774,9 +774,9 @@ impl Expression { pub fn is_truthy(&self) -> Option { match self { Expression::Base { term, follow } => { - guard!(let Some(mut truthy) = term.elem.is_truthy() else { + let Some(mut truthy) = term.elem.is_truthy() else { return None; - }); + }; for follow in follow.iter() { match follow.elem { Follow::Unary(UnaryOp::Not) => truthy = !truthy, @@ -786,12 +786,12 @@ impl Expression { Some(truthy) }, Expression::BinaryOp { op, lhs, rhs } => { - guard!(let Some(lhtruth) = lhs.is_truthy() else { + let Some(lhtruth) = lhs.is_truthy() else { return None - }); - guard!(let Some(rhtruth) = rhs.is_truthy() else { + }; + let Some(rhtruth) = rhs.is_truthy() else { return None - }); + }; match op { BinaryOp::And => Some(lhtruth && rhtruth), BinaryOp::Or => Some(lhtruth || rhtruth), @@ -809,9 +809,9 @@ impl Expression { } }, Expression::TernaryOp { cond, if_, else_ } => { - guard!(let Some(condtruth) = cond.is_truthy() else { + let Some(condtruth) = cond.is_truthy() else { return None - }); + }; if condtruth { if_.is_truthy() } else { diff --git a/crates/dreammaker/src/error.rs b/crates/dreammaker/src/error.rs index 05c7aa29..ff88bf87 100644 --- a/crates/dreammaker/src/error.rs +++ b/crates/dreammaker/src/error.rs @@ -171,9 +171,9 @@ impl Context { /// Push an error or other diagnostic to the context. pub fn register_error(&self, error: DMError) { - guard!(let Some(error) = self.config.borrow().set_configured_severity(error) else { + let Some(error) = self.config.borrow().set_configured_severity(error) else { return // errortype is disabled - }); + }; // ignore errors with severity above configured level if !self.config.borrow().registerable_error(&error) { return diff --git a/crates/dreammaker/src/lib.rs b/crates/dreammaker/src/lib.rs index 02473825..835e7bc9 100644 --- a/crates/dreammaker/src/lib.rs +++ b/crates/dreammaker/src/lib.rs @@ -5,7 +5,6 @@ extern crate indexmap; extern crate interval_tree; extern crate lodepng; #[macro_use] extern crate bitflags; -#[macro_use] extern crate guard; extern crate termcolor; extern crate ordered_float; extern crate serde; From 3797c66c2f93432dbc21432b6e085ecb3f6c2ccc Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 20 Jul 2023 17:30:38 -0700 Subject: [PATCH 043/197] Run cargo clippy --fix --- crates/dm-langserver/build.rs | 2 +- crates/dm-langserver/src/completion.rs | 2 +- crates/dm-langserver/src/document.rs | 2 +- crates/dm-langserver/src/main.rs | 18 +++++++++--------- crates/dmdoc/build.rs | 2 +- crates/dmdoc/src/main.rs | 6 +++--- crates/dmdoc/src/markdown.rs | 6 +++--- crates/dmm-tools-cli/build.rs | 2 +- crates/dmm-tools-cli/src/main.rs | 2 +- .../examples/duplicate_icon_states.rs | 2 +- crates/dmm-tools/src/dmi.rs | 2 +- crates/dmm-tools/src/dmm.rs | 4 ++-- .../src/render_passes/icon_smoothing.rs | 2 +- .../src/render_passes/icon_smoothing_2020.rs | 4 ++-- crates/dmm-tools/src/render_passes/mod.rs | 8 ++++---- .../dmm-tools/src/render_passes/structures.rs | 4 ++-- crates/dmm-tools/tests/parse_codebase.rs | 2 +- crates/dreamchecker/build.rs | 2 +- crates/dreamchecker/src/lib.rs | 7 +------ crates/dreamchecker/src/switch_rand_range.rs | 6 +++--- crates/dreammaker/src/ast.rs | 10 +++++----- crates/dreammaker/src/config.rs | 8 +++----- crates/dreammaker/src/constants.rs | 10 +++++----- crates/dreammaker/src/dmi.rs | 8 +++----- crates/dreammaker/src/docs.rs | 8 +++----- crates/dreammaker/src/error.rs | 16 ++++++---------- crates/dreammaker/src/lexer.rs | 4 ++-- crates/dreammaker/src/preprocessor.rs | 8 ++++---- crates/dreammaker/tests/ast_tests.rs | 2 +- crates/dreammaker/tests/format_tests.rs | 2 +- crates/dreammaker/tests/location_tests.rs | 2 +- crates/interval-tree/src/node.rs | 8 ++++---- crates/interval-tree/src/tests.rs | 4 ++-- crates/interval-tree/src/tree.rs | 5 ++--- 34 files changed, 82 insertions(+), 98 deletions(-) diff --git a/crates/dm-langserver/build.rs b/crates/dm-langserver/build.rs index ecc971fb..1dccc4d7 100644 --- a/crates/dm-langserver/build.rs +++ b/crates/dm-langserver/build.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; fn main() { // build info let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); - let mut f = File::create(&out_dir.join("build-info.txt")).unwrap(); + let mut f = File::create(out_dir.join("build-info.txt")).unwrap(); match read_commit() { Ok(commit) => writeln!(f, "commit: {}", commit).unwrap(), diff --git a/crates/dm-langserver/src/completion.rs b/crates/dm-langserver/src/completion.rs index 18356796..7b7c2b1b 100644 --- a/crates/dm-langserver/src/completion.rs +++ b/crates/dm-langserver/src/completion.rs @@ -430,7 +430,7 @@ impl<'a> Engine<'a> { // macros if let Some(ref defines) = self.defines { // TODO: verify that the macro is in scope at the location - for (_, &(ref name, ref define)) in defines.iter() { + for (_, (name, define)) in defines.iter() { if contains(name, query) { results.push(CompletionItem { label: name.to_owned(), diff --git a/crates/dm-langserver/src/document.rs b/crates/dm-langserver/src/document.rs index 33b1fc6f..78e1d090 100644 --- a/crates/dm-langserver/src/document.rs +++ b/crates/dm-langserver/src/document.rs @@ -220,7 +220,7 @@ pub fn find_word(text: &str, offset: usize) -> &str { } fn is_ident(ch: char) -> bool { - ('0'..='9').contains(&ch) || ('a'..='z').contains(&ch) || ('A'..='Z').contains(&ch) || ch == '_' + ch.is_ascii_digit() || ch.is_ascii_lowercase() || ch.is_ascii_uppercase() || ch == '_' } /// An adaptation of `std::io::Cursor` which works on an `Rc`, which diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index e539f3c0..2cad2bb2 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -812,7 +812,7 @@ impl<'a> Engine<'a> { let (_, file_id, annotations) = self.get_annotations(&text_document_position.text_document.uri)?; let location = dm::Location { file: file_id, - line: text_document_position.position.line as u32 + 1, + line: text_document_position.position.line + 1, column: text_document_position.position.character as u16 + 1, }; @@ -1207,7 +1207,7 @@ handle_method_call! { let mut results = Vec::new(); if let Some(ref defines) = self.defines { - for (range, &(ref name, ref define)) in defines.iter() { + for (range, (name, define)) in defines.iter() { if query.matches_define(name) { results.push(SymbolInformation { name: name.to_owned(), @@ -1280,7 +1280,7 @@ handle_method_call! { let (_, file_id, annotations) = self.get_annotations(&tdp.text_document.uri)?; let location = dm::Location { file: file_id, - line: tdp.position.line as u32 + 1, + line: tdp.position.line + 1, column: tdp.position.character as u16 + 1, }; let symbol_id = self.symbol_id_at(tdp)?; @@ -1429,7 +1429,7 @@ handle_method_call! { let (real_file_id, file_id, annotations) = self.get_annotations(&tdp.text_document.uri)?; let location = dm::Location { file: file_id, - line: tdp.position.line as u32 + 1, + line: tdp.position.line + 1, column: tdp.position.character as u16 + 1, }; let mut results = Vec::new(); @@ -1560,7 +1560,7 @@ handle_method_call! { let (_, file_id, annotations) = self.get_annotations(&tdp.text_document.uri)?; let location = dm::Location { file: file_id, - line: tdp.position.line as u32 + 1, + line: tdp.position.line + 1, column: tdp.position.character as u16 + 1, }; @@ -1657,7 +1657,7 @@ handle_method_call! { let (_, file_id, annotations) = self.get_annotations(¶ms.text_document_position.text_document.uri)?; let location = dm::Location { file: file_id, - line: params.text_document_position.position.line as u32 + 1, + line: params.text_document_position.position.line + 1, column: params.text_document_position.position.character as u16 + 1, }; let iter = annotations.get_location(location); @@ -1734,7 +1734,7 @@ handle_method_call! { let (_, file_id, annotations) = self.get_annotations(&tdp.text_document.uri)?; let location = dm::Location { file: file_id, - line: tdp.position.line as u32 + 1, + line: tdp.position.line + 1, column: tdp.position.character as u16 + 1, }; let iter = annotations.get_location(location); @@ -1977,7 +1977,7 @@ handle_method_call! { Annotation::Include(path) | Annotation::Resource(path) => { let pathbuf = if path.is_relative() { - std::env::current_dir().map_err(invalid_request)?.join(&path) + std::env::current_dir().map_err(invalid_request)?.join(path) } else { path.to_owned() }; @@ -2154,7 +2154,7 @@ fn is_constructor_name(name: &str) -> bool { fn location_to_position(loc: dm::Location) -> lsp_types::Position { lsp_types::Position { - line: loc.line.saturating_sub(1) as u32, + line: loc.line.saturating_sub(1), character: loc.column.saturating_sub(1) as u32, } } diff --git a/crates/dmdoc/build.rs b/crates/dmdoc/build.rs index cc4979da..d9951a53 100644 --- a/crates/dmdoc/build.rs +++ b/crates/dmdoc/build.rs @@ -8,7 +8,7 @@ use std::path::PathBuf; fn main() { let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); - let mut f = File::create(&out_dir.join("build-info.txt")).unwrap(); + let mut f = File::create(out_dir.join("build-info.txt")).unwrap(); if let Ok(commit) = read_commit() { writeln!(f, "commit: {}", commit).unwrap(); diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 412aadee..6e575dd1 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -644,7 +644,7 @@ fn main2() -> Result<(), Box> { index.write_all(tera.render("dm_index.html", &tera::Context::from_serialize(Index { env, html: index_docs.as_ref().map(|(_, docs)| &docs.html[..]), - modules: build_index_tree(modules.iter().map(|(_path, module)| IndexTree { + modules: build_index_tree(modules.values().map(|module| IndexTree { htmlname: &module.htmlname, full_name: &module.htmlname, self_name: match module.name { @@ -910,9 +910,9 @@ fn broken_link_fixer<'str>( eprint!(" [{}]: unknown crosslink, guessing [{}", reference, &progress[..best]); } if let Some(proc_name) = proc_name { - let _ = eprint!("/proc/{}", proc_name); + eprint!("/proc/{}", proc_name); } else if let Some(var_name) = var_name { - let _ = eprint!("/var/{}", var_name); + eprint!("/var/{}", var_name); } eprintln!("]"); progress.truncate(best); diff --git a/crates/dmdoc/src/markdown.rs b/crates/dmdoc/src/markdown.rs index 12c72e2c..c158fac1 100644 --- a/crates/dmdoc/src/markdown.rs +++ b/crates/dmdoc/src/markdown.rs @@ -5,7 +5,7 @@ use std::collections::VecDeque; use pulldown_cmark::{self, Parser, Tag, Event, BrokenLinkCallback, HeadingLevel}; -pub fn render<'string, 'func>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, 'func>) -> String { +pub fn render<'string>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, '_>) -> String { let mut buf = String::new(); push_html(&mut buf, parser(markdown, broken_link_callback)); buf @@ -20,11 +20,11 @@ pub struct DocBlock { } impl DocBlock { - pub fn parse<'string, 'func>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, 'func>) -> Self { + pub fn parse<'string>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, '_>) -> Self { parse_main(parser(markdown, broken_link_callback).peekable()) } - pub fn parse_with_title<'string, 'func>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, 'func>) -> (Option, Self) { + pub fn parse_with_title<'string>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, '_>) -> (Option, Self) { let mut parser = parser(markdown, broken_link_callback).peekable(); ( if let Some(&Event::Start(Tag::Heading(HeadingLevel::H1, _, _))) = parser.peek() { diff --git a/crates/dmm-tools-cli/build.rs b/crates/dmm-tools-cli/build.rs index cc4979da..d9951a53 100644 --- a/crates/dmm-tools-cli/build.rs +++ b/crates/dmm-tools-cli/build.rs @@ -8,7 +8,7 @@ use std::path::PathBuf; fn main() { let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); - let mut f = File::create(&out_dir.join("build-info.txt")).unwrap(); + let mut f = File::create(out_dir.join("build-info.txt")).unwrap(); if let Ok(commit) = read_commit() { writeln!(f, "commit: {}", commit).unwrap(); diff --git a/crates/dmm-tools-cli/src/main.rs b/crates/dmm-tools-cli/src/main.rs index 1d686128..b6e0eb5c 100644 --- a/crates/dmm-tools-cli/src/main.rs +++ b/crates/dmm-tools-cli/src/main.rs @@ -332,7 +332,7 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { if parallel { ((min.z - 1)..(max.z)).into_par_iter().for_each(do_z_level); } else { - ((min.z - 1)..(max.z)).into_iter().for_each(do_z_level); + ((min.z - 1)..(max.z)).for_each(do_z_level); } }; diff --git a/crates/dmm-tools/examples/duplicate_icon_states.rs b/crates/dmm-tools/examples/duplicate_icon_states.rs index 85b1b907..10e828cf 100644 --- a/crates/dmm-tools/examples/duplicate_icon_states.rs +++ b/crates/dmm-tools/examples/duplicate_icon_states.rs @@ -15,7 +15,7 @@ fn is_visible(entry: &DirEntry) -> bool { .file_name() .unwrap_or("".as_ref()) .to_str() - .map(|s| !s.starts_with(".")) + .map(|s| !s.starts_with('.')) .unwrap_or(true) } diff --git a/crates/dmm-tools/src/dmi.rs b/crates/dmm-tools/src/dmi.rs index d8f4bbbf..bd32d848 100644 --- a/crates/dmm-tools/src/dmi.rs +++ b/crates/dmm-tools/src/dmi.rs @@ -233,7 +233,7 @@ impl Image { dst[i] = 0; } } - dst.a = out_a as u8; + dst.a = out_a; sx += 1; } diff --git a/crates/dmm-tools/src/dmm.rs b/crates/dmm-tools/src/dmm.rs index 3519d393..65b48d41 100644 --- a/crates/dmm-tools/src/dmm.rs +++ b/crates/dmm-tools/src/dmm.rs @@ -333,9 +333,9 @@ impl fmt::Display for FormatKey { const BASE_52: &[u8] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; fn base_52_reverse(ch: u8) -> Result { - if (b'a'..=b'z').contains(&ch) { + if ch.is_ascii_lowercase() { Ok(ch as KeyType - b'a' as KeyType) - } else if (b'A'..=b'Z').contains(&ch) { + } else if ch.is_ascii_uppercase() { Ok(26 + ch as KeyType - b'A' as KeyType) } else { Err(format!("Not a base-52 character: {:?}", ch as char)) diff --git a/crates/dmm-tools/src/render_passes/icon_smoothing.rs b/crates/dmm-tools/src/render_passes/icon_smoothing.rs index 623a6c8f..1644897b 100644 --- a/crates/dmm-tools/src/render_passes/icon_smoothing.rs +++ b/crates/dmm-tools/src/render_passes/icon_smoothing.rs @@ -110,7 +110,7 @@ fn find_type_in_direction(objtree: &ObjectTree, adjacency: &Neighborhood, source } match source.get_var("canSmoothWith", objtree) { - &Constant::List(ref elements) => if smooth_flags & SMOOTH_MORE != 0 { + Constant::List(elements) => if smooth_flags & SMOOTH_MORE != 0 { // smooth with canSmoothWith + subtypes for atom in atom_list { let mut path = atom.get_path(); diff --git a/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs b/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs index 3ef0570b..08af1314 100644 --- a/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs +++ b/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs @@ -130,11 +130,11 @@ fn find_type_in_direction(objtree: &ObjectTree, adjacency: &Neighborhood, source } match source.get_var("canSmoothWith", objtree) { - &Constant::List(ref elements) => { + Constant::List(elements) => { // smooth with anything for which their smoothing_groups overlaps our canSmoothWith let set: std::collections::HashSet<_> = elements.iter().map(|x| &x.0).collect(); for atom in atom_list { - if let &Constant::List(ref elements2) = atom.get_var("smoothing_groups", objtree) { + if let Constant::List(elements2) = atom.get_var("smoothing_groups", objtree) { let set2: std::collections::HashSet<_> = elements2.iter().map(|x| &x.0).collect(); if set.intersection(&set2).next().is_some() { return true; diff --git a/crates/dmm-tools/src/render_passes/mod.rs b/crates/dmm-tools/src/render_passes/mod.rs index 0a20eb62..61a25d38 100644 --- a/crates/dmm-tools/src/render_passes/mod.rs +++ b/crates/dmm-tools/src/render_passes/mod.rs @@ -95,7 +95,7 @@ macro_rules! pass { name: $name, desc: $desc, default: $def, - new: || Box::new(<$typ>::default()) + new: || Box::::default() }) } @@ -290,11 +290,11 @@ impl RenderPass for Overlays { } else { "icon_state" }; - if let &Constant::String(ref door) = atom.get_var(var, objtree) { + if let Constant::String(door) = atom.get_var(var, objtree) { add_to(overlays, atom, bumpalo::format!(in bump, "{}_open", door).into_bump_str()); } } else { - if let &Constant::String(ref door) = atom + if let Constant::String(door) = atom .get_var_notnull("icon_door", objtree) .unwrap_or_else(|| atom.get_var("icon_state", objtree)) { @@ -484,7 +484,7 @@ impl RenderPass for FancyLayers { fn unary_aboveground(atom: &Atom, objtree: &ObjectTree) -> Option<&'static str> { Some(match atom.get_var("icon_state", objtree) { - &Constant::String(ref text) => match &**text { + Constant::String(text) => match &**text { "vent_map-1" | "vent_map-2" | "vent_map-3" | "vent_map-4" => "vent_off", "vent_map_on-1" | "vent_map_on-2" | "vent_map_on-3" | "vent_map_on-4" => "vent_out", "vent_map_siphon_on-1" | "vent_map_siphon_on-2" | "vent_map_siphon_on-3" | "vent_map_siphon_on-4" => "vent_in", diff --git a/crates/dmm-tools/src/render_passes/structures.rs b/crates/dmm-tools/src/render_passes/structures.rs index fb879c5f..a9fb9294 100644 --- a/crates/dmm-tools/src/render_passes/structures.rs +++ b/crates/dmm-tools/src/render_passes/structures.rs @@ -12,8 +12,8 @@ impl RenderPass for Spawners { return true; } match atom.get_var("spawn_list", objtree) { - &Constant::List(ref elements) => { - for &(ref key, _) in elements.iter() { + Constant::List(elements) => { + for (key, _) in elements.iter() { // TODO: use a more civilized lookup method let type_key; let reference = match *key { diff --git a/crates/dmm-tools/tests/parse_codebase.rs b/crates/dmm-tools/tests/parse_codebase.rs index 3bc01f2c..a319d983 100644 --- a/crates/dmm-tools/tests/parse_codebase.rs +++ b/crates/dmm-tools/tests/parse_codebase.rs @@ -11,7 +11,7 @@ fn is_visible(entry: &DirEntry) -> bool { .file_name() .unwrap_or("".as_ref()) .to_str() - .map(|s| !s.starts_with(".")) + .map(|s| !s.starts_with('.')) .unwrap_or(true) } diff --git a/crates/dreamchecker/build.rs b/crates/dreamchecker/build.rs index cc4979da..d9951a53 100644 --- a/crates/dreamchecker/build.rs +++ b/crates/dreamchecker/build.rs @@ -8,7 +8,7 @@ use std::path::PathBuf; fn main() { let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); - let mut f = File::create(&out_dir.join("build-info.txt")).unwrap(); + let mut f = File::create(out_dir.join("build-info.txt")).unwrap(); if let Ok(commit) = read_commit() { writeln!(f, "commit: {}", commit).unwrap(); diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 05948d4d..33793a7a 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -174,12 +174,7 @@ impl<'o> AssumptionSet<'o> { } fn conflicts_with(&self, new: &Assumption) -> Option<&Assumption> { - for each in self.set.iter() { - if each.oneway_conflict(new) || new.oneway_conflict(each) { - return Some(each); - } - } - None + self.set.iter().find(|&each| each.oneway_conflict(new) || new.oneway_conflict(each)) } } diff --git a/crates/dreamchecker/src/switch_rand_range.rs b/crates/dreamchecker/src/switch_rand_range.rs index aecf2b53..764f2de0 100644 --- a/crates/dreamchecker/src/switch_rand_range.rs +++ b/crates/dreamchecker/src/switch_rand_range.rs @@ -89,9 +89,9 @@ fn get_case_range(case: &Case, location: Location) -> Option<(f32, f32)> { fn get_rand_range(maybe_rand: &Expression) -> Option<(i32, i32)> { let (term, location) = match maybe_rand { - &Expression::Base { - ref term, - ref follow, + Expression::Base { + term, + follow, } if follow.is_empty() => (&term.elem, term.location), _ => return None, }; diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 6485d47b..6125d9f1 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -543,7 +543,7 @@ pub struct Ident2 { impl Ident2 { pub fn as_str(&self) -> &str { - &*self.inner + &self.inner } } @@ -574,7 +574,7 @@ impl From for String { impl std::ops::Deref for Ident2 { type Target = str; fn deref(&self) -> &str { - &*self.inner + &self.inner } } @@ -724,7 +724,7 @@ impl Expression { /// If this expression consists of a single term, return it. pub fn as_term(&self) -> Option<&Term> { match self { - &Expression::Base { ref term, ref follow } if follow.is_empty() => Some(&term.elem), + Expression::Base { term, follow } if follow.is_empty() => Some(&term.elem), _ => None, } } @@ -924,7 +924,7 @@ impl Term { } pub fn is_truthy(&self) -> Option { - return match self { + match self { // `null`, `0`, and empty strings are falsey. Term::Null => Some(false), Term::Int(i) => Some(*i != 0), @@ -953,7 +953,7 @@ impl Term { Term::Expr(e) => e.is_truthy(), _ => None, - }; + } } pub fn valid_for_range(&self, other: &Term, step: Option<&Expression>) -> Option { diff --git a/crates/dreammaker/src/config.rs b/crates/dreammaker/src/config.rs index 4adcb258..e056e654 100644 --- a/crates/dreammaker/src/config.rs +++ b/crates/dreammaker/src/config.rs @@ -69,6 +69,7 @@ pub struct Debugger { /// Severity overrides from configuration #[derive(Debug, Deserialize, Clone, Copy, PartialEq)] #[serde(rename_all(deserialize = "lowercase"))] +#[derive(Default)] pub enum WarningLevel { #[serde(alias = "errors")] Error = 1, @@ -80,6 +81,7 @@ pub enum WarningLevel { Hint = 4, #[serde(alias = "false", alias = "off")] Disabled = 5, + #[default] Unset = 6, } @@ -161,11 +163,7 @@ impl WarningLevel { } } -impl Default for WarningLevel { - fn default() -> WarningLevel { - WarningLevel::Unset - } -} + impl From for WarningLevel { fn from(severity: Severity) -> Self { diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index d4bb17bb..40adc04d 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -241,7 +241,7 @@ impl Constant { pub fn contains_key(&self, key: &Constant) -> bool { if let Constant::List(ref elements) = *self { - for &(ref k, _) in elements.iter() { + for (k, _) in elements.iter() { if key == k { return true; } @@ -253,8 +253,8 @@ impl Constant { pub fn index(&self, key: &Constant) -> Option<&Constant> { match (self, key) { // Narrowing conversion is intentional. - (&Constant::List(ref elements), &Constant::Float(i)) => return elements.get(i as usize).map(|&(ref k, _)| k), - (&Constant::List(ref elements), key) => for &(ref k, ref v) in elements.iter() { + (Constant::List(elements), &Constant::Float(i)) => return elements.get(i as usize).map(|(k, _)| k), + (Constant::List(elements), key) => for (k, v) in elements.iter() { if key == k { return v.as_ref(); } @@ -355,7 +355,7 @@ impl fmt::Display for Constant { write!(f, "list(")?; let mut first = true; let mut previous_assoc = false; - for &(ref key, ref val) in list.iter() { + for (key, val) in list.iter() { if !first { write!(f, ",")?; if previous_assoc { @@ -789,7 +789,7 @@ impl<'a> ConstantFolder<'a> { // If the path is all slashes, it's absolute, and doesn't need to be // further resolved. if prefab.path.iter().all(|&(op, _)| op == PathOp::Slash) { - let path: TreePath = prefab.path.iter().map(|&(_, ref name)| name.to_owned()).collect(); + let path: TreePath = prefab.path.iter().map(|(_, name)| name.to_owned()).collect(); return Ok(Pop { path, vars }) } diff --git a/crates/dreammaker/src/dmi.rs b/crates/dreammaker/src/dmi.rs index 4fdaacf3..85b04c76 100644 --- a/crates/dreammaker/src/dmi.rs +++ b/crates/dreammaker/src/dmi.rs @@ -38,8 +38,10 @@ impl From<&str> for StateIndex { /// The two-dimensional facing subset of BYOND's direction type. #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[derive(Default)] pub enum Dir { North = 1, + #[default] South = 2, East = 4, West = 8, @@ -192,11 +194,7 @@ impl Dir { } } -impl Default for Dir { - fn default() -> Self { - Dir::South - } -} + /// Embedded metadata describing a DMI spritesheet's layout. #[derive(Debug, Clone, PartialEq)] diff --git a/crates/dreammaker/src/docs.rs b/crates/dreammaker/src/docs.rs index 0fe0b9bc..1659a176 100644 --- a/crates/dreammaker/src/docs.rs +++ b/crates/dreammaker/src/docs.rs @@ -207,14 +207,12 @@ pub enum DocTarget { /// Information about where builtin docs can be found. #[derive(Clone, Debug, PartialEq)] +#[derive(Default)] pub enum BuiltinDocs { + #[default] None, /// A DM reference hash such as "/DM/vars". ReferenceHash(&'static str), } -impl Default for BuiltinDocs { - fn default() -> Self { - BuiltinDocs::None - } -} + diff --git a/crates/dreammaker/src/error.rs b/crates/dreammaker/src/error.rs index ff88bf87..6f1e4c98 100644 --- a/crates/dreammaker/src/error.rs +++ b/crates/dreammaker/src/error.rs @@ -341,7 +341,9 @@ pub(crate) trait HasLocation { /// The possible diagnostic severities available. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Default)] pub enum Severity { + #[default] Error = 1, Warning = 2, Info = 3, @@ -361,11 +363,7 @@ impl Severity { } } -impl Default for Severity { - fn default() -> Severity { - Severity::Error - } -} + impl fmt::Display for Severity { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -380,7 +378,9 @@ impl fmt::Display for Severity { /// A component which generated a diagnostic, when separation is desired. #[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[derive(Default)] pub enum Component { + #[default] Unspecified, DreamChecker, } @@ -394,11 +394,7 @@ impl Component { } } -impl Default for Component { - fn default() -> Component { - Component::Unspecified - } -} + impl fmt::Display for Component { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index 3343e766..171f6350 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -435,11 +435,11 @@ impl LocatedToken { } fn is_digit(ch: u8) -> bool { - (b'0'..=b'9').contains(&ch) + ch.is_ascii_digit() } fn is_ident(ch: u8) -> bool { - (b'a'..=b'z').contains(&ch) || (b'A'..=b'Z').contains(&ch) || ch == b'_' + ch.is_ascii_lowercase() || ch.is_ascii_uppercase() || ch == b'_' } fn from_latin1(bytes: &[u8]) -> String { diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index a12a3bd5..78dd70e1 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -232,7 +232,7 @@ impl DefineMap { /// Cut a DefineMap from the state of a DefineHistory at the given location. fn from_history(history: &InnerDefineHistory, location: Location) -> DefineMap { let mut map = DefineMap::default(); - for (range, &(ref name, ref define)) in history.range(range(location, location)) { + for (range, (name, define)) in history.range(range(location, location)) { map.insert(name.clone(), (range.start, define.clone())); } map @@ -405,7 +405,7 @@ pub struct Preprocessor<'ctx> { impl<'ctx> HasLocation for Preprocessor<'ctx> { fn location(&self) -> Location { match self.include_stack.stack.last() { - Some(&Include::File { ref lexer, .. }) => lexer.location(), + Some(Include::File { lexer, .. }) => lexer.location(), Some(&Include::Expansion { location, .. }) => location, None => Location::default() } @@ -1015,7 +1015,7 @@ impl<'ctx> Preprocessor<'ctx> { match expansion { Some((location, Define::Constant { subst, docs })) => { - self.annotate_macro(ident, location, Some(docs.clone())); + self.annotate_macro(ident, location, Some(docs)); self.include_stack.stack.push(Include::Expansion { //name: ident.to_owned(), tokens: subst.into_iter().collect(), @@ -1039,7 +1039,7 @@ impl<'ctx> Preprocessor<'ctx> { } } - self.annotate_macro(ident, location, Some(docs.clone())); + self.annotate_macro(ident, location, Some(docs)); // read arguments let mut args = Vec::new(); diff --git a/crates/dreammaker/tests/ast_tests.rs b/crates/dreammaker/tests/ast_tests.rs index 47d03975..345a482e 100644 --- a/crates/dreammaker/tests/ast_tests.rs +++ b/crates/dreammaker/tests/ast_tests.rs @@ -27,7 +27,7 @@ fn check_semicolon_in_proc_parameters() { let errors = context.errors(); assert_eq!(errors.len(), 2); - for error in errors.into_iter() { + for error in errors.iter() { assert_eq!(error.errortype().expect("No errortype set!"), "semicolon_in_proc_parameter"); } }); diff --git a/crates/dreammaker/tests/format_tests.rs b/crates/dreammaker/tests/format_tests.rs index 8fcf4b9c..1f16b363 100644 --- a/crates/dreammaker/tests/format_tests.rs +++ b/crates/dreammaker/tests/format_tests.rs @@ -16,7 +16,7 @@ fn floats() { assert_eq!(FormatFloat(99999.01).to_string(), "99999"); assert_eq!(FormatFloat(999999.0).to_string(), "999999"); assert_eq!(FormatFloat(5.0e6).to_string(), "5e+006"); - assert_eq!(FormatFloat(5000000i32 as f32).to_string(), "5e+006"); + assert_eq!(FormatFloat(5000000_f32).to_string(), "5e+006"); assert_eq!(FormatFloat(9999999.0).to_string(), "1e+007"); assert_eq!(FormatFloat(9999991.0).to_string(), "9.99999e+006"); diff --git a/crates/dreammaker/tests/location_tests.rs b/crates/dreammaker/tests/location_tests.rs index 912da1b6..cc36f9bc 100644 --- a/crates/dreammaker/tests/location_tests.rs +++ b/crates/dreammaker/tests/location_tests.rs @@ -74,7 +74,7 @@ fn reconstruct(tokens: &[LocatedToken], iffy: bool) -> String { write!(this_line, "{}", token.token).unwrap(); } for each in reconstructed.iter_mut() { - if !each.ends_with("\n") { + if !each.ends_with('\n') { each.push('\n'); } } diff --git a/crates/interval-tree/src/node.rs b/crates/interval-tree/src/node.rs index 2b2b7b24..9b6dc856 100644 --- a/crates/interval-tree/src/node.rs +++ b/crates/interval-tree/src/node.rs @@ -234,11 +234,11 @@ fn subtree_max(node: &Option>>) -> u64 { ///returns the smallest key and value after the given key. pub fn min_after<'a,V>(key: &RangeInclusive, root: &'a Box>) -> Option<(&'a RangeInclusive,&'a [V])> { match root.key.cmp(key){ - Ordering::Equal => root.right.as_ref().map_or(None, |succ| Some(succ.min_pair())), - Ordering::Less => root.right.as_ref().map_or(None, |succ| min_after(key, succ)), + Ordering::Equal => root.right.as_ref().map(|succ| succ.min_pair()), + Ordering::Less => root.right.as_ref().and_then(|succ| min_after(key, succ)), Ordering::Greater => { match root.left { - Some(ref succ) => min_after(key, &succ).or( Some((&root.key,&root.data)) ), + Some(ref succ) => min_after(key, succ).or( Some((&root.key,&root.data)) ), None => Some((&root.key, &root.data)) } } @@ -273,7 +273,7 @@ fn is_interval_node(node: &Box>) -> bool { let sorted = is_sorted_left(node) && is_sorted_right(node); let balanced = node.height == cmp::max(height(&node.left),height(&node.right))+1; let proper_max = node.max == cmp::max(subtree_max(&node.left), cmp::max(subtree_max(&node.right), node.key.end)); - return sorted && balanced && proper_max; + sorted && balanced && proper_max } pub fn is_interval_tree(root: &Option>>) -> bool { diff --git a/crates/interval-tree/src/tests.rs b/crates/interval-tree/src/tests.rs index fa372f7c..98e9d181 100644 --- a/crates/interval-tree/src/tests.rs +++ b/crates/interval-tree/src/tests.rs @@ -133,7 +133,7 @@ fn random_range() -> RangeInclusive { len = rand::random::()%(0xff_ff_ff_ff_ff_ff_ff_ff - offset) } - return RangeInclusive::new(offset, offset+len) + RangeInclusive::new(offset, offset+len) } #[test] @@ -155,7 +155,7 @@ fn test_range_iter_nontrivial(){ //assert!(t.test_theban_interval_tree()); }; let query = random_range(); - let should = set.iter().filter(|r| crate::range::intersect(&query, r)).map(|r| r.clone()).collect::>>(); + let should = set.iter().filter(|r| crate::range::intersect(&query, r)).copied().collect::>>(); let is = t.range(query).map(|(r,_)| r).collect::>>(); assert_eq!(should, is); }; diff --git a/crates/interval-tree/src/tree.rs b/crates/interval-tree/src/tree.rs index 5e1eafb6..8c056295 100644 --- a/crates/interval-tree/src/tree.rs +++ b/crates/interval-tree/src/tree.rs @@ -241,8 +241,8 @@ mod tests { fn random_range() -> RangeInclusive { let offset = rand::random::()%50; - let len: u64; - len = rand::random::()%50; + + let len: u64 = rand::random::()%50; crate::range(offset, offset+len) } @@ -262,6 +262,5 @@ mod tests { assert!(is_interval_tree(&t.root)); }; }; - return; } } From 5eb5358fd9126dfc6fe51acc24c68e16b82e1ef4 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 20 Jul 2023 17:45:05 -0700 Subject: [PATCH 044/197] Fix or quiet remaining clippy warnings --- crates/dm-langserver/src/find_references.rs | 2 ++ crates/dm-langserver/src/main.rs | 8 ++------ crates/dmm-tools/src/dmi.rs | 2 +- crates/dreamchecker/src/lib.rs | 12 ++++++------ crates/dreammaker/src/lexer.rs | 2 +- crates/dreammaker/src/parser.rs | 1 + crates/dreammaker/src/preprocessor.rs | 17 ++++++++++------- crates/interval-tree/src/node.rs | 6 +++--- crates/interval-tree/src/tests.rs | 9 ++++----- crates/interval-tree/src/tree.rs | 7 +++---- 10 files changed, 33 insertions(+), 33 deletions(-) diff --git a/crates/dm-langserver/src/find_references.rs b/crates/dm-langserver/src/find_references.rs index 756fc6e0..61cea365 100644 --- a/crates/dm-langserver/src/find_references.rs +++ b/crates/dm-langserver/src/find_references.rs @@ -358,6 +358,7 @@ impl<'o> WalkProc<'o> { } } + #[allow(clippy::only_used_in_recursion)] fn visit_expression(&mut self, location: Location, expression: &'o Expression, type_hint: Option>) -> StaticType<'o> { match expression { Expression::Base { term, follow } => { @@ -678,6 +679,7 @@ impl<'o> WalkProc<'o> { } } + #[allow(clippy::only_used_in_recursion)] fn static_type(&mut self, location: Location, mut of: &[String]) -> StaticType<'o> { while !of.is_empty() && ["static", "global", "const", "tmp", "final", "SpacemanDMM_final", "SpacemanDMM_private", "SpacemanDMM_protected"].contains(&&*of[0]) { of = &of[1..]; diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index 2cad2bb2..42ad7312 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -1404,12 +1404,8 @@ handle_method_call! { let next = self.find_scoped_type(&iter, priors); results.append(&mut self.construct_var_hover(var_name, next, true)?); } - Annotation::MacroUse { docs, .. } => { - if let Some(dc) = docs { - if !dc.is_empty() { - results.push(dc.text()); - } - } + Annotation::MacroUse { docs: Some(dc), .. } if !dc.is_empty() => { + results.push(dc.text()); } _ => {} } diff --git a/crates/dmm-tools/src/dmi.rs b/crates/dmm-tools/src/dmi.rs index bd32d848..88e905f1 100644 --- a/crates/dmm-tools/src/dmi.rs +++ b/crates/dmm-tools/src/dmi.rs @@ -216,7 +216,7 @@ impl Image { ) }; } - let mut dst = &mut self_dat[(y * self.width + x) as usize]; + let dst = &mut self_dat[(y * self.width + x) as usize]; let src_tint = Rgba8::new(tint!(0), tint!(1), tint!(2), tint!(3)); // out_A = src_A + dst_A (1 - src_A) diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 33793a7a..53e33c35 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -554,6 +554,7 @@ pub struct AnalyzeObjectTree<'o> { sleeping_procs: ViolatingProcs<'o>, impure_procs: ViolatingProcs<'o>, + /// Procs with waitfor=0 or waitfor=FALSE waitfor_procs: HashSet>, sleeping_overrides: ViolatingOverrides<'o>, @@ -1448,13 +1449,12 @@ impl<'o, 's> AnalyzeProc<'o, 's> { if name != "waitfor" { return ControlFlow::allfalse() } - match match value.as_term() { - Some(Term::Int(0)) => Some(true), - Some(Term::Ident(i)) if i == "FALSE" => Some(true), - _ => None, + if match value.as_term() { + Some(Term::Int(0)) => true, + Some(Term::Ident(i)) if i == "FALSE" => true, + _ => false, } { - Some(_) => { self.env.waitfor_procs.insert(self.proc_ref); }, - None => (), + self.env.waitfor_procs.insert(self.proc_ref); } }, Statement::Setting { .. } => {}, diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index 171f6350..ed4c46d2 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -204,7 +204,7 @@ fn make_speedy_table() { } } - if &SPEEDY_TABLE[..] != &table[..] { + if SPEEDY_TABLE[..] != table[..] { panic!( "\n\nSpeedy table outdated, replace with:\n\nstatic SPEEDY_TABLE: [(usize, usize); {}] = {:?};\n\n", table.len(), diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 813deb34..cde62424 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -1755,6 +1755,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { success(expr) } + #[allow(clippy::only_used_in_recursion)] fn expression_part(&mut self, lhs: Expression, prev_op: OpInfo, strength: Option, in_ternary: bool) -> Status { use std::cmp::Ordering; diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index 78dd70e1..bc191b1b 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -320,18 +320,21 @@ impl<'ctx> Iterator for IncludeStack<'ctx> { fn next(&mut self) -> Option { loop { match self.stack.last_mut() { - Some(&mut Include::File { ref mut lexer, .. }) => match lexer.next() { - //Some(Err(e)) => return Some(Err(e)), - Some(t) => return Some(t), - None => {} // fall through + Some(&mut Include::File { ref mut lexer, .. }) => { + if let Some(t) = lexer.next() { + return Some(t); + } + // else fallthrough to pop() }, Some(&mut Include::Expansion { ref mut tokens, location, .. - }) => match tokens.pop_front() { - Some(token) => return Some(LocatedToken { location, token }), - None => {} // fall through + }) => { + if let Some(token) = tokens.pop_front() { + return Some(LocatedToken { location, token }); + } + // else fallthrough to pop() }, None => return None, } diff --git a/crates/interval-tree/src/node.rs b/crates/interval-tree/src/node.rs index 9b6dc856..27b11e40 100644 --- a/crates/interval-tree/src/node.rs +++ b/crates/interval-tree/src/node.rs @@ -223,7 +223,7 @@ use super::*; type Node = super::Node; /// returns true iff key is stored in the tree given by root -pub fn contains(key: &RangeInclusive, root: &Box>) -> bool { +pub fn contains(key: &RangeInclusive, root: &Node) -> bool { root.search(key).is_some() } @@ -263,10 +263,10 @@ fn simple_tree(size: i32) -> Box> { } t } -fn is_sorted_left(node: &Box>) -> bool { +fn is_sorted_left(node: &Node) -> bool { node.left.as_ref().map_or(true, |succ| succ.key < node.key) } -fn is_sorted_right(node: &Box>) -> bool { +fn is_sorted_right(node: &Node) -> bool { node.right.as_ref().map_or(true, |succ| succ.key > node.key) } fn is_interval_node(node: &Box>) -> bool { diff --git a/crates/interval-tree/src/tests.rs b/crates/interval-tree/src/tests.rs index 98e9d181..3018029e 100644 --- a/crates/interval-tree/src/tests.rs +++ b/crates/interval-tree/src/tests.rs @@ -126,12 +126,11 @@ fn test_range_iter_non_pointwise(){ fn random_range() -> RangeInclusive { let offset = rand::random::(); - let len: u64; - if rand::random::() { - len = cmp::min(rand::random::()%500, 0xff_ff_ff_ff_ff_ff_ff_ff - offset) + let len: u64 = if rand::random::() { + cmp::min(rand::random::()%500, 0xff_ff_ff_ff_ff_ff_ff_ff - offset) } else { - len = rand::random::()%(0xff_ff_ff_ff_ff_ff_ff_ff - offset) - } + rand::random::()%(0xff_ff_ff_ff_ff_ff_ff_ff - offset) + }; RangeInclusive::new(offset, offset+len) } diff --git a/crates/interval-tree/src/tree.rs b/crates/interval-tree/src/tree.rs index 8c056295..1af6ca3d 100644 --- a/crates/interval-tree/src/tree.rs +++ b/crates/interval-tree/src/tree.rs @@ -92,9 +92,8 @@ impl IntervalTree { /// assert!(t.is_empty()); /// ``` pub fn remove(&mut self, key: RangeInclusive) { - match self.root.take() { - Some(box_to_node) => self.root = box_to_node.delete(key), - None => () + if let Some(box_to_node) = self.root.take() { + self.root = box_to_node.delete(key); } } @@ -241,7 +240,7 @@ mod tests { fn random_range() -> RangeInclusive { let offset = rand::random::()%50; - + let len: u64 = rand::random::()%50; crate::range(offset, offset+len) } From 269ae0ebb21de230380a4b31ab4407930b454bee Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 20 Jul 2023 18:10:18 -0700 Subject: [PATCH 045/197] Run cargo update Also explicitly declare our dependency on syn 1's "full" feature, as otherwise the phf_macros upgrade means the feature will go missing and cause failures in some situations. --- Cargo.lock | 417 +++++++++++--------------- crates/builtins-proc-macro/Cargo.toml | 2 +- 2 files changed, 172 insertions(+), 247 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 668465cc..0c35a059 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,21 +28,18 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" dependencies = [ "memchr", ] [[package]] -name = "aho-corasick" -version = "1.0.0" +name = "android-tzdata" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bce8d450891e3b36f85a2230cec441fddd60e0c455b61b15bb3ffba955ca85" -dependencies = [ - "memchr", -] +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" [[package]] name = "android_system_properties" @@ -105,9 +102,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.4.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" +checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" dependencies = [ "memchr", "serde", @@ -124,9 +121,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "bytemuck" @@ -145,7 +142,7 @@ checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] @@ -165,13 +162,13 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.24" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" dependencies = [ + "android-tzdata", "iana-time-zone", "js-sys", - "num-integer", "num-traits", "time", "wasm-bindgen", @@ -215,16 +212,6 @@ dependencies = [ "vec_map", ] -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - [[package]] name = "color_quant" version = "1.1.0" @@ -245,9 +232,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] @@ -284,9 +271,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", "cfg-if", @@ -297,9 +284,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] @@ -314,50 +301,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "cxx" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" -dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", -] - -[[package]] -name = "cxx-build" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" -dependencies = [ - "cc", - "codespan-reporting", - "once_cell", - "proc-macro2", - "quote", - "scratch", - "syn 2.0.15", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.15", -] - [[package]] name = "dap-types" version = "0.0.0" @@ -387,9 +330,9 @@ checksum = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690" [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", @@ -502,7 +445,7 @@ dependencies = [ "interval-tree", "lodepng", "ordered-float", - "phf 0.11.1", + "phf 0.11.2", "serde", "serde_derive", "termcolor", @@ -518,9 +461,9 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "fallible_collections" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9acf77205554f3cfeca94a4b910e159ad9824e8c2d164de02b3f12495cc1074d" +checksum = "a88c69768c0a15262df21899142bc6df9b9b823546d4b4b9a7bc2d6c448ec6fd" dependencies = [ "hashbrown 0.13.2", ] @@ -536,12 +479,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" dependencies = [ "crc32fast", - "miniz_oxide 0.6.2", + "miniz_oxide", ] [[package]] @@ -552,9 +495,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -615,7 +558,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] @@ -669,9 +612,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", @@ -714,11 +657,11 @@ dependencies = [ [[package]] name = "globset" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" dependencies = [ - "aho-corasick 0.7.20", + "aho-corasick", "bstr", "fnv", "log", @@ -771,12 +714,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "humansize" @@ -789,9 +729,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.56" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -803,19 +743,18 @@ dependencies = [ [[package]] name = "iana-time-zone-haiku" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ - "cxx", - "cxx-build", + "cc", ] [[package]] name = "idna" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -866,9 +805,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jobserver" @@ -881,9 +820,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -911,9 +850,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.142" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libgit2-sys" @@ -929,15 +868,15 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" +checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" [[package]] name = "libz-sys" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" +checksum = "56ee889ecc9568871456d42f603d6a0ce59ff328d291063a45cbdf0036baf6db" dependencies = [ "cc", "libc", @@ -945,15 +884,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "link-cplusplus" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" -dependencies = [ - "cc", -] - [[package]] name = "lodepng" version = "3.7.2" @@ -969,12 +899,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "lsp-types" @@ -991,10 +918,11 @@ dependencies = [ [[package]] name = "matrixmultiply" -version = "0.3.3" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb99c395ae250e1bf9133673f03ca9f97b7e71b705436bf8f089453445d1e9fe" +checksum = "090126dc04f95dc0d1c1c91f61bdd474b3930ca064c1edc8a849da2c6cbe1e77" dependencies = [ + "autocfg", "rawpointer", ] @@ -1006,22 +934,13 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] -[[package]] -name = "miniz_oxide" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.7.1" @@ -1066,34 +985,34 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi 0.3.2", "libc", ] [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "ordered-float" -version = "3.6.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13a384337e997e6860ffbaa83708b2ef329fd8c54cb67a5f64d421e0f943254f" +checksum = "2fc2dbde8f8a79f2102cc474ceb0ad68e3b80b85289ea62389b60e66777e4213" dependencies = [ "num-traits", ] @@ -1109,15 +1028,15 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.5.7" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1403e8401ad5dedea73c626b99758535b342502f8d1e361f4a2dd952749122" +checksum = "0d2d1d55045829d65aad9d389139882ad623b33b904e7c9f1b10c5b8927298e5" dependencies = [ "thiserror", "ucd-trie", @@ -1125,9 +1044,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.5.7" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be99c4c1d2fc2769b1d00239431d711d08f6efedcecb8b6e30707160aee99c15" +checksum = "5f94bca7e7a599d89dea5dfa309e217e7906c3c007fb9c3299c40b10d6a315d3" dependencies = [ "pest", "pest_generator", @@ -1135,22 +1054,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.5.7" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e56094789873daa36164de2e822b3888c6ae4b4f9da555a1103587658c805b1e" +checksum = "99d490fe7e8556575ff6911e45567ab95e71617f43781e5c05490dc8d75c965c" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] name = "pest_meta" -version = "2.5.7" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6733073c7cff3d8459fda0e42f13a047870242aed8b509fe98000928975f359e" +checksum = "2674c66ebb4b4d9036012091b537aae5878970d6999f81a265034d85b136b341" dependencies = [ "once_cell", "pest", @@ -1168,12 +1087,12 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ "phf_macros", - "phf_shared 0.11.1", + "phf_shared 0.11.2", ] [[package]] @@ -1198,25 +1117,25 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ - "phf_shared 0.11.1", + "phf_shared 0.11.2", "rand", ] [[package]] name = "phf_macros" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92aacdc5f16768709a569e913f7451034034178b05bdc8acda226659a3dccc66" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" dependencies = [ - "phf_generator 0.11.1", - "phf_shared 0.11.1", + "phf_generator 0.11.2", + "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.26", ] [[package]] @@ -1231,18 +1150,18 @@ dependencies = [ [[package]] name = "phf_shared" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" dependencies = [ "siphasher", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" [[package]] name = "pin-utils" @@ -1252,21 +1171,21 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "png" -version = "0.17.8" +version = "0.17.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaeebc51f9e7d2c150d3f3bfeb667f2aa985db5ef1e3d212847bdedb488beeaa" +checksum = "59871cc5b6cce7eaccca5a802b4173377a1c2ba90654246789a8fa2334426d11" dependencies = [ "bitflags", "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.7.1", + "miniz_oxide", ] [[package]] @@ -1301,18 +1220,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "pulldown-cmark" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63" +checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" dependencies = [ "bitflags", "getopts", @@ -1322,9 +1241,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.26" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" dependencies = [ "proc-macro2", ] @@ -1389,20 +1308,32 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac6cf59af1067a3fb53fbe5c88c053764e930f932be1d71d3ffe032cbe147f59" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" dependencies = [ - "aho-corasick 1.0.0", + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +dependencies = [ + "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.7.0" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6868896879ba532248f33598de5181522d8b3d9d724dfd230911e1a7d4822f5" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "rgb" @@ -1415,9 +1346,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "same-file" @@ -1430,41 +1361,35 @@ dependencies = [ [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "scratch" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.160" +version = "1.0.173" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "e91f70896d6720bc714a4a57d22fc91f1db634680e65c8efe13323f1fa38d53f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.160" +version = "1.0.173" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +checksum = "a6250dde8342e0232232be9ca3db7aa40aceb5a3e5dd9bddbc00d99a007cde49" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b" dependencies = [ "itoa", "ryu", @@ -1473,20 +1398,20 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" +checksum = "1d89a8107374290037607734c0b73a85db7ed80cae314b3c5791f192a496e731" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if", "cpufeatures", @@ -1566,9 +1491,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970" dependencies = [ "proc-macro2", "quote", @@ -1577,9 +1502,9 @@ dependencies = [ [[package]] name = "tera" -version = "1.18.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a665751302f22a03c56721e23094e4dc22b04a80f381e6737a07bf7a7c70c0" +checksum = "a5ab29bb4f3e256ae6ad5c3e2775aa1f8829f2c0c101fc407bfd3a6df15c60c5" dependencies = [ "chrono", "chrono-tz", @@ -1618,22 +1543,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] @@ -1688,15 +1613,15 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "ucd-trie" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "uncased" -version = "0.9.7" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" +checksum = "9b9bc53168a4be7402ab86c3aad243a84dd7381d09be0eddc81280c1da95ca68" dependencies = [ "version_check", ] @@ -1768,9 +1693,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-normalization" @@ -1795,9 +1720,9 @@ checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "url" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" dependencies = [ "form_urlencoded", "idna", @@ -1847,9 +1772,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1857,24 +1782,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.26", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1882,22 +1807,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.26", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "weezl" @@ -1947,9 +1872,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", diff --git a/crates/builtins-proc-macro/Cargo.toml b/crates/builtins-proc-macro/Cargo.toml index f4a85396..5d4cb9ea 100644 --- a/crates/builtins-proc-macro/Cargo.toml +++ b/crates/builtins-proc-macro/Cargo.toml @@ -8,6 +8,6 @@ edition = "2018" proc-macro = true [dependencies] -syn = "1.0" +syn = { version = "1.0", features = ["full"] } quote = "1.0" proc-macro2 = "1.0.43" From fb57ec3c25453c16fe7679ef3bc7200d19ae7046 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 20 Jul 2023 20:11:36 -0700 Subject: [PATCH 046/197] Replace unmaintained structopt with newer clap version --- Cargo.lock | 281 ++++++++++++++++++------------- crates/dmm-tools-cli/Cargo.toml | 3 +- crates/dmm-tools-cli/build.rs | 2 +- crates/dmm-tools-cli/src/main.rs | 64 +++---- 4 files changed, 200 insertions(+), 150 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c35a059..5b3a8965 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -51,23 +51,52 @@ dependencies = [ ] [[package]] -name = "ansi_term" -version = "0.12.1" +name = "anstream" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" dependencies = [ - "winapi", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", ] [[package]] -name = "atty" -version = "0.2.14" +name = "anstyle" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" + +[[package]] +name = "anstyle-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +dependencies = [ + "anstyle", + "windows-sys", ] [[package]] @@ -91,6 +120,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + [[package]] name = "block-buffer" version = "0.10.4" @@ -199,19 +234,45 @@ dependencies = [ [[package]] name = "clap" -version = "2.34.0" +version = "4.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "5b0827b011f6f8ab38590295339817b0d26f344aa4932c3ced71b45b0c54b4a9" dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim", - "textwrap", - "unicode-width", - "vec_map", + "clap_builder", + "clap_derive", + "once_cell", ] +[[package]] +name = "clap_builder" +version = "4.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9441b403be87be858db6a23edb493e7f694761acdc3343d5a0fcaafd304cbc9e" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "clap_lex" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" + [[package]] name = "color_quant" version = "1.1.0" @@ -224,6 +285,12 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3776b2bcc4e914db501bb9be9572dd706e344b9eb8f882894f3daa651d281381" +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "core-foundation-sys" version = "0.8.4" @@ -401,6 +468,7 @@ version = "1.7.3" dependencies = [ "ahash", "chrono", + "clap", "dmm-tools", "dreammaker", "git2", @@ -408,8 +476,6 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "structopt", - "structopt-derive", ] [[package]] @@ -418,7 +484,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33cf9537e2d06891448799b96d5a8c8083e0e90522a7fdabe6ebf4f41d79d651" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -437,7 +503,7 @@ name = "dreammaker" version = "0.1.0" dependencies = [ "ahash", - "bitflags", + "bitflags 1.3.2", "builtins-proc-macro", "color_space", "derivative", @@ -459,6 +525,27 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "fallible_collections" version = "0.4.9" @@ -627,7 +714,7 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75fbddaef2e12b4995900539d7209d947b988a3d87ee8737484d049b526e5441" dependencies = [ - "bitflags", + "bitflags 1.3.2", "draw_state", "log", ] @@ -648,7 +735,7 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc" dependencies = [ - "bitflags", + "bitflags 1.3.2", "libc", "libgit2-sys", "log", @@ -674,7 +761,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" dependencies = [ - "bitflags", + "bitflags 1.3.2", "ignore", "walkdir", ] @@ -696,21 +783,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.3.3" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" @@ -803,6 +878,17 @@ dependencies = [ "rand", ] +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi", + "rustix", + "windows-sys", +] + [[package]] name = "itoa" version = "1.0.9" @@ -884,6 +970,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" + [[package]] name = "lodepng" version = "3.7.2" @@ -909,7 +1001,7 @@ version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9be6e9c7e2d18f651974370d7aff703f9513e0df6e464fd795660edc77e6ca51" dependencies = [ - "bitflags", + "bitflags 1.3.2", "serde", "serde_json", "serde_repr", @@ -998,7 +1090,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi", "libc", ] @@ -1181,7 +1273,7 @@ version = "0.17.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59871cc5b6cce7eaccca5a802b4173377a1c2ba90654246789a8fa2334426d11" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crc32fast", "fdeflate", "flate2", @@ -1194,30 +1286,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" version = "1.0.66" @@ -1233,7 +1301,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" dependencies = [ - "bitflags", + "bitflags 1.3.2", "getopts", "memchr", "unicase", @@ -1344,6 +1412,19 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "rustix" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" +dependencies = [ + "bitflags 2.3.3", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "ryu" version = "1.0.15" @@ -1450,33 +1531,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "structopt" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" @@ -1532,15 +1589,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "thiserror" version = "1.0.43" @@ -1706,12 +1754,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - [[package]] name = "unicode-width" version = "0.1.10" @@ -1730,18 +1772,18 @@ dependencies = [ "serde", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" version = "0.9.4" @@ -1870,6 +1912,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" version = "0.48.1" diff --git a/crates/dmm-tools-cli/Cargo.toml b/crates/dmm-tools-cli/Cargo.toml index e560c042..2db4e074 100644 --- a/crates/dmm-tools-cli/Cargo.toml +++ b/crates/dmm-tools-cli/Cargo.toml @@ -10,8 +10,7 @@ name = "dmm-tools" path = "src/main.rs" [dependencies] -structopt = "0.3.26" -structopt-derive = "0.4.18" +clap = { version = "4.3.17", features = ["derive"] } serde = "1.0.144" serde_derive = "1.0.144" serde_json = "1.0.85" diff --git a/crates/dmm-tools-cli/build.rs b/crates/dmm-tools-cli/build.rs index d9951a53..31ff1307 100644 --- a/crates/dmm-tools-cli/build.rs +++ b/crates/dmm-tools-cli/build.rs @@ -13,7 +13,7 @@ fn main() { if let Ok(commit) = read_commit() { writeln!(f, "commit: {}", commit).unwrap(); } - writeln!(f, "build date: {}", chrono::Utc::now().date_naive()).unwrap(); + write!(f, "build date: {}", chrono::Utc::now().date_naive()).unwrap(); } fn read_commit() -> Result { diff --git a/crates/dmm-tools-cli/src/main.rs b/crates/dmm-tools-cli/src/main.rs index b6e0eb5c..221fc84e 100644 --- a/crates/dmm-tools-cli/src/main.rs +++ b/crates/dmm-tools-cli/src/main.rs @@ -3,7 +3,7 @@ #![doc(hidden)] // Don't interfere with lib docs. extern crate rayon; -extern crate structopt; +extern crate clap; extern crate serde; extern crate serde_json; @@ -20,8 +20,8 @@ use std::sync::atomic::{AtomicIsize, Ordering}; use std::sync::RwLock; use std::collections::HashSet; +use clap::{Parser, Subcommand}; use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator}; -use structopt::StructOpt; use dm::objtree::ObjectTree; use dmm_tools::*; @@ -32,13 +32,7 @@ use ahash::RandomState; // Main driver fn main() { - let opt = Opt::from_clap(&Opt::clap() - .long_version(concat!( - env!("CARGO_PKG_VERSION"), "\n", - include_str!(concat!(env!("OUT_DIR"), "/build-info.txt")), - ).trim_end()) - .get_matches()); - + let opt = Opt::parse(); let mut context = Context::default(); context.dm_context.set_print_severity(Some(dm::Severity::Error)); rayon::ThreadPoolBuilder::new() @@ -90,87 +84,93 @@ impl Context { } } -#[derive(StructOpt, Debug)] -#[structopt(name="dmm-tools", -author="Copyright (C) 2017-2023 Tad Hardesty", -about="This program comes with ABSOLUTELY NO WARRANTY. This is free software, +#[derive(Parser, Debug)] +#[command( + name="dmm-tools", + version=concat!( + env!("CARGO_PKG_VERSION"), "\n", + include_str!(concat!(env!("OUT_DIR"), "/build-info.txt")) + ), + author="Copyright (C) 2017-2023 Tad Hardesty", + about="This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under the conditions of the GNU -General Public License version 3.")] +General Public License version 3.", +)] struct Opt { /// The environment file to operate under. - #[structopt(short="e", long="env")] + #[arg(short='e', long="env")] environment: Option, - #[structopt(short="v", long="verbose")] + #[arg(short='v', long="verbose")] #[allow(dead_code)] verbose: bool, /// Set the number of threads to be used for parallel execution when /// possible. A value of 0 will select automatically, and 1 will be serial. - #[structopt(long="jobs", default_value="1")] + #[arg(long="jobs", default_value="1")] jobs: usize, - #[structopt(subcommand)] + #[command(subcommand)] command: Command, } // ---------------------------------------------------------------------------- // Subcommands -#[derive(StructOpt, Debug)] +#[derive(Subcommand, Debug)] enum Command { /// Show information about the render-pass list. - #[structopt(name = "list-passes")] + #[command(name = "list-passes")] ListPasses { /// Output as JSON. - #[structopt(short="j", long="json")] + #[arg(short='j', long="json")] json: bool, }, /// Build minimaps of the specified maps. - #[structopt(name = "minimap")] + #[command(name = "minimap")] Minimap { /// The output directory. - #[structopt(short="o", default_value="data/minimaps")] + #[arg(short='o', default_value="data/minimaps")] output: String, /// Set the minimum x,y or x,y,z coordinate to act upon (1-indexed, inclusive). - #[structopt(long="min")] + #[arg(long="min")] min: Option, /// Set the maximum x,y or x,y,z coordinate to act upon (1-indexed, inclusive). - #[structopt(long="max")] + #[arg(long="max")] max: Option, /// Enable render-passes, or "all" to only exclude those passed to --disable. - #[structopt(long="enable", default_value="")] + #[arg(long="enable", default_value="")] enable: String, /// Disable render-passes, or "all" to only use those passed to --enable. - #[structopt(long="disable", default_value="")] + #[arg(long="disable", default_value="")] disable: String, /// Run output through pngcrush automatically. Requires pngcrush. - #[structopt(long="pngcrush")] + #[arg(long="pngcrush")] pngcrush: bool, /// Run output through optipng automatically. Requires optipng. - #[structopt(long="optipng")] + #[arg(long="optipng")] optipng: bool, /// The list of maps to process. files: Vec, }, /// List the differing coordinates between two maps. - #[structopt(name="diff-maps")] + #[command(name="diff-maps")] DiffMaps { left: String, right: String, }, /// Show metadata information about the map. - #[structopt(name="map-info")] + #[command(name="map-info")] MapInfo { /// Output as JSON. - #[structopt(short="j", long="json")] + #[arg(short='j', long="json")] json: bool, /// The list of maps to show info on. From 9467bd3ab34a272c7da64023b0ede352bded5d77 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 20 Jul 2023 21:57:25 -0700 Subject: [PATCH 047/197] Clean up after clippy --fix, including one real error --- crates/dmm-tools/src/render_passes/mod.rs | 2 +- crates/dreammaker/src/config.rs | 2 -- crates/dreammaker/src/dmi.rs | 6 ++---- crates/dreammaker/src/docs.rs | 2 -- crates/dreammaker/src/error.rs | 4 ---- crates/interval-tree/src/tree.rs | 1 - 6 files changed, 3 insertions(+), 14 deletions(-) diff --git a/crates/dmm-tools/src/render_passes/mod.rs b/crates/dmm-tools/src/render_passes/mod.rs index 61a25d38..7bb92520 100644 --- a/crates/dmm-tools/src/render_passes/mod.rs +++ b/crates/dmm-tools/src/render_passes/mod.rs @@ -95,7 +95,7 @@ macro_rules! pass { name: $name, desc: $desc, default: $def, - new: || Box::::default() + new: || Box::<$typ>::default() }) } diff --git a/crates/dreammaker/src/config.rs b/crates/dreammaker/src/config.rs index e056e654..1523347d 100644 --- a/crates/dreammaker/src/config.rs +++ b/crates/dreammaker/src/config.rs @@ -163,8 +163,6 @@ impl WarningLevel { } } - - impl From for WarningLevel { fn from(severity: Severity) -> Self { match severity { diff --git a/crates/dreammaker/src/dmi.rs b/crates/dreammaker/src/dmi.rs index 85b04c76..f38bca4d 100644 --- a/crates/dreammaker/src/dmi.rs +++ b/crates/dreammaker/src/dmi.rs @@ -194,8 +194,6 @@ impl Dir { } } - - /// Embedded metadata describing a DMI spritesheet's layout. #[derive(Debug, Clone, PartialEq)] pub struct Metadata { @@ -558,7 +556,7 @@ state = "duplicate" /// information when a state has the number of frames edited. /// /// This means we need to truncate our delay list to the number of frames specified by the frames key. - /// + /// /// This always worked fine- however, we also simplify `delays = 1,1,...` to `Frames::Count(delays.len())`. /// /// The bug in our code was that we checked if our `delays = 1,1,...` *before* truncating the array @@ -580,4 +578,4 @@ state = "one" let state = metadata.get_icon_state(&StateIndex("one".to_owned(), 0)).expect("Only one state, named one, should be found"); assert_eq!(state.frames, Frames::Count(2)); } -} \ No newline at end of file +} diff --git a/crates/dreammaker/src/docs.rs b/crates/dreammaker/src/docs.rs index 1659a176..a8dd528e 100644 --- a/crates/dreammaker/src/docs.rs +++ b/crates/dreammaker/src/docs.rs @@ -214,5 +214,3 @@ pub enum BuiltinDocs { /// A DM reference hash such as "/DM/vars". ReferenceHash(&'static str), } - - diff --git a/crates/dreammaker/src/error.rs b/crates/dreammaker/src/error.rs index 6f1e4c98..3b718af3 100644 --- a/crates/dreammaker/src/error.rs +++ b/crates/dreammaker/src/error.rs @@ -363,8 +363,6 @@ impl Severity { } } - - impl fmt::Display for Severity { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -394,8 +392,6 @@ impl Component { } } - - impl fmt::Display for Component { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.name() { diff --git a/crates/interval-tree/src/tree.rs b/crates/interval-tree/src/tree.rs index 1af6ca3d..3476b1a4 100644 --- a/crates/interval-tree/src/tree.rs +++ b/crates/interval-tree/src/tree.rs @@ -240,7 +240,6 @@ mod tests { fn random_range() -> RangeInclusive { let offset = rand::random::()%50; - let len: u64 = rand::random::()%50; crate::range(offset, offset+len) } From 6fc78ac43bc7fcc1e903f59432f12996158b614b Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Wed, 17 May 2023 18:44:35 -0700 Subject: [PATCH 048/197] Add AST variants for :: operator --- crates/dreamchecker/src/lib.rs | 30 ++++++++++++++++++++++++++++++ crates/dreammaker/src/ast.rs | 14 ++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 53e33c35..d834efd8 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -1685,6 +1685,18 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Analysis::empty() } }, + Term::GlobalIdent(global_name) => { + if let Some(decl) = self.objtree.root().get_var_declaration(global_name) { + let mut ana = self.static_type(location, &decl.var_type.type_path) + .with_fix_hint(decl.location, "add additional type info here"); + ana.is_impure = Some(true); + ana + } else { + error(location, format!("undefined global var: {:?}", global_name)) + .register(self.context); + Analysis::empty() + } + }, Term::Expr(expr) => self.visit_expression(location, expr, type_hint, local_vars), Term::Prefab(prefab) => { @@ -1762,6 +1774,15 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Analysis::empty() } }, + Term::GlobalCall(global_name, args) => { + if let Some(proc) = self.objtree.root().get_proc(global_name) { + self.visit_call(location, self.objtree.root(), proc, args, true, local_vars) + } else { + error(location, format!("undefined global proc: {:?}", global_name)) + .register(self.context); + Analysis::empty() + } + }, Term::NewImplicit { args } => { if let Some(hint) = type_hint { @@ -1970,6 +1991,11 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Analysis::empty() } }, + Follow::StaticField(name) => { + // TODO + Analysis::empty() + }, + Follow::Call(kind, name, arguments) => { if let Some(ty) = lhs.static_ty.basic_type() { self.check_type_sleepers(ty, location, name); @@ -2006,6 +2032,10 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Analysis::empty() } }, + Follow::ProcReference(name) => { + // TODO + Analysis::empty() + }, } } diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 6125d9f1..49d8086a 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -910,6 +910,10 @@ pub enum Term { function_name: Box, args: Box<[Expression]>, }, + /// Unscoped `::A` is a shorthand for `global.A` + GlobalIdent(Ident2), + /// Unscoped `::A(...)` is a shorthand for `global.A(...)` + GlobalCall(Ident2, Box<[Expression]>), } impl Term { @@ -1012,6 +1016,16 @@ pub enum Follow { Call(PropertyAccessKind, Ident2, Box<[Expression]>), /// Apply a unary operator to the value. Unary(UnaryOp), + /// Any of: + /// - `/typepath::static_var` to read/write any type's static variables. + /// - `/typepath::normal_var` gets the initial value of any type var. + /// - `parent_type::normal_var` gets the initial value on the parent type. Only works outside procs. + /// - `type::normal_var` gets the initial value on the current type. Only works outside procs. Beware loops. + StaticField(Ident2), + /// `foo::bar()` is a proc reference. + /// If the LHS is a constant typepath, that is used. + /// Otherwise the **static** type of LHS is used. + ProcReference(Ident2), } /// Like a `Follow` but only supports field accesses. From 6df1be0be8f0315cf07f8811c87bf370ae5264f9 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 3 Sep 2023 22:06:49 -0700 Subject: [PATCH 049/197] Add :: stubs to find_references --- crates/dm-langserver/src/find_references.rs | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/crates/dm-langserver/src/find_references.rs b/crates/dm-langserver/src/find_references.rs index 61cea365..21e6156c 100644 --- a/crates/dm-langserver/src/find_references.rs +++ b/crates/dm-langserver/src/find_references.rs @@ -527,6 +527,23 @@ impl<'o> WalkProc<'o> { self.visit_arguments(location, args); StaticType::None }, + + Term::GlobalCall(name, args) => { + if let Some(proc) = self.objtree.root().get_proc(name) { + self.visit_call(location, self.objtree.root(), proc, args, false) + } else { + self.visit_arguments(location, args); + StaticType::None + } + }, + Term::GlobalIdent(name) => { + if let Some(decl) = self.objtree.root().get_var_declaration(name) { + self.tab.use_symbol(decl.id, location); + self.static_type(location, &decl.var_type.type_path) + } else { + StaticType::None + } + }, } } @@ -602,6 +619,7 @@ impl<'o> WalkProc<'o> { } }, Follow::Field(_, name) => self.visit_field(location, lhs, name), + Follow::StaticField(name) => self.visit_field(location, lhs, name), Follow::Call(_, name, arguments) => { if let Some(ty) = lhs.basic_type() { if let Some(proc) = ty.get_proc(name) { @@ -615,6 +633,14 @@ impl<'o> WalkProc<'o> { StaticType::None } }, + Follow::ProcReference(name) => { + if let Some(ty) = lhs.basic_type() { + if let Some(decl) = ty.get_proc_declaration(name) { + self.tab.use_symbol(decl.id, location); + } + } + StaticType::None + }, } } From 90992c7e6e3b40fa409e47c4599f598028195381 Mon Sep 17 00:00:00 2001 From: Jordan Dominion Date: Sat, 7 Oct 2023 20:36:12 -0400 Subject: [PATCH 050/197] Allow measuring the memory footprint of the Objtree with GetSize trait (#359) Useful for diagnostics. Co-authored-by: Tad Hardesty --- Cargo.lock | 134 +++++++++++++++++++++++++++++ crates/dreammaker/Cargo.toml | 2 + crates/dreammaker/src/ast.rs | 56 +++++++----- crates/dreammaker/src/constants.rs | 18 ++-- crates/dreammaker/src/docs.rs | 13 +-- crates/dreammaker/src/error.rs | 6 +- crates/dreammaker/src/lib.rs | 25 ++++++ crates/dreammaker/src/objtree.rs | 27 ++++-- 8 files changed, 238 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b3a8965..1a3d2c9c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -99,6 +99,34 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "attribute-derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c124f12ade4e670107b132722d0ad1a5c9790bcbc1b265336369ea05626b4498" +dependencies = [ + "attribute-derive-macro", + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "attribute-derive-macro" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b217a07446e0fb086f83401a98297e2d81492122f5874db5391bd270a185f88" +dependencies = [ + "collection_literals", + "interpolator", + "proc-macro-error", + "proc-macro-utils", + "proc-macro2", + "quote", + "quote-use", + "syn 2.0.26", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -273,6 +301,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +[[package]] +name = "collection_literals" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186dce98367766de751c42c4f03970fc60fc012296e706ccbb9d5df9b6c1e271" + [[package]] name = "color_quant" version = "1.1.0" @@ -389,6 +423,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive-where" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146398d62142a0f35248a608f17edf0dde57338354966d6e41d0eb2d16980ccb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + [[package]] name = "deunicode" version = "0.4.3" @@ -507,6 +552,8 @@ dependencies = [ "builtins-proc-macro", "color_space", "derivative", + "get-size", + "get-size-derive", "indexmap", "interval-tree", "lodepng", @@ -688,6 +735,23 @@ dependencies = [ "version_check", ] +[[package]] +name = "get-size" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b61e2dab7eedce93a83ab3468b919873ff16bac5a3e704011ff836d22b2120" + +[[package]] +name = "get-size-derive" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13a1bcfb855c1f340d5913ab542e36f25a1c56f57de79022928297632435dec2" +dependencies = [ + "attribute-derive", + "quote", + "syn 2.0.26", +] + [[package]] name = "getopts" version = "0.2.21" @@ -871,6 +935,12 @@ dependencies = [ "adler32", ] +[[package]] +name = "interpolator" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71dd52191aae121e8611f1e8dc3e324dd0dd1dee1e6dd91d10ee07a3cfb4d9d8" + [[package]] name = "interval-tree" version = "0.8.0" @@ -1286,6 +1356,41 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-utils" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f59e109e2f795a5070e69578c4dc101068139f74616778025ae1011d4cd41a8" +dependencies = [ + "proc-macro2", + "quote", + "smallvec", +] + [[package]] name = "proc-macro2" version = "1.0.66" @@ -1316,6 +1421,29 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "quote-use" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7b5abe3fe82fdeeb93f44d66a7b444dedf2e4827defb0a8e69c437b2de2ef94" +dependencies = [ + "quote", + "quote-use-macros", + "syn 2.0.26", +] + +[[package]] +name = "quote-use-macros" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ea44c7e20f16017a76a245bb42188517e13d16dcb1aa18044bc406cdc3f4af" +dependencies = [ + "derive-where", + "proc-macro2", + "quote", + "syn 2.0.26", +] + [[package]] name = "rand" version = "0.8.5" @@ -1529,6 +1657,12 @@ dependencies = [ "deunicode", ] +[[package]] +name = "smallvec" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" + [[package]] name = "strsim" version = "0.10.0" diff --git a/crates/dreammaker/Cargo.toml b/crates/dreammaker/Cargo.toml index 31292905..bdd4b8c0 100644 --- a/crates/dreammaker/Cargo.toml +++ b/crates/dreammaker/Cargo.toml @@ -19,6 +19,8 @@ color_space = "0.5.3" ahash = "0.8.0" indexmap = "1.9.1" derivative = "2.2.0" +get-size = "0.1.4" +get-size-derive = "0.1.3" [dev-dependencies] walkdir = "2.3.2" diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 49d8086a..5368a366 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -3,6 +3,9 @@ //! Most AST types can be pretty-printed using the `Display` trait. use std::fmt; use std::iter::FromIterator; + +use get_size::GetSize; +use get_size_derive::GetSize; use phf::phf_map; use crate::error::Location; @@ -17,7 +20,7 @@ pub type SwitchCases = [(Spanned>, Block)]; // Simple enums /// The unary operators, both prefix and postfix. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, GetSize)] pub enum UnaryOp { Neg, Not, @@ -78,7 +81,7 @@ impl UnaryOp { /// The DM path operators. /// /// Which path operator is used typically only matters at the start of a path. -#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, GetSize)] pub enum PathOp { /// `/` for absolute pathing. Slash, @@ -105,7 +108,7 @@ impl fmt::Display for PathOp { } /// The binary operators. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, GetSize)] pub enum BinaryOp { Add, Sub, @@ -164,7 +167,7 @@ impl fmt::Display for BinaryOp { } /// The assignment operators, including augmented assignment. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, GetSize)] pub enum AssignOp { Assign, AddAssign, @@ -249,7 +252,7 @@ pub enum TernaryOp { } /// The possible kinds of access operators for lists -#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, GetSize)] pub enum ListAccessKind { /// `[]` Normal, @@ -258,7 +261,7 @@ pub enum ListAccessKind { } /// The possible kinds of index operators, for both fields and methods. -#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, GetSize)] pub enum PropertyAccessKind { /// `a.b` Dot, @@ -292,7 +295,7 @@ impl fmt::Display for PropertyAccessKind { /// DM requires referencing proc paths to include whether the target is /// declared as a proc or verb, even though the two modes are functionally /// identical in many other respects. -#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash, GetSize)] pub enum ProcDeclKind { Proc, Verb, @@ -328,7 +331,7 @@ impl fmt::Display for ProcDeclKind { } } -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, GetSize)] pub enum SettingMode { /// As in `set name = "Use"`. Assign, @@ -398,6 +401,7 @@ macro_rules! type_table { type_table! { /// A type specifier for verb arguments and input() calls. + #[derive(GetSize)] pub struct InputType; // These values can be known with an invocation such as: @@ -421,7 +425,7 @@ type_table! { } bitflags! { - #[derive(Default)] + #[derive(Default, GetSize)] pub struct VarTypeFlags: u8 { // DM flags const STATIC = 1 << 0; @@ -590,8 +594,14 @@ impl fmt::Debug for Ident2 { } } +impl GetSize for Ident2 { + fn get_heap_size(&self) -> usize { + self.inner.as_bytes().len() + } +} + /// An AST element with an additional location attached. -#[derive(Copy, Clone, Eq, Debug)] +#[derive(Copy, Clone, Eq, Debug, GetSize)] pub struct Spanned { // TODO: add a Span type and use it here pub location: Location, @@ -643,7 +653,7 @@ impl<'a> fmt::Display for FormatTypePath<'a> { // Terms and Expressions /// A typepath optionally followed by a set of variables. -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, PartialEq, Debug, GetSize)] pub struct Prefab { pub path: TypePath, pub vars: Box<[(Ident2, Expression)]>, @@ -681,7 +691,7 @@ where } /// The structure of an expression, a tree of terms and operators. -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, PartialEq, Debug, GetSize)] pub enum Expression { /// An expression containing a term directly. The term is evaluated first, /// then its follows, then its unary operators in reverse order. @@ -835,7 +845,7 @@ impl From for Expression { } /// The structure of a term, the basic building block of the AST. -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, PartialEq, Debug, GetSize)] pub enum Term { // Terms with no recursive contents --------------------------------------- /// The literal `null`. @@ -999,14 +1009,14 @@ impl From for Term { } } -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, PartialEq, Debug, GetSize)] pub struct MiniExpr { pub ident: Ident2, pub fields: Box<[Field]>, } /// An expression part which is applied to a term or another follow. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, GetSize)] pub enum Follow { /// Index the value by an expression. Index(ListAccessKind, Box), @@ -1029,7 +1039,7 @@ pub enum Follow { } /// Like a `Follow` but only supports field accesses. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, GetSize)] pub struct Field { pub kind: PropertyAccessKind, pub ident: Ident2, @@ -1042,7 +1052,7 @@ impl From for Follow { } /// A parameter declaration in the header of a proc. -#[derive(Debug, Clone, PartialEq, Default)] +#[derive(Debug, Clone, PartialEq, Default, GetSize)] pub struct Parameter { pub var_type: VarType, pub name: Ident, @@ -1063,7 +1073,7 @@ impl fmt::Display for Parameter { } /// A type which may be ascribed to a `var`. -#[derive(Debug, Clone, PartialEq, Default)] +#[derive(Debug, Clone, PartialEq, Default, GetSize)] pub struct VarType { pub flags: VarTypeFlags, pub type_path: TreePath, @@ -1175,7 +1185,7 @@ impl VarSuffix { pub type Block = Box<[Spanned]>; /// A statement in a proc body. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, GetSize)] pub enum Statement { Expr(Expression), Return(Option), @@ -1235,20 +1245,20 @@ pub enum Statement { Crash(Option), } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, GetSize)] pub struct VarStatement { pub var_type: VarType, pub name: Ident, pub value: Option, } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, GetSize)] pub enum Case { Exact(Expression), Range(Expression, Expression), } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, GetSize)] pub struct ForListStatement { pub var_type: Option, pub name: Ident2, @@ -1259,7 +1269,7 @@ pub struct ForListStatement { pub block: Block, } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, GetSize)] pub struct ForRangeStatement { pub var_type: Option, pub name: Ident2, diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index 40adc04d..19ba0318 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -3,11 +3,16 @@ use std::fmt; use std::ops; use std::path::Path; +use get_size::GetSize; +use get_size_derive::GetSize; + use indexmap::IndexMap; use ahash::RandomState; use ordered_float::OrderedFloat; use color_space::{Hsl, Hsv, Lch, Rgb}; +use crate::heap_size_of_index_map; + use super::ast::*; use super::objtree::*; use super::preprocessor::DefineMap; @@ -18,9 +23,10 @@ pub type Arguments = [(Constant, Option)]; /// An absolute typepath and optional variables. /// /// The path may involve `/proc` or `/verb` references. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, GetSize)] pub struct Pop { pub path: TreePath, + #[get_size(size_fn = heap_size_of_index_map)] pub vars: IndexMap, } @@ -62,7 +68,7 @@ impl fmt::Display for Pop { /// /// This is intended to represent the degree to which constants are evaluated /// before being displayed in DreamMaker. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, GetSize)] pub enum Constant { /// The literal `null`. Null(Option), @@ -80,9 +86,9 @@ pub enum Constant { /// A prefab literal. Prefab(Box), /// A string literal. - String(Box), + String(Ident2), /// A resource literal. - Resource(Box), + Resource(Ident2), /// A floating-point (or integer) literal, following BYOND's rules. Float(f32), } @@ -132,7 +138,7 @@ impl std::cmp::PartialEq for Constant { impl std::cmp::Eq for Constant {} /// The constant functions which are represented as-is. -#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, GetSize)] pub enum ConstFn { /// The `icon()` type constructor. Icon, @@ -163,7 +169,7 @@ impl Constant { } #[inline] - pub fn string>>(s: S) -> Constant { + pub fn string>(s: S) -> Constant { Constant::String(s.into()) } diff --git a/crates/dreammaker/src/docs.rs b/crates/dreammaker/src/docs.rs index a8dd528e..d77160ff 100644 --- a/crates/dreammaker/src/docs.rs +++ b/crates/dreammaker/src/docs.rs @@ -2,8 +2,11 @@ use std::fmt; +use get_size::GetSize; +use get_size_derive::GetSize; + /// A collection of documentation comments targeting the same item. -#[derive(Default, Clone, Debug, PartialEq)] +#[derive(Default, Clone, Debug, PartialEq, GetSize)] pub struct DocCollection { elems: Vec, pub builtin_docs: BuiltinDocs, @@ -60,7 +63,7 @@ impl DocCollection { } /// A documentation comment. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, GetSize)] pub struct DocComment { pub kind: CommentKind, pub target: DocTarget, @@ -95,7 +98,7 @@ impl fmt::Display for DocComment { } /// The possible documentation comment kinds. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, GetSize)] pub enum CommentKind { /// A block `/** */` comment. Block, @@ -197,7 +200,7 @@ fn is_empty(text: &str, ignore_char: char) -> bool { } /// The possible items that a documentation comment may target. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, GetSize)] pub enum DocTarget { /// Starting with `*` or `/`, referring to the following item. FollowingItem, @@ -206,7 +209,7 @@ pub enum DocTarget { } /// Information about where builtin docs can be found. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, GetSize)] #[derive(Default)] pub enum BuiltinDocs { #[default] diff --git a/crates/dreammaker/src/error.rs b/crates/dreammaker/src/error.rs index 3b718af3..f6533f3b 100644 --- a/crates/dreammaker/src/error.rs +++ b/crates/dreammaker/src/error.rs @@ -7,6 +7,8 @@ use std::collections::HashMap; use ahash::RandomState; +use get_size::GetSize; +use get_size_derive::GetSize; use termcolor::{ColorSpec, Color}; use crate::config::Config; @@ -15,6 +17,8 @@ use crate::config::Config; #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct FileId(u16); +impl GetSize for FileId {} + const FILEID_BUILTINS: FileId = FileId(0x0000); const FILEID_MIN: FileId = FileId(0x0001); const FILEID_MAX: FileId = FileId(0xfffe); @@ -273,7 +277,7 @@ impl Context { // Location handling /// File, line, and column information for an error. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default, GetSize)] pub struct Location { /// The index into the file table. pub file: FileId, diff --git a/crates/dreammaker/src/lib.rs b/crates/dreammaker/src/lib.rs index 835e7bc9..ce330eb7 100644 --- a/crates/dreammaker/src/lib.rs +++ b/crates/dreammaker/src/lib.rs @@ -25,7 +25,10 @@ macro_rules! try_iter { } mod error; +use ahash::RandomState; pub use error::*; +use get_size::GetSize; +use indexmap::IndexMap; // roughly in order of stage pub mod docs; @@ -195,3 +198,25 @@ pub fn detect_environment_default() -> std::io::Result(index_map: &IndexMap) -> usize +where + K: GetSize, + V: GetSize, +{ + let mut total = 0; + + for (k, v) in index_map.iter() { + // We assume that keys and value are hold inside the heap. + total += GetSize::get_size(k); + total += GetSize::get_size(v); + } + + let additional: usize = index_map.capacity() - index_map.len(); + total += additional * K::get_stack_size(); + total += additional * V::get_stack_size(); + + total += u64::get_stack_size() * 4; // composition of RandomState + + total +} diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index 46169776..c122747c 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -3,9 +3,14 @@ use std::collections::BTreeMap; use std::fmt; +use get_size::GetSize; +use get_size_derive::GetSize; + use indexmap::IndexMap; use ahash::RandomState; +use crate::heap_size_of_index_map; + use super::ast::{Expression, VarType, VarTypeBuilder, VarSuffix, PathOp, Parameter, Block, ProcDeclKind, Ident}; use super::constants::Constant; use super::docs::DocCollection; @@ -18,6 +23,8 @@ use super::{DMError, Location, Context, Severity}; #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct SymbolId(u32); +impl GetSize for SymbolId {} + #[derive(Debug)] pub struct SymbolIdSource(SymbolId); @@ -47,14 +54,14 @@ impl SymbolIdSource { pub type Vars = IndexMap; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, GetSize)] pub struct VarDeclaration { pub var_type: VarType, pub location: Location, pub id: SymbolId, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, GetSize)] pub struct VarValue { pub location: Location, /// Syntactic value, as specified in the source. @@ -65,13 +72,13 @@ pub struct VarValue { pub docs: DocCollection, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, GetSize)] pub struct TypeVar { pub value: VarValue, pub declaration: Option, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, GetSize)] pub struct ProcDeclaration { pub location: Location, pub kind: ProcDeclKind, @@ -80,7 +87,7 @@ pub struct ProcDeclaration { pub is_protected: bool, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, GetSize)] pub struct ProcValue { pub location: Location, pub parameters: Box<[Parameter]>, @@ -88,7 +95,7 @@ pub struct ProcValue { pub code: Option, } -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, GetSize)] pub struct TypeProc { pub value: Vec, pub declaration: Option, @@ -104,15 +111,17 @@ impl TypeProc { // ---------------------------------------------------------------------------- // Types -#[derive(Debug)] +#[derive(Debug, GetSize)] pub struct Type { pub path: String, path_last_slash: usize, pub location: Location, location_specificity: usize, /// Variables which this type has declarations or overrides for. + #[get_size(size_fn = heap_size_of_index_map)] pub vars: IndexMap, /// Procs and verbs which this type has declarations or overrides for. + #[get_size(size_fn = heap_size_of_index_map)] pub procs: IndexMap, parent_path: NodeIndex, parent_type: NodeIndex, @@ -624,7 +633,7 @@ impl<'a> std::hash::Hash for ProcRef<'a> { // ---------------------------------------------------------------------------- // The object tree itself -#[derive(Debug, Default)] +#[derive(Debug, Default, GetSize)] pub struct ObjectTree { graph: Vec, types: BTreeMap, @@ -1295,3 +1304,5 @@ impl NodeIndex { NodeIndex(std::u32::MAX) } } + +impl GetSize for NodeIndex {} From 47ef0c58abac033f00e9ce82d1b5da131f7ffcd5 Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Sun, 8 Oct 2023 14:22:36 -0700 Subject: [PATCH 051/197] Implement %%, %%=, and operator"" (#371) The float stuff was easy. Operator was too, just took a bit to realize how it worked Nothin much else to say, outside that I needed to roll my own operation for this one, since float remainder is kinda hard to find (and I couldn't after cursory reading) --- crates/dreammaker/src/ast.rs | 5 +++++ crates/dreammaker/src/constants.rs | 8 ++++++++ crates/dreammaker/src/lexer.rs | 14 +++++++++----- crates/dreammaker/src/parser.rs | 12 ++++++++++-- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 5368a366..1e5b4178 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -116,6 +116,7 @@ pub enum BinaryOp { Div, Pow, Mod, + FloatMod, Eq, NotEq, Less, @@ -145,6 +146,7 @@ impl fmt::Display for BinaryOp { Div => "/", Pow => "**", Mod => "%", + FloatMod => "%%", Eq => "==", NotEq => "!=", Less => "<", @@ -175,6 +177,7 @@ pub enum AssignOp { MulAssign, DivAssign, ModAssign, + FloatModAssign, AssignInto, BitAndAssign, AndAssign, @@ -195,6 +198,7 @@ impl fmt::Display for AssignOp { MulAssign => "*=", DivAssign => "/=", ModAssign => "%=", + FloatModAssign => "%%=", AssignInto => ":=", BitAndAssign => "&=", AndAssign => "&&=", @@ -236,6 +240,7 @@ augmented! { Mul = MulAssign; Div = DivAssign; Mod = ModAssign; + FloatMod = FloatModAssign; BitAnd = BitAndAssign; BitOr = BitOrAssign; BitXor = BitXorAssign; diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index 19ba0318..640b8d7e 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -690,6 +690,14 @@ impl<'a> ConstantFolder<'a> { numeric!(LessEq <=); numeric!(Greater >); numeric!(GreaterEq >=); + match (op, lhs, rhs) { + (BinaryOp::FloatMod, Float(lhs), Float(rhs)) => return Ok(Constant::from(lhs - ((lhs / rhs).floor() * rhs))), + (_, lhs_, rhs_) => { + lhs = lhs_; + rhs = rhs_; + } + } + match (op, lhs, rhs) { (BinaryOp::Pow, Float(lhs), Float(rhs)) => return Ok(Constant::from(lhs.powf(rhs))), (_, lhs_, rhs_) => { diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index ed4c46d2..72c418a0 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -74,6 +74,8 @@ table! { "#", Hash; "##", TokenPaste; "%", Mod; + "%%", FloatMod; + "%%=", FloatModAssign; "%=", ModAssign; "&", BitAnd; "&&", And; @@ -150,18 +152,19 @@ static SPEEDY_TABLE: [(usize, usize); 127] = [ (0, 0), (0, 1), (1, 2), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (2, 3), (3, 5), (5, 6), (6, 8), (0, 0), (8, 10), (10, 14), (14, 15), - (15, 16), (16, 17), (17, 20), (20, 23), (23, 24), (24, 27), (27, 30), (30, 34), + (2, 3), (3, 5), (5, 6), (6, 8), (0, 0), (8, 12), (12, 16), (16, 17), + (17, 18), (18, 19), (19, 22), (22, 25), (25, 26), (26, 29), (29, 32), (32, 36), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (34, 37), (37, 38), (38, 43), (43, 45), (45, 49), (49, 53), + (0, 0), (0, 0), (36, 39), (39, 40), (40, 45), (45, 47), (47, 51), (51, 55), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (53, 54), (0, 0), (54, 55), (55, 57), (0, 0), + (0, 0), (0, 0), (0, 0), (55, 56), (0, 0), (56, 57), (57,59), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (57, 59), (59, 63), (63, 64), (64, 67)]; + (0, 0), (0, 0), (0, 0), (59, 61), (61, 65), (65, 66), (66, 69), + ]; #[test] fn make_speedy_table() { @@ -278,6 +281,7 @@ impl Token { Eq | NotEq | Mod | + FloatMod | And | BitAndAssign | AndAssign | diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index cde62424..f9e40bbb 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -150,11 +150,12 @@ oper_table! { BINARY_OPS; Pow { (BinaryOp, Pow), } - // * / % + // * / % %% Mul { (BinaryOp, Mul), // (BinaryOp, Div = Slash), // (BinaryOp, Mod), + (BinaryOp, FloatMod), } // + - Add { @@ -205,7 +206,7 @@ oper_table! { BINARY_OPS; Conditional { (TernaryOp, Conditional = QuestionMark), } - // = += -= -= *= /= %= &= |= ^= <<= >>= + // = += -= -= *= /= %= %%= &= |= ^= <<= >>= Assign { (AssignOp, Assign), (AssignOp, AddAssign), @@ -213,6 +214,7 @@ oper_table! { BINARY_OPS; (AssignOp, MulAssign), (AssignOp, DivAssign), (AssignOp, ModAssign), + (AssignOp, FloatModAssign), (AssignOp, BitAndAssign), (AssignOp, BitOrAssign), (AssignOp, BitXorAssign), @@ -887,6 +889,10 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { last_part.push('%'); } else if self.exact(Punct(ModAssign))?.is_some() { last_part.push_str("%="); + } else if self.exact(Punct(FloatMod))?.is_some() { + last_part.push_str("%%"); + } else if self.exact(Punct(FloatModAssign))?.is_some() { + last_part.push_str("%%="); } else if self.exact(Punct(BitAnd))?.is_some() { last_part.push('&'); } else if self.exact(Punct(BitAndAssign))?.is_some() { @@ -944,6 +950,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } else { last_part.push_str("[]"); } + } else if self.exact(Token::String("".to_string()))?.is_some() { + last_part.push_str("\"\"") } SUCCESS } From d3dbed0fb2abef7a3ce4e723807e607777326e98 Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Sat, 14 Oct 2023 23:05:18 -0700 Subject: [PATCH 052/197] Implements base functionality for __TYPE__ and __PROC__ (#366) We basically just capture them early, and then treat them as unique symbols. We don't replace inline or anything because the required context isn't quite there. --- crates/dm-langserver/src/find_references.rs | 14 ++++++++++++++ crates/dreamchecker/src/lib.rs | 16 ++++++++++++++++ crates/dreammaker/src/ast.rs | 8 ++++++++ crates/dreammaker/src/constants.rs | 9 +++++++++ crates/dreammaker/src/parser.rs | 11 +++++++++++ 5 files changed, 58 insertions(+) diff --git a/crates/dm-langserver/src/find_references.rs b/crates/dm-langserver/src/find_references.rs index 21e6156c..19727c56 100644 --- a/crates/dm-langserver/src/find_references.rs +++ b/crates/dm-langserver/src/find_references.rs @@ -544,6 +544,20 @@ impl<'o> WalkProc<'o> { StaticType::None } }, + + Term::__TYPE__ => { + self.tab.use_symbol(self.ty.id, location); + StaticType::None + }, + Term::__PROC__ => { + let Some(proc) = self.proc else { + return StaticType::None + }; + if let Some(decl) = self.ty.get_proc_declaration(proc.name()) { + self.tab.use_symbol(decl.id, location); + } + StaticType::None + } } } diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index d834efd8..6fcb5b19 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -1738,6 +1738,8 @@ impl<'o, 's> AnalyzeProc<'o, 's> { let src = self.ty; if let Some(proc) = self.ty.get_proc(unscoped_name) { self.visit_call(location, src, proc, args, false, local_vars) + } else if unscoped_name == "__PROC__" { + self.visit_call(location, src, self.proc_ref, args, false, local_vars) } else if unscoped_name == "SpacemanDMM_unlint" { // Escape hatch for cases like `src` in macros used in // global procs. @@ -1882,6 +1884,20 @@ impl<'o, 's> AnalyzeProc<'o, 's> { self.visit_arguments(location, args, local_vars); Analysis::empty() // TODO }, + Term::__TYPE__ => { + let pop = dm::constants::Pop::from(self.ty.path.split('/').skip(1).map(ToOwned::to_owned).collect::>().into_boxed_slice()); + Analysis { + static_ty: StaticType::None, + aset: assumption_set![Assumption::IsPath(true, self.ty)], + value: Some(Constant::Prefab(Box::new(pop))), + fix_hint: None, + is_impure: None, + } + }, + Term::__PROC__ => { + // Can't fuckin do it bros + Analysis::empty() + }, } } diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 1e5b4178..86ce0f08 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -643,6 +643,10 @@ impl<'a, T: fmt::Display> fmt::Display for FormatTreePath<'a, T> { /// A series of identifiers separated by path operators. pub type TypePath = Vec<(PathOp, Ident)>; +pub fn make_typepath(segments: Vec) -> TypePath { + segments.into_iter().fold(vec![], |mut acc, segment| { acc.push((PathOp::Slash, segment)); acc }) +} + pub struct FormatTypePath<'a>(pub &'a [(PathOp, Ident)]); impl<'a> fmt::Display for FormatTypePath<'a> { @@ -867,6 +871,10 @@ pub enum Term { Resource(String), /// An `as()` call, with an input type. Undocumented. As(InputType), + /// A reference to our current proc's name + __PROC__, + /// A reference to the current proc/scope's type + __TYPE__, // Non-function calls with recursive contents ----------------------------- /// An expression contained in a term. diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index 640b8d7e..f498c3fc 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -783,6 +783,15 @@ impl<'a> ConstantFolder<'a> { Term::Int(v) => Constant::Float(v as f32), Term::Float(v) => Constant::from(v), Term::Expr(expr) => self.expr(*expr, type_hint)?, + Term::__TYPE__ => { + if let Some(obj_tree) = &self.tree { + let typeval = TypeRef::new(obj_tree, self.ty).get(); + let path = make_typepath(typeval.path.split("/").filter(|elem| *elem != "").map(|segment| segment.to_string()).collect()); + Constant::Prefab(Box::new(self.prefab(Prefab::from(path))?)) + } else { + return Err(self.error("No type context".to_owned())) + } + }, _ => return Err(self.error("non-constant expression".to_owned())), }) } diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index f9e40bbb..4e905eb9 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -2073,6 +2073,17 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { require!(self.exact(Token::Punct(Punctuation::RParen))); Term::As(input_type) }, + // term :: __PROC__ + Token::Ident(ref i, _) if i == "__PROC__" => { + // We cannot replace with the proc path yet, you don't need one it's fine + Term::__PROC__ + }, + + // term :: __TYPE__ + Token::Ident(ref i, _) if i == "__TYPE__" => { + // We cannot replace with the typepath yet, so we'll hand back a term we can parse later + Term::__TYPE__ + }, // term :: ident arglist | ident Token::Ident(i, _) => { From 39ef2d9aacfb5f48f38689bb731de4d9c5e80ad8 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 14 Oct 2023 20:48:05 -0700 Subject: [PATCH 053/197] Run cargo update --- Cargo.lock | 528 ++++++++++++++++++++--------------------------------- 1 file changed, 198 insertions(+), 330 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a3d2c9c..e7ce033f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,9 +28,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] @@ -52,30 +52,29 @@ dependencies = [ [[package]] name = "anstream" -version = "0.3.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" dependencies = [ "utf8parse", ] @@ -91,9 +90,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", "windows-sys", @@ -108,7 +107,7 @@ dependencies = [ "attribute-derive-macro", "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.38", ] [[package]] @@ -124,7 +123,7 @@ dependencies = [ "proc-macro2", "quote", "quote-use", - "syn 2.0.26", + "syn 2.0.38", ] [[package]] @@ -148,12 +147,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitflags" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" - [[package]] name = "block-buffer" version = "0.10.4" @@ -165,9 +158,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" +checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019" dependencies = [ "memchr", "serde", @@ -184,37 +177,38 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytemuck" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192" +checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.38", ] [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", + "libc", ] [[package]] @@ -225,57 +219,55 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", - "time", "wasm-bindgen", - "winapi", + "windows-targets", ] [[package]] name = "chrono-tz" -version = "0.6.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58549f1842da3080ce63002102d5bc954c7bc843d4f47818e642abdc36253552" +checksum = "f1369bc6b9e9a7dfdae2055f6ec151fe9c554a9d23d357c0237cee2e25eaabb7" dependencies = [ "chrono", "chrono-tz-build", - "phf 0.10.1", + "phf", ] [[package]] name = "chrono-tz-build" -version = "0.0.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db058d493fb2f65f41861bfed7e3fe6335264a9f0f92710cab5bdf01fef09069" +checksum = "e2f5ebdc942f57ed96d560a6d1a459bae5851102a25d5bf89dc04ae453e31ecf" dependencies = [ "parse-zoneinfo", - "phf 0.10.1", + "phf", "phf_codegen", ] [[package]] name = "clap" -version = "4.3.17" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0827b011f6f8ab38590295339817b0d26f344aa4932c3ced71b45b0c54b4a9" +checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" dependencies = [ "clap_builder", "clap_derive", - "once_cell", ] [[package]] name = "clap_builder" -version = "4.3.17" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9441b403be87be858db6a23edb493e7f694761acdc3343d5a0fcaafd304cbc9e" +checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" dependencies = [ "anstream", "anstyle", @@ -285,21 +277,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.3.12" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.38", ] [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" [[package]] name = "collection_literals" @@ -349,16 +341,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" version = "0.8.3" @@ -431,14 +413,23 @@ checksum = "146398d62142a0f35248a608f17edf0dde57338354966d6e41d0eb2d16980ccb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.38", ] [[package]] name = "deunicode" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690" +checksum = "71dbf1bf89c23e9cd1baf5e654f622872655f195b36588dc9dc38f7eda30758c" +dependencies = [ + "deunicode 1.4.1", +] + +[[package]] +name = "deunicode" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a1abaf4d861455be59f64fd2b55606cb151fce304ede7165f410243ce96bde6" [[package]] name = "digest" @@ -529,7 +520,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33cf9537e2d06891448799b96d5a8c8083e0e90522a7fdabe6ebf4f41d79d651" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] [[package]] @@ -548,7 +539,7 @@ name = "dreammaker" version = "0.1.0" dependencies = [ "ahash", - "bitflags 1.3.2", + "bitflags", "builtins-proc-macro", "color_space", "derivative", @@ -558,7 +549,7 @@ dependencies = [ "interval-tree", "lodepng", "ordered-float", - "phf 0.11.2", + "phf", "serde", "serde_derive", "termcolor", @@ -568,30 +559,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" - -[[package]] -name = "errno" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "fallible_collections" @@ -613,9 +583,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", @@ -692,7 +662,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.38", ] [[package]] @@ -749,7 +719,7 @@ checksum = "13a1bcfb855c1f340d5913ab542e36f25a1c56f57de79022928297632435dec2" dependencies = [ "attribute-derive", "quote", - "syn 2.0.26", + "syn 2.0.38", ] [[package]] @@ -769,7 +739,7 @@ checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -778,7 +748,7 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75fbddaef2e12b4995900539d7209d947b988a3d87ee8737484d049b526e5441" dependencies = [ - "bitflags 1.3.2", + "bitflags", "draw_state", "log", ] @@ -799,7 +769,7 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc" dependencies = [ - "bitflags 1.3.2", + "bitflags", "libc", "libgit2-sys", "log", @@ -808,9 +778,9 @@ dependencies = [ [[package]] name = "globset" -version = "0.4.11" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" +checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" dependencies = [ "aho-corasick", "bstr", @@ -825,7 +795,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" dependencies = [ - "bitflags 1.3.2", + "bitflags", "ignore", "walkdir", ] @@ -851,12 +821,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" - [[package]] name = "humansize" version = "2.1.3" @@ -948,17 +912,6 @@ dependencies = [ "rand", ] -[[package]] -name = "is-terminal" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" -dependencies = [ - "hermit-abi", - "rustix", - "windows-sys", -] - [[package]] name = "itoa" version = "1.0.9" @@ -967,9 +920,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" dependencies = [ "libc", ] @@ -1006,9 +959,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "libgit2-sys" @@ -1024,15 +977,15 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libz-sys" -version = "1.1.9" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ee889ecc9568871456d42f603d6a0ce59ff328d291063a45cbdf0036baf6db" +checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" dependencies = [ "cc", "libc", @@ -1040,17 +993,11 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "linux-raw-sys" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" - [[package]] name = "lodepng" -version = "3.7.2" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0ad39f75bbaa4b10bb6f2316543632a8046a5bcf9c785488d79720b21f044f8" +checksum = "a3cdccd0cf57a5d456f0656ebcff72c2e19503287e1afbf3b84382812adc0606" dependencies = [ "crc32fast", "fallible_collections", @@ -1061,9 +1008,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "lsp-types" @@ -1071,7 +1018,7 @@ version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9be6e9c7e2d18f651974370d7aff703f9513e0df6e464fd795660edc77e6ca51" dependencies = [ - "bitflags 1.3.2", + "bitflags", "serde", "serde_json", "serde_repr", @@ -1080,9 +1027,9 @@ dependencies = [ [[package]] name = "matrixmultiply" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090126dc04f95dc0d1c1c91f61bdd474b3930ca064c1edc8a849da2c6cbe1e77" +checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2" dependencies = [ "autocfg", "rawpointer", @@ -1090,9 +1037,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" @@ -1128,9 +1075,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" +checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" dependencies = [ "num-traits", ] @@ -1147,23 +1094,13 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "once_cell" version = "1.18.0" @@ -1172,9 +1109,9 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "ordered-float" -version = "3.7.0" +version = "3.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fc2dbde8f8a79f2102cc474ceb0ad68e3b80b85289ea62389b60e66777e4213" +checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc" dependencies = [ "num-traits", ] @@ -1196,19 +1133,20 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d2d1d55045829d65aad9d389139882ad623b33b904e7c9f1b10c5b8927298e5" +checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" dependencies = [ + "memchr", "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f94bca7e7a599d89dea5dfa309e217e7906c3c007fb9c3299c40b10d6a315d3" +checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" dependencies = [ "pest", "pest_generator", @@ -1216,37 +1154,28 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d490fe7e8556575ff6911e45567ab95e71617f43781e5c05490dc8d75c965c" +checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.38", ] [[package]] name = "pest_meta" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2674c66ebb4b4d9036012091b537aae5878970d6999f81a265034d85b136b341" +checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" dependencies = [ "once_cell", "pest", "sha2", ] -[[package]] -name = "phf" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" -dependencies = [ - "phf_shared 0.10.0", -] - [[package]] name = "phf" version = "0.11.2" @@ -1254,27 +1183,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ "phf_macros", - "phf_shared 0.11.2", + "phf_shared", ] [[package]] name = "phf_codegen" -version = "0.10.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" -dependencies = [ - "phf_shared 0.10.0", - "rand", + "phf_generator", + "phf_shared", ] [[package]] @@ -1283,7 +1202,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ - "phf_shared 0.11.2", + "phf_shared", "rand", ] @@ -1293,21 +1212,11 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", + "phf_generator", + "phf_shared", "proc-macro2", "quote", - "syn 2.0.26", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher", - "uncased", + "syn 2.0.38", ] [[package]] @@ -1321,9 +1230,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.10" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -1339,11 +1248,11 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "png" -version = "0.17.9" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59871cc5b6cce7eaccca5a802b4173377a1c2ba90654246789a8fa2334426d11" +checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" dependencies = [ - "bitflags 1.3.2", + "bitflags", "crc32fast", "fdeflate", "flate2", @@ -1393,9 +1302,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] @@ -1406,7 +1315,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" dependencies = [ - "bitflags 1.3.2", + "bitflags", "getopts", "memchr", "unicase", @@ -1414,9 +1323,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.31" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -1429,7 +1338,7 @@ checksum = "a7b5abe3fe82fdeeb93f44d66a7b444dedf2e4827defb0a8e69c437b2de2ef94" dependencies = [ "quote", "quote-use-macros", - "syn 2.0.26", + "syn 2.0.38", ] [[package]] @@ -1441,7 +1350,7 @@ dependencies = [ "derive-where", "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.38", ] [[package]] @@ -1482,9 +1391,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ "either", "rayon-core", @@ -1492,21 +1401,19 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] name = "regex" -version = "1.9.1" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "aaac441002f822bc9705a681810a4dd2963094b9ca0ddc41cb963a4c189189ea" dependencies = [ "aho-corasick", "memchr", @@ -1516,9 +1423,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.3" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +checksum = "5011c7e263a695dc8ca064cddb722af1be54e517a280b12a5356f98366899e5d" dependencies = [ "aho-corasick", "memchr", @@ -1527,9 +1434,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rgb" @@ -1540,19 +1447,6 @@ dependencies = [ "bytemuck", ] -[[package]] -name = "rustix" -version = "0.38.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" -dependencies = [ - "bitflags 2.3.3", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - [[package]] name = "ryu" version = "1.0.15" @@ -1576,29 +1470,29 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.173" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91f70896d6720bc714a4a57d22fc91f1db634680e65c8efe13323f1fa38d53f" +checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.173" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6250dde8342e0232232be9ca3db7aa40aceb5a3e5dd9bddbc00d99a007cde49" +checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.38", ] [[package]] name = "serde_json" -version = "1.0.103" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", @@ -1607,20 +1501,20 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d89a8107374290037607734c0b73a85db7ed80cae314b3c5791f192a496e731" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.38", ] [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -1629,21 +1523,21 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "siphasher" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] @@ -1654,7 +1548,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373" dependencies = [ - "deunicode", + "deunicode 0.4.5", ] [[package]] @@ -1682,9 +1576,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.26" +version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ "proc-macro2", "quote", @@ -1693,9 +1587,9 @@ dependencies = [ [[package]] name = "tera" -version = "1.19.0" +version = "1.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ab29bb4f3e256ae6ad5c3e2775aa1f8829f2c0c101fc407bfd3a6df15c60c5" +checksum = "970dff17c11e884a4a09bc76e3a17ef71e01bb13447a11e85226e254fe6d10b8" dependencies = [ "chrono", "chrono-tz", @@ -1710,59 +1604,48 @@ dependencies = [ "serde", "serde_json", "slug", - "thread_local", "unic-segment", ] [[package]] name = "termcolor" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" -version = "1.0.43" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.43" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.38", ] [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ + "cfg-if", "once_cell", ] -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - [[package]] name = "tinyvec" version = "1.6.0" @@ -1789,9 +1672,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" @@ -1799,15 +1682,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" -[[package]] -name = "uncased" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b9bc53168a4be7402ab86c3aad243a84dd7381d09be0eddc81280c1da95ca68" -dependencies = [ - "version_check", -] - [[package]] name = "unic-char-property" version = "0.9.0" @@ -1860,9 +1734,9 @@ dependencies = [ [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] @@ -1875,9 +1749,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -1890,15 +1764,15 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "url" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", "idna", @@ -1926,20 +1800,14 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", ] -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1967,7 +1835,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.38", "wasm-bindgen-shared", ] @@ -1989,7 +1857,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.38", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2024,9 +1892,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -2057,9 +1925,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -2072,42 +1940,42 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" From a50249e6f8bd611809a9fbec49e06f9c246264c1 Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Mon, 16 Oct 2023 22:32:57 -0700 Subject: [PATCH 054/197] Handle #pragma multiple, ignore other pragmas (#372) I'm using a second hashmap to track multiple'd files. Not sure that this is the best way of going about it, but it's a living. --- crates/dreammaker/src/preprocessor.rs | 36 +++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index bc191b1b..0c1375c3 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -104,6 +104,7 @@ impl DefineHistory { env_file: self.env_file.clone(), include_stack: Default::default(), include_locations: Default::default(), + multiple_locations: Default::default(), history: Default::default(), // TODO: support branching a second time defines, maps: Default::default(), @@ -129,6 +130,7 @@ impl DefineHistory { env_file: self.env_file.clone(), include_stack: Default::default(), include_locations: Default::default(), + multiple_locations: Default::default(), history: Default::default(), // TODO: support branching a second time defines: DefineMap::from_history(self, self.last_input_loc), maps: Default::default(), @@ -385,6 +387,9 @@ pub struct Preprocessor<'ctx> { include_stack: IncludeStack<'ctx>, include_locations: HashMap, + // list of files with #pragma multiple to allow for more then one include + // should this be done as an enum in include_locations instead? + multiple_locations: HashMap, last_input_loc: Location, output: VecDeque, ifdef_stack: Vec, @@ -427,6 +432,7 @@ impl<'ctx> Preprocessor<'ctx> { env_file, include_stack: IncludeStack { stack: vec![include] }, include_locations: Default::default(), + multiple_locations: Default::default(), history: Default::default(), defines: DefineMap::with_builtins(), maps: Default::default(), @@ -456,6 +462,7 @@ impl<'ctx> Preprocessor<'ctx> { env_file, include_stack: IncludeStack { stack: vec![include] }, include_locations: Default::default(), + multiple_locations: Default::default(), history: Default::default(), defines: DefineMap::with_builtins(), maps: Default::default(), @@ -654,10 +661,18 @@ impl<'ctx> Preprocessor<'ctx> { // All DM source is effectively `#pragma once`. let file_id = self.context.register_file(register); if let Some(&loc) = self.include_locations.get(&file_id) { - Err(DMError::new(self.last_input_loc, format!("duplicate #include {:?}", path)) - .set_severity(Severity::Warning) - .with_note(loc, "previously included here") - .with_errortype("duplicate_include")) + if self.multiple_locations.get(&file_id) == None { + Err(DMError::new(self.last_input_loc, format!("duplicate #include {:?}", path)) + .set_severity(Severity::Warning) + .with_note(loc, "previously included here") + .with_errortype("duplicate_include")) + } else { + Ok(Include::File { + path, + //file: file_id, + lexer: Lexer::from_read(self.context, file_id, read)?, + }) + } } else { self.include_locations.insert(file_id, self.last_input_loc); Ok(Include::File { @@ -706,7 +721,7 @@ impl<'ctx> Preprocessor<'ctx> { const ALL_DIRECTIVES: &[&str] = &[ "if", "ifdef", "ifndef", "elif", "else", "endif", - "include", "define", "undef", "warn", "error", + "include", "define", "undef", "warn", "error", "pragma", ]; let disabled = !inside_condition && self.is_disabled(); match read { @@ -952,6 +967,17 @@ impl<'ctx> Preprocessor<'ctx> { expect_token!((text) = Token::String(text)); self.context.register_error(DMError::new(self.last_input_loc, format!("#{} {}", ident, text))); } + "pragma" if disabled => {} + "pragma" => { + expect_token!((text) = Token::Ident(text, _)); + let pragma_use_loc = _last_expected_loc; + match text.as_str() { + "multiple" => { + self.multiple_locations.insert(pragma_use_loc.file, pragma_use_loc); + }, + _ => {}, + } + } // none of this other stuff should even exist other => { let mut meant = ""; From e5dbc57757bfa919349ff010833ad6f3c295efd1 Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Mon, 16 Oct 2023 23:54:22 -0700 Subject: [PATCH 055/197] Implement __IMPLIED_TYPE__ (#368) It turns out this kinda sucks. it doesn't work with ::, so we don't even really need to care about its value. I threw in support for constant eval but that's inconsistent on our end cause type_hint doesn't always play. I figure it's good to at least have something, and issues can get sorted out as we go. It is also seemingly massively annoying to eval in like, an istype(), since it has special case behavior there. I just kinda left it sit since I'm pretty sure it'd be a massive change to support and it like does not matter. --- crates/dm-langserver/src/find_references.rs | 8 +++++++- crates/dreamchecker/src/lib.rs | 13 +++++++++++++ crates/dreammaker/src/ast.rs | 6 ++++++ crates/dreammaker/src/constants.rs | 7 +++++++ crates/dreammaker/src/parser.rs | 6 ++++++ 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/crates/dm-langserver/src/find_references.rs b/crates/dm-langserver/src/find_references.rs index 19727c56..8849531e 100644 --- a/crates/dm-langserver/src/find_references.rs +++ b/crates/dm-langserver/src/find_references.rs @@ -544,7 +544,6 @@ impl<'o> WalkProc<'o> { StaticType::None } }, - Term::__TYPE__ => { self.tab.use_symbol(self.ty.id, location); StaticType::None @@ -558,6 +557,13 @@ impl<'o> WalkProc<'o> { } StaticType::None } + Term::__IMPLIED_TYPE__ => { + let Some(implied_type) = type_hint else { + return StaticType::None + }; + self.tab.use_symbol(implied_type.id, location); + StaticType::Type(implied_type) + }, } } diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 6fcb5b19..fcdba106 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -1898,6 +1898,19 @@ impl<'o, 's> AnalyzeProc<'o, 's> { // Can't fuckin do it bros Analysis::empty() }, + Term::__IMPLIED_TYPE__ => { + let Some(implied_type) = type_hint else { + return Analysis::empty() + }; + let pop = dm::constants::Pop::from(implied_type.path.split('/').skip(1).map(ToOwned::to_owned).collect::>().into_boxed_slice()); + Analysis { + static_ty: StaticType::None, + aset: assumption_set![Assumption::IsPath(true, self.ty)], + value: Some(Constant::Prefab(Box::new(pop))), + fix_hint: None, + is_impure: None, + } + }, } } diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 86ce0f08..d103bb5e 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -854,6 +854,7 @@ impl From for Expression { } /// The structure of a term, the basic building block of the AST. +#[allow(non_camel_case_types)] #[derive(Clone, PartialEq, Debug, GetSize)] pub enum Term { // Terms with no recursive contents --------------------------------------- @@ -875,6 +876,11 @@ pub enum Term { __PROC__, /// A reference to the current proc/scope's type __TYPE__, + /// If rhs of an assignment op, this is a reference to the lhs var's type + /// If we're used as the second arg of an istype then it's the implied type of the first arg + /// Second case takes precedence over the first, but we don't properly implement because it would be impossible to + /// Tell. You can't DO anything to the __IMPLIED_TYPE__ so we don't really need to care about it + __IMPLIED_TYPE__, // Non-function calls with recursive contents ----------------------------- /// An expression contained in a term. diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index f498c3fc..5740cb94 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -792,6 +792,13 @@ impl<'a> ConstantFolder<'a> { return Err(self.error("No type context".to_owned())) } }, + Term::__IMPLIED_TYPE__ => { + if let Some(lhs_type) = type_hint { + Constant::Prefab(Box::new(Pop::from(lhs_type.clone()))) + } else { + return Err(self.error("No type hint".to_owned())) + } + }, _ => return Err(self.error("non-constant expression".to_owned())), }) } diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 4e905eb9..8cf90514 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -2085,6 +2085,12 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { Term::__TYPE__ }, + // term :: __IMPLIED_TYPE__ + Token::Ident(ref i, _) if i == "__IMPLIED_TYPE__" => { + // We cannot replace with the typepath yet, so we'll hand back a term we can parse later + Term::__IMPLIED_TYPE__ + }, + // term :: ident arglist | ident Token::Ident(i, _) => { let first_token = self.updated_location(); From 61165ec2200819e1e3590824606249dff42714f5 Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Tue, 17 Oct 2023 17:26:38 -0700 Subject: [PATCH 056/197] Implement /proc/final, piped into should not override (#369) As a part of this we need to make a struct when building proc defs, to keep track of their flags AND their kind at the same time. We then pass that down into a new flags var on the proc decl struct, and we're golden. Only thing of note is I removed the is_private and is_protected vars from proc declarations because they were totally unused. Spooky added em a long time ago and I think it was for not much reason. --- crates/dreamchecker/src/lib.rs | 15 ++++- crates/dreamchecker/tests/directive_tests.rs | 27 ++++++++ crates/dreammaker/src/ast.rs | 67 ++++++++++++++++++++ crates/dreammaker/src/objtree.rs | 26 ++++---- crates/dreammaker/src/parser.rs | 53 +++++++++------- 5 files changed, 153 insertions(+), 35 deletions(-) diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index fcdba106..d500cba9 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -750,8 +750,21 @@ impl<'o> AnalyzeObjectTree<'o> { } } - /// Gather and store set directives for the given proc using the provided code body + /// Gather and store set directives for the given proc using the provided code body and already existing flags pub fn gather_settings(&mut self, proc: ProcRef<'o>, code: &'o [Spanned]) { + let proc_location = proc.get().location; + // Need to extract OUR declaration, and not our parent's. so we do the stupid + if let Some(proc_type) = proc.ty().get().procs.get(proc.name()) { + if let Some(declaration) = &proc_type.declaration { + let proc_flags = declaration.flags; + if proc_flags.is_final() { + // lemon todo: this should run, but it doesn't appear to trigger an error like I'd want. needs looking into imo + if let Err(error) = self.must_not_override.insert(proc, true, proc_location) { + self.context.register_error(error); + } + } + } + } for statement in code.iter() { if let Statement::Setting { ref name, ref value, .. } = statement.elem { if name == "SpacemanDMM_return_type" { diff --git a/crates/dreamchecker/tests/directive_tests.rs b/crates/dreamchecker/tests/directive_tests.rs index a9570866..e725887f 100644 --- a/crates/dreamchecker/tests/directive_tests.rs +++ b/crates/dreamchecker/tests/directive_tests.rs @@ -62,11 +62,25 @@ fn no_override() { check_errors_match(code, NO_OVERRIDE_ERRORS); } + +#[test] +fn final_proc() { + let code = r##" +/mob/proc/final/test() + return + +/mob/subtype/test() + return +"##.trim(); + check_errors_match(code, NO_OVERRIDE_ERRORS); +} + pub const NO_OVERRIDE_DISABLE_ERRORS: &[(u32, u16, &str)] = &[ (5, 5, "/mob/subtype/proc/test sets SpacemanDMM_should_not_override false, but it cannot be disabled."), (4, 18, "proc overrides parent, prohibited by /mob/proc/test"), ]; + #[test] fn no_override_disable() { let code = r##" @@ -80,6 +94,19 @@ fn no_override_disable() { check_errors_match(code, NO_OVERRIDE_DISABLE_ERRORS); } +#[test] +fn final_proc_intermix() { + let code = r##" +/mob/proc/final/test() + return + +/mob/subtype/test() + set SpacemanDMM_should_not_override = 0 + return +"##.trim(); + check_errors_match(code, NO_OVERRIDE_DISABLE_ERRORS); +} + #[test] fn can_be_redefined() { let code = r##" diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index d103bb5e..4f989d53 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -295,6 +295,36 @@ impl fmt::Display for PropertyAccessKind { } } +/// Information about a proc declaration +/// +/// Holds what sort of decl it was (did it use /proc or /verb), alongside a set of flags +/// That describe extra info pulled from the path +#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)] +pub struct ProcDeclBuilder { + pub kind: ProcDeclKind, + pub flags: ProcFlags, +} + +impl ProcDeclBuilder { + pub fn new(kind: ProcDeclKind, flags: Option) -> ProcDeclBuilder { + ProcDeclBuilder { kind: kind, flags: flags.unwrap_or(ProcFlags::default()) } + } + + pub fn kind(self) -> &'static str { + self.kind.name() + } + + pub fn is_final(self) -> bool { + self.flags.is_final() + } +} + +impl fmt::Display for ProcDeclBuilder { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{}{}", self.kind, self.flags) + } +} + /// The proc declaration kind, either `proc` or `verb`. /// /// DM requires referencing proc paths to include whether the target is @@ -336,6 +366,43 @@ impl fmt::Display for ProcDeclKind { } } +bitflags! { + #[derive(Default, GetSize)] + pub struct ProcFlags: u8 { + // DM flags + const FINAL = 1 << 0; + } +} + +impl ProcFlags { + pub fn from_name(name: &str) -> Option { + match name { + // DM flags + "final" => Some(ProcFlags::FINAL), + // Fallback + _ => None, + } + } + + #[inline] + pub fn is_final(&self) -> bool { + self.contains(ProcFlags::FINAL) + } + + pub fn to_vec(&self) -> Vec<&'static str> { + let mut v = Vec::new(); + if self.is_final() { v.push("final"); } + v + } +} + +impl fmt::Display for ProcFlags { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + if self.is_final() { fmt.write_str("/final")?; } + Ok(()) + } +} + #[derive(Debug, Clone, Copy, PartialEq, GetSize)] pub enum SettingMode { /// As in `set name = "Use"`. diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index c122747c..7b4ce34e 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -11,7 +11,7 @@ use ahash::RandomState; use crate::heap_size_of_index_map; -use super::ast::{Expression, VarType, VarTypeBuilder, VarSuffix, PathOp, Parameter, Block, ProcDeclKind, Ident}; +use super::ast::{Expression, VarType, VarTypeBuilder, VarSuffix, PathOp, Parameter, Block, ProcDeclBuilder, ProcDeclKind, ProcFlags, Ident}; use super::constants::Constant; use super::docs::DocCollection; use super::{DMError, Location, Context, Severity}; @@ -82,9 +82,8 @@ pub struct TypeVar { pub struct ProcDeclaration { pub location: Location, pub kind: ProcDeclKind, + pub flags: ProcFlags, pub id: SymbolId, - pub is_private: bool, - pub is_protected: bool, } #[derive(Debug, Clone, GetSize)] @@ -1117,7 +1116,7 @@ impl ObjectTreeBuilder { location: Location, parent: NodeIndex, name: &str, - declaration: Option, + declaration: Option, parameters: Vec, code: Option, ) -> Result<(usize, &mut ProcValue), DMError> { @@ -1126,18 +1125,17 @@ impl ObjectTreeBuilder { value: Vec::with_capacity(1), declaration: None, }); - if let Some(kind) = declaration { + if let Some(decl_builder) = declaration { if let Some(ref decl) = proc.declaration { - DMError::new(location, format!("duplicate definition of {}/{}", kind, name)) + DMError::new(location, format!("duplicate definition of {}/{}", decl_builder.kind, name)) .with_note(decl.location, "previous definition") .register(context); } else { proc.declaration = Some(ProcDeclaration { location, - kind, + kind: decl_builder.kind, + flags: decl_builder.flags, id: self.symbols.allocate(), - is_private: false, - is_protected: false, }); } } @@ -1250,8 +1248,14 @@ impl ObjectTreeBuilder { let (parent, mut proc_name) = self.get_from_path(location, &mut path, len)?; let mut declaration = None; if let Some(kind) = ProcDeclKind::from_name(proc_name) { - declaration = Some(kind); - proc_name = match path.next() { + let mut next_entry = path.next(); + let flags = ProcFlags::from_name(next_entry.unwrap_or("")); + if let Some(_) = flags { + // did something? take another step + next_entry = path.next(); + } + declaration = Some(ProcDeclBuilder::new(kind, flags)); + proc_name = match next_entry { Some(name) => name, None => return Err(DMError::new(location, "proc must have a name")), }; diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 8cf90514..8cf26bd2 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -590,13 +590,13 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { self.tree_entries(self.tree.root_index(), None, None, Token::Eof) } - fn tree_block(&mut self, current: NodeIndex, proc_kind: Option, var_type: Option) -> Status<()> { + fn tree_block(&mut self, current: NodeIndex, proc_builder: Option, var_type: Option) -> Status<()> { leading!(self.exact(Token::Punct(Punctuation::LBrace))); - require!(self.tree_entries(current, proc_kind, var_type, Token::Punct(Punctuation::RBrace))); + require!(self.tree_entries(current, proc_builder, var_type, Token::Punct(Punctuation::RBrace))); SUCCESS } - fn tree_entries(&mut self, current: NodeIndex, proc_kind: Option, var_type: Option, terminator: Token) -> Status<()> { + fn tree_entries(&mut self, current: NodeIndex, proc_builder: Option, var_type: Option, terminator: Token) -> Status<()> { loop { let message: Cow<'static, str> = match terminator { Token::Eof => "newline".into(), @@ -609,7 +609,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { continue; } self.put_back(next); - require!(self.tree_entry(current, proc_kind, var_type.clone())); + require!(self.tree_entry(current, proc_builder, var_type.clone())); } SUCCESS } @@ -694,7 +694,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } } - fn tree_entry(&mut self, mut current: NodeIndex, mut proc_kind: Option, mut var_type: Option) -> Status<()> { + fn tree_entry(&mut self, mut current: NodeIndex, mut proc_builder: Option, mut var_type: Option) -> Status<()> { // tree_entry :: path ';' // tree_entry :: path tree_block // tree_entry :: path '=' expression ';' @@ -739,10 +739,16 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { var_type.type_path.push(each.to_owned()); } } else if let Some(kind) = ProcDeclKind::from_name(each) { - proc_kind = Some(kind); - } else if proc_kind.is_some() { - self.error("cannot have sub-blocks of `proc/` block") - .register(self.context); + proc_builder = Some(ProcDeclBuilder::new(kind, None)); + } else if let Some(builder) = proc_builder.as_mut() { + let flags = ProcFlags::from_name(each); + if let Some(found) = flags { + builder.flags |= found + } + else { + self.error("cannot have sub-blocks of `proc/` block") + .register(self.context); + } } else { let len = self.tree.get_path(current).chars().filter(|&c| c == '/').count() + path_len; current = self.tree.subtype_or_add(self.location, current, each, len); @@ -787,16 +793,16 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { handle_relative_type_error!(); let start = self.updated_location(); - if proc_kind.is_some() || var_type.is_some() { + if proc_builder.is_some() || var_type.is_some() { // Can't apply docs to `var/` or `proc/` blocks. - require!(self.tree_block(current, proc_kind, var_type.clone())); + require!(self.tree_block(current, proc_builder, var_type.clone())); } else { - let (comment, ()) = require!(self.doc_comment(|this| this.tree_block(current, proc_kind, var_type.clone()))); + let (comment, ()) = require!(self.doc_comment(|this| this.tree_block(current, proc_builder, var_type.clone()))); self.tree.extend_docs(current, comment); } let node = self.tree.get_path(current).to_owned(); - self.annotate(start, || Annotation::TreeBlock(reconstruct_path(&node, proc_kind, var_type.as_ref(), ""))); + self.annotate(start, || Annotation::TreeBlock(reconstruct_path(&node, proc_builder, var_type.as_ref(), ""))); SUCCESS } Punct(Assign) => { @@ -813,7 +819,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // We have to annotate prior to consuming the statement terminator, as we // will otherwise consume following whitespace resulting in a bad annotation range let node = this.tree.get_path(current).to_owned(); - this.annotate(entry_start, || Annotation::Variable(reconstruct_path(&node, proc_kind, var_type.as_ref(), last_part))); + this.annotate(entry_start, || Annotation::Variable(reconstruct_path(&node, proc_builder, var_type.as_ref(), last_part))); require!(this.statement_terminator()); success(expr) @@ -831,7 +837,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { t @ Punct(LParen) => { // `something(` - proc self.put_back(t); - require!(self.proc_params_and_body(current, proc_kind, last_part, entry_start, absolute)); + require!(self.proc_params_and_body(current, proc_builder, last_part, entry_start, absolute)); SUCCESS } other => { @@ -852,14 +858,14 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let docs = std::mem::take(&mut self.docs_following); var_type.suffix(&var_suffix); let node = self.tree.get_path(current).to_owned(); - self.annotate(entry_start, || Annotation::Variable(reconstruct_path(&node, proc_kind, Some(&var_type), last_part))); + self.annotate(entry_start, || Annotation::Variable(reconstruct_path(&node, proc_builder, Some(&var_type), last_part))); self.tree.declare_var(current, last_part, self.location, docs, var_type.build(), var_suffix.into_initializer()); } } else if ProcDeclKind::from_name(last_part).is_some() { self.error("`proc;` item has no effect") .set_severity(Severity::Warning) .register(self.context); - } else if proc_kind.is_some() { + } else if proc_builder.is_some() { self.error("child of `proc/` without body") .register(self.context); } else { @@ -956,7 +962,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { SUCCESS } - fn proc_params_and_body(&mut self, current: NodeIndex, proc_kind: Option, name: &str, entry_start: Location, absolute: bool) -> Status<()> { + fn proc_params_and_body(&mut self, current: NodeIndex, proc_builder: Option, name: &str, entry_start: Location, absolute: bool) -> Status<()> { use super::lexer::Token::*; use super::lexer::Punctuation::*; @@ -1024,12 +1030,12 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { None }; - match self.tree.register_proc(self.context, location, current, name, proc_kind, parameters, code) { + match self.tree.register_proc(self.context, location, current, name, proc_builder, parameters, code) { Ok((idx, proc)) => { proc.docs.extend(comment); // manually performed for borrowck reasons if let Some(dest) = self.annotations.as_mut() { - let new_stack = reconstruct_path(self.tree.get_path(current), proc_kind, None, name); + let new_stack = reconstruct_path(self.tree.get_path(current), proc_builder, None, name); dest.insert(entry_start..body_start, Annotation::ProcHeader(new_stack.to_vec(), idx)); dest.insert(body_start..self.location, Annotation::ProcBody(new_stack.to_vec(), idx)); } @@ -2395,13 +2401,14 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } } -fn reconstruct_path(node: &str, proc_kind: Option, var_type: Option<&VarTypeBuilder>, last: &str) -> Vec { +fn reconstruct_path(node: &str, proc_deets: Option, var_type: Option<&VarTypeBuilder>, last: &str) -> Vec { let mut result = Vec::new(); for entry in node.split('/').skip(1) { result.push(entry.to_owned()); } - if let Some(kind) = proc_kind { - result.push(kind.to_string()); + if let Some(deets) = proc_deets { + result.push(deets.kind.to_string()); + deets.flags.to_vec().into_iter().for_each(|elem| result.push(elem.to_string())); } if let Some(var) = var_type { result.extend(var.flags.to_vec().into_iter().map(ToOwned::to_owned)); From 970e9d0cfdecb34b96c4d141ea397927e505ea4c Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Tue, 17 Oct 2023 17:58:25 -0700 Subject: [PATCH 057/197] Fix operator/ and operator/= Neither was handled in try_read_operator_name, and `operator/` needed special handling in tree_path so that the `/` isn't taken as a tree path separator and the method is ultimately named just `operator`. Fixes #362. --- crates/dreammaker/src/parser.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 8cf26bd2..c8f4a59c 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -641,10 +641,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } } // followed by ('/' ident)* - loop { - if self.slash()?.is_none() { - break; - } + while parts.last().unwrap() != "operator" && self.slash()?.is_some() { let mut slash_loc = self.location; if let Some(i) = self.ident_in_seq(parts.len())? { parts.push(i); @@ -909,6 +906,10 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { last_part.push_str("**"); } else if self.exact(Punct(MulAssign))?.is_some() { last_part.push_str("*="); + } else if self.exact(Punct(Slash))?.is_some() { + last_part.push('/'); + } else if self.exact(Punct(DivAssign))?.is_some() { + last_part.push_str("/="); } else if self.exact(Punct(Add))?.is_some() { last_part.push('+'); } else if self.exact(Punct(PlusPlus))?.is_some() { From cdbb02897c12ed2f9e2a914caf007c92b2656443 Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Thu, 19 Oct 2023 17:55:12 -0700 Subject: [PATCH 058/197] Parse 'as' return type syntax, but don't check it (#370) I'm not hooking it into the existing return type system because I'm pretty sure it doesn't already support primitives, and I am not prepared to deal with that bullshit. It will parse without erroring tho, so that's based. --- crates/dreamchecker/tests/proc_tests.rs | 37 ++++++++++++++ crates/dreammaker/src/ast.rs | 52 ++++++++++++++++++++ crates/dreammaker/src/objtree.rs | 8 +++- crates/dreammaker/src/parser.rs | 64 +++++++++++++++++++++---- 4 files changed, 150 insertions(+), 11 deletions(-) diff --git a/crates/dreamchecker/tests/proc_tests.rs b/crates/dreamchecker/tests/proc_tests.rs index ec6545e9..366f44be 100644 --- a/crates/dreamchecker/tests/proc_tests.rs +++ b/crates/dreamchecker/tests/proc_tests.rs @@ -2,6 +2,7 @@ extern crate dreamchecker as dc; use dc::test_helpers::check_errors_match; +use dc::test_helpers::parse_a_file_for_test; pub const NO_PARENT_ERRORS: &[(u32, u16, &str)] = &[ (2, 5, "proc has no parent: /mob/proc/test"), @@ -16,3 +17,39 @@ fn no_parent() { "##.trim(); check_errors_match(code, NO_PARENT_ERRORS); } + +#[test] +fn return_type() { + let code = r##" +/mob/proc/test() as /datum + return + +/mob/proc/test2() as num + return +"##.trim(); + let context = parse_a_file_for_test(code); + let error_text: Vec = context.errors().iter().map(|error| format!("{}", error)).collect(); + if error_text.len() > 0 { + panic!("\n{}", error_text.join("\n")) + } +} + +pub const RETURN_TYPE_FAILURE_ERRORS: &[(u32, u16, &str)] = &[ + (4, 13, "Cannot specify a return type for a proc override"), + (7, 22, "Invalid return type"), +]; + +#[test] +fn return_type_failure() { + let code = r##" +/datum/proc/test() as /datum + return + +/mob/test() as /mob + return + +/mob/proc/test2() as bullshit + return +"##.trim(); + check_errors_match(code, RETURN_TYPE_FAILURE_ERRORS); +} diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 4f989d53..0a64c88f 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -295,6 +295,58 @@ impl fmt::Display for PropertyAccessKind { } } +/// Description of the type of an as block, particularly in the context of proc return types +#[derive(Debug, Clone, PartialEq, Eq, Hash, GetSize)] +pub enum AsType { + // These lummy stole from the InputType spec + // There are more but we will parse them into a typepath/string + Text, + Num, + Null, + List, + File, + Anything, + // Any typepath + Type(Vec), +} + +impl AsType { + pub fn from_name(name: &str) -> Option{ + match name { + // First class pairings + "text" => Some(AsType::Text), + "num" => Some(AsType::Num), + "null" => Some(AsType::Null), + "list" => Some(AsType::List), + "file" => Some(AsType::File), + "anything" => Some(AsType::Anything), + + // Vestiges of input(), we just treat these as text I think + "message" | "command_text" | "password" | "color" | "key" => + Some(AsType::Text), + + // Type handling + "mob" => AsType::from_name("/mob"), + "obj" => AsType::from_name("/obj"), + "turf" => AsType::from_name("/turf"), + "area" => AsType::from_name("/area"), + "icon" => AsType::from_name("/icon"), + "sound" => AsType::from_name("/sound"), + // If it looks like a typepath, we'll process it as a typepath (figure out reality later ya feel?) + _ if name.chars().next().unwrap_or(' ') == '/' => + Some(AsType::from_vec(name.split("/").into_iter().filter_map(|part| match part { + "" => None, + _ => Some(part.to_string()), + }).collect::>())), + _ => None, + } + } + + pub fn from_vec(vec: Vec) -> AsType{ + AsType::Type(vec) + } +} + /// Information about a proc declaration /// /// Holds what sort of decl it was (did it use /proc or /verb), alongside a set of flags diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index 7b4ce34e..87fca7b8 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -11,7 +11,7 @@ use ahash::RandomState; use crate::heap_size_of_index_map; -use super::ast::{Expression, VarType, VarTypeBuilder, VarSuffix, PathOp, Parameter, Block, ProcDeclBuilder, ProcDeclKind, ProcFlags, Ident}; +use super::ast::{AsType, Expression, VarType, VarTypeBuilder, VarSuffix, PathOp, Parameter, Block, ProcDeclBuilder, ProcDeclKind, ProcFlags, Ident}; use super::constants::Constant; use super::docs::DocCollection; use super::{DMError, Location, Context, Severity}; @@ -82,6 +82,8 @@ pub struct TypeVar { pub struct ProcDeclaration { pub location: Location, pub kind: ProcDeclKind, + // todo: tie this into our return type, add support for the funky types + pub return_type: AsType, pub flags: ProcFlags, pub id: SymbolId, } @@ -1118,6 +1120,7 @@ impl ObjectTreeBuilder { name: &str, declaration: Option, parameters: Vec, + return_type: AsType, code: Option, ) -> Result<(usize, &mut ProcValue), DMError> { let node = &mut self.inner.graph[parent.index()]; @@ -1135,6 +1138,7 @@ impl ObjectTreeBuilder { location, kind: decl_builder.kind, flags: decl_builder.flags, + return_type, id: self.symbols.allocate(), }); } @@ -1269,7 +1273,7 @@ impl ObjectTreeBuilder { )); } - self.register_proc(context, location, parent, proc_name, declaration, parameters, code) + self.register_proc(context, location, parent, proc_name, declaration, parameters, AsType::Anything, code) } } diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index c8f4a59c..03ff4c80 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -971,14 +971,9 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let location = self.location; let parameters = require!(self.separated(Comma, RParen, None, Parser::proc_parameter)); - - // TODO: store this information. - let _return_type = if let Some(()) = self.exact_ident("as")? { - // For now loosely interpret this as an expression, but really it - // should be either an absolute typepath or some |'d input types. - Some(require!(self.expression())) - } else { - None + let return_type = match self.return_type(proc_builder)? { + Some(type_to_use) => type_to_use, + None => AsType::Anything, }; // split off a subparser so we can keep parsing the objtree @@ -1031,7 +1026,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { None }; - match self.tree.register_proc(self.context, location, current, name, proc_builder, parameters, code) { + match self.tree.register_proc(self.context, location, current, name, proc_builder, parameters, return_type, code) { Ok((idx, proc)) => { proc.docs.extend(comment); // manually performed for borrowck reasons @@ -1159,6 +1154,57 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { success((input_type, in_list)) } + /// Parse an optional as return type signifier (for procs) + fn return_type(&mut self, proc_builder: Option) -> Status { + if self.exact_ident("as")?.is_none() { + return Ok(None); + }; + if proc_builder.is_none() { + self.error("Cannot specify a return type for a proc override") + .register(self.context); + } + // While loop over self.next, extracting either the first string with from_name OR + // if the first string is a slash, continue to extract, and check for a slash again, and finish with from_vec + let return_result: Result = self.next("return type"); + let next_token = return_result?; + if let Token::Ident(text, _) = next_token { + let Some(return_type) = AsType::from_name(text.as_str()) else { + return Err(self.error("Invalid return type")); + }; + return Ok(Some(return_type)); + }; + if Token::Punct(Punctuation::Slash) != next_token { + self.put_back(next_token); + return Err(self.error("Invalid return type")); + }; + // We're pulling out just the text, and we go until the end of the text or until we hit something unexpected + let mut path_vec = vec![]; + let mut slash_last = true; + loop { + let path_component = self.next("return type")?; + match path_component { + Token::Ident(text, whitespace) if slash_last => { + path_vec.push(text); + slash_last = false; + if whitespace { + break; + } + }, + Token::Punct(Punctuation::Slash) if !slash_last => slash_last = true, + _ => { + // If we're done, put back what we just fond so someone else can process it, in case they care + self.put_back(path_component); + break; + }, + } + } + if path_vec.len() > 0 { + Ok(Some(AsType::from_vec(path_vec))) + } else { + Err(self.error("Invalid return type")) + } + } + /// Parse a verb input type. Used by proc params and the input() form. fn input_type(&mut self) -> Status { // Not supporting `as((mob|obj)|turf)` constructs right now. From 2b3d30b9acd62ba34c59326c161d60d0be05542c Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Thu, 19 Oct 2023 18:27:48 -0700 Subject: [PATCH 059/197] Implement the scope operator (#367) Adds support for :: to the parser, in all its forms (global proc/var, off type). Also implements behavior for it. We'll properly read the type of what we attach to, and double check that everything matches. Works for the proc refs too. I've added unit tests for all this to double check my work. I DIDN'T mirror the static var detection byond does. problem for another day. --- crates/dreamchecker/src/lib.rs | 87 +++++++++++- crates/dreammaker/src/ast.rs | 3 + crates/dreammaker/src/constants.rs | 74 +++++++++- crates/dreammaker/src/parser.rs | 31 +++- crates/dreammaker/tests/ast_tests.rs | 205 +++++++++++++++++++++++++++ 5 files changed, 393 insertions(+), 7 deletions(-) diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index d500cba9..47bb4683 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -2034,8 +2034,41 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } }, Follow::StaticField(name) => { - // TODO - Analysis::empty() + let real_type = match lhs.static_ty.basic_type() { + Some(existing_type) => existing_type, + None => { + let Some(to_our_side) = lhs.value else { + error(location, format!("no typepath found for: {:?}", name)) + .register(self.context); + return Analysis::empty() + }; + let Constant::Prefab(typepop) = to_our_side else { + error(location, format!("static access requires a static typepath, {} found instead", to_our_side)) + .register(self.context); + return Analysis::empty() + }; + if !&typepop.vars.is_empty() { + error(location, format!("static access requires a static typepath, {} found instead", typepop)) + .register(self.context); + return Analysis::empty() + } + let typepath = dm::ast::FormatTreePath(&typepop.path).to_string(); + let Some(found_type) = self.objtree.find(typepath.as_str()) else { + error(location, format!("static access requires an existing typepath, {} found instead", typepath)) + .register(self.context); + return Analysis::empty() + }; + found_type + } + }; + let Some(decl) = real_type.get_var_declaration(name) else { + error(location, format!("undefined field: {:?} on {}", name, real_type)) + .register(self.context); + return Analysis::empty() + }; + + self.static_type(location, &decl.var_type.type_path) + .with_fix_hint(decl.location, "add additional type info here") }, Follow::Call(kind, name, arguments) => { @@ -2075,8 +2108,54 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } }, Follow::ProcReference(name) => { - // TODO - Analysis::empty() + let real_type = match lhs.static_ty.basic_type() { + Some(existing_type) => existing_type, + None => { + let Some(to_our_side) = lhs.value else { + error(location, format!("no typepath found for: {:?}", name)) + .register(self.context); + return Analysis::empty() + }; + let Constant::Prefab(typepop) = to_our_side else { + error(location, format!("static proc reference requires a static typepath, {} found instead", to_our_side)) + .register(self.context); + return Analysis::empty() + }; + if !&typepop.vars.is_empty() { + error(location, format!("static proc reference requires a static typepath, {} found instead", typepop)) + .register(self.context); + return Analysis::empty() + } + let typepath = dm::ast::FormatTreePath(&typepop.path).to_string(); + let Some(found_type) = self.objtree.find(typepath.as_str()) else { + error(location, format!("static proc reference requires an existing typepath, {} found instead", typepath)) + .register(self.context); + return Analysis::empty() + }; + found_type + } + }; + let Some(decl) = real_type.get_proc(name) else { + error(location, format!("undefined proc: {:?} on {}", name, real_type)) + .register(self.context); + return Analysis::empty() + }; + + // Gonna build the proc's path + let mut path_elements: Vec = real_type.get().path.split("/").filter(|elem| *elem != "").map(|segment| segment.to_string()).collect(); + // Only tricky bit is adding on the type if required + if let Some(declaration) = decl.get_declaration() { + path_elements.push(declaration.kind.name().to_string()); + } + path_elements.push(decl.name().to_string()); + let path_const = dm::constants::Pop::from(path_elements.into_boxed_slice()); + Analysis { + static_ty: StaticType::None, + aset: assumption_set![Assumption::IsPath(true, real_type)], + value: Some(Constant::Prefab(Box::new(path_const))), + fix_hint: None, + is_impure: None, + } }, } } diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 0a64c88f..69a7062a 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -276,6 +276,8 @@ pub enum PropertyAccessKind { SafeDot, /// `a?:b` SafeColon, + /// 'a::b' + Scope, } impl PropertyAccessKind { @@ -285,6 +287,7 @@ impl PropertyAccessKind { PropertyAccessKind::Colon => ":", PropertyAccessKind::SafeDot => "?.", PropertyAccessKind::SafeColon => "?:", + PropertyAccessKind::Scope => "::", } } } diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index 5740cb94..f9c4d21f 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -652,6 +652,36 @@ impl<'a> ConstantFolder<'a> { } } (term, Follow::Unary(op)) => self.unary(term, op), + (term, Follow::StaticField(field)) => { + let Constant::Prefab(read_from) = term else { + return Err(self.error(format!("non typepath {} used with ::", term))) + }; + if read_from.vars.len() > 0 { + return Err(self.error(format!("non typepath {} used with ::", read_from))) + } + let Some(ref tree) = self.tree else { + return Err(self.error("no type tree available")) + }; + let Some(real_type) = tree.find(FormatTreePath(&read_from.path).to_string().as_str()) else { + return Err(self.error(format!("{} was not a valid type", FormatTreePath(&read_from.path)))) + }; + self.recursive_lookup(real_type.index(), &field, false) + }, + (term, Follow::ProcReference(field)) => { + let Constant::Prefab(read_from) = term else { + return Err(self.error(format!("non typepath {} used with ::", term))) + }; + if read_from.vars.len() > 0 { + return Err(self.error(format!("non typepath {} used with ::", read_from))) + } + let Some(ref tree) = self.tree else { + return Err(self.error("no type tree available")) + }; + let Some(real_type) = tree.find(FormatTreePath(&read_from.path).to_string().as_str()) else { + return Err(self.error(format!("{} was not a valid type", FormatTreePath(&read_from.path)))) + }; + self.proc_ref_lookup(real_type.index(), &field) + }, (term, follow) => Err(self.error(format!("non-constant expression follower: {} {:?}", term, follow))), } } @@ -777,7 +807,33 @@ impl<'a> ConstantFolder<'a> { _ => return Err(self.error(format!("non-constant function call: {}", ident))), }, Term::Prefab(prefab) => Constant::Prefab(Box::new(self.prefab(*prefab)?)), - Term::Ident(ident) => self.ident(ident, false)?, + Term::Ident(ident) => match ident.as_str() { + // We need to handle type and parent_type here + // They technically resolve to their respective values only in type defs when using :: + // But that's annoying so let's not + "type" => { + if let Some(obj_tree) = &self.tree { + let typeval = TypeRef::new(obj_tree, self.ty).get(); + let path = make_typepath(typeval.path.split("/").filter(|elem| *elem != "").map(|segment| segment.to_string()).collect()); + Constant::Prefab(Box::new(self.prefab(Prefab::from(path))?)) + } else { + return Err(self.error("no type context".to_owned())) + } + }, + "parent_type" => { + if let Some(obj_tree) = &self.tree { + let typeref = TypeRef::new(obj_tree, self.ty); + let Some(parent_type) = typeref.parent_type() else { + return Err(self.error(format!("no parent type for {}", typeref))) + }; + let path = make_typepath(parent_type.path.split("/").filter(|elem| *elem != "").map(|segment| segment.to_string()).collect()); + Constant::Prefab(Box::new(self.prefab(Prefab::from(path))?)) + } else { + return Err(self.error("no type context".to_owned())) + } + } + _ => self.ident(ident, false)?, + }, Term::String(v) => Constant::String(v.into()), Term::Resource(v) => Constant::Resource(v.into()), Term::Int(v) => Constant::Float(v as f32), @@ -875,6 +931,22 @@ impl<'a> ConstantFolder<'a> { Err(self.error(format!("unknown variable: {}", ident))) } + fn proc_ref_lookup(&mut self, ty: NodeIndex, name: &str) -> Result { + let tree = self.tree.as_mut().unwrap(); + let proc_type = TypeRef::new(tree, ty); + let Some(proc_ref) = proc_type.get_proc(name) else { + return Err(self.error(format!("unknown proc: {}", name))) + }; + // Gonna build the proc's path + let mut path_elements: Vec = proc_type.get().path.split("/").filter(|elem| *elem != "").map(|segment| segment.to_string()).collect(); + // Only tricky bit is adding on the type if required + if let Some(declaration) = proc_ref.get_declaration() { + path_elements.push(declaration.kind.name().to_string()); + } + path_elements.push(proc_ref.name().to_string()); + Ok(Constant::Prefab(Box::new(self.prefab(Prefab::from(make_typepath(path_elements)))?))) + } + fn rgb(&mut self, args: Box<[Expression]>) -> Result { enum ColorSpace { Rgb = 0, diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 03ff4c80..f99f0b14 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -2186,6 +2186,18 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { Term::Ident(".".to_owned()) } }, + Token::Punct(Punctuation::Scope) => { + if let Some(ident) = self.ident()? { + if let Some(args) = self.arguments(&[], "::")? { + Term::GlobalCall(Ident2::from(ident), args) + } else { + Term::GlobalIdent(Ident2::from(ident)) + } + } else { + // Go away + return self.parse_error() + } + } // term :: path_lit t @ Token::Punct(Punctuation::Slash) | t @ Token::Punct(Punctuation::CloseColon) => { @@ -2269,6 +2281,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { Token::Punct(Punctuation::CloseColon) if !belongs_to.is_empty() || !in_ternary => PropertyAccessKind::Colon, Token::Punct(Punctuation::SafeDot) => PropertyAccessKind::SafeDot, Token::Punct(Punctuation::SafeColon) => PropertyAccessKind::SafeColon, + Token::Punct(Punctuation::Scope) => PropertyAccessKind::Scope, other => return self.try_another(other), }; @@ -2295,14 +2308,28 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let past = std::mem::take(belongs_to); self.annotate_precise(start..end, || Annotation::ScopedCall(past, ident.clone())); } - Follow::Call(kind, ident.into(), args) + match kind { + PropertyAccessKind::Scope => { + Follow::ProcReference(ident.into()) + } + _ => { + Follow::Call(kind, ident.into(), args) + } + } }, None => { if !belongs_to.is_empty() { self.annotate_precise(start..end, || Annotation::ScopedVar(belongs_to.clone(), ident.clone())); belongs_to.push(ident.clone()); } - Follow::Field(kind, ident.into()) + match kind { + PropertyAccessKind::Scope => { + Follow::StaticField(ident.into()) + } + _ => { + Follow::Field(kind, ident.into()) + } + } }, }; success(Spanned::new(first_location, follow)) diff --git a/crates/dreammaker/tests/ast_tests.rs b/crates/dreammaker/tests/ast_tests.rs index 345a482e..a0ce5333 100644 --- a/crates/dreammaker/tests/ast_tests.rs +++ b/crates/dreammaker/tests/ast_tests.rs @@ -1,6 +1,10 @@ extern crate dreammaker as dm; +use core::panic; + use dm::*; +use dm::constants::*; +use dm::ast::*; use dm::preprocessor::Preprocessor; use dm::objtree::ObjectTree; @@ -16,6 +20,7 @@ fn with_code(code: &'static str, f: F) { f(context, _tree) } + #[test] fn check_semicolon_in_proc_parameters() { with_code(" @@ -32,3 +37,203 @@ fn check_semicolon_in_proc_parameters() { } }); } + +#[test] +fn process_scope() { + with_code(" +/datum/test + var/hell = type::base + var/base = 10 + var/heck = type::base + var/static/stat = 1 + var/proc_holder = type::reference() + +/datum/test/proc/reference() + +/datum/test/sub + base = parent_type::base + 10 + heck = /datum/test::heck + 2 + +var/global/bill = 1 + +/proc/work() + var/x = /datum/test::base + var/datum/test/larry = /datum/test + x = larry::stat + x = /datum/test::reference() + /datum/test::stat = 2 + ::extra() + x = ::bill + +/proc/extra() +", |context, tree| { + let errors = context.errors(); + + // Check for errors + let mut sum_errors: Vec = vec![]; + for error in errors.iter() { + sum_errors.push(format!("{}", error)); + } + if sum_errors.len() > 0 { + panic!("\n{}", sum_errors.join("\n").as_str()); + } + // test type::var in typedef + let parent_type = tree.find("/datum/test").unwrap(); + let type_read = parent_type.get_value("heck").unwrap(); + let Some(constant) = type_read.constant.as_ref() else { + panic!("Failed to constant evaluate :: operator") + }; + if let Constant::Float(value) = constant { + assert_eq!(*value, 10f32) + } else { + panic!("{} was expected to be a float, but it wasn't!", type_read.constant.as_ref().unwrap()) + } + // test type::proc() in typedef + let parent_type = tree.find("/datum/test").unwrap(); + let type_read = parent_type.get_value("proc_holder").unwrap(); + let Some(constant) = type_read.constant.as_ref() else { + panic!("Failed to constant evaluate :: proc operator") + }; + if let Constant::Prefab(value) = constant { + let pop_list = FormatTreePath(&value.path).to_string(); + assert_eq!(pop_list, "/datum/test/proc/reference") + } else { + panic!("{} was expected to be a path, but it wasn't!", type_read.constant.as_ref().unwrap()) + } + // parent_type::var in a subtype + let child_type = tree.find("/datum/test/sub").unwrap(); + let type_read = child_type.get_value("base").unwrap(); + let Some(constant) = type_read.constant.as_ref() else { + panic!("Failed to constant evaluate :: operator") + }; + if let Constant::Float(value) = constant { + assert_eq!(*value, 10f32 + 10f32) + } else { + panic!("{} was expected to be a float, but it wasn't!", type_read.constant.as_ref().unwrap()) + } + // /datum/explicit::var in a type + let child_type = tree.find("/datum/test/sub").unwrap(); + let type_read = child_type.get_value("heck").unwrap(); + let Some(constant) = type_read.constant.as_ref() else { + panic!("Failed to constant evaluate :: operator") + }; + if let Constant::Float(value) = constant { + assert_eq!(*value, 10f32 + 2f32) + } else { + panic!("{} was expected to be a float, but it wasn't!", type_read.constant.as_ref().unwrap()) + } + let global_procs = tree.root(); + let work_proc = global_procs.get_proc("work").unwrap(); + let work_code = work_proc.code.as_ref().unwrap().into_iter().map(|statement| { + &statement.elem + }).collect::>(); + // /datum/explicit::var + let Statement::Var(x_init) = work_code.first().unwrap() else { + panic!("First statement was not an expression") + }; + let Expression::Base { term: _, follow } = x_init.value.as_ref().unwrap() else { + panic!("/datum/test::base was NOT evaluated as a base expression") + }; + match &follow.first().unwrap().elem { + Follow::StaticField(field) => { + if field != "base" { + panic!("/datum/test::base did not eval base as the var to read") + } + } + _ => panic!("/datum/test::base failed to eval :: as a static field") + } + // implicit_type::variable + let Statement::Expr(larrys_read) = work_code.get(2).unwrap() else { + panic!("Third statement was not an expression") + }; + + let Expression::AssignOp { op: _, lhs: _, rhs } = larrys_read else { + panic!("x = larry::stat was NOT evaluated as an assignment expression") + }; + let Expression::Base { term: _, ref follow } = **rhs else { + panic!("larry::stat was NOT evaluated as a base expression") + }; + match &follow.first().unwrap().elem { + Follow::StaticField(field) => { + if field != "stat" { + panic!("larry::stat did not eval stat as the var to read") + } + } + _ => panic!("larry::stat failed to eval :: as a static field") + } + + // /datum/explicit::proc() + let Statement::Expr(proc_ref) = work_code.get(3).unwrap() else { + panic!("Fourth statement was not an expression") + }; + + let Expression::AssignOp { op: _, lhs: _, rhs } = proc_ref else { + panic!("x = /datum/test::reference() was NOT evaluated as an assignment expression") + }; + let Expression::Base { term: _, ref follow } = **rhs else { + panic!("/datum/test::reference() was NOT evaluated as a base expression") + }; + match &follow.first().unwrap().elem { + Follow::ProcReference(proc_name) => { + if proc_name != "reference" { + panic!("/datum/test::reference() did not eval reference() as the ref to read") + } + } + _ => panic!("/datum/test::reference() failed to eval :: as a proc reference") + } + // /datum/explicit::static_var = value + let Statement::Expr(static_set) = work_code.get(4).unwrap() else { + panic!("Fifth statement was not an expression") + }; + + let Expression::AssignOp { op: _, lhs, rhs: _ } = static_set else { + panic!("/datum/test::stat = 2 was NOT evaluated as an assignment expression") + }; + let Expression::Base { term: _, ref follow } = **lhs else { + panic!("/datum/test::stat was NOT evaluated as a base expression") + }; + match &follow.first().unwrap().elem { + Follow::StaticField(field) => { + if field != "stat" { + panic!("/datum/test::stat did not eval stat as the var to set") + } + } + _ => panic!("/datum/test::stat failed to eval :: as a static field") + } + // ::global_proc() + let Statement::Expr(static_set) = work_code.get(5).unwrap() else { + panic!("Sixth statement was not an expression") + }; + + let Expression::Base { term, follow: _ } = static_set else { + panic!("::extra() was NOT evaluated as a base expression") + }; + match &term.elem { + Term::GlobalCall(function, _) => { + if function != "extra" { + panic!("::extra() did not eval extra as the proc to call") + } + } + _ => panic!("::extra() failed to eval :: as a global call") + } + // ::global_var + let Statement::Expr(proc_ref) = work_code.get(6).unwrap() else { + panic!("Seventh statement was not an expression") + }; + + let Expression::AssignOp { op: _, lhs: _, rhs } = proc_ref else { + panic!("x = ::bill was NOT evaluated as an assignment expression") + }; + let Expression::Base { ref term, follow: _ } = **rhs else { + panic!("::bill was NOT evaluated as a base expression") + }; + match &term.elem { + Term::GlobalIdent(field) => { + if field != "bill" { + panic!("::bill did not eval bill as the global var to read") + } + } + _ => panic!("::bill failed to eval :: as a global var read") + } + }) +} From e5291ce927d859746894f4a966173c08bff01f16 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 19 Oct 2023 18:29:59 -0700 Subject: [PATCH 060/197] Add consteval for nameof() --- crates/dreammaker/src/ast.rs | 34 ++++++++++++++++++++++++++++++ crates/dreammaker/src/constants.rs | 9 ++++++++ 2 files changed, 43 insertions(+) diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 69a7062a..9e25a38b 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -961,6 +961,19 @@ impl Expression { } } } + + pub fn nameof(&self) -> Option<&str> { + match self { + Expression::Base { term, follow } => { + if let Some(last) = follow.last() { + last.elem.nameof() + } else { + term.elem.nameof() + } + } + _ => None + } + } } impl From for Expression { @@ -1132,6 +1145,16 @@ impl Term { } None } + + pub fn nameof(&self) -> Option<&str> { + match self { + Term::Expr(e) => e.nameof(), + Term::Ident(i) => Some(i), + Term::Prefab(fab) if fab.vars.is_empty() => Some(&fab.path.last()?.1), + Term::GlobalIdent(i) => Some(i), + _ => None, + } + } } impl From for Term { @@ -1179,6 +1202,17 @@ pub enum Follow { ProcReference(Ident2), } +impl Follow { + pub fn nameof(&self) -> Option<&str> { + match self { + Follow::Field(_, i) => Some(i), + Follow::StaticField(i) => Some(i), + Follow::ProcReference(i) => Some(i), + _ => None, + } + } +} + /// Like a `Follow` but only supports field accesses. #[derive(Debug, Clone, PartialEq, GetSize)] pub struct Field { diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index f9c4d21f..61aa84d6 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -803,6 +803,15 @@ impl<'a> ConstantFolder<'a> { _ => return Err(self.error("malformed defined() call, argument given isn't an Ident.")), } } + "nameof" => { + if args.len() != 1 { + return Err(self.error(format!("malformed nameof() call, must have 1 argument and instead has {}", args.len()))); + } + match args[0].nameof() { + Some(name) => Constant::string(name), + None => return Err(self.error("malformed nameof() call, expression appears to have no name")), + } + } // other functions are no-goes _ => return Err(self.error(format!("non-constant function call: {}", ident))), }, From 62071889631f5300201830d7bcdcf0b1cfcda038 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 19 Oct 2023 18:53:49 -0700 Subject: [PATCH 061/197] Run cargo clippy --fix Plus undo a formatting botch near `for candidate in` in preprocessor.rs. --- crates/dreamchecker/src/lib.rs | 2 +- crates/dreamchecker/tests/kwargs_tests.rs | 4 ++-- crates/dreamchecker/tests/new_tests.rs | 4 ++-- crates/dreamchecker/tests/proc_tests.rs | 2 +- crates/dreamchecker/tests/sleep_pure_tests.rs | 4 ++-- crates/dreammaker/src/ast.rs | 4 ++-- crates/dreammaker/src/constants.rs | 12 ++++++------ crates/dreammaker/src/dmi.rs | 8 ++++---- crates/dreammaker/src/objtree.rs | 2 +- crates/dreammaker/src/parser.rs | 6 +++--- crates/dreammaker/src/preprocessor.rs | 6 +++--- crates/dreammaker/tests/annotation_tests.rs | 4 ++-- crates/dreammaker/tests/ast_tests.rs | 4 ++-- crates/dreammaker/tests/lexer_tests.rs | 4 ++-- crates/dreammaker/tests/location_tests.rs | 4 ++-- crates/interval-tree/src/node.rs | 2 +- 16 files changed, 36 insertions(+), 36 deletions(-) diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 47bb4683..d797b4c6 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -2142,7 +2142,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { }; // Gonna build the proc's path - let mut path_elements: Vec = real_type.get().path.split("/").filter(|elem| *elem != "").map(|segment| segment.to_string()).collect(); + let mut path_elements: Vec = real_type.get().path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect(); // Only tricky bit is adding on the type if required if let Some(declaration) = decl.get_declaration() { path_elements.push(declaration.kind.name().to_string()); diff --git a/crates/dreamchecker/tests/kwargs_tests.rs b/crates/dreamchecker/tests/kwargs_tests.rs index 0ba97435..624edf46 100644 --- a/crates/dreamchecker/tests/kwargs_tests.rs +++ b/crates/dreamchecker/tests/kwargs_tests.rs @@ -29,7 +29,7 @@ pub const FILTER_KWARGS_ERRORS: &[(u32, u16, &str)] = &[ #[test] fn filter_kwarg() { - let code = r##" + let code = r#" /proc/test() filter(type="alpha", x=1, y=2, icon=null, render_source=null, flags=0) filter(type="angular_blur", x=1, y=2, size=null) @@ -50,6 +50,6 @@ fn filter_kwarg() { filter(x=4) filter("alpha", x=1, flags=MASK_INVERSE|MASK_INVERSE|MASK_INVERSE|MASK_INVERSE|MASK_INVERSE|MASK_INVERSE) filter(type="wave", color=null) -"##.trim(); +"#.trim(); check_errors_match(code, FILTER_KWARGS_ERRORS); } diff --git a/crates/dreamchecker/tests/new_tests.rs b/crates/dreamchecker/tests/new_tests.rs index 2f434912..18e4ccba 100644 --- a/crates/dreamchecker/tests/new_tests.rs +++ b/crates/dreamchecker/tests/new_tests.rs @@ -9,7 +9,7 @@ pub const NEW_DOT_ERRORS: &[(u32, u16, &str)] = &[ #[test] fn new_dot() { - let code = r##" + let code = r#" /mob/subtype /mob/proc/foo() /mob/proc/test() @@ -24,7 +24,7 @@ fn new_dot() { new foo()() new /obj[0]() // TODO: see parser.rs new 2 + 2() // TODO: see parser.rs -"##.trim(); +"#.trim(); check_errors_match(code, NEW_DOT_ERRORS); } diff --git a/crates/dreamchecker/tests/proc_tests.rs b/crates/dreamchecker/tests/proc_tests.rs index 366f44be..ab8616c9 100644 --- a/crates/dreamchecker/tests/proc_tests.rs +++ b/crates/dreamchecker/tests/proc_tests.rs @@ -29,7 +29,7 @@ fn return_type() { "##.trim(); let context = parse_a_file_for_test(code); let error_text: Vec = context.errors().iter().map(|error| format!("{}", error)).collect(); - if error_text.len() > 0 { + if !error_text.is_empty() { panic!("\n{}", error_text.join("\n")) } } diff --git a/crates/dreamchecker/tests/sleep_pure_tests.rs b/crates/dreamchecker/tests/sleep_pure_tests.rs index 1f62b56a..dd53bd1b 100644 --- a/crates/dreamchecker/tests/sleep_pure_tests.rs +++ b/crates/dreamchecker/tests/sleep_pure_tests.rs @@ -181,7 +181,7 @@ pub const PURE_ERRORS: &[(u32, u16, &str)] = &[ #[test] fn pure() { - let code = r##" + let code = r#" /proc/pure() return 1 /proc/impure() @@ -196,7 +196,7 @@ fn pure() { /mob/proc/test2() set SpacemanDMM_should_be_pure = TRUE bar() -"##.trim(); +"#.trim(); check_errors_match(code, PURE_ERRORS); } diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 9e25a38b..95a3ccd0 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -337,7 +337,7 @@ impl AsType { "sound" => AsType::from_name("/sound"), // If it looks like a typepath, we'll process it as a typepath (figure out reality later ya feel?) _ if name.chars().next().unwrap_or(' ') == '/' => - Some(AsType::from_vec(name.split("/").into_iter().filter_map(|part| match part { + Some(AsType::from_vec(name.split('/').filter_map(|part| match part { "" => None, _ => Some(part.to_string()), }).collect::>())), @@ -362,7 +362,7 @@ pub struct ProcDeclBuilder { impl ProcDeclBuilder { pub fn new(kind: ProcDeclKind, flags: Option) -> ProcDeclBuilder { - ProcDeclBuilder { kind: kind, flags: flags.unwrap_or(ProcFlags::default()) } + ProcDeclBuilder { kind, flags: flags.unwrap_or_default() } } pub fn kind(self) -> &'static str { diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index 61aa84d6..acbe5f38 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -656,7 +656,7 @@ impl<'a> ConstantFolder<'a> { let Constant::Prefab(read_from) = term else { return Err(self.error(format!("non typepath {} used with ::", term))) }; - if read_from.vars.len() > 0 { + if !read_from.vars.is_empty() { return Err(self.error(format!("non typepath {} used with ::", read_from))) } let Some(ref tree) = self.tree else { @@ -671,7 +671,7 @@ impl<'a> ConstantFolder<'a> { let Constant::Prefab(read_from) = term else { return Err(self.error(format!("non typepath {} used with ::", term))) }; - if read_from.vars.len() > 0 { + if !read_from.vars.is_empty() { return Err(self.error(format!("non typepath {} used with ::", read_from))) } let Some(ref tree) = self.tree else { @@ -823,7 +823,7 @@ impl<'a> ConstantFolder<'a> { "type" => { if let Some(obj_tree) = &self.tree { let typeval = TypeRef::new(obj_tree, self.ty).get(); - let path = make_typepath(typeval.path.split("/").filter(|elem| *elem != "").map(|segment| segment.to_string()).collect()); + let path = make_typepath(typeval.path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect()); Constant::Prefab(Box::new(self.prefab(Prefab::from(path))?)) } else { return Err(self.error("no type context".to_owned())) @@ -835,7 +835,7 @@ impl<'a> ConstantFolder<'a> { let Some(parent_type) = typeref.parent_type() else { return Err(self.error(format!("no parent type for {}", typeref))) }; - let path = make_typepath(parent_type.path.split("/").filter(|elem| *elem != "").map(|segment| segment.to_string()).collect()); + let path = make_typepath(parent_type.path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect()); Constant::Prefab(Box::new(self.prefab(Prefab::from(path))?)) } else { return Err(self.error("no type context".to_owned())) @@ -851,7 +851,7 @@ impl<'a> ConstantFolder<'a> { Term::__TYPE__ => { if let Some(obj_tree) = &self.tree { let typeval = TypeRef::new(obj_tree, self.ty).get(); - let path = make_typepath(typeval.path.split("/").filter(|elem| *elem != "").map(|segment| segment.to_string()).collect()); + let path = make_typepath(typeval.path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect()); Constant::Prefab(Box::new(self.prefab(Prefab::from(path))?)) } else { return Err(self.error("No type context".to_owned())) @@ -947,7 +947,7 @@ impl<'a> ConstantFolder<'a> { return Err(self.error(format!("unknown proc: {}", name))) }; // Gonna build the proc's path - let mut path_elements: Vec = proc_type.get().path.split("/").filter(|elem| *elem != "").map(|segment| segment.to_string()).collect(); + let mut path_elements: Vec = proc_type.get().path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect(); // Only tricky bit is adding on the type if required if let Some(declaration) = proc_ref.get_declaration() { path_elements.push(declaration.kind.name().to_string()); diff --git a/crates/dreammaker/src/dmi.rs b/crates/dreammaker/src/dmi.rs index f38bca4d..02763a01 100644 --- a/crates/dreammaker/src/dmi.rs +++ b/crates/dreammaker/src/dmi.rs @@ -510,7 +510,7 @@ mod test { #[test] fn duplicate_states() { - let description = r##" + let description = r#" # BEGIN DMI version = 4.0 width = 32 @@ -525,7 +525,7 @@ state = "duplicate" dirs = 1 frames = 1 # END DMI -"##.trim(); +"#.trim(); let metadata = parse_metadata(description).expect("Metadata is valid"); assert_eq!(metadata.state_names.len(), 3); @@ -562,7 +562,7 @@ state = "duplicate" /// The bug in our code was that we checked if our `delays = 1,1,...` *before* truncating the array /// in the truncation case, so we would output `Frames::Delays([1,1])` for this metadata. fn delay_overflow_edge_case() { - let description = r##" + let description = r#" # BEGIN DMI version = 4.0 width = 32 @@ -572,7 +572,7 @@ state = "one" frames = 2 delay = 1,1,0.5,0.5 # END DMI -"##.trim(); +"#.trim(); let metadata = parse_metadata(description).expect("Metadata is valid"); let state = metadata.get_icon_state(&StateIndex("one".to_owned(), 0)).expect("Only one state, named one, should be found"); diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index 87fca7b8..2c40caf0 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -1254,7 +1254,7 @@ impl ObjectTreeBuilder { if let Some(kind) = ProcDeclKind::from_name(proc_name) { let mut next_entry = path.next(); let flags = ProcFlags::from_name(next_entry.unwrap_or("")); - if let Some(_) = flags { + if flags.is_some() { // did something? take another step next_entry = path.next(); } diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index f99f0b14..a580cf3d 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -57,7 +57,7 @@ pub fn parse(context: &Context, iter: I) -> ObjectTree where I: IntoIterator, { - Parser::new(context, iter.into_iter()).parse_object_tree() + Parser::new(context, iter).parse_object_tree() } /// Parse a token stream into an expression. @@ -68,7 +68,7 @@ pub fn parse_expression(context: &Context, location: Location, iter: I) -> Re where I: IntoIterator, { - let mut parser = Parser::new(context, iter.into_iter()); + let mut parser = Parser::new(context, iter); parser.location = location; Ok(require!(parser.expression())) } @@ -1198,7 +1198,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { }, } } - if path_vec.len() > 0 { + if !path_vec.is_empty() { Ok(Some(AsType::from_vec(path_vec))) } else { Err(self.error("Invalid return type")) diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index 0c1375c3..c474f563 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -661,7 +661,7 @@ impl<'ctx> Preprocessor<'ctx> { // All DM source is effectively `#pragma once`. let file_id = self.context.register_file(register); if let Some(&loc) = self.include_locations.get(&file_id) { - if self.multiple_locations.get(&file_id) == None { + if self.multiple_locations.get(&file_id).is_none() { Err(DMError::new(self.last_input_loc, format!("duplicate #include {:?}", path)) .set_severity(Severity::Warning) .with_note(loc, "previously included here") @@ -772,11 +772,11 @@ impl<'ctx> Preprocessor<'ctx> { expect_token!(() = Token::Punct(Punctuation::Newline)); let path = PathBuf::from(path_str.replace('\\', "/")); - for candidate in vec![ + for candidate in [ // 1. relative to file in which `#include` appears. self.include_stack.top_file_path().parent().unwrap().join(&path), // 2. relative to root `.dme` file. - self.env_file.parent().unwrap().join(&path), + self.env_file.parent().unwrap().join(&path) ] { if !candidate.exists() { continue; diff --git a/crates/dreammaker/tests/annotation_tests.rs b/crates/dreammaker/tests/annotation_tests.rs index f26a1ddf..1c362bf4 100644 --- a/crates/dreammaker/tests/annotation_tests.rs +++ b/crates/dreammaker/tests/annotation_tests.rs @@ -8,7 +8,7 @@ use dm::indents::IndentProcessor; #[test] fn annotation_basic() { - let code = r##" + let code = r#" /var/foo = bar /datum/globals var/number = 7 + 5 @@ -19,7 +19,7 @@ fn annotation_basic() { proc/Init() world.log << new/obj() -"##.trim(); +"#.trim(); let context = Default::default(); let lexer = Lexer::new(&context, Default::default(), code.as_bytes()); diff --git a/crates/dreammaker/tests/ast_tests.rs b/crates/dreammaker/tests/ast_tests.rs index a0ce5333..c29fce09 100644 --- a/crates/dreammaker/tests/ast_tests.rs +++ b/crates/dreammaker/tests/ast_tests.rs @@ -74,7 +74,7 @@ var/global/bill = 1 for error in errors.iter() { sum_errors.push(format!("{}", error)); } - if sum_errors.len() > 0 { + if !sum_errors.is_empty() { panic!("\n{}", sum_errors.join("\n").as_str()); } // test type::var in typedef @@ -124,7 +124,7 @@ var/global/bill = 1 } let global_procs = tree.root(); let work_proc = global_procs.get_proc("work").unwrap(); - let work_code = work_proc.code.as_ref().unwrap().into_iter().map(|statement| { + let work_code = work_proc.code.as_ref().unwrap().iter().map(|statement| { &statement.elem }).collect::>(); // /datum/explicit::var diff --git a/crates/dreammaker/tests/lexer_tests.rs b/crates/dreammaker/tests/lexer_tests.rs index 817f5dee..6f147f6f 100644 --- a/crates/dreammaker/tests/lexer_tests.rs +++ b/crates/dreammaker/tests/lexer_tests.rs @@ -68,7 +68,7 @@ fn empty_block_comment() { #[test] fn raw_strings() { let desired = Token::String("content".to_owned()); - let stuff = lex(r###" + let stuff = lex(r#" @"content" @xcontentx @/content/ @@ -77,7 +77,7 @@ fn raw_strings() { @(very long terminator)contentvery long terminator @{"content"} @{content{ -"###); +"#); for each in stuff.iter() { if each == &Punct(Newline) { continue } assert_eq!(each, &desired); diff --git a/crates/dreammaker/tests/location_tests.rs b/crates/dreammaker/tests/location_tests.rs index cc36f9bc..a1ce2e0a 100644 --- a/crates/dreammaker/tests/location_tests.rs +++ b/crates/dreammaker/tests/location_tests.rs @@ -4,7 +4,7 @@ use dm::lexer::*; #[test] fn simple_location_test() { - let code = r##" + let code = r#" #define islist(thing) istype(thing, /list) /datum/globals @@ -15,7 +15,7 @@ fn simple_location_test() { world.log << new/ obj() /var/foo = bar -"##.trim(); +"#.trim(); let context = Default::default(); let located_tokens: Vec<_> = Lexer::new(&context, Default::default(), code.as_bytes()).collect(); diff --git a/crates/interval-tree/src/node.rs b/crates/interval-tree/src/node.rs index 27b11e40..c6d36976 100644 --- a/crates/interval-tree/src/node.rs +++ b/crates/interval-tree/src/node.rs @@ -106,7 +106,7 @@ impl Node { fn rotate_if_necessary(self: Box) -> Box { match self.diff_of_successors_height() { 2 => self.rotate_left_successor(), - 1 | 0 | -1 => self, + -1..=1 => self, -2 => self.rotate_right_successor(), _ => unreachable!(), } From 311e43472aae4cf540f8e574075efee0e5474ee2 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 19 Oct 2023 18:59:27 -0700 Subject: [PATCH 062/197] Fix additional clippy lints --- crates/dreammaker/src/ast.rs | 12 +++--------- crates/dreammaker/src/preprocessor.rs | 7 ++----- crates/interval-tree/src/node.rs | 10 +++++----- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 95a3ccd0..fbef071b 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -927,12 +927,8 @@ impl Expression { Some(truthy) }, Expression::BinaryOp { op, lhs, rhs } => { - let Some(lhtruth) = lhs.is_truthy() else { - return None - }; - let Some(rhtruth) = rhs.is_truthy() else { - return None - }; + let lhtruth = lhs.is_truthy()?; + let rhtruth = rhs.is_truthy()?; match op { BinaryOp::And => Some(lhtruth && rhtruth), BinaryOp::Or => Some(lhtruth || rhtruth), @@ -950,9 +946,7 @@ impl Expression { } }, Expression::TernaryOp { cond, if_, else_ } => { - let Some(condtruth) = cond.is_truthy() else { - return None - }; + let condtruth = cond.is_truthy()?; if condtruth { if_.is_truthy() } else { diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index c474f563..052357bb 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -971,11 +971,8 @@ impl<'ctx> Preprocessor<'ctx> { "pragma" => { expect_token!((text) = Token::Ident(text, _)); let pragma_use_loc = _last_expected_loc; - match text.as_str() { - "multiple" => { - self.multiple_locations.insert(pragma_use_loc.file, pragma_use_loc); - }, - _ => {}, + if text.as_str() == "multiple" { + self.multiple_locations.insert(pragma_use_loc.file, pragma_use_loc); } } // none of this other stuff should even exist diff --git a/crates/interval-tree/src/node.rs b/crates/interval-tree/src/node.rs index c6d36976..a3fa0bcf 100644 --- a/crates/interval-tree/src/node.rs +++ b/crates/interval-tree/src/node.rs @@ -232,7 +232,7 @@ fn subtree_max(node: &Option>>) -> u64 { } ///returns the smallest key and value after the given key. -pub fn min_after<'a,V>(key: &RangeInclusive, root: &'a Box>) -> Option<(&'a RangeInclusive,&'a [V])> { +pub fn min_after<'a,V>(key: &RangeInclusive, root: &'a Node) -> Option<(&'a RangeInclusive,&'a [V])> { match root.key.cmp(key){ Ordering::Equal => root.right.as_ref().map(|succ| succ.min_pair()), Ordering::Less => root.right.as_ref().and_then(|succ| min_after(key, succ)), @@ -246,13 +246,13 @@ pub fn min_after<'a,V>(key: &RangeInclusive, root: &'a Box>) -> Opt } ///returns the minimal value within this tree -pub fn min(root: &Box>) -> &[V] { - root.left.as_ref().map_or(&root.data, min) +pub fn min(root: &Node) -> &[V] { + root.left.as_ref().map_or(&root.data, |v| min(v)) } ///returns the minimal value within this tree -pub fn max(root: &Box>) -> &[V] { - root.right.as_ref().map_or(&root.data, max) +pub fn max(root: &Node) -> &[V] { + root.right.as_ref().map_or(&root.data, |v| max(v)) } From 587361db60d6af5365dfb968a25abd76375a3ca6 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 19 Oct 2023 23:25:20 -0700 Subject: [PATCH 063/197] Handle type::foo in dreamchecker --- crates/dreamchecker/src/lib.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index d797b4c6..35074c4f 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -1683,11 +1683,21 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Term::Ident(unscoped_name) => { if let Some(var) = local_vars.get(unscoped_name) { - return var.analysis.clone() + var.analysis.clone() .with_fix_hint(var.location, "add additional type info here") - } - if let Some(decl) = self.ty.get_var_declaration(unscoped_name) { - //println!("found type var"); + } else if unscoped_name == "type" { + // Strictly speaking "type" might be any subset of our current type, but let's return something useful + // so that `nameof(type::foo)` is sensible. + let ty = self.ty; + let pop = dm::constants::Pop::from(ty.path.split('/').skip(1).map(ToOwned::to_owned).collect::>().into_boxed_slice()); + Analysis { + static_ty: StaticType::None, + aset: assumption_set![Assumption::IsPath(true, ty)], + value: Some(Constant::Prefab(Box::new(pop))), + fix_hint: None, + is_impure: None, + } + } else if let Some(decl) = self.ty.get_var_declaration(unscoped_name) { let mut ana = self.static_type(location, &decl.var_type.type_path) .with_fix_hint(decl.location, "add additional type info here"); ana.is_impure = Some(true); @@ -2047,7 +2057,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { .register(self.context); return Analysis::empty() }; - if !&typepop.vars.is_empty() { + if !typepop.vars.is_empty() { error(location, format!("static access requires a static typepath, {} found instead", typepop)) .register(self.context); return Analysis::empty() From 7dc22d522bdda6370516c8de9092d446fe5017a5 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 19 Oct 2023 23:26:09 -0700 Subject: [PATCH 064/197] Bump declared BYOND version to 515.1619 --- crates/dreammaker/src/builtins.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/dreammaker/src/builtins.rs b/crates/dreammaker/src/builtins.rs index 014fc44f..e3f0271e 100644 --- a/crates/dreammaker/src/builtins.rs +++ b/crates/dreammaker/src/builtins.rs @@ -8,8 +8,8 @@ use super::preprocessor::{DefineMap, Define}; use super::constants::Constant; use super::docs::{BuiltinDocs, DocCollection}; -const DM_VERSION: i32 = 514; -const DM_BUILD: i32 = 1556; +const DM_VERSION: i32 = 515; +const DM_BUILD: i32 = 1619; /// Register BYOND builtin macros to the given define map. pub fn default_defines(defines: &mut DefineMap) { From ec65eb1cf9baf8c90b58c208d26ef2b858e63f54 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 29 Oct 2023 12:56:22 -0700 Subject: [PATCH 065/197] Run cargo update --- Cargo.lock | 137 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 79 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e7ce033f..420e68eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,14 +16,15 @@ checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", "getrandom", "once_cell", "version_check", + "zerocopy", ] [[package]] @@ -255,9 +256,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.6" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" dependencies = [ "clap_builder", "clap_derive", @@ -265,9 +266,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" dependencies = [ "anstream", "anstyle", @@ -277,9 +278,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", @@ -289,9 +290,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "collection_literals" @@ -325,9 +326,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -608,9 +609,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ "futures-channel", "futures-core", @@ -623,9 +624,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", "futures-sink", @@ -633,15 +634,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" dependencies = [ "futures-core", "futures-task", @@ -650,15 +651,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", @@ -667,21 +668,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-channel", "futures-core", @@ -832,16 +833,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -1133,9 +1134,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" +checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" dependencies = [ "memchr", "thiserror", @@ -1144,9 +1145,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" +checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" dependencies = [ "pest", "pest_generator", @@ -1154,9 +1155,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" +checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" dependencies = [ "pest", "pest_meta", @@ -1167,9 +1168,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" +checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" dependencies = [ "once_cell", "pest", @@ -1411,9 +1412,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaac441002f822bc9705a681810a4dd2963094b9ca0ddc41cb963a4c189189ea" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", @@ -1423,9 +1424,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5011c7e263a695dc8ca064cddb722af1be54e517a280b12a5356f98366899e5d" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", @@ -1440,9 +1441,9 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rgb" -version = "0.8.36" +version = "0.8.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" +checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" dependencies = [ "bytemuck", ] @@ -1470,18 +1471,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.189" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.189" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" dependencies = [ "proc-macro2", "quote", @@ -1618,18 +1619,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", @@ -1906,10 +1907,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ "windows-targets", ] @@ -1979,3 +1980,23 @@ name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "zerocopy" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2bd783c6247b80c3ac2267afe3042452f184478184264e0c1532bbf59adcb7" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56feebc4664bdb37f39c0b1b8fc8fa2f5648e3ec5f9cf4344978b4b7ca561fff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] From f6b4c8f6fecfacf6899c4b8d7e0fb8d9d1ae9400 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 29 Oct 2023 12:56:45 -0700 Subject: [PATCH 066/197] Bump versions for suite 1.8 --- Cargo.lock | 8 ++++---- crates/dm-langserver/Cargo.toml | 2 +- crates/dmdoc/Cargo.toml | 2 +- crates/dmm-tools-cli/Cargo.toml | 2 +- crates/dreamchecker/Cargo.toml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 420e68eb..d57f03f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -444,7 +444,7 @@ dependencies = [ [[package]] name = "dm-langserver" -version = "1.7.3" +version = "1.8.0" dependencies = [ "ahash", "bincode", @@ -467,7 +467,7 @@ dependencies = [ [[package]] name = "dmdoc" -version = "1.7.3" +version = "1.8.0" dependencies = [ "chrono", "dreammaker", @@ -501,7 +501,7 @@ dependencies = [ [[package]] name = "dmm-tools-cli" -version = "1.7.3" +version = "1.8.0" dependencies = [ "ahash", "chrono", @@ -526,7 +526,7 @@ dependencies = [ [[package]] name = "dreamchecker" -version = "1.7.3" +version = "1.8.0" dependencies = [ "ahash", "chrono", diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index 23b713d8..dac465a7 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dm-langserver" -version = "1.7.3" +version = "1.8.0" authors = ["Tad Hardesty "] edition = "2018" diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index e1b3775d..5ce6417b 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dmdoc" -version = "1.7.3" +version = "1.8.0" authors = ["Tad Hardesty "] homepage = "https://github.com/SpaceManiac/SpacemanDMM/blob/master/crates/dmdoc/README.md" edition = "2018" diff --git a/crates/dmm-tools-cli/Cargo.toml b/crates/dmm-tools-cli/Cargo.toml index 2db4e074..3bf3ec6b 100644 --- a/crates/dmm-tools-cli/Cargo.toml +++ b/crates/dmm-tools-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dmm-tools-cli" -version = "1.7.3" +version = "1.8.0" authors = ["Tad Hardesty "] description = "BYOND map rendering and analysis tools powered by SpacemanDMM" edition = "2018" diff --git a/crates/dreamchecker/Cargo.toml b/crates/dreamchecker/Cargo.toml index 1bc74326..09f13973 100644 --- a/crates/dreamchecker/Cargo.toml +++ b/crates/dreamchecker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dreamchecker" -version = "1.7.3" +version = "1.8.0" authors = ["Tad Hardesty "] edition = "2018" From 0213b66f109b52ccec07039db3aefb029942b7fe Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 5 Nov 2023 21:57:57 -0800 Subject: [PATCH 067/197] Fix Markdown headings rendering as instead of

--- crates/dmdoc/src/markdown.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/dmdoc/src/markdown.rs b/crates/dmdoc/src/markdown.rs index c158fac1..6a2b2997 100644 --- a/crates/dmdoc/src/markdown.rs +++ b/crates/dmdoc/src/markdown.rs @@ -129,8 +129,8 @@ impl<'a, I: Iterator>> Iterator for HeadingLinker<'a, I> { self.output.push_back(event); } - self.output.push_back(Event::Html(format!("", heading).into())); - return Some(Event::Html(format!("", heading, slugify(&text_buf)).into())); + self.output.push_back(Event::Html(format!("", heading).into())); + return Some(Event::Html(format!("<{} id=\"{}\">", heading, slugify(&text_buf)).into())); } original } From 53f9447fa028e936c04bf91dacb4378b9107bd9f Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 5 Nov 2023 22:51:54 -0800 Subject: [PATCH 068/197] Speed up dmdoc massively by replacing Tera with Maud A ton of time was spent constructing/destructing the Tera contexts, so skipping that step by using a compile-time templater helps a lot. Takes dmdoc time on /tg/station13 down from 10+ minutes to <5 seconds. --- Cargo.lock | 381 ++----------------------- crates/dmdoc/Cargo.toml | 4 +- crates/dmdoc/src/main.rs | 159 +++++------ crates/dmdoc/src/markdown.rs | 14 +- crates/dmdoc/src/template/mod.rs | 463 ++++++++++++++++++++++++++++++- 5 files changed, 554 insertions(+), 467 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d57f03f5..1e5c5e83 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -148,25 +148,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bstr" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "builtins-proc-macro" version = "0.0.0" @@ -232,28 +213,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "chrono-tz" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1369bc6b9e9a7dfdae2055f6ec151fe9c554a9d23d357c0237cee2e25eaabb7" -dependencies = [ - "chrono", - "chrono-tz-build", - "phf", -] - -[[package]] -name = "chrono-tz-build" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2f5ebdc942f57ed96d560a6d1a459bae5851102a25d5bf89dc04ae453e31ecf" -dependencies = [ - "parse-zoneinfo", - "phf", - "phf_codegen", -] - [[package]] name = "clap" version = "4.4.7" @@ -324,15 +283,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" -[[package]] -name = "cpufeatures" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" -dependencies = [ - "libc", -] - [[package]] name = "crc32fast" version = "1.3.2" @@ -375,16 +325,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - [[package]] name = "dap-types" version = "0.0.0" @@ -417,31 +357,6 @@ dependencies = [ "syn 2.0.38", ] -[[package]] -name = "deunicode" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71dbf1bf89c23e9cd1baf5e654f622872655f195b36588dc9dc38f7eda30758c" -dependencies = [ - "deunicode 1.4.1", -] - -[[package]] -name = "deunicode" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a1abaf4d861455be59f64fd2b55606cb151fce304ede7165f410243ce96bde6" - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - [[package]] name = "dm-langserver" version = "1.8.0" @@ -472,10 +387,8 @@ dependencies = [ "chrono", "dreammaker", "git2", + "maud", "pulldown-cmark", - "serde", - "serde_derive", - "tera", "walkdir", ] @@ -592,12 +505,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "form_urlencoded" version = "1.2.0" @@ -696,16 +603,6 @@ dependencies = [ "slab", ] -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "get-size" version = "0.1.4" @@ -777,30 +674,6 @@ dependencies = [ "url", ] -[[package]] -name = "globset" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" -dependencies = [ - "aho-corasick", - "bstr", - "fnv", - "log", - "regex", -] - -[[package]] -name = "globwalk" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" -dependencies = [ - "bitflags", - "ignore", - "walkdir", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -822,15 +695,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "humansize" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" -dependencies = [ - "libm", -] - [[package]] name = "iana-time-zone" version = "0.1.58" @@ -864,23 +728,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "ignore" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" -dependencies = [ - "globset", - "lazy_static", - "log", - "memchr", - "regex", - "same-file", - "thread_local", - "walkdir", - "winapi-util", -] - [[package]] name = "indexmap" version = "1.9.3" @@ -976,12 +823,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - [[package]] name = "libz-sys" version = "1.1.12" @@ -1036,6 +877,28 @@ dependencies = [ "rawpointer", ] +[[package]] +name = "maud" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0bab19cef8a7fe1c18a43e881793bfc9d4ea984befec3ae5bd0415abf3ecf00" +dependencies = [ + "itoa", + "maud_macros", +] + +[[package]] +name = "maud_macros" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0be95d66c3024ffce639216058e5bae17a83ecaf266ffc6e4d060ad447c9eed2" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "memchr" version = "2.6.4" @@ -1117,66 +980,12 @@ dependencies = [ "num-traits", ] -[[package]] -name = "parse-zoneinfo" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" -dependencies = [ - "regex", -] - [[package]] name = "percent-encoding" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" -[[package]] -name = "pest" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "pest_meta" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" -dependencies = [ - "once_cell", - "pest", - "sha2", -] - [[package]] name = "phf" version = "0.11.2" @@ -1187,16 +996,6 @@ dependencies = [ "phf_shared", ] -[[package]] -name = "phf_codegen" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" -dependencies = [ - "phf_generator", - "phf_shared", -] - [[package]] name = "phf_generator" version = "0.11.2" @@ -1511,17 +1310,6 @@ dependencies = [ "syn 2.0.38", ] -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "simd-adler32" version = "0.3.7" @@ -1543,15 +1331,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "slug" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373" -dependencies = [ - "deunicode 0.4.5", -] - [[package]] name = "smallvec" version = "1.11.1" @@ -1586,28 +1365,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "tera" -version = "1.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "970dff17c11e884a4a09bc76e3a17ef71e01bb13447a11e85226e254fe6d10b8" -dependencies = [ - "chrono", - "chrono-tz", - "globwalk", - "humansize", - "lazy_static", - "percent-encoding", - "pest", - "pest_derive", - "rand", - "regex", - "serde", - "serde_json", - "slug", - "unic-segment", -] - [[package]] name = "termcolor" version = "1.3.0" @@ -1617,36 +1374,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "thiserror" -version = "1.0.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "thread_local" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" -dependencies = [ - "cfg-if", - "once_cell", -] - [[package]] name = "tinyvec" version = "1.6.0" @@ -1671,68 +1398,6 @@ dependencies = [ "serde", ] -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "ucd-trie" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" - -[[package]] -name = "unic-char-property" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" -dependencies = [ - "unic-char-range", -] - -[[package]] -name = "unic-char-range" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" - -[[package]] -name = "unic-common" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" - -[[package]] -name = "unic-segment" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23" -dependencies = [ - "unic-ucd-segment", -] - -[[package]] -name = "unic-ucd-segment" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-version" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" -dependencies = [ - "unic-common", -] - [[package]] name = "unicase" version = "2.7.0" diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index 5ce6417b..ec1b323e 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -8,11 +8,9 @@ edition = "2018" [dependencies] dreammaker = { path = "../dreammaker" } pulldown-cmark = "0.9.2" -tera = "1.17.0" -serde = "1.0.144" -serde_derive = "1.0.144" walkdir = "2.3.2" git2 = { version = "0.16.1", default-features = false } +maud = "0.25.0" [dev-dependencies] walkdir = "2.3.2" diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 6e575dd1..8aac7d0c 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -2,24 +2,21 @@ #![forbid(unsafe_code)] extern crate dreammaker as dm; extern crate pulldown_cmark; -extern crate tera; extern crate git2; extern crate walkdir; -#[macro_use] extern crate serde_derive; mod markdown; mod template; -use std::collections::{BTreeMap, BTreeSet, HashMap}; +use std::collections::{BTreeMap, BTreeSet}; use std::io::{self, Write}; use std::fs::{self, File}; use std::path::{Path, PathBuf}; use std::sync::Arc; use dm::objtree::ObjectTree; +use maud::{Markup, PreEscaped}; use pulldown_cmark::{BrokenLink, CowStr}; -use tera::Value; - use dm::docs::*; use markdown::DocBlock; @@ -215,7 +212,7 @@ fn main2() -> Result<(), Box> { range.start.line, ModuleItem::Define { name, - teaser: docs.teaser().to_owned(), + teaser: PreEscaped(docs.teaser().0.to_owned()), }, )); module.defines.insert( @@ -337,7 +334,7 @@ fn main2() -> Result<(), Box> { var.value.location.line, ModuleItem::GlobalVar { name, - teaser: block.teaser().to_owned(), + teaser: PreEscaped(block.teaser().0.to_owned()), } )); } @@ -347,9 +344,9 @@ fn main2() -> Result<(), Box> { is_static: decl.var_type.flags.is_static(), is_const: decl.var_type.flags.is_const(), is_tmp: decl.var_type.flags.is_tmp(), - is_final: decl.var_type.flags.is_final(), - is_private: decl.var_type.flags.is_private(), - is_protected: decl.var_type.flags.is_protected(), + //is_final: decl.var_type.flags.is_final(), + //is_private: decl.var_type.flags.is_private(), + //is_protected: decl.var_type.flags.is_protected(), path: &decl.var_type.type_path, }); parsed_type.vars.insert(name, Var { @@ -396,7 +393,7 @@ fn main2() -> Result<(), Box> { proc_value.location.line, ModuleItem::GlobalProc { name, - teaser: block.teaser().to_owned(), + teaser: PreEscaped(block.teaser().0.to_owned()), } )); } @@ -428,7 +425,7 @@ fn main2() -> Result<(), Box> { ty.location.line, ModuleItem::Type { path: ty.get().pretty_path(), - teaser: block.teaser().to_owned(), + teaser: PreEscaped(block.teaser().0.to_owned()), substance, }, )); @@ -489,7 +486,7 @@ fn main2() -> Result<(), Box> { _first = false; let (title, block) = DocBlock::parse_with_title(&doc.text(), Some(broken_link_callback)); module.name = title; - module.teaser = block.teaser().to_owned(); + module.teaser = PreEscaped(block.teaser().0.to_owned()); module.items.push(ModuleItem::Docs(block.html)); } else { module.items.push(ModuleItem::Docs(markdown::render(&doc.text(), Some(broken_link_callback)))); @@ -550,12 +547,13 @@ fn main2() -> Result<(), Box> { } } + /* // load tera templates println!("loading templates"); let mut tera = template::builtin()?; // register tera extensions - let linkify_typenames = all_type_names; + let linkify_typenames = all_type_names.clone(); tera.register_filter("linkify_type", move |value: &Value, _: &HashMap| { match *value { tera::Value::String(ref s) => Ok(linkify_type(&linkify_typenames, s.split('/').skip_while(|b| b.is_empty())).into()), @@ -588,6 +586,7 @@ fn main2() -> Result<(), Box> { _ => Err("substring() input must be string".into()), } }); + */ // render println!("saving static resources"); @@ -611,6 +610,7 @@ fn main2() -> Result<(), Box> { println!("incomplete git info: {}", e); } let env = &Environment { + all_type_names: &all_type_names, dmdoc: DmDoc { version: env!("CARGO_PKG_VERSION"), url: env!("CARGO_PKG_HOMEPAGE"), @@ -632,18 +632,10 @@ fn main2() -> Result<(), Box> { println!("rendering html"); { - #[derive(Serialize)] - struct Index<'a> { - env: &'a Environment<'a>, - html: Option<&'a str>, - modules: Vec>, - types: Vec>, - } - let mut index = create(&output_path.join("index.html"))?; - index.write_all(tera.render("dm_index.html", &tera::Context::from_serialize(Index { + index.write_all(template::dm_index(&Index { env, - html: index_docs.as_ref().map(|(_, docs)| &docs.html[..]), + html: index_docs.as_ref().map(|(_, docs)| PreEscaped(docs.html.0.as_str())), modules: build_index_tree(modules.values().map(|module| IndexTree { htmlname: &module.htmlname, full_name: &module.htmlname, @@ -651,7 +643,7 @@ fn main2() -> Result<(), Box> { None => last_element(&module.htmlname), Some(ref t) => t.as_str(), }, - teaser: &module.teaser, + teaser: PreEscaped(&module.teaser.0), no_substance: false, children: Vec::new(), })), @@ -663,22 +655,14 @@ fn main2() -> Result<(), Box> { } else { &ty.name }, - teaser: ty.docs.as_ref().map_or("", |d| d.teaser()), + teaser: ty.docs.as_ref().map_or(PreEscaped(""), |d| d.teaser()), no_substance: !ty.substance, children: Vec::new(), })), - })?)?.as_bytes())?; + }).0.as_bytes())?; } - for (path, details) in modules.iter() { - #[derive(Serialize)] - struct ModuleArgs<'a> { - env: &'a Environment<'a>, - base_href: &'a str, - path: &'a str, - details: &'a Module<'a>, - } - + for (_path, details) in modules.iter() { let fname = format!("{}.html", details.htmlname); let mut base = String::new(); @@ -687,12 +671,12 @@ fn main2() -> Result<(), Box> { } let mut f = create(&output_path.join(&fname))?; - f.write_all(tera.render("dm_module.html", &tera::Context::from_serialize(ModuleArgs { + f.write_all(template::dm_module(&ModuleArgs { env, base_href: &base, - path, + //path, details, - })?)?.as_bytes())?; + }).0.as_bytes())?; } for (path, details) in type_docs.iter() { @@ -700,15 +684,6 @@ fn main2() -> Result<(), Box> { continue; } - #[derive(Serialize)] - struct Type<'a> { - env: &'a Environment<'a>, - base_href: &'a str, - path: &'a str, - details: &'a ParsedType<'a>, - types: &'a BTreeMap<&'a str, ParsedType<'a>>, - } - let fname = format!("{}.html", details.htmlname); let mut base = String::new(); @@ -717,13 +692,13 @@ fn main2() -> Result<(), Box> { } let mut f = create(&output_path.join(&fname))?; - f.write_all(tera.render("dm_type.html", &tera::Context::from_serialize(Type { + f.write_all(template::dm_type(&Type { env, base_href: &base, path, details, - types: &type_docs, - })?)?.as_bytes())?; + //types: &type_docs, + }).0.as_bytes())?; } Ok(()) @@ -1106,12 +1081,11 @@ fn strip_propriety(name: &str) -> &str { // ---------------------------------------------------------------------------- // Tree stuff -#[derive(Serialize)] struct IndexTree<'a> { htmlname: &'a str, // href="{{htmlname}}.html" full_name: &'a str, self_name: &'a str, - teaser: &'a str, + teaser: PreEscaped<&'a str>, no_substance: bool, children: Vec>, } @@ -1124,7 +1098,7 @@ where htmlname: "", full_name: "", self_name: "", - teaser: "", + teaser: PreEscaped(""), no_substance: false, children: Vec::new(), }]; @@ -1164,7 +1138,7 @@ where htmlname: "", full_name: &each.full_name[..len + bit.len()], self_name: bit, - teaser: "", + teaser: PreEscaped(""), no_substance: true, children: Vec::new(), }); @@ -1206,7 +1180,7 @@ struct Module1<'a> { htmlname: String, orig_filename: String, name: Option, - teaser: String, + teaser: PreEscaped, items_wip: Vec<(u32, ModuleItem<'a>)>, defines: BTreeMap<&'a str, Define<'a>>, } @@ -1214,8 +1188,30 @@ struct Module1<'a> { // ---------------------------------------------------------------------------- // Templating structs -#[derive(Serialize)] +struct Index<'a> { + env: &'a Environment<'a>, + html: Option>, + modules: Vec>, + types: Vec>, +} + +struct ModuleArgs<'a> { + env: &'a Environment<'a>, + base_href: &'a str, + //path: &'a str, + details: &'a Module<'a>, +} + +struct Type<'a> { + env: &'a Environment<'a>, + base_href: &'a str, + path: &'a str, + details: &'a ParsedType<'a>, + //types: &'a BTreeMap<&'a str, ParsedType<'a>>, +} + struct Environment<'a> { + all_type_names: &'a BTreeSet, dmdoc: DmDoc, filename: &'a str, world_name: &'a str, @@ -1224,14 +1220,22 @@ struct Environment<'a> { git: Git, } -#[derive(Serialize)] +impl<'a> Environment<'a> { + fn linkify_type_str(&self, s: &str) -> Markup { + PreEscaped(linkify_type(self.all_type_names, s.split('/').skip_while(|b| b.is_empty()))) + } + + fn linkify_type_array(&self, a: &[String]) -> Markup { + PreEscaped(linkify_type(self.all_type_names, a.iter().map(|x| x.as_str()))) + } +} + struct DmDoc { version: &'static str, url: &'static str, build_info: &'static str, } -#[derive(Serialize)] struct Coverage { modules: usize, macros_documented: usize, @@ -1241,7 +1245,7 @@ struct Coverage { types_all: usize, } -#[derive(Serialize, Default)] +#[derive(Default)] struct Git { revision: String, branch: String, @@ -1250,7 +1254,7 @@ struct Git { } /// A parsed documented type. -#[derive(Default, Serialize)] +#[derive(Default)] struct ParsedType<'a> { name: std::borrow::Cow<'a, str>, parent_type: Option<&'a str>, @@ -1263,29 +1267,25 @@ struct ParsedType<'a> { line: u32, } -#[derive(Serialize)] struct Var<'a> { docs: DocBlock, decl: &'static str, - #[serde(rename="type")] type_: Option>, file: PathBuf, line: u32, parent: Option, } -#[derive(Serialize)] struct VarType<'a> { is_static: bool, is_const: bool, is_tmp: bool, - is_final: bool, - is_private: bool, - is_protected: bool, + //is_final: bool, + //is_private: bool, + //is_protected: bool, path: &'a [String], } -#[derive(Serialize)] struct Proc { docs: DocBlock, decl: &'static str, @@ -1295,24 +1295,22 @@ struct Proc { parent: Option, } -#[derive(Serialize)] struct Param { name: String, type_path: String, } /// Module struct exposed to templates. -#[derive(Default, Serialize)] +#[derive(Default)] struct Module<'a> { htmlname: String, orig_filename: String, name: Option, - teaser: String, + teaser: PreEscaped, items: Vec>, defines: BTreeMap<&'a str, Define<'a>>, } -#[derive(Serialize)] struct Define<'a> { docs: DocBlock, has_params: bool, @@ -1321,34 +1319,27 @@ struct Define<'a> { line: u32, } -#[derive(Serialize)] enum ModuleItem<'a> { // preparation - #[serde(skip)] DocComment(DocComment), // rendering - #[serde(rename="docs")] - Docs(String), - #[serde(rename="define")] + Docs(PreEscaped), Define { name: &'a str, - teaser: String, + teaser: PreEscaped, }, - #[serde(rename="type")] Type { path: &'a str, - teaser: String, + teaser: PreEscaped, substance: bool, }, - #[serde(rename="global_proc")] GlobalProc { name: &'a str, - teaser: String, + teaser: PreEscaped, }, - #[serde(rename="global_var")] GlobalVar { name: &'a str, - teaser: String, + teaser: PreEscaped, }, } diff --git a/crates/dmdoc/src/markdown.rs b/crates/dmdoc/src/markdown.rs index 6a2b2997..667e5d11 100644 --- a/crates/dmdoc/src/markdown.rs +++ b/crates/dmdoc/src/markdown.rs @@ -3,18 +3,18 @@ use std::ops::Range; use std::collections::VecDeque; +use maud::PreEscaped; use pulldown_cmark::{self, Parser, Tag, Event, BrokenLinkCallback, HeadingLevel}; -pub fn render<'string>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, '_>) -> String { +pub fn render<'string>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, '_>) -> PreEscaped { let mut buf = String::new(); push_html(&mut buf, parser(markdown, broken_link_callback)); - buf + PreEscaped(buf) } /// A rendered markdown document with the teaser identified. -#[derive(Serialize)] pub struct DocBlock { - pub html: String, + pub html: PreEscaped, pub has_description: bool, teaser: Range, } @@ -47,8 +47,8 @@ impl DocBlock { ) } - pub fn teaser(&self) -> &str { - &self.html[self.teaser.clone()] + pub fn teaser(&self) -> PreEscaped<&str> { + PreEscaped(&self.html.0[self.teaser.clone()]) } } @@ -83,7 +83,7 @@ fn parse_main(mut parser: std::iter::Peekable) -> DocBlock { let has_description = parser.peek().is_some(); push_html(&mut html, parser); trim_right(&mut html); - DocBlock { html, teaser, has_description } + DocBlock { html: PreEscaped(html), teaser, has_description } } fn push_html<'a, I: IntoIterator>>(buf: &mut String, iter: I) { diff --git a/crates/dmdoc/src/template/mod.rs b/crates/dmdoc/src/template/mod.rs index a5f8ab3c..2a33c20c 100644 --- a/crates/dmdoc/src/template/mod.rs +++ b/crates/dmdoc/src/template/mod.rs @@ -1,26 +1,459 @@ //! The built-in template. use std::path::Path; -use tera::Tera; -pub fn builtin() -> Result { - #[cfg(debug_assertions)] { - Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/src/template/*.html")) - } +use maud::{html, DOCTYPE, Markup, Render, display, PreEscaped}; - #[cfg(not(debug_assertions))] { - let mut tera = Tera::default(); - tera.add_raw_templates(vec![ - ("macros.html", include_str!("macros.html")), - ("base.html", include_str!("base.html")), - ("dm_index.html", include_str!("dm_index.html")), - ("dm_type.html", include_str!("dm_type.html")), - ("dm_module.html", include_str!("dm_module.html")), - ])?; - Ok(tera) +use crate::{Environment, Index, IndexTree, ModuleArgs, Type, ModuleItem, markdown::DocBlock}; + +pub(crate) fn base( + env: &Environment, + base_href: &str, + title: &dyn Render, + head: &dyn Render, + header: &dyn Render, + content: &dyn Render, +) -> Markup { + html! { + (DOCTYPE) + html lang="en" { + head { + meta charset="utf-8"; + @if !base_href.is_empty() { + base href=(base_href); + } + link rel="stylesheet" href="dmdoc.css"; + title { + (title) " - " (env.world_name) + } + (head) + } + body { + header { + a href="index.html" { (env.world_name) } " - " + a href="index.html#modules" { "Modules" } " - " + a href="index.html#types" { "Types" } + (header) + } + main { + (content) + } + footer { + (env.filename) + @if !env.git.revision.is_empty() { + " " + @if !env.git.web_url.is_empty() { + a href=(format!("{}/tree/{}", env.git.web_url, env.git.revision)) { + (env.git.revision[..7]) + } + } @else { + (env.git.revision) + } + @if !env.git.branch.is_empty() { + " (" + (env.git.branch) + @if !env.git.remote_branch.is_empty() && env.git.remote_branch != env.git.branch { + " → " (env.git.remote_branch) + } + ")" + } + " — " + @if !env.dmdoc.url.is_empty() { + a href=(env.dmdoc.url) { + "dmdoc " (env.dmdoc.version) + } + } @else { + "dmdoc " (env.dmdoc.version) + } + } + } + } + } } } +fn teaser(block: &DocBlock, prefix: &str) -> Markup { + let teaser = block.teaser(); + html! { + @if !teaser.0.is_empty() { + (prefix) + (teaser) + } + } +} + +fn git_link(env: &Environment, file: &str, line: u32) -> Markup { + let icon = html! { + img src="git.png" width="16" height="16" title=(format!("{}{}{}", file, if line != 0 { " " } else { "" }, line)); + }; + html! { + @if !file.is_empty() { + " " + @if !env.git.web_url.is_empty() && !env.git.revision.is_empty() { + a href=(format!( + "{}/blob/{}/{}{}{}", + env.git.web_url, + env.git.revision, + file, + if line != 0 { "#L" } else { "" }, + line + )) { + (icon) + } + } @else { + (icon) + } + } + } +} + +fn index_tree(elems: &[IndexTree], extra_class: &str) -> Markup { + html! { + ul .index-tree .(extra_class) { + @for tree in elems { + (index_tree_elem(tree, "")) + } + } + } +} + +fn index_tree_elem(tree: &IndexTree, prefix: &str) -> Markup { + html! { + @if tree.children.len() == 1 && tree.htmlname.is_empty() && tree.teaser.0.is_empty() { + (index_tree_elem(&tree.children[0], &format!("{}{}/", prefix, tree.self_name))) + } @else { + li .(if !tree.children.is_empty() { "has-children" } else { "" }) { + @if !prefix.is_empty() { + span class="no-substance" { (prefix) } + } + @if tree.htmlname.is_empty() { + span .(if tree.no_substance { "no-substance" } else { "" }) title=(tree.full_name) { (tree.self_name) } + } @else { + a href=(format!("{}.html", tree.htmlname)) title=(tree.full_name) { (tree.self_name) } + } + @if !tree.teaser.0.is_empty() { + " - " (tree.teaser) + } + @if !tree.children.is_empty() { + (index_tree(&tree.children, "")) + } + } + } + } +} + +fn percentage(amt: usize, total: usize) -> Markup { + if total > 0 { + PreEscaped(format!(", {:.1}%", (amt as f32) * 100.0 / (total as f32))) + } else { + Markup::default() + } +} + +pub(crate) fn dm_index(index: &Index) -> Markup { + let Index { env, html, modules, types } = index; + base( + env, + "", + &display("Index"), + &html! { + (maud::PreEscaped("\n\n")) + script src="dmdoc.js" {} + }, + &display(""), + &html! { + h1 { (env.title) } + @if let Some(html) = html { (html) } + + @if !modules.is_empty() { + h3 id="modules" { + "Modules " + aside { + "(" + (env.coverage.modules) " modules, " + (env.coverage.macros_documented)"/"(env.coverage.macros_all)" macros" + (percentage(env.coverage.macros_documented, env.coverage.macros_all)) + ")" + } + } + (index_tree(modules, "modules")) + } + + @if !types.is_empty() { + h3 id="types" { + "Types " + aside { + "(" + (env.coverage.types_detailed) " detailed/" + (env.coverage.types_documented) " documented/" + (env.coverage.types_all) " total" + (percentage(env.coverage.types_documented, env.coverage.types_all)) + ")" + } + } + (index_tree(types, "")) + } + } + ) +} + +pub(crate) fn dm_module(module: &ModuleArgs) -> Markup { + let ModuleArgs { env, base_href, details } = *module; + base( + env, + base_href, + &display(&details.orig_filename), + &display(""), + &html! { + @if !details.defines.is_empty() { + " — " + a href=(format!("{}.html#define", details.htmlname)) { "Define Details" } + } + }, + &html! { + h1 { + @if let Some(ref name) = details.name { + (name) " " + aside { + (details.orig_filename) + } + } @else { + (details.orig_filename) + } + (git_link(env, &details.orig_filename, 0)) + } + + table class="summary" cellspacing="0" { + @for item in details.items.iter() { + @match item { + ModuleItem::Docs(docs) => { + tr { + td colspan="2" { + (docs) + } + } + }, + ModuleItem::Define { name, teaser } => { + tr { + th { + a href=(format!("{}.html#define/{}", details.htmlname, name)) { (name) } + } + td { + (teaser) + } + } + }, + ModuleItem::Type { path, teaser, substance } => { + tr { + th { + @if *substance { + a href=(format!("{}.html", &path[1..])) { + (path) + } + } @else { + (env.linkify_type_str(path)) + } + } + td { + (teaser) + } + } + }, + ModuleItem::GlobalProc { name, teaser } => { + tr { + th { + "/proc/" + a href=(format!("global.html#proc/{}", name)) { + (name) + } + } + td { + (teaser) + } + } + }, + ModuleItem::GlobalVar { name, teaser } => { + tr { + th { + "/var/" + a href=(format!("global.html#var/{}", name)) { + (name) + } + } + td { + (teaser) + } + } + }, + ModuleItem::DocComment { .. } => {} + } + } + } + + @if !details.defines.is_empty() { + h2 id="define" { "Define Details" } + @for (name, define) in details.defines.iter() { + h3 id=(format!("define/{}", name)) { + aside class="declaration" { + "#define " + } + (name) + @if define.has_params { + aside { + "(" + @for (i, param) in define.params.iter().enumerate() { + @if i > 0 { + ", " + } + (param) + } + @if define.is_variadic { + " ..." + } + ")" + } + } + (git_link(env, &details.orig_filename, define.line)) + } + (define.docs.html) + } + } + } + ) +} + +pub(crate) fn dm_type(ty: &Type) -> Markup { + let Type { env, base_href, path, details } = *ty; + base( + env, + &base_href, + &display(path), + &display(""), + &html! { + @if !details.vars.is_empty() { + " — " + a href=(format!("{}.html#var", details.htmlname)) { "Var Details" } + } + @if !details.procs.is_empty() { + @if !details.vars.is_empty() { " - " } @else { " — " } + a href=(format!("{}.html#proc", details.htmlname)) { "Proc Details" } + } + }, + &html! { + h1 { + @if path == "global" { + "(global)" + } @else if !details.name.is_empty() { + (details.name) + " " + aside { + (env.linkify_type_str(path)) + } + } @else { + (env.linkify_type_str(path)) + } + @if let Some(parent_type) = details.parent_type { + aside { + " inherits " + (env.linkify_type_str(parent_type)) + } + } + (git_link(env, &details.file.to_string_lossy(), details.line)) + } + @if let Some(ref docs) = details.docs { + (docs.html) + } + + @if !details.vars.is_empty() || !details.procs.is_empty() { + table class="summary" cellspacing="0" { + @if !details.vars.is_empty() { + tr { td colspan="2" { h2 { "Vars" } } } + @for (name, var) in details.vars.iter() { + tr { + th { a href=(format!("{}.html#var/{}", details.htmlname, name)) { (name) } } + td { (teaser(&var.docs, "")) } + } + } + } + @if !details.procs.is_empty() { + tr { td colspan="2" { h2 { "Procs" } } } + @for (name, proc) in details.procs.iter() { + tr { + th { a href=(format!("{}.html#proc/{}", details.htmlname, name)) { (name) } } + td { (teaser(&proc.docs, "")) } + } + } + } + } + } + + @if !details.vars.is_empty() { + h2 id="var" { "Var Details" } + @for (name, var) in details.vars.iter() { + h3 id=(format!("var/{}", name)) { + @if !var.decl.is_empty() { + aside class="declaration" { (var.decl) " " } + } @else if let Some(ref parent) = var.parent { + aside class="parent" { + a title=(format!("/{}", parent)) href=(format!("{}.html#var/{}", parent, name)) { + "\u{2191}" // ↑ + } + } + } + (name) + @if let Some(ref ty) = var.type_ { + " " + aside { + "\u{2013} " // – + @if ty.is_static { "/static" } + @if ty.is_const { "/const" } + @if ty.is_tmp { "/tmp" } + (env.linkify_type_array(ty.path)) + } + } + (git_link(env, &var.file.to_string_lossy(), var.line)) + } + (var.docs.html) + } + } + + @if !details.procs.is_empty() { + h2 id="proc" { "Proc Details" } + @for (name, proc) in details.procs.iter() { + h3 id=(format!("proc/{}", name)) { + @if !proc.decl.is_empty() { + aside class="declaration" { (proc.decl) " " } + } @else if let Some(ref parent) = proc.parent { + aside class="parent" { + a title=(format!("/{}", parent)) href=(format!("{}.html#proc/{}", parent, name)) { + "\u{2191}" // ↑ + } + } + } + (name) + aside { + "(" + @for (i, param) in proc.params.iter().enumerate() { + @if i > 0 { ", " } + @if !param.type_path.is_empty() { + (env.linkify_type_str(¶m.type_path)) + "/" + } + (param.name) + } + ") " + (git_link(env, &proc.file.to_string_lossy(), proc.line)) + } + } + (proc.docs.html) + } + } + } + ) +} + pub fn save_resources(output_path: &Path) -> std::io::Result<()> { #[cfg(debug_assertions)] macro_rules! resources { From 6d0e149cc39d02238e96813b99aaa531319c0cb3 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 5 Nov 2023 22:54:48 -0800 Subject: [PATCH 069/197] Include /final in var documentation This was excluded back when it was a SpacemanDMM-specific feature, but with BYOND 515 adding a real /final, it should be represented here. --- crates/dmdoc/src/main.rs | 4 ++-- crates/dmdoc/src/template/mod.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 8aac7d0c..54afced6 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -344,7 +344,7 @@ fn main2() -> Result<(), Box> { is_static: decl.var_type.flags.is_static(), is_const: decl.var_type.flags.is_const(), is_tmp: decl.var_type.flags.is_tmp(), - //is_final: decl.var_type.flags.is_final(), + is_final: decl.var_type.flags.is_final(), //is_private: decl.var_type.flags.is_private(), //is_protected: decl.var_type.flags.is_protected(), path: &decl.var_type.type_path, @@ -1280,7 +1280,7 @@ struct VarType<'a> { is_static: bool, is_const: bool, is_tmp: bool, - //is_final: bool, + is_final: bool, //is_private: bool, //is_protected: bool, path: &'a [String], diff --git a/crates/dmdoc/src/template/mod.rs b/crates/dmdoc/src/template/mod.rs index 2a33c20c..e94a3e41 100644 --- a/crates/dmdoc/src/template/mod.rs +++ b/crates/dmdoc/src/template/mod.rs @@ -410,6 +410,7 @@ pub(crate) fn dm_type(ty: &Type) -> Markup { @if ty.is_static { "/static" } @if ty.is_const { "/const" } @if ty.is_tmp { "/tmp" } + @if ty.is_final { "/final" } (env.linkify_type_array(ty.path)) } } From 5b4ba580ab1f0c332c38ac5dcc204678f6d9812e Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 5 Nov 2023 23:02:06 -0800 Subject: [PATCH 070/197] Remove Tera template files See 53f9447fa028e936c04bf91dacb4378b9107bd9f --- .../src/{template/mod.rs => template.rs} | 2 +- crates/dmdoc/src/template/base.html | 37 --------- crates/dmdoc/src/template/dm_index.html | 30 ------- crates/dmdoc/src/template/dm_module.html | 55 ------------- crates/dmdoc/src/template/dm_type.html | 81 ------------------- crates/dmdoc/src/template/macros.html | 53 ------------ 6 files changed, 1 insertion(+), 257 deletions(-) rename crates/dmdoc/src/{template/mod.rs => template.rs} (99%) delete mode 100644 crates/dmdoc/src/template/base.html delete mode 100644 crates/dmdoc/src/template/dm_index.html delete mode 100644 crates/dmdoc/src/template/dm_module.html delete mode 100644 crates/dmdoc/src/template/dm_type.html delete mode 100644 crates/dmdoc/src/template/macros.html diff --git a/crates/dmdoc/src/template/mod.rs b/crates/dmdoc/src/template.rs similarity index 99% rename from crates/dmdoc/src/template/mod.rs rename to crates/dmdoc/src/template.rs index e94a3e41..b79e9aed 100644 --- a/crates/dmdoc/src/template/mod.rs +++ b/crates/dmdoc/src/template.rs @@ -471,7 +471,7 @@ pub fn save_resources(output_path: &Path) -> std::io::Result<()> { ($($name:expr,)*) => {{ use std::io::Write; $( - crate::create(&output_path.join($name))?.write_all(include_bytes!($name))?; + crate::create(&output_path.join($name))?.write_all(include_bytes!(concat!("template/", $name)))?; )* }} } diff --git a/crates/dmdoc/src/template/base.html b/crates/dmdoc/src/template/base.html deleted file mode 100644 index a561caba..00000000 --- a/crates/dmdoc/src/template/base.html +++ /dev/null @@ -1,37 +0,0 @@ - - -{% block head %} - - {% if base_href %}{% endif %} - - {% block title %}{% endblock title %} - {{ env.world_name }} -{% endblock head %} - -
{% block header %} - {{ env.world_name }} - - Modules - - Types -{% endblock header %}
-
{% block content %}{% endblock content %}
-
{% block footer %} - {{ env.filename }} - {% if env.git.revision -%} - {%- if env.git.web_url -%} - {{ env.git.revision | substring(end=7) }} - {%- else -%} - {{ env.git.revision }} - {%- endif -%} - {%- if env.git.branch %} - ({{ env.git.branch }} - {%- if env.git.remote_branch and env.git.remote_branch != env.git.branch %} - → {{ env.git.remote_branch }} - {%- endif -%} - ){% endif %} - {%- endif %} — {% if env.dmdoc.url -%} - dmdoc {{ env.dmdoc.version }} - {%- else -%} - dmdoc {{ env.dmdoc.version }} - {%- endif -%} -{% endblock footer %}
- - diff --git a/crates/dmdoc/src/template/dm_index.html b/crates/dmdoc/src/template/dm_index.html deleted file mode 100644 index 4529ad87..00000000 --- a/crates/dmdoc/src/template/dm_index.html +++ /dev/null @@ -1,30 +0,0 @@ -{% extends "base.html" %} -{% import "macros.html" as macros %} -{% block title %}Index{% endblock %} -{% block head %}{{ super() }} - - -{% endblock head %} -{% block content %} -

{{ env.title }}

-{% if html %}{{ html | safe }}{% endif %} - -{% if modules %} -

Modules -

-{{ macros::index_tree(elems=modules, extra_class="modules") }} -{% endif %} - -{% if types %} -

Types -

-{{ macros::index_tree(elems=types) }} -{% endif %} - -{% endblock content %} diff --git a/crates/dmdoc/src/template/dm_module.html b/crates/dmdoc/src/template/dm_module.html deleted file mode 100644 index 417953ea..00000000 --- a/crates/dmdoc/src/template/dm_module.html +++ /dev/null @@ -1,55 +0,0 @@ -{% extends "base.html" %} -{% import "macros.html" as macros %} -{% block title %}{{ details.orig_filename }}{% endblock %} -{% block header -%} -{{ super() }} -{%- if details.defines %} — Define Details{% endif %} -{%- endblock %} -{% block content %} -

{% if details.name -%} - {{ details.name }} -{%- else -%} - {{ details.orig_filename | safe }} -{%- endif %} {{ macros::git_link(env=env, file=details.orig_filename) }}

- - - {%- for item in details.items %} - {% if item.docs -%} - - {%- elif item.define -%} - - {%- elif item.type -%} - - {%- elif item.global_proc -%} - - - {%- elif item.global_var -%} - - - {%- endif %} - {%- endfor -%} -
{{ item.docs | safe }}
{{item.define.name}}{{ item.define.teaser | safe }}
{% if item.type.substance -%} - {{item.type.path}} - {%- else -%} - {{ item.type.path | linkify_type | safe }} - {%- endif %}{{ item.type.teaser | safe }}
/proc/{{item.global_proc.name}}{{ item.global_proc.teaser | safe }}
/var/{{item.global_var.name}}{{ item.global_var.teaser | safe }}
- -{%- if details.defines -%} -

Define Details

-{% for name, define in details.defines -%} -

{{ name }} - {%- if define.has_params %} - - {%- endif -%} - {{ macros::git_link(env=env, item=define, file=details.orig_filename) }} -

- {{ define.docs.html | safe }} -{%- endfor -%} -{%- endif -%} -{% endblock content %} diff --git a/crates/dmdoc/src/template/dm_type.html b/crates/dmdoc/src/template/dm_type.html deleted file mode 100644 index 526f8322..00000000 --- a/crates/dmdoc/src/template/dm_type.html +++ /dev/null @@ -1,81 +0,0 @@ -{% extends "base.html" %} -{% import "macros.html" as macros %} -{% block title %}{{ path }}{% endblock %} -{% block header -%} -{{ super() }} -{%- if details.vars %} — Var Details{% endif %} -{%- if details.procs %}{% if details.vars %} - {% else %} — {% endif -%} - Proc Details{% endif %} -{%- endblock %} -{% block content %} -

{% if path == "(global)" -%} - (global) -{%- elif details.name -%} - {{ details.name }} -{%- else -%} - {{ path | linkify_type | safe }} -{%- endif %} -{%- if details.parent_type %}{% endif -%} -{{ macros::git_link(env=env, item=details) }}

- -{% if details.docs %}{{ details.docs.html | safe }}{% endif %} - -{%- if details.vars or details.procs -%} - - {%- if details.vars -%} - - {%- for name, var in details.vars %} - - {%- endfor %} - {%- endif -%} - - {%- if details.procs -%} - - {%- for name, proc in details.procs %} - - {%- endfor %} - {%- endif -%} -

Vars

{{ name }}{{ macros::teaser(block=var.docs) }}

Procs

{{ name }}{{ macros::teaser(block=proc.docs) }}
-{%- endif -%} - -{% if details.vars %} -

Var Details

- {%- for name, var in details.vars -%} -

- {%- if var.decl -%} - - {%- elif var.parent -%} - - {%- endif -%} - {{ name }} - {%- if var.type %} - - {%- endif -%} - {{ macros::git_link(env=env, item=var) }}

- {{ var.docs.html | safe }} - {%- endfor -%} -{% endif %} - -{%- if details.procs -%} -

Proc Details

- {%- for name, proc in details.procs -%} -

- {%- if proc.decl -%} - - {%- elif proc.parent -%} - - {%- endif -%} - {{ name }} -

- {{ proc.docs.html | safe }} - {%- endfor -%} -{%- endif -%} -{% endblock content %} diff --git a/crates/dmdoc/src/template/macros.html b/crates/dmdoc/src/template/macros.html deleted file mode 100644 index edd1124c..00000000 --- a/crates/dmdoc/src/template/macros.html +++ /dev/null @@ -1,53 +0,0 @@ -{% macro teaser(block, prefix="") -%} - {%- if block -%} - {%- set teaser = block.html | safe | substring(start=block.teaser.start, end=block.teaser.end) -%} - {%- if teaser %}{{ prefix }}{{ teaser | safe }}{% endif -%} - {%- endif -%} -{%- endmacro teaser %} - -{% macro git_link(env, item=false, file=false) -%} - {% if item and item.file %} - {% set file = item.file %} - {% endif %} - {%- if file -%} - {%- if env.git.web_url and env.git.revision %} - - {%- endif %} - - {%- if env.git.web_url and env.git.revision %}{% endif %} - {%- endif -%} -{%- endmacro git_link %} - -{% macro index_tree(elems, extra_class="") -%} -
    - {% for tree in elems -%} - {{ self::index_tree_elem(tree=tree) }} - {% endfor -%} -
-{%- endmacro %} - -{% macro index_tree_elem(tree, prefix="") -%} - {%- if tree.children | length == 1 and not tree.htmlname and not tree.teaser -%} - {{ self::index_tree_elem(tree=tree.children[0], prefix=prefix ~ tree.self_name ~ "/") }} - {%- else -%} - - {%- if prefix -%} - {{prefix}} - {%- endif -%} - {%- if not tree.htmlname -%} - {{ tree.self_name }} - {%- else -%} - {{ tree.self_name }} - {%- endif %} - {%- if tree.teaser %} - {{ tree.teaser | safe }}{%- endif -%} - {% if tree.children %}{{ self::index_tree(elems=tree.children) }}{% endif -%} - - {%- endif -%} -{%- endmacro %} - -{% macro percentage(amt, total) -%} - {%- if total -%} - , {{ amt * 1000 / total | round / 10 }}% - {%- endif -%} -{%- endmacro %} From cef9528642461a97865cc0072647c1d8d505ad05 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Tue, 7 Nov 2023 19:16:12 -0800 Subject: [PATCH 071/197] Implement /proc/operator:=() Fixes #376. --- crates/dreammaker/src/parser.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index a580cf3d..7ad3e425 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -950,6 +950,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { last_part.push('~'); } else if self.exact(Punct(Equiv))?.is_some() { last_part.push_str("~="); + } else if self.exact(Punct(AssignInto))?.is_some() { + last_part.push_str(":="); } else if self.exact(Punct(LBracket))?.is_some() { require!(self.exact(Punct(RBracket))); if self.exact(Punct(Assign))?.is_some() { From 356eeacab00b080e5040fa41ac2689a64f82f925 Mon Sep 17 00:00:00 2001 From: DreamySkrell <107256943+DreamySkrell@users.noreply.github.com> Date: Fri, 17 Nov 2023 05:33:11 +0100 Subject: [PATCH 072/197] Derive Ord/PartialOrd for Coord2/Coord3 (#377) So they can be used as keys in maps or the like, in external tooling that depends on this. --- crates/dmm-tools/src/dmm.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/dmm-tools/src/dmm.rs b/crates/dmm-tools/src/dmm.rs index 65b48d41..b0db43e2 100644 --- a/crates/dmm-tools/src/dmm.rs +++ b/crates/dmm-tools/src/dmm.rs @@ -28,7 +28,7 @@ pub struct Key(KeyType); /// An XY coordinate pair in the BYOND coordinate system. /// /// The lower-left corner is `{ x: 1, y: 1 }`. -#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Coord2 { pub x: i32, pub y: i32, @@ -71,7 +71,7 @@ impl std::ops::Add for Coord2 { /// /// Note that BYOND by default considers "UP" to be Z+1, but this does not /// necessarily apply to a given game's logic. -#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Coord3 { pub x: i32, pub y: i32, From 5311ff5f028be1560c3533ac463fce1ff5555245 Mon Sep 17 00:00:00 2001 From: DreamySkrell <107256943+DreamySkrell@users.noreply.github.com> Date: Fri, 17 Nov 2023 05:38:22 +0100 Subject: [PATCH 073/197] Let TGM writer take &mut impl Write (#378) Also `dmm_tools::dmm::Map::to_writer()`, so it can be used to save to a string and not just a file, for use in external tooling that depends on this, and may want to, for example, pass the string back to byond from rust-g. `dmm_tools::dmm::Map::to_file()` is kept for convenience (and backwards compatibility I guess to not break code), but it just uses the `::to_writer()` function. --- crates/dmm-tools/src/dmm.rs | 7 +++++-- crates/dmm-tools/src/dmm/save_tgm.rs | 5 ++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/crates/dmm-tools/src/dmm.rs b/crates/dmm-tools/src/dmm.rs index b0db43e2..df36ff37 100644 --- a/crates/dmm-tools/src/dmm.rs +++ b/crates/dmm-tools/src/dmm.rs @@ -181,9 +181,12 @@ impl Map { Ok(map) } + pub fn to_writer(&self, writer: &mut impl std::io::Write) -> io::Result<()> { + save_tgm::save_tgm(self, writer) + } + pub fn to_file(&self, path: &Path) -> io::Result<()> { - // DMM saver later - save_tgm::save_tgm(self, File::create(path)?) + self.to_writer(&mut File::create(path)?) } pub fn key_length(&self) -> u8 { diff --git a/crates/dmm-tools/src/dmm/save_tgm.rs b/crates/dmm-tools/src/dmm/save_tgm.rs index b37418cb..1afa720f 100644 --- a/crates/dmm-tools/src/dmm/save_tgm.rs +++ b/crates/dmm-tools/src/dmm/save_tgm.rs @@ -1,5 +1,4 @@ //! TGM map writer. -use std::fs::File; use std::io::{self, Write, BufWriter}; use ndarray::Axis; @@ -10,8 +9,8 @@ const TGM_HEADER: &str = "//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREV // Note: writeln! currently (2022-04-30) writes the \n character alone on all platforms // If that changes, this will break. -pub fn save_tgm(map: &Map, f: File) -> io::Result<()> { - let mut f = BufWriter::new(f); +pub fn save_tgm(map: &Map, w: &mut impl Write) -> io::Result<()> { + let mut f = BufWriter::new(w); writeln!(f, "{}", TGM_HEADER)?; // dictionary From af80187a7fbd7916f88d5b5c3e32d75757d15c03 Mon Sep 17 00:00:00 2001 From: DreamySkrell <107256943+DreamySkrell@users.noreply.github.com> Date: Sun, 19 Nov 2023 02:41:40 +0100 Subject: [PATCH 074/197] Fix Map::adjust_key_length() (#379) Currently, there is `Map::adjust_key_length()`, but it sets key length based on the amount of items in the dictionary. Which is fine if keys in order like 1-2-3-4-...-N, but it falls apart if the keys are not in order - which is valid for a dmm map. If a map has keys like [1, 2, 3000], then, currently, `Map::adjust_key_length()` will set key length to 1, but the map will panic on save cause the 3000 key is bigger than max key for this key length (52). This PR fixes `adjust_key_length` to work properly in that case, where it sets key length based on the biggest key in the map dictionary. --- crates/dmm-tools/src/dmm.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/crates/dmm-tools/src/dmm.rs b/crates/dmm-tools/src/dmm.rs index df36ff37..6a29204c 100644 --- a/crates/dmm-tools/src/dmm.rs +++ b/crates/dmm-tools/src/dmm.rs @@ -194,12 +194,15 @@ impl Map { } pub fn adjust_key_length(&mut self) { - if self.dictionary.len() > 2704 { - self.key_length = 3; - } else if self.dictionary.len() > 52 { - self.key_length = 2; - } else { - self.key_length = 1; + if let Some(max_key) = self.dictionary.keys().max() { + let max_key = max_key.0; + if max_key >= 2704 { + self.key_length = 3; + } else if max_key >= 52 { + self.key_length = 2; + } else { + self.key_length = 1; + } } } From 219269b9c46eb3aa881aecfb95c97f415385cc65 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 14 Dec 2023 17:35:31 -0800 Subject: [PATCH 075/197] Update to auxtools debug server v2.3.0 --- scripts/download-auxtools.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/download-auxtools.sh b/scripts/download-auxtools.sh index 32c3b62c..0d66431e 100755 --- a/scripts/download-auxtools.sh +++ b/scripts/download-auxtools.sh @@ -2,9 +2,9 @@ set -euo pipefail # Settings -DEBUG_SERVER_TAG=v2.2.4 -DEBUG_SERVER_DLL_URL=https://github.com/willox/auxtools/releases/download/v2.2.4/debug_server.dll -DEBUG_SERVER_DLL_SHA256=2a81e64d5cacef372043af476e9b1b2d21e38a6f9f708e0da8ca573bdcfcf0d3 +DEBUG_SERVER_TAG=v2.3.0 +DEBUG_SERVER_DLL_URL=https://github.com/willox/auxtools/releases/download/v2.3.0/debug_server.dll +DEBUG_SERVER_DLL_SHA256=824fb6e814520f0e24e6c3c8fb2316eaa9412e03dee6cc46de44ab6e58061698 # ----------------------------------------------------------------------------- cd "$(dirname "${BASH_SOURCE[0]}")" From 02b7d9c10d42e815c66e8fee670378916f3e46de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Dec 2023 22:10:53 -0800 Subject: [PATCH 076/197] Bump zerocopy from 0.7.19 to 0.7.31 (#380) Bumps [zerocopy](https://github.com/google/zerocopy) from 0.7.19 to 0.7.31. - [Release notes](https://github.com/google/zerocopy/releases) - [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/zerocopy/compare/v0.7.19...v0.7.31) --- updated-dependencies: - dependency-name: zerocopy dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1e5c5e83..e90c1786 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1648,18 +1648,18 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "zerocopy" -version = "0.7.19" +version = "0.7.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2bd783c6247b80c3ac2267afe3042452f184478184264e0c1532bbf59adcb7" +checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.19" +version = "0.7.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56feebc4664bdb37f39c0b1b8fc8fa2f5648e3ec5f9cf4344978b4b7ca561fff" +checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a" dependencies = [ "proc-macro2", "quote", From 74cc3b870bcdf6457933f40b3620b703e6ed8ca3 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 30 Dec 2023 15:42:48 -0800 Subject: [PATCH 077/197] Update to auxtools debug server v2.3.1 --- scripts/download-auxtools.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/download-auxtools.sh b/scripts/download-auxtools.sh index 0d66431e..3a718270 100755 --- a/scripts/download-auxtools.sh +++ b/scripts/download-auxtools.sh @@ -2,9 +2,9 @@ set -euo pipefail # Settings -DEBUG_SERVER_TAG=v2.3.0 -DEBUG_SERVER_DLL_URL=https://github.com/willox/auxtools/releases/download/v2.3.0/debug_server.dll -DEBUG_SERVER_DLL_SHA256=824fb6e814520f0e24e6c3c8fb2316eaa9412e03dee6cc46de44ab6e58061698 +DEBUG_SERVER_TAG=v2.3.1 +DEBUG_SERVER_DLL_URL=https://github.com/willox/auxtools/releases/download/v2.3.1/debug_server.dll +DEBUG_SERVER_DLL_SHA256=b6df3c9b6052c59932f702769a2acb2b18052d174d04c6b4d34fb6ad8b6e76ee # ----------------------------------------------------------------------------- cd "$(dirname "${BASH_SOURCE[0]}")" From 59cfdbf826acb4f72adc2cbd4ffe2147baa7c0ad Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 1 Jan 2024 11:49:52 -0800 Subject: [PATCH 078/197] Revert "Update to auxtools debug server v2.3.1" This reverts commit 74cc3b870bcdf6457933f40b3620b703e6ed8ca3. --- scripts/download-auxtools.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/download-auxtools.sh b/scripts/download-auxtools.sh index 3a718270..0d66431e 100755 --- a/scripts/download-auxtools.sh +++ b/scripts/download-auxtools.sh @@ -2,9 +2,9 @@ set -euo pipefail # Settings -DEBUG_SERVER_TAG=v2.3.1 -DEBUG_SERVER_DLL_URL=https://github.com/willox/auxtools/releases/download/v2.3.1/debug_server.dll -DEBUG_SERVER_DLL_SHA256=b6df3c9b6052c59932f702769a2acb2b18052d174d04c6b4d34fb6ad8b6e76ee +DEBUG_SERVER_TAG=v2.3.0 +DEBUG_SERVER_DLL_URL=https://github.com/willox/auxtools/releases/download/v2.3.0/debug_server.dll +DEBUG_SERVER_DLL_SHA256=824fb6e814520f0e24e6c3c8fb2316eaa9412e03dee6cc46de44ab6e58061698 # ----------------------------------------------------------------------------- cd "$(dirname "${BASH_SOURCE[0]}")" From e5fa81d78e436cd663a638824da28fe363a8c1ab Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 4 Mar 2024 14:32:45 -0800 Subject: [PATCH 079/197] Properly swallow input types on bare variables ex: var/foo as text|null --- crates/dreammaker/src/parser.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 7ad3e425..7921a42c 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -811,7 +811,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // translators note: this allows comments of the form ``//! blah`` at the end of the line let (docs, expression) = require!(self.doc_comment(|this| { let expr = require!(this.expression()); - let _ = require!(this.input_specifier()); + let _ = require!(this.input_specifier()); // TODO: save to VarType instead of ignoring // We have to annotate prior to consuming the statement terminator, as we // will otherwise consume following whitespace resulting in a bad annotation range @@ -842,6 +842,10 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // TODO: allow enclosing-targeting docs here somehow? self.put_back(other); + if var_type.is_some() { + let _ = require!(self.input_specifier()); // TODO: save to VarType instead of ignoring + } + if last_part == "var" { self.error("`var;` item has no effect") .set_severity(Severity::Warning) From 671f484b4085d1501c0aecffc05e6026018e08e0 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 9 Mar 2024 21:12:43 -0800 Subject: [PATCH 080/197] Run cargo update --- Cargo.lock | 430 +++++++++++++++++++++++++---------------------------- 1 file changed, 206 insertions(+), 224 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e90c1786..46d370a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,9 +16,9 @@ checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom", @@ -53,9 +53,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" dependencies = [ "anstyle", "anstyle-parse", @@ -67,33 +67,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", "windows-sys", @@ -108,7 +108,7 @@ dependencies = [ "attribute-derive-macro", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -124,7 +124,7 @@ dependencies = [ "proc-macro2", "quote", "quote-use", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -148,6 +148,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + [[package]] name = "builtins-proc-macro" version = "0.0.0" @@ -159,15 +165,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" dependencies = [ "bytemuck_derive", ] @@ -180,14 +186,14 @@ checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] name = "cc" -version = "1.0.83" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" dependencies = [ "jobserver", "libc", @@ -201,9 +207,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" dependencies = [ "android-tzdata", "iana-time-zone", @@ -215,9 +221,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.7" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651" dependencies = [ "clap_builder", "clap_derive", @@ -225,9 +231,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.7" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstream", "anstyle", @@ -237,21 +243,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "collection_literals" @@ -279,51 +285,43 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "dap-types" @@ -348,13 +346,13 @@ dependencies = [ [[package]] name = "derive-where" -version = "1.2.5" +version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146398d62142a0f35248a608f17edf0dde57338354966d6e41d0eb2d16980ccb" +checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -434,7 +432,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33cf9537e2d06891448799b96d5a8c8083e0e90522a7fdabe6ebf4f41d79d651" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -453,7 +451,7 @@ name = "dreammaker" version = "0.1.0" dependencies = [ "ahash", - "bitflags", + "bitflags 1.3.2", "builtins-proc-macro", "color_space", "derivative", @@ -473,9 +471,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "fallible_collections" @@ -488,9 +486,9 @@ dependencies = [ [[package]] name = "fdeflate" -version = "0.3.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" dependencies = [ "simd-adler32", ] @@ -507,18 +505,18 @@ dependencies = [ [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "futures" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -531,9 +529,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -541,15 +539,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -558,38 +556,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -617,7 +615,7 @@ checksum = "13a1bcfb855c1f340d5913ab542e36f25a1c56f57de79022928297632435dec2" dependencies = [ "attribute-derive", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -631,9 +629,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -646,7 +644,7 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75fbddaef2e12b4995900539d7209d947b988a3d87ee8737484d049b526e5441" dependencies = [ - "bitflags", + "bitflags 1.3.2", "draw_state", "log", ] @@ -667,7 +665,7 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc" dependencies = [ - "bitflags", + "bitflags 1.3.2", "libc", "libgit2-sys", "log", @@ -697,9 +695,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -720,9 +718,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -762,24 +760,24 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -807,9 +805,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libgit2-sys" @@ -825,9 +823,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.12" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" +checksum = "037731f5d3aaa87a5675e895b63ddff1a87624bc29f77004ea829809654e48f6" dependencies = [ "cc", "libc", @@ -837,9 +835,9 @@ dependencies = [ [[package]] name = "lodepng" -version = "3.9.1" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3cdccd0cf57a5d456f0656ebcff72c2e19503287e1afbf3b84382812adc0606" +checksum = "a42d298694b14401847de29abd44adf278b42e989e516deac7b72018400002d8" dependencies = [ "crc32fast", "fallible_collections", @@ -850,9 +848,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "lsp-types" @@ -860,7 +858,7 @@ version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9be6e9c7e2d18f651974370d7aff703f9513e0df6e464fd795660edc77e6ca51" dependencies = [ - "bitflags", + "bitflags 1.3.2", "serde", "serde_json", "serde_repr", @@ -901,24 +899,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", "simd-adler32", @@ -939,37 +928,36 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" dependencies = [ "num-traits", ] [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "ordered-float" @@ -982,9 +970,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" @@ -1016,7 +1004,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -1042,17 +1030,17 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "png" -version = "0.17.10" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crc32fast", "fdeflate", "flate2", @@ -1102,20 +1090,20 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] [[package]] name = "pulldown-cmark" -version = "0.9.3" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags", + "bitflags 2.4.2", "getopts", "memchr", "unicase", @@ -1123,9 +1111,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -1138,7 +1126,7 @@ checksum = "a7b5abe3fe82fdeeb93f44d66a7b444dedf2e4827defb0a8e69c437b2de2ef94" dependencies = [ "quote", "quote-use-macros", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -1150,7 +1138,7 @@ dependencies = [ "derive-where", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -1191,9 +1179,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" dependencies = [ "either", "rayon-core", @@ -1201,9 +1189,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -1211,9 +1199,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", @@ -1223,9 +1211,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -1249,9 +1237,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "same-file" @@ -1262,37 +1250,31 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - [[package]] name = "serde" -version = "1.0.190" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.190" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -1301,13 +1283,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.16" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" +checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -1333,15 +1315,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" [[package]] name = "syn" @@ -1356,9 +1338,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -1367,9 +1349,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -1409,9 +1391,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -1421,9 +1403,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -1436,9 +1418,9 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -1466,9 +1448,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -1482,9 +1464,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1492,24 +1474,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1517,28 +1499,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "weezl" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" [[package]] name = "winapi" @@ -1573,27 +1555,27 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ "windows-targets", ] [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -1606,62 +1588,62 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "zerocopy" -version = "0.7.31" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.31" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] From 707c7b4fb830647cab245c31a22c3d9dcddd77a2 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 9 Mar 2024 22:03:54 -0800 Subject: [PATCH 081/197] Update git2 dependency --- Cargo.lock | 10 +++++----- crates/dm-langserver/Cargo.toml | 2 +- crates/dmdoc/Cargo.toml | 4 ++-- crates/dmm-tools-cli/Cargo.toml | 2 +- crates/dreamchecker/Cargo.toml | 2 +- crates/spaceman-dmm/Cargo.toml | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46d370a0..a71ac89b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -661,11 +661,11 @@ dependencies = [ [[package]] name = "git2" -version = "0.16.1" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc" +checksum = "1b3ba52851e73b46a4c3df1d89343741112003f0f6f13beb0dfac9e457c3fdcd" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.2", "libc", "libgit2-sys", "log", @@ -811,9 +811,9 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libgit2-sys" -version = "0.14.2+1.5.1" +version = "0.16.2+1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f3d95f6b51075fe9810a7ae22c7095f12b98005ab364d8544797a825ce946a4" +checksum = "ee4126d8b4ee5c9d9ea891dd875cfdc1e9d0950437179104b183d7d8a74d24e8" dependencies = [ "cc", "libc", diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index dac465a7..413e478b 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -23,4 +23,4 @@ ahash = "0.8.0" [build-dependencies] chrono = "0.4.22" -git2 = { version = "0.16.1", default-features = false } +git2 = { version = "0.18.2", default-features = false } diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index ec1b323e..340836ca 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -9,7 +9,7 @@ edition = "2018" dreammaker = { path = "../dreammaker" } pulldown-cmark = "0.9.2" walkdir = "2.3.2" -git2 = { version = "0.16.1", default-features = false } +git2 = { version = "0.18.2", default-features = false } maud = "0.25.0" [dev-dependencies] @@ -17,4 +17,4 @@ walkdir = "2.3.2" [build-dependencies] chrono = "0.4.22" -git2 = { version = "0.16.1", default-features = false } +git2 = { version = "0.18.2", default-features = false } diff --git a/crates/dmm-tools-cli/Cargo.toml b/crates/dmm-tools-cli/Cargo.toml index 3bf3ec6b..080f415d 100644 --- a/crates/dmm-tools-cli/Cargo.toml +++ b/crates/dmm-tools-cli/Cargo.toml @@ -21,4 +21,4 @@ ahash = "0.8.0" [build-dependencies] chrono = "0.4.22" -git2 = { version = "0.16.1", default-features = false } +git2 = { version = "0.18.2", default-features = false } diff --git a/crates/dreamchecker/Cargo.toml b/crates/dreamchecker/Cargo.toml index 09f13973..a7ea7261 100644 --- a/crates/dreamchecker/Cargo.toml +++ b/crates/dreamchecker/Cargo.toml @@ -11,4 +11,4 @@ ahash = "0.8.0" [build-dependencies] chrono = "0.4.22" -git2 = { version = "0.16.1", default-features = false } +git2 = { version = "0.18.2", default-features = false } diff --git a/crates/spaceman-dmm/Cargo.toml b/crates/spaceman-dmm/Cargo.toml index 7d471fb0..bb75a549 100644 --- a/crates/spaceman-dmm/Cargo.toml +++ b/crates/spaceman-dmm/Cargo.toml @@ -35,4 +35,4 @@ branch = "zenity" [build-dependencies] chrono = "0.4.19" -git2 = { version = "0.14.2", default-features = false } +git2 = { version = "0.18.2", default-features = false } From 4883ef0e156b68295c084edc2591ea458155b41f Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Wed, 13 Mar 2024 00:02:49 -0700 Subject: [PATCH 082/197] Enable secret debugServerDll setting in release builds too --- crates/dm-langserver/src/debugger/mod.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/crates/dm-langserver/src/debugger/mod.rs b/crates/dm-langserver/src/debugger/mod.rs index 3cee3110..bd09014e 100644 --- a/crates/dm-langserver/src/debugger/mod.rs +++ b/crates/dm-langserver/src/debugger/mod.rs @@ -434,11 +434,9 @@ handle_request! { #[allow(unused_mut)] let mut extools_dll = None; - #[cfg(debug_assertions)] { - if let Some(dll) = self.extools_dll.as_ref() { - debug_output!(in self.seq, "[main] configured override: {:?}", dll); - extools_dll = Some(dll.into()); - } + if let Some(dll) = self.extools_dll.as_ref() { + debug_output!(in self.seq, "[main] configured override: {:?}", dll); + extools_dll = Some(dll.into()); } #[cfg(extools_bundle)] { @@ -460,11 +458,9 @@ handle_request! { #[allow(unused_mut)] let mut debug_server_dll = None; - #[cfg(debug_assertions)] { - if let Some(dll) = self.debug_server_dll.as_ref() { - debug_output!(in self.seq, "[main] configured override: {:?}", dll); - debug_server_dll = Some(dll.into()); - } + if let Some(dll) = self.debug_server_dll.as_ref() { + debug_output!(in self.seq, "[main] configured override: {:?}", dll); + debug_server_dll = Some(dll.into()); } #[cfg(auxtools_bundle)] { From 2dac6eba150c6e284ef063a4d05198d9932fd422 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Wed, 13 Mar 2024 22:15:04 -0700 Subject: [PATCH 083/197] Update copyright years --- crates/dm-langserver/src/main.rs | 2 +- crates/dmdoc/src/main.rs | 2 +- crates/dmm-tools-cli/src/main.rs | 2 +- crates/dreamchecker/src/main.rs | 2 +- crates/spaceman-dmm/src/main.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index 42ad7312..18835a0f 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -52,7 +52,7 @@ fn main() { std::env::set_var("RUST_BACKTRACE", "1"); eprintln!( - "dm-langserver {} Copyright (C) 2017-2023 Tad Hardesty", + "dm-langserver {} Copyright (C) 2017-2024 Tad Hardesty", env!("CARGO_PKG_VERSION") ); eprintln!("This program comes with ABSOLUTELY NO WARRANTY. This is free software,"); diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 54afced6..76eb2492 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -22,7 +22,7 @@ use dm::docs::*; use markdown::DocBlock; const BUILD_INFO: &str = concat!( - "dmdoc ", env!("CARGO_PKG_VERSION"), " Copyright (C) 2017-2023 Tad Hardesty\n", + "dmdoc ", env!("CARGO_PKG_VERSION"), " Copyright (C) 2017-2024 Tad Hardesty\n", include_str!(concat!(env!("OUT_DIR"), "/build-info.txt")), "\n", "This program comes with ABSOLUTELY NO WARRANTY. This is free software,\n", "and you are welcome to redistribute it under the conditions of the GNU\n", diff --git a/crates/dmm-tools-cli/src/main.rs b/crates/dmm-tools-cli/src/main.rs index 221fc84e..42425a3b 100644 --- a/crates/dmm-tools-cli/src/main.rs +++ b/crates/dmm-tools-cli/src/main.rs @@ -91,7 +91,7 @@ impl Context { env!("CARGO_PKG_VERSION"), "\n", include_str!(concat!(env!("OUT_DIR"), "/build-info.txt")) ), - author="Copyright (C) 2017-2023 Tad Hardesty", + author="Copyright (C) 2017-2024 Tad Hardesty", about="This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under the conditions of the GNU General Public License version 3.", diff --git a/crates/dreamchecker/src/main.rs b/crates/dreamchecker/src/main.rs index 3114321b..50d4eece 100644 --- a/crates/dreamchecker/src/main.rs +++ b/crates/dreamchecker/src/main.rs @@ -21,7 +21,7 @@ fn main() { while let Some(arg) = args.next() { if arg == "-V" || arg == "--version" { println!( - "dreamchecker {} Copyright (C) 2017-2023 Tad Hardesty", + "dreamchecker {} Copyright (C) 2017-2024 Tad Hardesty", env!("CARGO_PKG_VERSION") ); println!("{}", include_str!(concat!(env!("OUT_DIR"), "/build-info.txt"))); diff --git a/crates/spaceman-dmm/src/main.rs b/crates/spaceman-dmm/src/main.rs index 1d50829a..04a0434c 100644 --- a/crates/spaceman-dmm/src/main.rs +++ b/crates/spaceman-dmm/src/main.rs @@ -590,7 +590,7 @@ impl EditorScene { ui.menu(im_str!("Help"), true, || { ui.menu(im_str!("About SpacemanDMM"), true, || { ui.text(&im_str!( - "{} {} Copyright (C) 2017-2023 Tad Hardesty", + "{} {} Copyright (C) 2017-2024 Tad Hardesty", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"), )); From 1f331f5db10581050d331da2ae29b26be328ef42 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Tue, 19 Mar 2024 13:13:22 -0700 Subject: [PATCH 084/197] Improve update-auxtools in case of staged changes --- scripts/update-auxtools.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/update-auxtools.sh b/scripts/update-auxtools.sh index b81c87cd..528519e9 100755 --- a/scripts/update-auxtools.sh +++ b/scripts/update-auxtools.sh @@ -19,5 +19,4 @@ sed \ download-auxtools.sh # Prepare the commit -git add download-auxtools.sh -git commit -m "Update to auxtools debug server $DEBUG_SERVER_TAG" +git commit -m "Update to auxtools debug server $DEBUG_SERVER_TAG" -- download-auxtools.sh From 6c5a751516ae0e8add4b2aa4388a1e84e96e7082 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Tue, 19 Mar 2024 13:13:31 -0700 Subject: [PATCH 085/197] Update to auxtools debug server v2.3.3 --- scripts/download-auxtools.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/download-auxtools.sh b/scripts/download-auxtools.sh index 0d66431e..92738f06 100755 --- a/scripts/download-auxtools.sh +++ b/scripts/download-auxtools.sh @@ -2,9 +2,9 @@ set -euo pipefail # Settings -DEBUG_SERVER_TAG=v2.3.0 -DEBUG_SERVER_DLL_URL=https://github.com/willox/auxtools/releases/download/v2.3.0/debug_server.dll -DEBUG_SERVER_DLL_SHA256=824fb6e814520f0e24e6c3c8fb2316eaa9412e03dee6cc46de44ab6e58061698 +DEBUG_SERVER_TAG=v2.3.3 +DEBUG_SERVER_DLL_URL=https://github.com/willox/auxtools/releases/download/v2.3.3/debug_server.dll +DEBUG_SERVER_DLL_SHA256=8c3633d8237738be39a8c8f34bbd3d819cdaa270d1f30774c5007481fc32418c # ----------------------------------------------------------------------------- cd "$(dirname "${BASH_SOURCE[0]}")" From c6d85c798f00701fd5d4782ab658819a46938f87 Mon Sep 17 00:00:00 2001 From: ZeWaka Date: Thu, 23 May 2024 22:30:58 -0700 Subject: [PATCH 086/197] fexists can be called in the preprocessor (#388) 515 feature https://www.byond.com/forum/post/2857912 currently, ```dm #if fexists("secret/secret.dme") // non-constant function call: fexists #warn wow you have a secret.dme file #endif ``` can't actually const eval since it can have diff. behavior at runtime obv --------- Co-authored-by: Tad Hardesty --- crates/dreamchecker/src/lib.rs | 1 + crates/dreammaker/src/constants.rs | 12 ++++++++++++ crates/dreammaker/tests/constants_tests.rs | 8 ++++++++ crates/dreammaker/tests/macro_tests.rs | 17 +++++++++++++++++ 4 files changed, 38 insertions(+) diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 35074c4f..a556d776 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -143,6 +143,7 @@ impl<'o> AssumptionSet<'o> { ConstFn::Newlist => AssumptionSet::from_valid_instance(objtree.expect("/list")), ConstFn::Sound => AssumptionSet::from_valid_instance(objtree.expect("/sound")), ConstFn::Generator => AssumptionSet::from_valid_instance(objtree.expect("/generator")), + ConstFn::FileExists => AssumptionSet::default(), ConstFn::Filter => AssumptionSet::default(), ConstFn::File => AssumptionSet::default(), }, diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index acbe5f38..6e99adc3 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -154,6 +154,8 @@ pub enum ConstFn { File, /// The `generator()` type constructor. Generator, + /// `fexists()`, which can be used in preprocessor expressions. + FileExists, } /// A constant-evaluation error (usually type mismatch). @@ -411,6 +413,7 @@ impl fmt::Display for ConstFn { ConstFn::Filter => "filter", ConstFn::File => "file", ConstFn::Generator => "generator", + ConstFn::FileExists => "fexists" }) } } @@ -812,6 +815,15 @@ impl<'a> ConstantFolder<'a> { None => return Err(self.error("malformed nameof() call, expression appears to have no name")), } } + "fexists" if self.defines.is_some() => { + if args.len() != 1 { + return Err(self.error(format!("malformed fexists() call, must have 1 argument and instead has {}", args.len()))); + } + match args[0].as_term() { + Some(Term::String(ref path)) => Constant::from(std::path::Path::new(path).exists()), + _ => return Err(self.error("malformed fexists() call, argument given isn't a string.")), + } + } // other functions are no-goes _ => return Err(self.error(format!("non-constant function call: {}", ident))), }, diff --git a/crates/dreammaker/tests/constants_tests.rs b/crates/dreammaker/tests/constants_tests.rs index 130436e0..13c43f72 100644 --- a/crates/dreammaker/tests/constants_tests.rs +++ b/crates/dreammaker/tests/constants_tests.rs @@ -110,3 +110,11 @@ fn rgb_hcy() { Constant::string("#000000"), ); } + +#[test] +fn no_fexists_outside_preproc() { + assert_eq!( + eval("fexists()").unwrap_err().description(), + "non-constant function call: fexists", + ); +} diff --git a/crates/dreammaker/tests/macro_tests.rs b/crates/dreammaker/tests/macro_tests.rs index afefbe84..2dbeaa85 100644 --- a/crates/dreammaker/tests/macro_tests.rs +++ b/crates/dreammaker/tests/macro_tests.rs @@ -69,3 +69,20 @@ ok2 Ident("ok2".into(), false), ]); } + +#[test] +fn fexists_function() { + assert_eq!(process(r#" +#if fexists("README.md") +exists +#endif +"#), &[ + Ident("exists".into(), false), + ]); + + assert_eq!(process(r#" +#if fexists("this file does not exist") +exists +#endif +"#), &[]); +} From 30055a5b9fc284fb2e94b7503bc6f53168cd8352 Mon Sep 17 00:00:00 2001 From: Waterpig <49160555+Majkl-J@users.noreply.github.com> Date: Fri, 24 May 2024 09:16:33 +0200 Subject: [PATCH 087/197] Add delay argument to animate (#387) 515.1590 added the delay argument to animate() and I happen to be using it --- crates/dreammaker/src/builtins.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/dreammaker/src/builtins.rs b/crates/dreammaker/src/builtins.rs index e3f0271e..2718f197 100644 --- a/crates/dreammaker/src/builtins.rs +++ b/crates/dreammaker/src/builtins.rs @@ -403,7 +403,7 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { proc/abs(A); proc/addtext(Arg1, Arg2/*, ...*/); proc/alert(Usr/*=usr*/,Message,Title,Button1/*="Ok"*/,Button2,Button3); - proc/animate(Object, time, loop, easing, flags, // +2 forms + proc/animate(Object, time, loop, easing, flags, delay, // +2 forms // these kwargs alpha, color, infra_luminosity, layer, maptext_width, maptext_height, maptext_x, maptext_y, luminosity, pixel_x, pixel_y, pixel_w, pixel_z, From 551c3c921fc77bd3943cf5d8f6e80d97de13f94c Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 27 May 2024 23:43:07 -0700 Subject: [PATCH 088/197] Fix unused field warning in constant folder --- crates/dreammaker/src/constants.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index 6e99adc3..047ee843 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -471,7 +471,7 @@ pub(crate) fn evaluate_all(context: &Context, tree: &mut ObjectTree) { } match constant_ident_lookup(tree, ty, &key, false) { Err(err) => context.register_error(err), - Ok(ConstLookup::Found(_, _)) => {} + Ok(ConstLookup::Found(_)) => {} Ok(ConstLookup::Continue(_)) => { context.register_error(DMError::new( tree[ty].vars[&key].value.location, @@ -488,7 +488,7 @@ pub(crate) fn evaluate_all(context: &Context, tree: &mut ObjectTree) { } enum ConstLookup { - Found(TreePath, Constant), + Found(Constant), Continue(Option), } @@ -514,7 +514,7 @@ fn constant_ident_lookup( match type_.vars.get_mut(ident) { None => return Ok(ConstLookup::Continue(parent)), Some(var) => match var.value.constant.clone() { - Some(constant) => return Ok(ConstLookup::Found(decl.var_type.type_path, constant)), + Some(constant) => return Ok(ConstLookup::Found(/*decl.var_type.type_path,*/ constant)), None => match var.value.expression.clone() { Some(expr) => { if var.value.being_evaluated { @@ -539,7 +539,7 @@ fn constant_ident_lookup( None => { let c = Constant::Null(Some(decl.var_type.type_path.clone())); var.value.constant = Some(c.clone()); - return Ok(ConstLookup::Found(decl.var_type.type_path, c)); + return Ok(ConstLookup::Found(/*decl.var_type.type_path,*/ c)); } }, }, @@ -556,7 +556,7 @@ fn constant_ident_lookup( let var = tree[ty].vars.get_mut(ident).unwrap(); var.value.constant = Some(value.clone()); var.value.being_evaluated = false; - Ok(ConstLookup::Found(type_hint, value)) + Ok(ConstLookup::Found(/*type_hint,*/ value)) } struct ConstantFolder<'a> { @@ -945,7 +945,7 @@ impl<'a> ConstantFolder<'a> { match constant_ident_lookup(tree, ty, ident, must_be_const) .map_err(|e| e.with_location(location))? { - ConstLookup::Found(_, v) => return Ok(v), + ConstLookup::Found(v) => return Ok(v), ConstLookup::Continue(i) => idx = i, } } From 1a03fe0d272c2eb168c53980aba6f366166a70be Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 27 May 2024 23:55:26 -0700 Subject: [PATCH 089/197] Fix Unicode being mangled in doc comments --- crates/dreammaker/src/lexer.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index 72c418a0..7c519125 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -729,6 +729,7 @@ impl<'ctx> Lexer<'ctx> { fn skip_block_comments(&mut self) -> Option { let mut depth = 1; let mut buffer = [0, 0]; + let mut comment_text = Vec::new(); // read the first character and check for being a comment let mut comment = None; @@ -766,14 +767,15 @@ impl<'ctx> Lexer<'ctx> { } } - if buffer[0] != 0 { - if let Some(ref mut comment) = comment { - comment.text.push(buffer[0] as char); - } + if buffer[0] != 0 && comment.is_some() { + comment_text.push(buffer[0]); } } - comment.filter(|c| !c.text.is_empty()).map(Token::DocComment) + comment.filter(|_| !comment_text.is_empty()).map(|mut c| { + c.text = from_utf8_or_latin1(comment_text); + Token::DocComment(c) + }) } fn skip_line_comment(&mut self) -> Option { @@ -781,6 +783,7 @@ impl<'ctx> Lexer<'ctx> { // read the first character and check for being a comment let mut comment = None; + let mut comment_text = Vec::new(); match self.next() { Some(b'/') => comment = Some(DocComment::new(CommentKind::Line, DocTarget::FollowingItem)), Some(b'!') => comment = Some(DocComment::new(CommentKind::Line, DocTarget::EnclosingItem)), @@ -793,10 +796,8 @@ impl<'ctx> Lexer<'ctx> { } while let Some(ch) = self.next() { - if ch != b'\r' && ch != b'\n' { - if let Some(ref mut comment) = comment { - comment.text.push(ch as char); - } + if ch != b'\r' && ch != b'\n' && comment.is_some() { + comment_text.push(ch); } if ch == b'\r' { @@ -816,7 +817,10 @@ impl<'ctx> Lexer<'ctx> { } } - comment.map(Token::DocComment) + comment.map(|mut c| { + c.text = from_utf8_or_latin1(comment_text); + Token::DocComment(c) + }) } fn read_number_inner(&mut self, first: u8) -> (bool, u32, Cow<'static, str>) { From a4afc52612564d61f6412c9f0c5a9a6170f639a3 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Tue, 28 May 2024 00:39:04 -0700 Subject: [PATCH 090/197] Allow extending DocCollection from Vec --- crates/dreammaker/src/docs.rs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/crates/dreammaker/src/docs.rs b/crates/dreammaker/src/docs.rs index d77160ff..9e49c2be 100644 --- a/crates/dreammaker/src/docs.rs +++ b/crates/dreammaker/src/docs.rs @@ -19,8 +19,8 @@ impl DocCollection { } /// Combine another collection into this one. - pub fn extend(&mut self, collection: DocCollection) { - self.elems.extend(collection.elems); + pub fn extend(&mut self, collection: impl IntoIterator) { + self.elems.extend(collection); } /// Check whether this collection is empty. @@ -62,6 +62,16 @@ impl DocCollection { } } +impl IntoIterator for DocCollection { + type Item = DocComment; + + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.elems.into_iter() + } +} + /// A documentation comment. #[derive(Clone, Debug, PartialEq, GetSize)] pub struct DocComment { @@ -84,6 +94,16 @@ impl DocComment { fn is_empty(&self) -> bool { is_empty(&self.text, self.kind.ignore_char()) } + + /// Return the 3-character sequence that started this comment. + pub fn describe_type(&self) -> &'static str { + match (self.kind, self.target) { + (CommentKind::Block, DocTarget::FollowingItem) => "/**", + (CommentKind::Block, DocTarget::EnclosingItem) => "/*!", + (CommentKind::Line, DocTarget::FollowingItem) => "///", + (CommentKind::Line, DocTarget::EnclosingItem) => "//!", + } + } } impl fmt::Display for DocComment { From 8bbd2e1b19faf6f3ab7a929f3f0b0da1951be872 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Tue, 28 May 2024 03:35:41 -0700 Subject: [PATCH 091/197] Overhaul doc comment parsing Fixes #332. --- crates/dreammaker/src/lexer.rs | 4 +- crates/dreammaker/src/parser.rs | 340 ++++++++++++++++---------- crates/dreammaker/src/preprocessor.rs | 98 ++++---- 3 files changed, 269 insertions(+), 173 deletions(-) diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index 7c519125..0c29ecff 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -354,7 +354,7 @@ impl fmt::Display for Token { use self::Token::*; match *self { Eof => f.write_str("__EOF__"), - Punct(p) => write!(f, "{}", p), + Punct(p) => p.fmt(f), Ident(ref i, _) => f.write_str(i), String(ref i) => Quote(i).fmt(f), InterpStringBegin(ref i) => write!(f, "\"{}[", i), @@ -363,7 +363,7 @@ impl fmt::Display for Token { Resource(ref i) => write!(f, "'{}'", i), Int(i) => FormatFloat(i as f32).fmt(f), Float(i) => FormatFloat(i).fmt(f), - DocComment(ref c) => write!(f, "{}", c), + DocComment(ref c) => c.fmt(f), } } } diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 7921a42c..592b9321 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -1,7 +1,7 @@ //! Minimalist parser which turns a token stream into an object tree. use std::borrow::Cow; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, VecDeque}; use std::ops::Range; use std::str::FromStr; @@ -297,10 +297,9 @@ pub struct Parser<'ctx, 'an, 'inp> { location: Location, expected: Vec>, - docs_following: DocCollection, - docs_enclosing: DocCollection, + doc_comments_pending: VecDeque<(Location, DocComment)>, + doc_comments_on_notice: bool, module_docs: BTreeMap>, - in_docs: usize, procs: bool, procs_bad: u64, @@ -329,10 +328,9 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { location: Default::default(), expected: Vec::new(), - docs_following: Default::default(), - docs_enclosing: Default::default(), + doc_comments_pending: Default::default(), + doc_comments_on_notice: false, module_docs: Default::default(), - in_docs: 0, procs: false, procs_bad: 0, @@ -414,9 +412,9 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { if self.eof { return self.error(format!("got EOF, expected one of: {}", expected)); } - match self.next("") { + match self.next_quiet() { Ok(got) => { - let message = format!("got '{}', expected one of: {}", got, expected); + let message = format!("got '{:#}', expected one of: {}", got, expected); self.put_back(got); let mut e = self.error(message); if self.possible_indentation_error { @@ -446,45 +444,94 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } } + /// Push an alternative to the "got X, expected one of: ..." list. + fn expected(&mut self, expected: Cow<'static, str>) { + if !expected.is_empty() && !self.expected.contains(&expected) { + self.expected.push(expected); + } + } + + /// Get the next token and push something to the "expected" list. fn next>>(&mut self, expected: S) -> Result { - let tok = loop { + self.expected(expected.into()); + self.next_quiet() + } + + /// Get the next token without pushing anything to the "expected" list. + fn next_quiet(&mut self) -> Result { + loop { if let Some(next) = self.next.take() { - break Ok(next); + self.doc_comments_on_notice = false; + return Ok(next); } match self.input.next() { - Some(LocatedToken { - location, - token: Token::DocComment(dc), - }) => match dc.target { - DocTarget::EnclosingItem if self.in_docs == 0 => { - self.module_docs - .entry(location.file) - .or_default() - .push((location.line, dc)); - } - DocTarget::EnclosingItem => self.docs_enclosing.push(dc), - DocTarget::FollowingItem => self.docs_following.push(dc), - }, + // To allow comments that look like doc comments in arbitrary + // positions, buffer them until they are specifically read, + // or drop them if we've read TWO non-doc tokens, meaning the + // first non-doc token can no longer be put_back. + Some(LocatedToken { location, token: Token::DocComment(comment) }) => { + self.doc_comments_pending.push_back((location, comment)); + self.doc_comments_on_notice = false; + } Some(token) => { self.expected.clear(); self.location = token.location; - break Ok(token.token); + if self.doc_comments_on_notice { + // This is where we would diagnose "doc comment has no + // effect", but it would probably be more annoying than + // useful. + self.doc_comments_pending.clear(); + } else if !self.doc_comments_pending.is_empty() { + self.doc_comments_on_notice = true; + } + return Ok(token.token); } None => { if !self.eof { self.eof = true; - break Ok(Token::Eof); + return Ok(Token::Eof); } else { - break self.parse_error(); + return self.parse_error(); } } } - }; - let what = expected.into(); - if !what.is_empty() && !self.expected.contains(&what) { - self.expected.push(what); } - tok + } + + fn next_comment_of_target(&mut self, target: DocTarget) -> Status { + loop { + if let Some((location, comment)) = self.doc_comments_pending.pop_front() { + if comment.target == target { + self.location = location; + return success(comment); + } else if comment.target == DocTarget::FollowingItem { + //^ out-of-position `//!` comments have to be dropped or they infect later declarations + self.doc_comments_pending.push_front((location, comment)); + return Ok(None); + } + } + if self.next.is_some() { + return Ok(None); + } + match self.input.next() { + Some(LocatedToken { location, token: Token::DocComment(comment) }) => { + if comment.target == target { + self.location = location; + return success(comment); + } else if comment.target == DocTarget::FollowingItem { + //^ out-of-position `//!` comments have to be dropped or they infect later declarations + self.doc_comments_pending.push_front((location, comment)); + return Ok(None); + } + } + Some(other) => { + self.location = other.location; + self.next = Some(other.token); + return Ok(None); + } + None => return Ok(None), + } + } } fn put_back(&mut self, tok: Token) { @@ -495,7 +542,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } fn updated_location(&mut self) -> Location { - if let Ok(token) = self.next("") { + if let Ok(token) = self.next_quiet() { self.put_back(token); } self.location @@ -567,20 +614,16 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // ------------------------------------------------------------------------ // Doc comment tracking - fn doc_comment Status>(&mut self, f: F) -> Status<(DocCollection, R)> { - use std::mem::replace; + fn following_doc_comment(&mut self) -> Status { + self.expected("'///'".into()); + self.expected("'/**'".into()); + self.next_comment_of_target(DocTarget::FollowingItem) + } - let enclosing = std::mem::take(&mut self.docs_enclosing); - let mut docs = std::mem::take(&mut self.docs_following); - self.in_docs += 1; - let result = f(self); - self.in_docs -= 1; - docs.extend(replace(&mut self.docs_enclosing, enclosing)); - match result { - Ok(Some(found)) => Ok(Some((docs, found))), - Ok(None) => Ok(None), - Err(err) => Err(err), - } + fn enclosing_doc_comment(&mut self) -> Status { + self.expected("'//!'".into()); + self.expected("'/*!'".into()); + self.next_comment_of_target(DocTarget::EnclosingItem) } // ------------------------------------------------------------------------ @@ -590,22 +633,31 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { self.tree_entries(self.tree.root_index(), None, None, Token::Eof) } - fn tree_block(&mut self, current: NodeIndex, proc_builder: Option, var_type: Option) -> Status<()> { - leading!(self.exact(Token::Punct(Punctuation::LBrace))); - require!(self.tree_entries(current, proc_builder, var_type, Token::Punct(Punctuation::RBrace))); - SUCCESS - } - fn tree_entries(&mut self, current: NodeIndex, proc_builder: Option, var_type: Option, terminator: Token) -> Status<()> { loop { - let message: Cow<'static, str> = match terminator { - Token::Eof => "newline".into(), - ref other => format!("newline, '{}'", other).into(), - }; - let next = self.next(message)?; + self.expected("newline".into()); + if terminator != Token::Eof { + self.expected(format!("'{terminator}'").into()); + } + + if current == self.tree.root_index() { + self.expected("'//!'".into()); + self.expected("'/*!'".into()); + if let Some(module_comment) = self.enclosing_doc_comment()? { + // If we're not inside a type, this is where module `//!` comments appear. + self.module_docs + .entry(self.location.file) + .or_default() + .push((self.location.line, module_comment)); + continue; + } + } + + let next = self.next_quiet()?; if next == terminator || next == Token::Eof { break; } else if next == Token::Punct(Punctuation::Semicolon) { + self.doc_comments_on_notice = false; continue; } self.put_back(next); @@ -693,7 +745,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { fn tree_entry(&mut self, mut current: NodeIndex, mut proc_builder: Option, mut var_type: Option) -> Status<()> { // tree_entry :: path ';' - // tree_entry :: path tree_block + // tree_entry :: path '{' tree_entry* '}' // tree_entry :: path '=' expression ';' // tree_entry :: path '(' argument_list ')' ';' // tree_entry :: path '(' argument_list ')' code_block @@ -703,8 +755,17 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let entry_start = self.updated_location(); + let mut docs = DocCollection::default(); + while let Some(doc_comment) = self.following_doc_comment()? { + docs.push(doc_comment); + } + // read and calculate the current path - let (absolute, mut path) = leading!(self.tree_path(false)); + let (absolute, mut path) = if docs.is_empty() { + leading!(self.tree_path(false)) + } else { + require!(self.tree_path(false)) + }; if absolute && current != self.tree.root_index() { DMError::new(entry_start, format!("nested absolute path inside {}", self.tree.get_path(current))) @@ -781,22 +842,36 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { Default::default() }; + // Same-line `//!` comment for types. + // Also incidentally allows putting `/*!` in weird places, but that's probably fine. + while let Some(doc_comment) = self.enclosing_doc_comment()? { + docs.push(doc_comment); + } + // read the contents for real - match self.next("contents")? { - t @ Punct(LBrace) => { + self.expected("'='".into()); + self.expected("'('".into()); + self.expected("'{'".into()); + match self.next_quiet()? { + Punct(LBrace) => { // `thing{` - block - self.put_back(t); traverse_tree!(last_part); handle_relative_type_error!(); let start = self.updated_location(); - if proc_builder.is_some() || var_type.is_some() { - // Can't apply docs to `var/` or `proc/` blocks. - require!(self.tree_block(current, proc_builder, var_type.clone())); - } else { - let (comment, ()) = require!(self.doc_comment(|this| this.tree_block(current, proc_builder, var_type.clone()))); - self.tree.extend_docs(current, comment); + // Inside-block `//!` comments for types. + while let Some(comment) = self.enclosing_doc_comment()? { + docs.push(comment); } + if !docs.is_empty() && (proc_builder.is_some() || var_type.is_some()) { + // Can't apply docs to `var/` or `proc/` blocks. + DMError::new(start, "docs on `var/` or `proc/` block will be applied to their type") + .set_severity(Severity::Warning) + .register(self.context); + } + self.tree.extend_docs(current, docs); + + require!(self.tree_entries(current, proc_builder, var_type.clone(), Token::Punct(Punctuation::RBrace))); let node = self.tree.get_path(current).to_owned(); self.annotate(start, || Annotation::TreeBlock(reconstruct_path(&node, proc_builder, var_type.as_ref(), ""))); @@ -807,20 +882,20 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { handle_relative_type_error!(); let location = self.location; - // kind of goofy, but allows "enclosing" doc comments at the end of the line - // translators note: this allows comments of the form ``//! blah`` at the end of the line - let (docs, expression) = require!(self.doc_comment(|this| { - let expr = require!(this.expression()); - let _ = require!(this.input_specifier()); // TODO: save to VarType instead of ignoring + let expression = require!(self.expression()); + let _ = require!(self.input_specifier()); // TODO: save to VarType instead of ignoring - // We have to annotate prior to consuming the statement terminator, as we - // will otherwise consume following whitespace resulting in a bad annotation range - let node = this.tree.get_path(current).to_owned(); - this.annotate(entry_start, || Annotation::Variable(reconstruct_path(&node, proc_builder, var_type.as_ref(), last_part))); + // We have to annotate prior to consuming the statement terminator, as we + // will otherwise consume following whitespace resulting in a bad annotation range + let node = self.tree.get_path(current).to_owned(); + self.annotate(entry_start, || Annotation::Variable(reconstruct_path(&node, proc_builder, var_type.as_ref(), last_part))); - require!(this.statement_terminator()); - success(expr) - })); + // Allow `//!` doc comments at the end of the line. + while let Some(comment) = self.enclosing_doc_comment()? { + docs.push(comment); + } + + require!(self.statement_terminator()); if let Some(mut var_type) = var_type { var_type.suffix(&var_suffix); @@ -834,18 +909,22 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { t @ Punct(LParen) => { // `something(` - proc self.put_back(t); - require!(self.proc_params_and_body(current, proc_builder, last_part, entry_start, absolute)); + require!(self.proc_params_and_body(current, proc_builder, last_part, entry_start, absolute, docs)); SUCCESS } other => { // usually `thing;` - a contentless declaration - // TODO: allow enclosing-targeting docs here somehow? self.put_back(other); if var_type.is_some() { let _ = require!(self.input_specifier()); // TODO: save to VarType instead of ignoring } + // Same-line `//!` comment AFTER + while let Some(comment) = self.enclosing_doc_comment()? { + docs.push(comment); + } + if last_part == "var" { self.error("`var;` item has no effect") .set_severity(Severity::Warning) @@ -856,7 +935,6 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { .set_severity(Severity::Warning) .register(self.context); } else { - let docs = std::mem::take(&mut self.docs_following); var_type.suffix(&var_suffix); let node = self.tree.get_path(current).to_owned(); self.annotate(entry_start, || Annotation::Variable(reconstruct_path(&node, proc_builder, Some(&var_type), last_part))); @@ -867,11 +945,11 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { .set_severity(Severity::Warning) .register(self.context); } else if proc_builder.is_some() { + eprintln!("-- {:?}", last_part); self.error("child of `proc/` without body") .register(self.context); } else { handle_relative_type_error!(); - let docs = std::mem::take(&mut self.docs_following); let len = self.tree.get_path(current).chars().filter(|&c| c == '/').count() + path_len; current = self.tree.subtype_or_add(self.location, current, last_part, len); self.tree.extend_docs(current, docs); @@ -969,7 +1047,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { SUCCESS } - fn proc_params_and_body(&mut self, current: NodeIndex, proc_builder: Option, name: &str, entry_start: Location, absolute: bool) -> Status<()> { + fn proc_params_and_body(&mut self, current: NodeIndex, proc_builder: Option, name: &str, entry_start: Location, absolute: bool, mut docs: DocCollection) -> Status<()> { use super::lexer::Token::*; use super::lexer::Punctuation::*; @@ -984,26 +1062,38 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // split off a subparser so we can keep parsing the objtree // even when the proc body doesn't parse - let mut body_start = self.location; let mut body_tt = Vec::new(); - // check that it doesn't end immediately (empty body) - let (comment, ()) = require!(self.doc_comment(|this| { - body_start = this.updated_location(); - if let Some(()) = this.statement_terminator()? { - body_tt.push(LocatedToken::new(this.location, Punct(Semicolon))); - } else { - // read an initial token tree - require!(this.read_any_tt(&mut body_tt)); - // if the first token is not an LBrace, it's on one line - if body_tt[0].token != Punct(LBrace) { - while this.statement_terminator()?.is_none() { - require!(this.read_any_tt(&mut body_tt)); - } - body_tt.push(LocatedToken::new(this.location, Punct(Semicolon))); - } + let body_start = self.updated_location(); + + // Accept `//!` comments right after the `)` of the proc. + while let Some(comment) = self.enclosing_doc_comment()? { + docs.push(comment); + } + + if let Some(()) = self.statement_terminator()? { + // proc has no body and just ends with `;` + body_tt.push(LocatedToken::new(self.location, Punct(Semicolon))); + } else if let Some(()) = self.exact(Punct(LBrace))? { + // proc has a body starting with `{` + body_tt.push(LocatedToken::new(self.location, Punct(LBrace))); + + // enclosing doc comments `//!` can appear after the `{` + while let Some(comment) = self.enclosing_doc_comment()? { + docs.push(comment); } - SUCCESS - })); + + // read the rest of the line + while self.exact(Punct(RBrace))?.is_none() { + require!(self.read_any_tt(&mut body_tt)); + } + body_tt.push(LocatedToken::new(self.location, Punct(RBrace))); + } else { + // proc has a same-line body, read until statement terminator + while self.statement_terminator()?.is_none() { + require!(self.read_any_tt(&mut body_tt)); + } + body_tt.push(LocatedToken::new(self.location, Punct(Semicolon))); + } let code = if self.procs { let result = { @@ -1034,7 +1124,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { match self.tree.register_proc(self.context, location, current, name, proc_builder, parameters, return_type, code) { Ok((idx, proc)) => { - proc.docs.extend(comment); + proc.docs.extend(docs); // manually performed for borrowck reasons if let Some(dest) = self.annotations.as_mut() { let new_stack = reconstruct_path(self.tree.get_path(current), proc_builder, None, name); @@ -1178,11 +1268,11 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { return Err(self.error("Invalid return type")); }; return Ok(Some(return_type)); - }; + } if Token::Punct(Punctuation::Slash) != next_token { - self.put_back(next_token); - return Err(self.error("Invalid return type")); - }; + self.put_back(next_token); + return Err(self.error("Invalid return type")); + } // We're pulling out just the text, and we go until the end of the text or until we hit something unexpected let mut path_vec = vec![]; let mut slash_last = true; @@ -1452,19 +1542,23 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { require!(self.exact(Token::Punct(Punctuation::RParen))); require!(self.exact(Token::Punct(Punctuation::LBrace))); let mut cases = Vec::new(); - while let Some(()) = self.exact_ident("if")? { - require!(self.exact(Token::Punct(Punctuation::LParen))); - let what = require!(self.separated(Punctuation::Comma, Punctuation::RParen, None, Parser::case)); - if what.is_empty() { - self.context.register_error(self.error("switch case cannot be empty")); + let default = loop { + if let Some(()) = self.exact_ident("if")? { + require!(self.exact(Token::Punct(Punctuation::LParen))); + let what = require!(self.separated(Punctuation::Comma, Punctuation::RParen, None, Parser::case)); + if what.is_empty() { + self.context.register_error(self.error("switch case cannot be empty")); + } + let block = require!(self.block(loop_ctx)); + cases.push((Spanned::new(self.location(), what), block)); + } else if let Some(()) = self.exact_ident("else")? { + break Some(require!(self.block(loop_ctx))); + } else if let Some(()) = self.exact(Token::Punct(Punctuation::Semicolon))? { + // Tolerate stray semicolons here because inert doc + // comments might synthesize them. + } else { + break None; } - let block = require!(self.block(loop_ctx)); - cases.push((Spanned::new(self.location(), what), block)); - } - let default = if let Some(()) = self.exact_ident("else")? { - Some(require!(self.block(loop_ctx))) - } else { - None }; require!(self.exact(Token::Punct(Punctuation::RBrace))); spanned(Statement::Switch { @@ -1538,7 +1632,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // Handle if(1){a=1;b=2} without a trailing semicolon fn statement_terminator(&mut self) -> Status<()> { - match self.next("';'")? { + match self.next("newline")? { Token::Punct(Punctuation::Semicolon) => SUCCESS, p @ Token::Punct(Punctuation::RBrace) => { self.put_back(p); @@ -2461,7 +2555,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { fn read_any_tt(&mut self, target: &mut Vec) -> Status<()> { // read a single arbitrary "token tree", either a group or a single token - let start = self.next("anything")?; + let start = self.next_quiet()?; let kind = TTKind::from_token(&start); target.push(LocatedToken::new(self.location(), start)); let kind = match kind { @@ -2469,7 +2563,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { None => return SUCCESS, }; loop { - let token = self.next("anything")?; + let token = self.next_quiet()?; if kind.is_end(&token) { target.push(LocatedToken::new(self.location(), token)); return SUCCESS; diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index 052357bb..38a956d0 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -12,7 +12,7 @@ use interval_tree::{IntervalTree, range}; use super::{DMError, Location, HasLocation, FileId, Context, Severity}; use super::lexer::*; -use super::docs::{DocComment, DocTarget, DocCollection}; +use super::docs::{DocComment, DocTarget, DocCollection, CommentKind}; use super::annotation::*; use super::ast::Ident; @@ -117,7 +117,6 @@ impl DefineHistory { output: Default::default(), danger_idents: Default::default(), docs_in: Default::default(), - docs_out: Default::default(), in_interp_string: 0, annotations: None, } @@ -143,7 +142,6 @@ impl DefineHistory { output: Default::default(), danger_idents: Default::default(), docs_in: Default::default(), - docs_out: Default::default(), in_interp_string: 0, annotations: None, } @@ -391,7 +389,7 @@ pub struct Preprocessor<'ctx> { // should this be done as an enum in include_locations instead? multiple_locations: HashMap, last_input_loc: Location, - output: VecDeque, + output: VecDeque, ifdef_stack: Vec, ifdef_history: IntervalTree, annotations: Option, @@ -407,7 +405,6 @@ pub struct Preprocessor<'ctx> { in_interp_string: u32, docs_in: VecDeque<(Location, DocComment)>, - docs_out: VecDeque<(Location, DocComment)>, } impl<'ctx> HasLocation for Preprocessor<'ctx> { @@ -445,7 +442,6 @@ impl<'ctx> Preprocessor<'ctx> { output: Default::default(), danger_idents: Default::default(), docs_in: Default::default(), - docs_out: Default::default(), in_interp_string: 0, annotations: None, }) @@ -475,7 +471,6 @@ impl<'ctx> Preprocessor<'ctx> { output: Default::default(), danger_idents: Default::default(), docs_in: Default::default(), - docs_out: Default::default(), in_interp_string: 0, annotations: None, } @@ -619,7 +614,7 @@ impl<'ctx> Preprocessor<'ctx> { let expr = crate::parser::parse_expression( self.context, start, - self.output.drain(..).map(|token| LocatedToken::new(start, token)) + self.output.drain(..), )?; Ok(crate::constants::preprocessor_evaluate(start, expr, &self.defines)?.to_bool()) } @@ -641,7 +636,11 @@ impl<'ctx> Preprocessor<'ctx> { /// Something other than a `#define` was encountered, docs are not for us. fn flush_docs(&mut self) { if !self.docs_in.is_empty() { - self.docs_out.extend(self.docs_in.drain(..)); + self.output.extend( + self.docs_in + .drain(..) + .map(|(l, d)| LocatedToken::new(l, Token::DocComment(d))), + ); } } @@ -692,6 +691,10 @@ impl<'ctx> Preprocessor<'ctx> { } } + fn push_output(&mut self, token: Token) { + self.output.push_back(LocatedToken::new(self.last_input_loc, token)); + } + fn inner_next(&mut self) -> Option { self.include_stack.next() } @@ -825,7 +828,7 @@ impl<'ctx> Preprocessor<'ctx> { // A phantom newline keeps the include // directive being indented from making // the first line of the file indented. - self.output.push_back(Token::Punct(Punctuation::Newline)); + self.push_output(Token::Punct(Punctuation::Newline)); self.include_stack.stack.push(include); }, Err(e) => self.context.register_error(e), @@ -850,21 +853,8 @@ impl<'ctx> Preprocessor<'ctx> { } "define" => { // accumulate just-seen Following doc comments - let mut our_docs = Vec::new(); - while let Some((loc, doc)) = self.docs_in.pop_back() { - if doc.target == DocTarget::FollowingItem { - our_docs.push(doc); - } else { - self.docs_in.push_back((loc, doc)); - break; - } - } let mut docs = DocCollection::default(); - for each in our_docs.into_iter().rev() { - docs.push(each); - } - // flush all docs which do not apply to this define - self.flush_docs(); + docs.extend(self.docs_in.drain(..).map(|x| x.1)); expect_token!((define_name, ws) = Token::Ident(define_name, ws)); let define_name_loc = _last_expected_loc; @@ -907,7 +897,18 @@ impl<'ctx> Preprocessor<'ctx> { } } Token::Punct(Punctuation::Newline) => break 'outer, - Token::DocComment(doc) => docs.push(doc), + Token::DocComment(doc) => { + if doc.target != DocTarget::EnclosingItem { + let message = match doc.kind { + CommentKind::Block => "after a #define, should be `/*!` instead of `/**`", + CommentKind::Line => "after a #define, should be `//!` instead of `///`", + }; + self.error(message) + .set_severity(Severity::Hint) + .register(&self.context); + } + docs.push(doc); + } other => { subst.push(other); } @@ -915,7 +916,18 @@ impl<'ctx> Preprocessor<'ctx> { loop { match next!() { Token::Punct(Punctuation::Newline) => break 'outer, - Token::DocComment(doc) => docs.push(doc), + Token::DocComment(doc) => { + if doc.target != DocTarget::EnclosingItem { + let message = match doc.kind { + CommentKind::Block => "after a #define, should be `/*!` instead of `/**`", + CommentKind::Line => "after a #define, should be `//!` instead of `///`", + }; + self.error(message) + .set_severity(Severity::Hint) + .register(&self.context); + } + docs.push(doc); + } other => subst.push(other), } } @@ -988,7 +1000,7 @@ impl<'ctx> Preprocessor<'ctx> { } } // yield a newline - self.output.push_back(Token::Punct(Punctuation::Newline)); + self.push_output(Token::Punct(Punctuation::Newline)); return Ok(()); } // anything other than directives may be ifdef'd out @@ -1007,24 +1019,24 @@ impl<'ctx> Preprocessor<'ctx> { self.annotate_macro(ident, Location::builtins(), None); for include in self.include_stack.stack.iter().rev() { if let Include::File { ref path, .. } = *include { - self.output.push_back(Token::String(path.display().to_string())); + self.push_output(Token::String(path.display().to_string())); return Ok(()); } } - self.output.push_back(Token::String(String::new())); + self.push_output(Token::String(String::new())); return Ok(()); } else if ident == "__LINE__" { self.annotate_macro(ident, Location::builtins(), None); - self.output.push_back(Token::Int(self.last_input_loc.line as i32)); + self.push_output(Token::Int(self.last_input_loc.line as i32)); return Ok(()); } // special case for inside a defined() call - if let Some(Token::Punct(Punctuation::LParen)) = self.output.back() { + if let Some(LocatedToken { token: Token::Punct(Punctuation::LParen), .. }) = self.output.back() { if let Some(idx) = self.output.len().checked_sub(2) { - if let Some(Token::Ident(identname, _)) = self.output.get(idx) { + if let Some(LocatedToken { token: Token::Ident(identname, _), .. }) = self.output.get(idx) { if identname.as_str() == "defined" { - self.output.push_back(Token::Ident(ident.to_owned(), whitespace)); + self.push_output(Token::Ident(ident.to_owned(), whitespace)); return Ok(()); } } @@ -1054,13 +1066,13 @@ impl<'ctx> Preprocessor<'ctx> { match next!() { Token::Punct(Punctuation::LParen) => {} other => { - self.output.push_back(Token::Ident(ident.to_owned(), false)); + self.push_output(Token::Ident(ident.to_owned(), false)); match other { Token::InterpStringBegin(_) => self.in_interp_string += 1, Token::InterpStringEnd(_) => self.in_interp_string -= 1, _ => {} } - self.output.push_back(other); + self.push_output(other); return Ok(()); } } @@ -1202,7 +1214,7 @@ impl<'ctx> Preprocessor<'ctx> { Token::InterpStringBegin(_) => self.in_interp_string += 1, Token::InterpStringEnd(_) => self.in_interp_string -= 1, // documentation is accumulated, and flushed if no #define follows - Token::DocComment(doc) => { + Token::DocComment(doc) if doc.target == DocTarget::FollowingItem => { self.docs_in.push_back((self.last_input_loc, doc)); return Ok(()); }, @@ -1212,7 +1224,7 @@ impl<'ctx> Preprocessor<'ctx> { if !read.is_whitespace() { self.flush_docs(); } - self.output.push_back(read); + self.push_output(read); Ok(()) } } @@ -1222,18 +1234,8 @@ impl<'ctx> Iterator for Preprocessor<'ctx> { fn next(&mut self) -> Option { loop { - if let Some((location, doc)) = self.docs_out.pop_front() { - return Some(LocatedToken { - location, - token: Token::DocComment(doc), - }); - } - if let Some(token) = self.output.pop_front() { - return Some(LocatedToken { - location: self.last_input_loc, - token, - }); + return Some(token); } if let Some(tok) = self.inner_next() { From b4a6857928309ed6e8397a06f431f5e3607cc07f Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Tue, 28 May 2024 22:53:24 -0700 Subject: [PATCH 092/197] rustfmt: Sort imports --- crates/builtins-proc-macro/src/lib.rs | 4 +- crates/dap-types/src/lib.rs | 6 +-- crates/dm-langserver/build.rs | 4 +- crates/dm-langserver/src/completion.rs | 6 +-- crates/dm-langserver/src/debugger/auxtools.rs | 2 +- crates/dm-langserver/src/debugger/evaluate.rs | 2 +- crates/dm-langserver/src/debugger/extools.rs | 10 ++--- .../src/debugger/extools_bundle.rs | 2 +- .../src/debugger/extools_types.rs | 12 +++-- crates/dm-langserver/src/debugger/mod.rs | 4 +- crates/dm-langserver/src/document.rs | 8 ++-- crates/dm-langserver/src/extras.rs | 2 +- crates/dm-langserver/src/find_references.rs | 4 +- crates/dm-langserver/src/macros.rs | 4 +- crates/dm-langserver/src/main.rs | 45 ++++++++++--------- crates/dmdoc/src/main.rs | 12 ++--- crates/dmdoc/src/markdown.rs | 4 +- crates/dmdoc/src/template.rs | 4 +- crates/dmm-tools-cli/src/main.rs | 9 ++-- .../examples/duplicate_icon_states.rs | 10 ++--- crates/dmm-tools/src/dmi.rs | 4 +- crates/dmm-tools/src/dmm.rs | 12 ++--- crates/dmm-tools/src/dmm/read.rs | 6 +-- crates/dmm-tools/src/dmm/save_tgm.rs | 2 +- crates/dmm-tools/src/icon_cache.rs | 4 +- crates/dmm-tools/src/lib.rs | 15 ++++--- crates/dmm-tools/src/minimap.rs | 10 ++--- .../src/render_passes/icon_smoothing.rs | 6 +-- .../src/render_passes/icon_smoothing_2020.rs | 6 +-- crates/dmm-tools/src/render_passes/mod.rs | 16 +++---- crates/dmm-tools/src/render_passes/random.rs | 2 +- crates/dmm-tools/tests/parse_codebase.rs | 5 +-- crates/dreamchecker/src/lib.rs | 6 +-- crates/dreamchecker/src/main.rs | 2 +- crates/dreamchecker/src/test_helpers.rs | 2 +- .../dreamchecker/tests/branch_eval_tests.rs | 1 - crates/dreamchecker/tests/directive_tests.rs | 1 - crates/dreamchecker/tests/kwargs_tests.rs | 1 - crates/dreamchecker/tests/local_vars_tests.rs | 1 - crates/dreamchecker/tests/new_tests.rs | 1 - crates/dreamchecker/tests/private_tests.rs | 1 - crates/dreamchecker/tests/proc_tests.rs | 1 - crates/dreamchecker/tests/sleep_pure_tests.rs | 1 - .../dreamchecker/tests/static_type_tests.rs | 1 - .../tests/switch_rand_range_tests.rs | 1 - .../dreamchecker/tests/var_declare_tests.rs | 1 - crates/dreammaker/src/annotation.rs | 4 +- crates/dreammaker/src/builtins.rs | 6 +-- crates/dreammaker/src/config.rs | 2 +- crates/dreammaker/src/constants.rs | 4 +- crates/dreammaker/src/dmi.rs | 2 +- crates/dreammaker/src/error.rs | 8 ++-- crates/dreammaker/src/indents.rs | 4 +- crates/dreammaker/src/lexer.rs | 8 ++-- crates/dreammaker/src/lib.rs | 21 ++++----- crates/dreammaker/src/objtree.rs | 9 ++-- crates/dreammaker/src/parser.rs | 6 +-- crates/dreammaker/src/preprocessor.rs | 14 +++--- crates/dreammaker/tests/annotation_tests.rs | 6 +-- crates/dreammaker/tests/ast_tests.rs | 6 +-- crates/dreammaker/tests/expression_tests.rs | 2 +- crates/dreammaker/tests/format_tests.rs | 2 +- crates/dreammaker/tests/lexer_tests.rs | 4 +- crates/dreammaker/tests/macro_tests.rs | 4 +- crates/dreammaker/tests/pipeline_tests.rs | 2 +- crates/interval-tree/src/iterators.rs | 4 +- crates/interval-tree/src/lib.rs | 10 ++--- crates/interval-tree/src/node.rs | 2 +- crates/interval-tree/src/tree.rs | 6 +-- 69 files changed, 199 insertions(+), 200 deletions(-) diff --git a/crates/builtins-proc-macro/src/lib.rs b/crates/builtins-proc-macro/src/lib.rs index 22757591..9d64abcf 100644 --- a/crates/builtins-proc-macro/src/lib.rs +++ b/crates/builtins-proc-macro/src/lib.rs @@ -1,11 +1,11 @@ use proc_macro::TokenStream; +use proc_macro2::TokenStream as TokenStream2; use quote::{quote, quote_spanned}; -use syn::*; use syn::ext::IdentExt; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::spanned::Spanned; -use proc_macro2::TokenStream as TokenStream2; +use syn::*; #[derive(Clone, Default)] struct Header { diff --git a/crates/dap-types/src/lib.rs b/crates/dap-types/src/lib.rs index 33d9f610..2e2db820 100644 --- a/crates/dap-types/src/lib.rs +++ b/crates/dap-types/src/lib.rs @@ -4,10 +4,10 @@ #![deny(unsafe_code)] #![allow(non_snake_case)] -use std::collections::HashMap; -use serde_json::Value; -use serde_derive::{Serialize, Deserialize}; use ahash::RandomState; +use serde_derive::{Deserialize, Serialize}; +use serde_json::Value; +use std::collections::HashMap; pub trait Request { type Params; diff --git a/crates/dm-langserver/build.rs b/crates/dm-langserver/build.rs index 1dccc4d7..d37a7a2c 100644 --- a/crates/dm-langserver/build.rs +++ b/crates/dm-langserver/build.rs @@ -1,9 +1,9 @@ extern crate chrono; extern crate git2; -use std::io::Write; -use std::fs::File; use std::env; +use std::fs::File; +use std::io::Write; use std::path::PathBuf; fn main() { diff --git a/crates/dm-langserver/src/completion.rs b/crates/dm-langserver/src/completion.rs index 7b7c2b1b..9812ec50 100644 --- a/crates/dm-langserver/src/completion.rs +++ b/crates/dm-langserver/src/completion.rs @@ -4,12 +4,12 @@ use std::collections::HashSet; use lsp_types::*; -use dm::ast::PathOp; use dm::annotation::Annotation; -use dm::objtree::{TypeRef, TypeVar, TypeProc, ProcValue}; +use dm::ast::PathOp; +use dm::objtree::{ProcValue, TypeProc, TypeRef, TypeVar}; -use crate::{Engine, Span, is_constructor_name}; use crate::symbol_search::contains; +use crate::{is_constructor_name, Engine, Span}; use ahash::RandomState; diff --git a/crates/dm-langserver/src/debugger/auxtools.rs b/crates/dm-langserver/src/debugger/auxtools.rs index 31791f37..d2fce5ae 100644 --- a/crates/dm-langserver/src/debugger/auxtools.rs +++ b/crates/dm-langserver/src/debugger/auxtools.rs @@ -1,5 +1,4 @@ use super::auxtools_types::*; -use std::{net::TcpListener, sync::mpsc}; use std::thread; use std::{ io::{Read, Write}, @@ -9,6 +8,7 @@ use std::{ sync::{Arc, RwLock}, thread::JoinHandle, }; +use std::{net::TcpListener, sync::mpsc}; use super::SequenceNumber; diff --git a/crates/dm-langserver/src/debugger/evaluate.rs b/crates/dm-langserver/src/debugger/evaluate.rs index b8570aa0..4b8a9ca7 100644 --- a/crates/dm-langserver/src/debugger/evaluate.rs +++ b/crates/dm-langserver/src/debugger/evaluate.rs @@ -1,5 +1,5 @@ -use dap_types::*; use super::*; +use dap_types::*; const EXTOOLS_HELP: &str = " #dis, #disassemble: show disassembly for current stack frame"; diff --git a/crates/dm-langserver/src/debugger/extools.rs b/crates/dm-langserver/src/debugger/extools.rs index cde71385..15829474 100644 --- a/crates/dm-langserver/src/debugger/extools.rs +++ b/crates/dm-langserver/src/debugger/extools.rs @@ -1,16 +1,16 @@ //! Client for the Extools debugger protocol. -use std::time::Duration; -use std::sync::{mpsc, Arc, Mutex}; -use std::net::{SocketAddr, Ipv4Addr, TcpStream, TcpListener}; use std::collections::HashMap; -use std::io::{Read, Write}; use std::error::Error; +use std::io::{Read, Write}; +use std::net::{Ipv4Addr, SocketAddr, TcpListener, TcpStream}; +use std::sync::{mpsc, Arc, Mutex}; +use std::time::Duration; use ahash::RandomState; -use super::SequenceNumber; use super::extools_types::*; +use super::SequenceNumber; pub const DEFAULT_PORT: u16 = 2448; diff --git a/crates/dm-langserver/src/debugger/extools_bundle.rs b/crates/dm-langserver/src/debugger/extools_bundle.rs index 02396526..04c631c8 100644 --- a/crates/dm-langserver/src/debugger/extools_bundle.rs +++ b/crates/dm-langserver/src/debugger/extools_bundle.rs @@ -1,7 +1,7 @@ #![cfg(extools_bundle)] +use std::fs::File; use std::io::{Result, Write}; use std::path::{Path, PathBuf}; -use std::fs::File; const BYTES: &[u8] = include_bytes!(env!("EXTOOLS_BUNDLE_DLL")); diff --git a/crates/dm-langserver/src/debugger/extools_types.rs b/crates/dm-langserver/src/debugger/extools_types.rs index 131aeeb9..e580adb2 100644 --- a/crates/dm-langserver/src/debugger/extools_types.rs +++ b/crates/dm-langserver/src/debugger/extools_types.rs @@ -1,14 +1,12 @@ //! Serde types for the Extools debugger protocol. //! //! * https://github.com/MCHSL/extools/blob/master/byond-extools/src/debug_server/protocol.h -/// -/// > All communication happens over a TCP socket using a JSON-based protocol. -/// > A null byte signifies the end of a message. - -use std::collections::HashMap; -use serde_json::Value as Json; - +//! +//! > All communication happens over a TCP socket using a JSON-based protocol. +//! > A null byte signifies the end of a message. use ahash::RandomState; +use serde_json::Value as Json; +use std::collections::HashMap; // ---------------------------------------------------------------------------- // Extools data structures diff --git a/crates/dm-langserver/src/debugger/mod.rs b/crates/dm-langserver/src/debugger/mod.rs index bd09014e..c845b954 100644 --- a/crates/dm-langserver/src/debugger/mod.rs +++ b/crates/dm-langserver/src/debugger/mod.rs @@ -50,11 +50,11 @@ use auxtools::Auxtools; use ahash::RandomState; -use dap_types::*; use self::auxtools::AuxtoolsScopes; use self::extools::ExtoolsHolder; -use self::launched::{Launched, EngineParams}; +use self::launched::{EngineParams, Launched}; use crate::jrpc_io; +use dap_types::*; /// line, path, name, override_id pub type LineNumber = (i64, String, String, usize); diff --git a/crates/dm-langserver/src/document.rs b/crates/dm-langserver/src/document.rs index 78e1d090..98407555 100644 --- a/crates/dm-langserver/src/document.rs +++ b/crates/dm-langserver/src/document.rs @@ -2,14 +2,16 @@ //! language server protocol. #![allow(dead_code)] -use std::io::{self, Read, BufRead}; use std::borrow::Cow; use std::collections::HashMap; +use std::io::{self, BufRead, Read}; use std::rc::Rc; use url::Url; -use lsp_types::{TextDocumentItem, TextDocumentIdentifier, - VersionedTextDocumentIdentifier, TextDocumentContentChangeEvent}; +use lsp_types::{ + TextDocumentContentChangeEvent, TextDocumentIdentifier, TextDocumentItem, + VersionedTextDocumentIdentifier, +}; use super::{invalid_request, url_to_path}; diff --git a/crates/dm-langserver/src/extras.rs b/crates/dm-langserver/src/extras.rs index cc7022ca..aec4a5bd 100644 --- a/crates/dm-langserver/src/extras.rs +++ b/crates/dm-langserver/src/extras.rs @@ -1,8 +1,8 @@ //! Extensions to the language server protocol. -use lsp_types::SymbolKind; use lsp_types::notification::*; use lsp_types::request::*; +use lsp_types::SymbolKind; pub enum WindowStatus {} impl Notification for WindowStatus { diff --git a/crates/dm-langserver/src/find_references.rs b/crates/dm-langserver/src/find_references.rs index 8849531e..49291475 100644 --- a/crates/dm-langserver/src/find_references.rs +++ b/crates/dm-langserver/src/find_references.rs @@ -2,9 +2,9 @@ use std::collections::HashMap; -use dm::Location; -use dm::objtree::*; use dm::ast::*; +use dm::objtree::*; +use dm::Location; use ahash::RandomState; diff --git a/crates/dm-langserver/src/macros.rs b/crates/dm-langserver/src/macros.rs index 31785c05..e7d25ea1 100644 --- a/crates/dm-langserver/src/macros.rs +++ b/crates/dm-langserver/src/macros.rs @@ -1,13 +1,13 @@ //! Utility macros. pub mod all_methods { - pub use lsp_types::request::*; pub use crate::extras::*; + pub use lsp_types::request::*; } pub mod all_notifications { - pub use lsp_types::notification::*; pub use crate::extras::*; + pub use lsp_types::notification::*; } macro_rules! handle_method_call { diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index 18835a0f..bf9ab3f7 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -7,44 +7,47 @@ //! * https://github.com/rust-lang-nursery/rls #![deny(unsafe_code)] -extern crate url; extern crate serde; extern crate serde_json; -#[macro_use] extern crate serde_derive; -extern crate interval_tree; -extern crate lsp_types; -extern crate jsonrpc_core as jsonrpc; -extern crate dreammaker as dm; +extern crate url; +#[macro_use] +extern crate serde_derive; extern crate dreamchecker; +extern crate dreammaker as dm; +extern crate interval_tree; +extern crate jsonrpc_core as jsonrpc; extern crate libc; +extern crate lsp_types; extern crate regex; -#[macro_use] extern crate lazy_static; +#[macro_use] +extern crate lazy_static; -#[macro_use] mod macros; -mod jrpc_io; -mod document; -mod symbol_search; -mod find_references; -mod extras; -mod completion; -mod color; +#[macro_use] +mod macros; mod background; +mod color; +mod completion; +mod document; +mod extras; +mod find_references; +mod jrpc_io; +mod symbol_search; mod debugger; -use std::path::PathBuf; -use std::collections::{HashMap, HashSet, VecDeque}; use std::collections::hash_map::Entry; -use std::sync::{Arc, Mutex}; +use std::collections::{HashMap, HashSet, VecDeque}; +use std::path::PathBuf; use std::rc::Rc; +use std::sync::{Arc, Mutex}; -use url::Url; -use jsonrpc::{Request, Call, Response, Output}; +use jsonrpc::{Call, Output, Request, Response}; use lsp_types::MessageType; +use url::Url; -use dm::FileId; use dm::annotation::{Annotation, AnnotationTree}; use dm::objtree::TypeRef; +use dm::FileId; use ahash::RandomState; diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 76eb2492..c5651ce6 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -1,21 +1,21 @@ //! A CLI tool to generate HTML documentation of DreamMaker codebases. #![forbid(unsafe_code)] extern crate dreammaker as dm; -extern crate pulldown_cmark; extern crate git2; +extern crate pulldown_cmark; extern crate walkdir; mod markdown; mod template; -use std::collections::{BTreeMap, BTreeSet}; -use std::io::{self, Write}; -use std::fs::{self, File}; -use std::path::{Path, PathBuf}; -use std::sync::Arc; use dm::objtree::ObjectTree; use maud::{Markup, PreEscaped}; use pulldown_cmark::{BrokenLink, CowStr}; +use std::collections::{BTreeMap, BTreeSet}; +use std::fs::{self, File}; +use std::io::{self, Write}; +use std::path::{Path, PathBuf}; +use std::sync::Arc; use dm::docs::*; diff --git a/crates/dmdoc/src/markdown.rs b/crates/dmdoc/src/markdown.rs index 667e5d11..e0eab5a0 100644 --- a/crates/dmdoc/src/markdown.rs +++ b/crates/dmdoc/src/markdown.rs @@ -1,10 +1,10 @@ //! Parser for "doc-block" markdown documents. -use std::ops::Range; use std::collections::VecDeque; +use std::ops::Range; use maud::PreEscaped; -use pulldown_cmark::{self, Parser, Tag, Event, BrokenLinkCallback, HeadingLevel}; +use pulldown_cmark::{self, BrokenLinkCallback, Event, HeadingLevel, Parser, Tag}; pub fn render<'string>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, '_>) -> PreEscaped { let mut buf = String::new(); diff --git a/crates/dmdoc/src/template.rs b/crates/dmdoc/src/template.rs index b79e9aed..0f5b50fb 100644 --- a/crates/dmdoc/src/template.rs +++ b/crates/dmdoc/src/template.rs @@ -2,9 +2,9 @@ use std::path::Path; -use maud::{html, DOCTYPE, Markup, Render, display, PreEscaped}; +use maud::{display, html, Markup, PreEscaped, Render, DOCTYPE}; -use crate::{Environment, Index, IndexTree, ModuleArgs, Type, ModuleItem, markdown::DocBlock}; +use crate::{markdown::DocBlock, Environment, Index, IndexTree, ModuleArgs, ModuleItem, Type}; pub(crate) fn base( env: &Environment, diff --git a/crates/dmm-tools-cli/src/main.rs b/crates/dmm-tools-cli/src/main.rs index 42425a3b..c1724f22 100644 --- a/crates/dmm-tools-cli/src/main.rs +++ b/crates/dmm-tools-cli/src/main.rs @@ -2,23 +2,24 @@ #![forbid(unsafe_code)] #![doc(hidden)] // Don't interfere with lib docs. -extern crate rayon; extern crate clap; +extern crate rayon; extern crate serde; extern crate serde_json; -#[macro_use] extern crate serde_derive; +#[macro_use] +extern crate serde_derive; -extern crate dreammaker as dm; extern crate dmm_tools; +extern crate dreammaker as dm; use std::collections::HashMap; +use std::collections::HashSet; use std::fmt; use std::io::Write; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicIsize, Ordering}; use std::sync::RwLock; -use std::collections::HashSet; use clap::{Parser, Subcommand}; use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator}; diff --git a/crates/dmm-tools/examples/duplicate_icon_states.rs b/crates/dmm-tools/examples/duplicate_icon_states.rs index 10e828cf..4fe90fca 100644 --- a/crates/dmm-tools/examples/duplicate_icon_states.rs +++ b/crates/dmm-tools/examples/duplicate_icon_states.rs @@ -1,13 +1,13 @@ -extern crate dreammaker as dm; extern crate dmm_tools; -extern crate walkdir; +extern crate dreammaker as dm; extern crate ndarray; +extern crate walkdir; -use std::path::Path; -use std::collections::HashMap; -use walkdir::{DirEntry, WalkDir}; use dmm_tools::dmi::*; use ndarray::s; +use std::collections::HashMap; +use std::path::Path; +use walkdir::{DirEntry, WalkDir}; fn is_visible(entry: &DirEntry) -> bool { entry diff --git a/crates/dmm-tools/src/dmi.rs b/crates/dmm-tools/src/dmi.rs index 88e905f1..499575c6 100644 --- a/crates/dmm-tools/src/dmi.rs +++ b/crates/dmm-tools/src/dmi.rs @@ -2,11 +2,11 @@ //! //! Includes re-exports from `dreammaker::dmi`. +use bytemuck::Pod; use std::io; use std::path::Path; -use bytemuck::Pod; -use lodepng::{self, RGBA, Decoder, ColorType}; +use lodepng::{self, ColorType, Decoder, RGBA}; use ndarray::Array2; pub use dm::dmi::*; diff --git a/crates/dmm-tools/src/dmm.rs b/crates/dmm-tools/src/dmm.rs index 6a29204c..4b9420f7 100644 --- a/crates/dmm-tools/src/dmm.rs +++ b/crates/dmm-tools/src/dmm.rs @@ -1,16 +1,16 @@ use std::collections::BTreeMap; -use std::path::Path; +use std::fmt; use std::fs::File; use std::io; -use std::fmt; +use std::path::Path; -use ndarray::{self, Array3, Axis}; -use indexmap::IndexMap; use ahash::RandomState; +use indexmap::IndexMap; +use ndarray::{self, Array3, Axis}; -use dm::DMError; -use dm::constants::Constant; use crate::dmi::Dir; +use dm::constants::Constant; +use dm::DMError; mod read; mod save_tgm; diff --git a/crates/dmm-tools/src/dmm/read.rs b/crates/dmm-tools/src/dmm/read.rs index a07452f2..13f86c2c 100644 --- a/crates/dmm-tools/src/dmm/read.rs +++ b/crates/dmm-tools/src/dmm/read.rs @@ -1,14 +1,14 @@ //! Map parser, supporting standard DMM or TGM-format files. -use std::collections::BTreeMap; use std::cmp::max; +use std::collections::BTreeMap; use std::mem::take; use ndarray::Array3; +use dm::lexer::{from_utf8_or_latin1, LocationTracker}; use dm::{DMError, Location}; -use dm::lexer::{LocationTracker, from_utf8_or_latin1}; -use super::{Map, Key, KeyType, Prefab}; +use super::{Key, KeyType, Map, Prefab}; pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { let file_id = Default::default(); diff --git a/crates/dmm-tools/src/dmm/save_tgm.rs b/crates/dmm-tools/src/dmm/save_tgm.rs index 1afa720f..98cee5e8 100644 --- a/crates/dmm-tools/src/dmm/save_tgm.rs +++ b/crates/dmm-tools/src/dmm/save_tgm.rs @@ -1,5 +1,5 @@ //! TGM map writer. -use std::io::{self, Write, BufWriter}; +use std::io::{self, BufWriter, Write}; use ndarray::Axis; diff --git a/crates/dmm-tools/src/icon_cache.rs b/crates/dmm-tools/src/icon_cache.rs index 57fd8a8f..24b2e80f 100644 --- a/crates/dmm-tools/src/icon_cache.rs +++ b/crates/dmm-tools/src/icon_cache.rs @@ -1,6 +1,6 @@ -use std::sync::{Arc, RwLock}; +use std::collections::{hash_map, HashMap}; use std::path::{Path, PathBuf}; -use std::collections::{HashMap, hash_map}; +use std::sync::{Arc, RwLock}; use super::dmi::IconFile; diff --git a/crates/dmm-tools/src/lib.rs b/crates/dmm-tools/src/lib.rs index 54ca27a6..f4c45ab7 100644 --- a/crates/dmm-tools/src/lib.rs +++ b/crates/dmm-tools/src/lib.rs @@ -3,20 +3,23 @@ extern crate dreammaker as dm; -#[cfg(feature="png")] extern crate png; -extern crate lodepng; extern crate inflate; +extern crate lodepng; +#[cfg(feature = "png")] +extern crate png; -#[macro_use] extern crate bytemuck; -extern crate rand; +#[macro_use] +extern crate bytemuck; extern crate bumpalo; +extern crate rand; -#[cfg(feature="gfx_core")] extern crate gfx_core; +#[cfg(feature = "gfx_core")] +extern crate gfx_core; +pub mod dmi; pub mod dmm; mod icon_cache; pub mod minimap; pub mod render_passes; -pub mod dmi; pub use icon_cache::IconCache; diff --git a/crates/dmm-tools/src/minimap.rs b/crates/dmm-tools/src/minimap.rs index 92c5d1c7..42430a44 100644 --- a/crates/dmm-tools/src/minimap.rs +++ b/crates/dmm-tools/src/minimap.rs @@ -1,14 +1,14 @@ +use std::collections::{BTreeMap, HashSet}; use std::sync::RwLock; -use std::collections::{HashSet, BTreeMap}; use ndarray::Axis; -use dm::objtree::*; -use dm::constants::Constant; -use crate::dmm::{Map, ZLevel, Prefab}; use crate::dmi::{self, Dir, Image}; -use crate::render_passes::RenderPass; +use crate::dmm::{Map, Prefab, ZLevel}; use crate::icon_cache::IconCache; +use crate::render_passes::RenderPass; +use dm::constants::Constant; +use dm::objtree::*; use ahash::RandomState; diff --git a/crates/dmm-tools/src/render_passes/icon_smoothing.rs b/crates/dmm-tools/src/render_passes/icon_smoothing.rs index 1644897b..5302708a 100644 --- a/crates/dmm-tools/src/render_passes/icon_smoothing.rs +++ b/crates/dmm-tools/src/render_passes/icon_smoothing.rs @@ -1,9 +1,9 @@ //! Port of icon smoothing subsystem. -use dm::objtree::ObjectTree; -use dm::constants::Constant; use crate::dmi::Dir; -use crate::minimap::{Sprite, Atom, GetVar, Neighborhood}; +use crate::minimap::{Atom, GetVar, Neighborhood, Sprite}; +use dm::constants::Constant; +use dm::objtree::ObjectTree; use super::RenderPass; diff --git a/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs b/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs index 08af1314..1b39662a 100644 --- a/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs +++ b/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs @@ -4,10 +4,10 @@ //! followed by //! https://github.com/tgstation/tgstation/pull/53906 -use dm::objtree::ObjectTree; -use dm::constants::Constant; use crate::dmi::Dir; -use crate::minimap::{Sprite, Atom, GetVar, Neighborhood}; +use crate::minimap::{Atom, GetVar, Neighborhood, Sprite}; +use dm::constants::Constant; +use dm::objtree::ObjectTree; use super::RenderPass; diff --git a/crates/dmm-tools/src/render_passes/mod.rs b/crates/dmm-tools/src/render_passes/mod.rs index 7bb92520..3f717160 100644 --- a/crates/dmm-tools/src/render_passes/mod.rs +++ b/crates/dmm-tools/src/render_passes/mod.rs @@ -1,20 +1,20 @@ -use dm::objtree::*; +use crate::minimap::{Atom, GetVar, Layer, Neighborhood, Sprite}; use dm::constants::Constant; -use crate::minimap::{Atom, GetVar, Sprite, Layer, Neighborhood}; +use dm::objtree::*; -mod transit_tube; -mod random; -mod structures; mod icon_smoothing; mod icon_smoothing_2020; +mod random; mod smart_cables; +mod structures; +mod transit_tube; -pub use self::transit_tube::TransitTube; -pub use self::random::Random; -pub use self::structures::{GravityGen, Spawners}; pub use self::icon_smoothing::IconSmoothing as IconSmoothing2016; pub use self::icon_smoothing_2020::IconSmoothing; +pub use self::random::Random; pub use self::smart_cables::SmartCables; +pub use self::structures::{GravityGen, Spawners}; +pub use self::transit_tube::TransitTube; /// A map rendering pass. /// diff --git a/crates/dmm-tools/src/render_passes/random.rs b/crates/dmm-tools/src/render_passes/random.rs index 25c0921b..d773efe7 100644 --- a/crates/dmm-tools/src/render_passes/random.rs +++ b/crates/dmm-tools/src/render_passes/random.rs @@ -1,7 +1,7 @@ use super::*; -use rand::Rng; use rand::seq::SliceRandom; +use rand::Rng; #[derive(Default)] pub struct Random; diff --git a/crates/dmm-tools/tests/parse_codebase.rs b/crates/dmm-tools/tests/parse_codebase.rs index a319d983..c28abf9a 100644 --- a/crates/dmm-tools/tests/parse_codebase.rs +++ b/crates/dmm-tools/tests/parse_codebase.rs @@ -1,9 +1,9 @@ -extern crate walkdir; extern crate dmm_tools; +extern crate walkdir; +use dmm_tools::*; use std::path::Path; use walkdir::{DirEntry, WalkDir}; -use dmm_tools::*; fn is_visible(entry: &DirEntry) -> bool { entry @@ -46,4 +46,3 @@ fn parse_all_dmi() { dmi::Metadata::from_file(path).unwrap(); }); } - diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index a556d776..b5d1d3de 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -3,10 +3,10 @@ #![allow(dead_code, unused_variables)] extern crate dreammaker as dm; -use dm::{Context, DMError, Location, Severity}; -use dm::objtree::{ObjectTree, TypeRef, ProcRef}; -use dm::constants::{Constant, ConstFn}; use dm::ast::*; +use dm::constants::{ConstFn, Constant}; +use dm::objtree::{ObjectTree, ProcRef, TypeRef}; +use dm::{Context, DMError, Location, Severity}; use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; diff --git a/crates/dreamchecker/src/main.rs b/crates/dreamchecker/src/main.rs index 50d4eece..17e3c314 100644 --- a/crates/dreamchecker/src/main.rs +++ b/crates/dreamchecker/src/main.rs @@ -1,8 +1,8 @@ //! DreamChecker, a robust static analysis and typechecking engine for //! DreamMaker. -extern crate dreammaker as dm; extern crate dreamchecker; +extern crate dreammaker as dm; #[macro_use] extern crate serde_json; diff --git a/crates/dreamchecker/src/test_helpers.rs b/crates/dreamchecker/src/test_helpers.rs index e0ea5e0c..b02b68ba 100644 --- a/crates/dreamchecker/src/test_helpers.rs +++ b/crates/dreamchecker/src/test_helpers.rs @@ -1,7 +1,7 @@ use dm::Context; use std::borrow::Cow; -use crate::{run_inner}; +use crate::run_inner; pub const NO_ERRORS: &[(u32, u16, &str)] = &[]; diff --git a/crates/dreamchecker/tests/branch_eval_tests.rs b/crates/dreamchecker/tests/branch_eval_tests.rs index 7e085331..b0c50f32 100644 --- a/crates/dreamchecker/tests/branch_eval_tests.rs +++ b/crates/dreamchecker/tests/branch_eval_tests.rs @@ -1,4 +1,3 @@ - extern crate dreamchecker as dc; use dc::test_helpers::*; diff --git a/crates/dreamchecker/tests/directive_tests.rs b/crates/dreamchecker/tests/directive_tests.rs index e725887f..a671e9a3 100644 --- a/crates/dreamchecker/tests/directive_tests.rs +++ b/crates/dreamchecker/tests/directive_tests.rs @@ -1,4 +1,3 @@ - extern crate dreamchecker as dc; use dc::test_helpers::*; diff --git a/crates/dreamchecker/tests/kwargs_tests.rs b/crates/dreamchecker/tests/kwargs_tests.rs index 624edf46..abb75226 100644 --- a/crates/dreamchecker/tests/kwargs_tests.rs +++ b/crates/dreamchecker/tests/kwargs_tests.rs @@ -1,4 +1,3 @@ - extern crate dreamchecker as dc; use dc::test_helpers::*; diff --git a/crates/dreamchecker/tests/local_vars_tests.rs b/crates/dreamchecker/tests/local_vars_tests.rs index ffe538e5..6bb3187e 100644 --- a/crates/dreamchecker/tests/local_vars_tests.rs +++ b/crates/dreamchecker/tests/local_vars_tests.rs @@ -1,4 +1,3 @@ - extern crate dreamchecker as dc; use dc::test_helpers::check_errors_match; diff --git a/crates/dreamchecker/tests/new_tests.rs b/crates/dreamchecker/tests/new_tests.rs index 18e4ccba..0f74f3f1 100644 --- a/crates/dreamchecker/tests/new_tests.rs +++ b/crates/dreamchecker/tests/new_tests.rs @@ -1,4 +1,3 @@ - extern crate dreamchecker as dc; use dc::test_helpers::*; diff --git a/crates/dreamchecker/tests/private_tests.rs b/crates/dreamchecker/tests/private_tests.rs index 8421fea3..aca74d15 100644 --- a/crates/dreamchecker/tests/private_tests.rs +++ b/crates/dreamchecker/tests/private_tests.rs @@ -1,4 +1,3 @@ - extern crate dreamchecker as dc; use dc::test_helpers::*; diff --git a/crates/dreamchecker/tests/proc_tests.rs b/crates/dreamchecker/tests/proc_tests.rs index ab8616c9..c97a5089 100644 --- a/crates/dreamchecker/tests/proc_tests.rs +++ b/crates/dreamchecker/tests/proc_tests.rs @@ -1,4 +1,3 @@ - extern crate dreamchecker as dc; use dc::test_helpers::check_errors_match; diff --git a/crates/dreamchecker/tests/sleep_pure_tests.rs b/crates/dreamchecker/tests/sleep_pure_tests.rs index dd53bd1b..c709d9bd 100644 --- a/crates/dreamchecker/tests/sleep_pure_tests.rs +++ b/crates/dreamchecker/tests/sleep_pure_tests.rs @@ -1,4 +1,3 @@ - extern crate dreamchecker as dc; use dc::test_helpers::check_errors_match; diff --git a/crates/dreamchecker/tests/static_type_tests.rs b/crates/dreamchecker/tests/static_type_tests.rs index cd42b0c6..4da1e0c3 100644 --- a/crates/dreamchecker/tests/static_type_tests.rs +++ b/crates/dreamchecker/tests/static_type_tests.rs @@ -1,4 +1,3 @@ - extern crate dreamchecker as dc; use dc::test_helpers::*; diff --git a/crates/dreamchecker/tests/switch_rand_range_tests.rs b/crates/dreamchecker/tests/switch_rand_range_tests.rs index acc32c0c..c6685de7 100644 --- a/crates/dreamchecker/tests/switch_rand_range_tests.rs +++ b/crates/dreamchecker/tests/switch_rand_range_tests.rs @@ -1,4 +1,3 @@ - extern crate dreamchecker as dc; use dc::test_helpers::*; diff --git a/crates/dreamchecker/tests/var_declare_tests.rs b/crates/dreamchecker/tests/var_declare_tests.rs index 185f3872..3f175487 100644 --- a/crates/dreamchecker/tests/var_declare_tests.rs +++ b/crates/dreamchecker/tests/var_declare_tests.rs @@ -1,4 +1,3 @@ - extern crate dreamchecker as dc; use dc::test_helpers::*; diff --git a/crates/dreammaker/src/annotation.rs b/crates/dreammaker/src/annotation.rs index cd79fd2f..bfebf1c3 100644 --- a/crates/dreammaker/src/annotation.rs +++ b/crates/dreammaker/src/annotation.rs @@ -3,11 +3,11 @@ use std::rc::Rc; -use interval_tree::{IntervalTree, RangePairIter, RangeInclusive, range}; use crate::docs::DocCollection; +use interval_tree::{range, IntervalTree, RangeInclusive, RangePairIter}; -use super::Location; use super::ast::*; +use super::Location; pub type Iter<'a> = RangePairIter<'a, Location, Annotation>; diff --git a/crates/dreammaker/src/builtins.rs b/crates/dreammaker/src/builtins.rs index 2718f197..0a98524f 100644 --- a/crates/dreammaker/src/builtins.rs +++ b/crates/dreammaker/src/builtins.rs @@ -2,11 +2,11 @@ use builtins_proc_macro::builtins_table; -use super::objtree::*; -use super::Location; -use super::preprocessor::{DefineMap, Define}; use super::constants::Constant; use super::docs::{BuiltinDocs, DocCollection}; +use super::objtree::*; +use super::preprocessor::{Define, DefineMap}; +use super::Location; const DM_VERSION: i32 = 515; const DM_BUILD: i32 = 1619; diff --git a/crates/dreammaker/src/config.rs b/crates/dreammaker/src/config.rs index 1523347d..2c1e9424 100644 --- a/crates/dreammaker/src/config.rs +++ b/crates/dreammaker/src/config.rs @@ -1,9 +1,9 @@ //! Configuration file for diagnostics. +use std::collections::HashMap; use std::fs::File; use std::io::Read; use std::path::{Path, PathBuf}; -use std::collections::HashMap; use ahash::RandomState; use serde::Deserialize; diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index 047ee843..dc3e5f01 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -6,10 +6,10 @@ use std::path::Path; use get_size::GetSize; use get_size_derive::GetSize; -use indexmap::IndexMap; use ahash::RandomState; -use ordered_float::OrderedFloat; use color_space::{Hsl, Hsv, Lch, Rgb}; +use indexmap::IndexMap; +use ordered_float::OrderedFloat; use crate::heap_size_of_index_map; diff --git a/crates/dreammaker/src/dmi.rs b/crates/dreammaker/src/dmi.rs index 02763a01..e3bdb5cc 100644 --- a/crates/dreammaker/src/dmi.rs +++ b/crates/dreammaker/src/dmi.rs @@ -1,9 +1,9 @@ //! DMI metadata parsing and representation. +use std::collections::{BTreeMap, HashMap}; use std::fmt::Display; use std::io; use std::path::Path; -use std::collections::{BTreeMap, HashMap}; use derivative::Derivative; use lodepng::Decoder; diff --git a/crates/dreammaker/src/error.rs b/crates/dreammaker/src/error.rs index f6533f3b..5c2ffafe 100644 --- a/crates/dreammaker/src/error.rs +++ b/crates/dreammaker/src/error.rs @@ -1,15 +1,15 @@ //! Error, warning, and other diagnostics handling. -use std::{fmt, error, io}; -use std::path::{PathBuf, Path}; -use std::cell::{RefCell, Ref, RefMut}; +use std::cell::{Ref, RefCell, RefMut}; use std::collections::HashMap; +use std::path::{Path, PathBuf}; +use std::{error, fmt, io}; use ahash::RandomState; use get_size::GetSize; use get_size_derive::GetSize; -use termcolor::{ColorSpec, Color}; +use termcolor::{Color, ColorSpec}; use crate::config::Config; diff --git a/crates/dreammaker/src/indents.rs b/crates/dreammaker/src/indents.rs index 06261ae5..ab8bdafd 100644 --- a/crates/dreammaker/src/indents.rs +++ b/crates/dreammaker/src/indents.rs @@ -1,8 +1,8 @@ //! The indentation processor. use std::collections::VecDeque; -use crate::{Location, Context, DMError}; -use crate::lexer::{LocatedToken, Token, Punctuation}; +use crate::lexer::{LocatedToken, Punctuation, Token}; +use crate::{Context, DMError, Location}; /// Eliminates blank lines, parses and validates indentation, braces, and semicolons. /// diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index 0c29ecff..6a7f8991 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -1,12 +1,12 @@ //! The lexer/tokenizer. +use std::borrow::Cow; +use std::fmt; use std::io::Read; use std::str::FromStr; -use std::fmt; -use std::borrow::Cow; -use super::{DMError, Location, HasLocation, FileId, Context, Severity}; -use super::docs::*; use super::ast::Ident; +use super::docs::*; +use super::{Context, DMError, FileId, HasLocation, Location, Severity}; macro_rules! table { ( diff --git a/crates/dreammaker/src/lib.rs b/crates/dreammaker/src/lib.rs index ce330eb7..86171232 100644 --- a/crates/dreammaker/src/lib.rs +++ b/crates/dreammaker/src/lib.rs @@ -4,15 +4,16 @@ extern crate indexmap; extern crate interval_tree; extern crate lodepng; -#[macro_use] extern crate bitflags; -extern crate termcolor; +#[macro_use] +extern crate bitflags; extern crate ordered_float; extern crate serde; extern crate serde_derive; +extern crate termcolor; extern crate toml; -use std::path::Path; use std::borrow::Cow; +use std::path::Path; #[allow(unused_macros)] macro_rules! try_iter { @@ -31,18 +32,18 @@ use get_size::GetSize; use indexmap::IndexMap; // roughly in order of stage -pub mod docs; -pub mod lexer; -pub mod preprocessor; -pub mod indents; -pub mod parser; pub mod annotation; pub mod ast; -pub mod objtree; mod builtins; +pub mod config; pub mod constants; pub mod dmi; -pub mod config; +pub mod docs; +pub mod indents; +pub mod lexer; +pub mod objtree; +pub mod parser; +pub mod preprocessor; impl Context { /// Run the parsing suite on a given `.dme` file, producing an object tree. diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index 2c40caf0..c1f86afc 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -6,15 +6,18 @@ use std::fmt; use get_size::GetSize; use get_size_derive::GetSize; -use indexmap::IndexMap; use ahash::RandomState; +use indexmap::IndexMap; use crate::heap_size_of_index_map; -use super::ast::{AsType, Expression, VarType, VarTypeBuilder, VarSuffix, PathOp, Parameter, Block, ProcDeclBuilder, ProcDeclKind, ProcFlags, Ident}; +use super::ast::{ + AsType, Block, Expression, Ident, Parameter, PathOp, ProcDeclBuilder, ProcDeclKind, ProcFlags, + VarSuffix, VarType, VarTypeBuilder, +}; use super::constants::Constant; use super::docs::DocCollection; -use super::{DMError, Location, Context, Severity}; +use super::{Context, DMError, Location, Severity}; // ---------------------------------------------------------------------------- // Symbol IDs diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 592b9321..c895a999 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -7,12 +7,12 @@ use std::str::FromStr; use crate::ast; -use super::{DMError, Location, HasLocation, Context, Severity, FileId}; -use super::lexer::{LocatedToken, Token, Punctuation}; -use super::objtree::{ObjectTreeBuilder, ObjectTree, NodeIndex}; use super::annotation::*; use super::ast::*; use super::docs::*; +use super::lexer::{LocatedToken, Punctuation, Token}; +use super::objtree::{NodeIndex, ObjectTree, ObjectTreeBuilder}; +use super::{Context, DMError, FileId, HasLocation, Location, Severity}; // ---------------------------------------------------------------------------- // Error handling diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index 38a956d0..86565a5b 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -1,20 +1,20 @@ //! The preprocessor. +use std::borrow::Cow; use std::collections::{HashMap, VecDeque}; -use std::rc::Rc; -use std::{io, fmt}; use std::fs::File; use std::path::{Path, PathBuf}; -use std::borrow::Cow; +use std::rc::Rc; +use std::{fmt, io}; use ahash::RandomState; -use interval_tree::{IntervalTree, range}; +use interval_tree::{range, IntervalTree}; -use super::{DMError, Location, HasLocation, FileId, Context, Severity}; -use super::lexer::*; -use super::docs::{DocComment, DocTarget, DocCollection, CommentKind}; use super::annotation::*; use super::ast::Ident; +use super::docs::{CommentKind, DocCollection, DocComment, DocTarget}; +use super::lexer::*; +use super::{Context, DMError, FileId, HasLocation, Location, Severity}; /// The maximum recursion depth of macro expansion. const MAX_RECURSION_DEPTH: usize = 32; diff --git a/crates/dreammaker/tests/annotation_tests.rs b/crates/dreammaker/tests/annotation_tests.rs index 1c362bf4..4757f44f 100644 --- a/crates/dreammaker/tests/annotation_tests.rs +++ b/crates/dreammaker/tests/annotation_tests.rs @@ -1,10 +1,10 @@ extern crate dreammaker as dm; -use dm::Location; -use dm::lexer::*; use dm::annotation::*; -use dm::parser::Parser; use dm::indents::IndentProcessor; +use dm::lexer::*; +use dm::parser::Parser; +use dm::Location; #[test] fn annotation_basic() { diff --git a/crates/dreammaker/tests/ast_tests.rs b/crates/dreammaker/tests/ast_tests.rs index c29fce09..00458945 100644 --- a/crates/dreammaker/tests/ast_tests.rs +++ b/crates/dreammaker/tests/ast_tests.rs @@ -2,11 +2,11 @@ extern crate dreammaker as dm; use core::panic; -use dm::*; -use dm::constants::*; use dm::ast::*; -use dm::preprocessor::Preprocessor; +use dm::constants::*; use dm::objtree::ObjectTree; +use dm::preprocessor::Preprocessor; +use dm::*; fn with_code(code: &'static str, f: F) { let context = Context::default(); diff --git a/crates/dreammaker/tests/expression_tests.rs b/crates/dreammaker/tests/expression_tests.rs index f8cb4bb7..440dd65d 100644 --- a/crates/dreammaker/tests/expression_tests.rs +++ b/crates/dreammaker/tests/expression_tests.rs @@ -1,8 +1,8 @@ extern crate dreammaker as dm; +use dm::ast::*; use dm::lexer::Lexer; use dm::parser::*; -use dm::ast::*; fn parse_expr(f: &str) -> Expression { let context = Default::default(); diff --git a/crates/dreammaker/tests/format_tests.rs b/crates/dreammaker/tests/format_tests.rs index 1f16b363..6a1c3aea 100644 --- a/crates/dreammaker/tests/format_tests.rs +++ b/crates/dreammaker/tests/format_tests.rs @@ -1,6 +1,6 @@ extern crate dreammaker as dm; -use dm::lexer::{Quote, FormatFloat}; +use dm::lexer::{FormatFloat, Quote}; #[test] fn strings() { diff --git a/crates/dreammaker/tests/lexer_tests.rs b/crates/dreammaker/tests/lexer_tests.rs index 6f147f6f..98fbd65c 100644 --- a/crates/dreammaker/tests/lexer_tests.rs +++ b/crates/dreammaker/tests/lexer_tests.rs @@ -1,8 +1,8 @@ extern crate dreammaker as dm; -use dm::lexer::*; -use dm::lexer::Token::*; use dm::lexer::Punctuation::*; +use dm::lexer::Token::*; +use dm::lexer::*; fn lex(f: &str) -> Vec { let context = Default::default(); diff --git a/crates/dreammaker/tests/macro_tests.rs b/crates/dreammaker/tests/macro_tests.rs index 2dbeaa85..2d30ee45 100644 --- a/crates/dreammaker/tests/macro_tests.rs +++ b/crates/dreammaker/tests/macro_tests.rs @@ -1,8 +1,8 @@ extern crate dreammaker as dm; -use dm::preprocessor::*; -use dm::lexer::Token::*; use dm::lexer::Punctuation::*; +use dm::lexer::Token::*; +use dm::preprocessor::*; fn process(source: &'static str) -> Vec { let ctx = dm::Context::default(); diff --git a/crates/dreammaker/tests/pipeline_tests.rs b/crates/dreammaker/tests/pipeline_tests.rs index 7903c05c..821497c5 100644 --- a/crates/dreammaker/tests/pipeline_tests.rs +++ b/crates/dreammaker/tests/pipeline_tests.rs @@ -2,8 +2,8 @@ extern crate dreammaker as dm; use std::path::PathBuf; -use dm::*; use dm::preprocessor::Preprocessor; +use dm::*; fn with_test_dme(context: &Context, f: F) { let dme = match std::env::var_os("TEST_DME") { diff --git a/crates/interval-tree/src/iterators.rs b/crates/interval-tree/src/iterators.rs index 2a3f9cda..ef22488c 100644 --- a/crates/interval-tree/src/iterators.rs +++ b/crates/interval-tree/src/iterators.rs @@ -1,7 +1,7 @@ +use crate::node::Node; +use crate::{IntervalTree, RangeInclusive}; use std::collections::Bound; use std::vec; -use crate::{IntervalTree, RangeInclusive}; -use crate::node::Node; #[derive(Debug, Clone)] enum Visiting { diff --git a/crates/interval-tree/src/lib.rs b/crates/interval-tree/src/lib.rs index 65239d53..e381f15b 100644 --- a/crates/interval-tree/src/lib.rs +++ b/crates/interval-tree/src/lib.rs @@ -3,14 +3,14 @@ //! [interval tree]: https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree #![forbid(unsafe_code)] -mod range; -mod node; -mod tree; mod iterators; +mod node; +mod range; +mod tree; -pub use range::{RangeInclusive, range}; -pub use tree::IntervalTree; pub use iterators::RangePairIter; +pub use range::{range, RangeInclusive}; +pub use tree::IntervalTree; #[cfg(test)] mod tests; diff --git a/crates/interval-tree/src/node.rs b/crates/interval-tree/src/node.rs index a3fa0bcf..d5977012 100644 --- a/crates/interval-tree/src/node.rs +++ b/crates/interval-tree/src/node.rs @@ -1,5 +1,5 @@ -use std::cmp::{self, Ordering}; use crate::range::RangeInclusive; +use std::cmp::{self, Ordering}; #[derive(Debug, Clone)] pub struct Node { diff --git a/crates/interval-tree/src/tree.rs b/crates/interval-tree/src/tree.rs index 3476b1a4..9d707dea 100644 --- a/crates/interval-tree/src/tree.rs +++ b/crates/interval-tree/src/tree.rs @@ -1,7 +1,7 @@ -use std::collections::Bound; +use crate::iterators::{IntoIter, RangePairIter}; +use crate::node::{height, Node}; use crate::range::RangeInclusive; -use crate::node::{Node, height}; -use crate::iterators::{RangePairIter, IntoIter}; +use std::collections::Bound; /// An interval tree. #[derive(Debug, Clone)] From e1b51dfee93076ba6a32199eb21f724d600200d7 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Tue, 28 May 2024 23:08:34 -0700 Subject: [PATCH 093/197] rustfmt: Add spaces around = in attributes --- crates/dap-types/src/lib.rs | 28 ++++++++++++++-------------- crates/dmm-tools-cli/src/main.rs | 28 ++++++++++++++-------------- crates/dmm-tools/src/minimap.rs | 2 +- crates/dreammaker/src/dmi.rs | 2 +- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/crates/dap-types/src/lib.rs b/crates/dap-types/src/lib.rs index 2e2db820..e254f20b 100644 --- a/crates/dap-types/src/lib.rs +++ b/crates/dap-types/src/lib.rs @@ -578,7 +578,7 @@ pub struct EvaluateResponse { /** * The optional type of the evaluate result. */ - #[serde(rename="type")] + #[serde(rename = "type")] pub type_: Option, /** @@ -1078,9 +1078,9 @@ pub struct VariablesArguments { #[derive(Serialize, Deserialize, Debug)] pub enum VariablesFilter { - #[serde(rename="indexed")] + #[serde(rename = "indexed")] Indexed, - #[serde(rename="named")] + #[serde(rename = "named")] Named, } @@ -1359,16 +1359,16 @@ pub struct DisassembledInstruction { #[derive(Serialize, Deserialize, Debug)] pub enum ExceptionBreakMode { /// never breaks - #[serde(rename="never")] + #[serde(rename = "never")] Never, /// always breaks - #[serde(rename="always")] + #[serde(rename = "always")] Always, /// breaks when exception unhandled - #[serde(rename="unhandled")] + #[serde(rename = "unhandled")] Unhandled, /// breaks if the exception is not handled by user code - #[serde(rename="userUnhandled")] + #[serde(rename = "userUnhandled")] UserUnhandled, } @@ -1670,11 +1670,11 @@ pub struct Source { #[derive(Serialize, Deserialize, Debug)] pub enum SourcePresentationHint { - #[serde(rename="normal")] + #[serde(rename = "normal")] Normal, - #[serde(rename="emphasize")] + #[serde(rename = "emphasize")] Emphasize, - #[serde(rename="deemphasize")] + #[serde(rename = "deemphasize")] Deemphasize, } @@ -1763,11 +1763,11 @@ pub struct StackFrame { #[derive(Serialize, Deserialize, Debug)] pub enum StackFramePresentationHint { - #[serde(rename="normal")] + #[serde(rename = "normal")] Normal, - #[serde(rename="label")] + #[serde(rename = "label")] Label, - #[serde(rename="subtle")] + #[serde(rename = "subtle")] Subtle, } @@ -1871,7 +1871,7 @@ pub struct Variable { /** * The type of the variable's value. Typically shown in the UI when hovering over the value. */ - #[serde(rename="type")] + #[serde(rename = "type")] pub type_: Option, /** diff --git a/crates/dmm-tools-cli/src/main.rs b/crates/dmm-tools-cli/src/main.rs index c1724f22..119decf0 100644 --- a/crates/dmm-tools-cli/src/main.rs +++ b/crates/dmm-tools-cli/src/main.rs @@ -99,16 +99,16 @@ General Public License version 3.", )] struct Opt { /// The environment file to operate under. - #[arg(short='e', long="env")] + #[arg(short = 'e', long = "env")] environment: Option, - #[arg(short='v', long="verbose")] + #[arg(short = 'v', long = "verbose")] #[allow(dead_code)] verbose: bool, /// Set the number of threads to be used for parallel execution when /// possible. A value of 0 will select automatically, and 1 will be serial. - #[arg(long="jobs", default_value="1")] + #[arg(long = "jobs", default_value = "1")] jobs: usize, #[command(subcommand)] @@ -124,54 +124,54 @@ enum Command { #[command(name = "list-passes")] ListPasses { /// Output as JSON. - #[arg(short='j', long="json")] + #[arg(short = 'j', long = "json")] json: bool, }, /// Build minimaps of the specified maps. #[command(name = "minimap")] Minimap { /// The output directory. - #[arg(short='o', default_value="data/minimaps")] + #[arg(short = 'o', default_value = "data/minimaps")] output: String, /// Set the minimum x,y or x,y,z coordinate to act upon (1-indexed, inclusive). - #[arg(long="min")] + #[arg(long = "min")] min: Option, /// Set the maximum x,y or x,y,z coordinate to act upon (1-indexed, inclusive). - #[arg(long="max")] + #[arg(long = "max")] max: Option, /// Enable render-passes, or "all" to only exclude those passed to --disable. - #[arg(long="enable", default_value="")] + #[arg(long = "enable", default_value = "")] enable: String, /// Disable render-passes, or "all" to only use those passed to --enable. - #[arg(long="disable", default_value="")] + #[arg(long = "disable", default_value = "")] disable: String, /// Run output through pngcrush automatically. Requires pngcrush. - #[arg(long="pngcrush")] + #[arg(long = "pngcrush")] pngcrush: bool, /// Run output through optipng automatically. Requires optipng. - #[arg(long="optipng")] + #[arg(long = "optipng")] optipng: bool, /// The list of maps to process. files: Vec, }, /// List the differing coordinates between two maps. - #[command(name="diff-maps")] + #[command(name = "diff-maps")] DiffMaps { left: String, right: String, }, /// Show metadata information about the map. - #[command(name="map-info")] + #[command(name = "map-info")] MapInfo { /// Output as JSON. - #[arg(short='j', long="json")] + #[arg(short = 'j', long = "json")] json: bool, /// The list of maps to show info on. diff --git a/crates/dmm-tools/src/minimap.rs b/crates/dmm-tools/src/minimap.rs index 42430a44..701902ff 100644 --- a/crates/dmm-tools/src/minimap.rs +++ b/crates/dmm-tools/src/minimap.rs @@ -478,7 +478,7 @@ impl From for Layer { } } -#[cfg(feature="gfx_core")] +#[cfg(feature = "gfx_core")] impl gfx_core::shade::BaseTyped for Layer { fn get_base_type() -> gfx_core::shade::BaseType { i32::get_base_type() diff --git a/crates/dreammaker/src/dmi.rs b/crates/dreammaker/src/dmi.rs index e3bdb5cc..4ced6159 100644 --- a/crates/dreammaker/src/dmi.rs +++ b/crates/dreammaker/src/dmi.rs @@ -216,7 +216,7 @@ pub struct State { /// Whether this is a movement state (shown during gliding). pub movement: bool, /// The number of frames in the spritesheet before this state's first frame. - #[derivative(PartialEq="ignore")] + #[derivative(PartialEq = "ignore")] pub offset: usize, /// 0 for infinite, 1+ for finite. pub loop_: u32, From f030e316b912b24d1a4ffa6d078959b2bf4e9fd6 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Tue, 28 May 2024 23:26:07 -0700 Subject: [PATCH 094/197] rustfmt: Blind-format crates/interval-tree --- crates/interval-tree/src/iterators.rs | 118 +++++--- crates/interval-tree/src/node.rs | 393 ++++++++++++++------------ crates/interval-tree/src/tests.rs | 193 +++++++------ crates/interval-tree/src/tree.rs | 302 ++++++++++---------- 4 files changed, 552 insertions(+), 454 deletions(-) diff --git a/crates/interval-tree/src/iterators.rs b/crates/interval-tree/src/iterators.rs index ef22488c..d79a9732 100644 --- a/crates/interval-tree/src/iterators.rs +++ b/crates/interval-tree/src/iterators.rs @@ -32,24 +32,28 @@ impl<'a, K: Ord, V> RangePairIter<'a, K, V> { match node.left { Some(ref lsucc) => { self.stack.push((node, Visiting::Center)); - if match self.start { // left_subtree_relevant + if match self.start { + // left_subtree_relevant Bound::Included(ref start) => node.max >= *start, Bound::Excluded(ref start) => node.max > *start, Bound::Unbounded => true, } { self.stack.push((&**lsucc, Visiting::Left)) } - }, - None => self.stack.push((node, Visiting::Center)) + } + None => self.stack.push((node, Visiting::Center)), } } fn visit_right(&mut self, node: &'a Node) { - if !match self.end { // right_subtree_relevant + if !match self.end { + // right_subtree_relevant Bound::Included(ref end) => *end >= node.key.start, Bound::Excluded(ref end) => *end > node.key.start, Bound::Unbounded => true, - } { return } + } { + return; + } if let Some(ref rsucc) = node.right { self.stack.push((&**rsucc, Visiting::Left)); } @@ -87,7 +91,8 @@ impl<'a, K: Ord + Clone, V> Iterator for RangePairIter<'a, K, V> { type Item = (RangeInclusive, &'a V); fn next(&mut self) -> Option<(RangeInclusive, &'a V)> { - self.get_next_node().map(|(n, i)| (n.key.clone(), &n.data[i])) + self.get_next_node() + .map(|(n, i)| (n.key.clone(), &n.data[i])) } } @@ -163,55 +168,88 @@ impl Iterator for IntoIter { #[test] fn test_iterators() { let mut tree = IntervalTree::::new(); - tree.insert(RangeInclusive::new(18,18), 1337); - tree.insert(RangeInclusive::new(13,13), 1338); - tree.insert(RangeInclusive::new(17,17), 1339); - tree.insert(RangeInclusive::new(10,10), 1321); - tree.insert(RangeInclusive::new(1 ,1), 1321); - tree.insert(RangeInclusive::new(3 ,3), 1322); + tree.insert(RangeInclusive::new(18, 18), 1337); + tree.insert(RangeInclusive::new(13, 13), 1338); + tree.insert(RangeInclusive::new(17, 17), 1339); + tree.insert(RangeInclusive::new(10, 10), 1321); + tree.insert(RangeInclusive::new(1, 1), 1321); + tree.insert(RangeInclusive::new(3, 3), 1322); let iter = RangePairIter::new(&tree, Bound::Included(0), Bound::Included(1000)); - for (k,v) in iter { - println!("{:?} {}",k,v); + for (k, v) in iter { + println!("{:?} {}", k, v); } let mut iter = RangePairIter::new(&tree, Bound::Included(0), Bound::Included(1000)); - assert_eq!(iter.next().expect("should have a few values").0, RangeInclusive::new(1 ,1 )); - assert_eq!(iter.next().expect("should have a few values").0, RangeInclusive::new(3 ,3 )); - assert_eq!(iter.next().expect("should have a few values").0, RangeInclusive::new(10,10)); - assert_eq!(iter.next().expect("should have a few values").0, RangeInclusive::new(13,13)); - assert_eq!(iter.next().expect("should have a few values").0, RangeInclusive::new(17,17)); - assert_eq!(iter.next().expect("should have a few values").0, RangeInclusive::new(18,18)); + assert_eq!( + iter.next().expect("should have a few values").0, + RangeInclusive::new(1, 1) + ); + assert_eq!( + iter.next().expect("should have a few values").0, + RangeInclusive::new(3, 3) + ); + assert_eq!( + iter.next().expect("should have a few values").0, + RangeInclusive::new(10, 10) + ); + assert_eq!( + iter.next().expect("should have a few values").0, + RangeInclusive::new(13, 13) + ); + assert_eq!( + iter.next().expect("should have a few values").0, + RangeInclusive::new(17, 17) + ); + assert_eq!( + iter.next().expect("should have a few values").0, + RangeInclusive::new(18, 18) + ); assert!(iter.next().is_none()); let mut iter = RangePairIter::new(&tree, Bound::Included(3), Bound::Included(17)); - assert_eq!(iter.next().expect("should have a few values").0, RangeInclusive::new(3 ,3 )); - assert_eq!(iter.next().expect("should have a few values").0, RangeInclusive::new(10,10)); - assert_eq!(iter.next().expect("should have a few values").0, RangeInclusive::new(13,13)); - assert_eq!(iter.next().expect("should have a few values").0, RangeInclusive::new(17,17)); + assert_eq!( + iter.next().expect("should have a few values").0, + RangeInclusive::new(3, 3) + ); + assert_eq!( + iter.next().expect("should have a few values").0, + RangeInclusive::new(10, 10) + ); + assert_eq!( + iter.next().expect("should have a few values").0, + RangeInclusive::new(13, 13) + ); + assert_eq!( + iter.next().expect("should have a few values").0, + RangeInclusive::new(17, 17) + ); assert!(iter.next().is_none()); } #[test] fn test_into_iter() { let mut tree = IntervalTree::::new(); - tree.insert(RangeInclusive::new(18,18), 1337); - tree.insert(RangeInclusive::new(13,13), 1338); - tree.insert(RangeInclusive::new(17,17), 1339); - tree.insert(RangeInclusive::new(10,10), 1321); - tree.insert(RangeInclusive::new(1 ,1), 1321); - tree.insert(RangeInclusive::new(1 ,1), 1350); - tree.insert(RangeInclusive::new(3 ,3), 1322); + tree.insert(RangeInclusive::new(18, 18), 1337); + tree.insert(RangeInclusive::new(13, 13), 1338); + tree.insert(RangeInclusive::new(17, 17), 1339); + tree.insert(RangeInclusive::new(10, 10), 1321); + tree.insert(RangeInclusive::new(1, 1), 1321); + tree.insert(RangeInclusive::new(1, 1), 1350); + tree.insert(RangeInclusive::new(3, 3), 1322); let values: Vec<_> = tree.into_iter().collect(); - assert_eq!(values, vec![ - (RangeInclusive::new(1, 1), 1321), - (RangeInclusive::new(1, 1), 1350), - (RangeInclusive::new(3, 3), 1322), - (RangeInclusive::new(10, 10), 1321), - (RangeInclusive::new(13, 13), 1338), - (RangeInclusive::new(17, 17), 1339), - (RangeInclusive::new(18, 18), 1337), - ]); + assert_eq!( + values, + vec![ + (RangeInclusive::new(1, 1), 1321), + (RangeInclusive::new(1, 1), 1350), + (RangeInclusive::new(3, 3), 1322), + (RangeInclusive::new(10, 10), 1321), + (RangeInclusive::new(13, 13), 1338), + (RangeInclusive::new(17, 17), 1339), + (RangeInclusive::new(18, 18), 1337), + ] + ); } diff --git a/crates/interval-tree/src/node.rs b/crates/interval-tree/src/node.rs index d5977012..7b32495e 100644 --- a/crates/interval-tree/src/node.rs +++ b/crates/interval-tree/src/node.rs @@ -48,12 +48,16 @@ impl Node { ///returns the minimal key,value pair within this tree pub fn min_pair(&self) -> (&RangeInclusive, &[V]) { - self.left.as_ref().map_or((&self.key, &self.data), |n| n.min_pair()) + self.left + .as_ref() + .map_or((&self.key, &self.data), |n| n.min_pair()) } ///returns the maximal key,value pair within this tree pub fn max_pair(&self) -> (&RangeInclusive, &[V]) { - self.right.as_ref().map_or((&self.key, &self.data), |n| n.max_pair()) + self.right + .as_ref() + .map_or((&self.key, &self.data), |n| n.max_pair()) } /// Perform a single right rotation on this (sub) tree @@ -121,10 +125,10 @@ impl Node { //Return a new Interval tree, where the root has been removed fn delete_root(mut self) -> Option> { match (self.left.take(), self.right.take()) { - (None, None) => None, - (Some(l), None) => Some(l), - (None, Some(r)) => Some(r), - (Some(l), Some(r)) => Some(Node::combine_two_subtrees(l, r)) + (None, None) => None, + (Some(l), None) => Some(l), + (None, Some(r)) => Some(r), + (Some(l), Some(r)) => Some(Node::combine_two_subtrees(l, r)), } } @@ -165,7 +169,7 @@ impl Node { self.right = succ.delete(key); return Some(self.updated_node()); } - }, + } Ordering::Greater => { if let Some(succ) = self.left.take() { self.left = succ.delete(key); @@ -195,9 +199,12 @@ impl Node { /// root may now differ due to rotations, thus the old root is moved into the function) pub fn insert(mut self: Box, key: RangeInclusive, data: V) -> Box { match self.key.cmp(&key) { - Ordering::Equal => { self.data.push(data); return self }, - Ordering::Less => self.right = Node::insert_in_successor(self.right.take(), key, data), - Ordering::Greater => self.left = Node::insert_in_successor(self.left.take(), key, data) + Ordering::Equal => { + self.data.push(data); + return self; + } + Ordering::Less => self.right = Node::insert_in_successor(self.right.take(), key, data), + Ordering::Greater => self.left = Node::insert_in_successor(self.left.take(), key, data), } self.update_height(); self.rotate_if_necessary() @@ -205,7 +212,11 @@ impl Node { /// recursively insert the (key,data) pair into the given optional succesor and return its new /// value - fn insert_in_successor(succ: Option>, key: RangeInclusive, data: V) -> Option> { + fn insert_in_successor( + succ: Option>, + key: RangeInclusive, + data: V, + ) -> Option> { Some(match succ { Some(succ) => succ.insert(key, data), None => Box::new(Node::new(key, data)), @@ -219,175 +230,205 @@ pub fn height(node: &Option>>) -> u32 { #[cfg(test)] pub mod tests { -use super::*; -type Node = super::Node; + use super::*; + type Node = super::Node; -/// returns true iff key is stored in the tree given by root -pub fn contains(key: &RangeInclusive, root: &Node) -> bool { - root.search(key).is_some() -} + /// returns true iff key is stored in the tree given by root + pub fn contains(key: &RangeInclusive, root: &Node) -> bool { + root.search(key).is_some() + } -fn subtree_max(node: &Option>>) -> u64 { - node.as_ref().map_or(0, |succ| succ.max) -} + fn subtree_max(node: &Option>>) -> u64 { + node.as_ref().map_or(0, |succ| succ.max) + } -///returns the smallest key and value after the given key. -pub fn min_after<'a,V>(key: &RangeInclusive, root: &'a Node) -> Option<(&'a RangeInclusive,&'a [V])> { - match root.key.cmp(key){ - Ordering::Equal => root.right.as_ref().map(|succ| succ.min_pair()), - Ordering::Less => root.right.as_ref().and_then(|succ| min_after(key, succ)), - Ordering::Greater => { - match root.left { - Some(ref succ) => min_after(key, succ).or( Some((&root.key,&root.data)) ), - None => Some((&root.key, &root.data)) + ///returns the smallest key and value after the given key. + pub fn min_after<'a, V>( + key: &RangeInclusive, + root: &'a Node, + ) -> Option<(&'a RangeInclusive, &'a [V])> { + match root.key.cmp(key) { + Ordering::Equal => root.right.as_ref().map(|succ| succ.min_pair()), + Ordering::Less => root.right.as_ref().and_then(|succ| min_after(key, succ)), + Ordering::Greater => match root.left { + Some(ref succ) => min_after(key, succ).or(Some((&root.key, &root.data))), + None => Some((&root.key, &root.data)), + }, + } + } + + ///returns the minimal value within this tree + pub fn min(root: &Node) -> &[V] { + root.left.as_ref().map_or(&root.data, |v| min(v)) + } + + ///returns the minimal value within this tree + pub fn max(root: &Node) -> &[V] { + root.right.as_ref().map_or(&root.data, |v| max(v)) + } + + fn simple_tree(size: i32) -> Box> { + let mut t = Box::new(Node:: { + key: RangeInclusive::new(1, 1), + data: vec![1337], + height: 0, + max: 1, + left: None, + right: None, + }); + for x in 2..size + 1 { + t = t.insert(RangeInclusive::new(x as u64, x as u64), 1337 + x - 1) + } + t + } + fn is_sorted_left(node: &Node) -> bool { + node.left.as_ref().map_or(true, |succ| succ.key < node.key) + } + fn is_sorted_right(node: &Node) -> bool { + node.right.as_ref().map_or(true, |succ| succ.key > node.key) + } + fn is_interval_node(node: &Box>) -> bool { + let sorted = is_sorted_left(node) && is_sorted_right(node); + let balanced = node.height == cmp::max(height(&node.left), height(&node.right)) + 1; + let proper_max = node.max + == cmp::max( + subtree_max(&node.left), + cmp::max(subtree_max(&node.right), node.key.end), + ); + sorted && balanced && proper_max + } + + pub fn is_interval_tree(root: &Option>>) -> bool { + (*root).as_ref().map_or(true, is_interval_node) + } + + #[test] + fn simple_tree_operations() { + let mut t = Box::new(Node:: { + key: RangeInclusive::new(3, 3), + data: vec![4], + max: 3, + height: 2, + left: Some(Box::new(Node:: { + key: RangeInclusive::new(2, 2), + data: vec![5], + height: 1, + max: 2, + left: None, + right: None, + })), + right: None, + }); + assert!(is_interval_node(&t)); + assert!(contains::(&RangeInclusive::new(3, 3), &t)); + assert!(contains::(&RangeInclusive::new(2, 2), &t)); + assert!(!contains::(&RangeInclusive::new(6, 6), &t)); + assert!(!contains::(&RangeInclusive::new(4, 4), &t)); + t = t.insert(RangeInclusive::new(4, 4), 7); + t = t.insert(RangeInclusive::new(5, 5), 7); + t = t.insert(RangeInclusive::new(6, 6), 8); + assert!(contains::(&RangeInclusive::new(4, 4), &t)); + assert!(contains::(&RangeInclusive::new(6, 6), &t)); + assert!(!contains::(&RangeInclusive::new(7, 7), &t)); + } + + #[test] + fn rotations_on_tree() { + let mut t = Box::new(Node:: { + key: RangeInclusive::new(1, 1), + data: vec![1337], + height: 1, + max: 1, + left: None, + right: None, + }); + for i in 2..255 { + t = t.insert(RangeInclusive::new(i, i), 1337); + assert!(is_interval_node(&t)); + } + //check that the tree is indeed balanced + assert!(height(&Some(t)) <= 8); + } + + #[test] + fn test_drop_min() { + let mut t = simple_tree(3); + let (maybe_tree, min) = t.drop_min(); + t = maybe_tree.expect("failure to get tree for first min delete"); + assert!(is_interval_node(&t)); + assert!(min.key == RangeInclusive::new(1, 1)); + assert!(!contains::(&RangeInclusive::new(1, 1), &t)); + assert!(contains::(&RangeInclusive::new(2, 2), &t)); + assert!(contains::(&RangeInclusive::new(3, 3), &t)); + + let (maybe_tree, min) = t.drop_min(); + t = maybe_tree.expect("failure to get tree for second min delete"); + assert!(is_interval_node(&t)); + assert!(min.key == RangeInclusive::new(2, 2)); + assert!(!contains::(&RangeInclusive::new(1, 1), &t)); + assert!(!contains::(&RangeInclusive::new(2, 2), &t)); + assert!(contains::(&RangeInclusive::new(3, 3), &t)); + + let (maybe_tree, min) = t.drop_min(); + assert!(maybe_tree.is_none()); + assert!(min.key == RangeInclusive::new(3, 3)); + } + + #[test] + fn test_drop_root() { + let mut t = simple_tree(3); + let maybe_tree = t.delete_root(); + t = maybe_tree.expect("failure to get tree for first root drop"); + assert!(is_interval_node(&t)); + assert!(t.height == 2); + assert!(contains::(&RangeInclusive::new(1, 1), &t)); + assert!(!contains::(&RangeInclusive::new(2, 2), &t)); + assert!(contains::(&RangeInclusive::new(3, 3), &t)); + + let maybe_tree = t.delete_root(); + t = maybe_tree.expect("failure to get tree for second root drop"); + assert!(is_interval_node(&t)); + assert!(contains::(&RangeInclusive::new(1, 1), &t)); + assert!(!contains::(&RangeInclusive::new(2, 2), &t)); + assert!(!contains::(&RangeInclusive::new(3, 3), &t)); + + let maybe_tree = t.delete_root(); + assert!(maybe_tree.is_none()); + } + + #[test] + fn test_delete() { + let mut t = simple_tree(10); + for i in 1..10 { + assert!(contains::(&RangeInclusive::new(i, i), &t)); + let maybe_tree = t.delete(RangeInclusive::new(i, i)); + t = maybe_tree.expect("failure to get tree for delete"); + assert!(!contains::(&RangeInclusive::new(i, i), &t)); + assert!(is_interval_node(&t)); + } + assert!(contains::(&RangeInclusive::new(10, 10), &t)); + let maybe_tree = t.delete(RangeInclusive::new(10, 10)); + assert!(maybe_tree.is_none()); + } + + #[test] + fn test_min_max() { + let t = simple_tree(50); + assert_eq!(min(&t), &[1337]); + assert_eq!(max(&t), &[1337 + 50 - 1]); + assert_eq!(t.max_pair().0, &RangeInclusive::new(50, 50)); + assert_eq!(t.min_pair().0, &RangeInclusive::new(1, 1)); + } + + #[test] + fn test_min_after() { + let t = simple_tree(50); + for old_key in 0..55 { + println!("trying value: {}", old_key); + match min_after(&RangeInclusive::new(old_key, old_key), &t) { + Some((k, _d)) => assert_eq!(k, &(RangeInclusive::new(old_key + 1, old_key + 1))), + None => assert!(old_key >= 50), } } } } - -///returns the minimal value within this tree -pub fn min(root: &Node) -> &[V] { - root.left.as_ref().map_or(&root.data, |v| min(v)) -} - -///returns the minimal value within this tree -pub fn max(root: &Node) -> &[V] { - root.right.as_ref().map_or(&root.data, |v| max(v)) -} - - -fn simple_tree(size: i32) -> Box> { - let mut t = Box::new(Node::{key: RangeInclusive::new(1,1), data: vec![1337], height: 0, max: 1, left:None, right: None}); - for x in 2..size+1 { - t = t.insert(RangeInclusive::new(x as u64, x as u64 ),1337+x-1) - } - t -} -fn is_sorted_left(node: &Node) -> bool { - node.left.as_ref().map_or(true, |succ| succ.key < node.key) -} -fn is_sorted_right(node: &Node) -> bool { - node.right.as_ref().map_or(true, |succ| succ.key > node.key) -} -fn is_interval_node(node: &Box>) -> bool { - let sorted = is_sorted_left(node) && is_sorted_right(node); - let balanced = node.height == cmp::max(height(&node.left),height(&node.right))+1; - let proper_max = node.max == cmp::max(subtree_max(&node.left), cmp::max(subtree_max(&node.right), node.key.end)); - sorted && balanced && proper_max -} - -pub fn is_interval_tree(root: &Option>>) -> bool { - (*root).as_ref().map_or(true, is_interval_node) -} - -#[test] -fn simple_tree_operations() { - let mut t = Box::new(Node::{key: RangeInclusive::new(3,3), data: vec![4], max:3, height: 2, - left: Some(Box::new(Node::{key: RangeInclusive::new(2,2), data: vec![5], height:1, max: 2, left: None, right: None})), - right: None}); - assert!(is_interval_node(&t)); - assert!( contains::(&RangeInclusive::new(3,3),&t) ); - assert!( contains::(&RangeInclusive::new(2,2),&t) ); - assert!( !contains::(&RangeInclusive::new(6,6),&t) ); - assert!( !contains::(&RangeInclusive::new(4,4),&t) ); - t = t.insert(RangeInclusive::new(4,4),7); - t = t.insert(RangeInclusive::new(5,5),7); - t = t.insert(RangeInclusive::new(6,6),8); - assert!( contains::(&RangeInclusive::new(4,4),&t) ); - assert!( contains::(&RangeInclusive::new(6,6),&t) ); - assert!( !contains::(&RangeInclusive::new(7,7),&t) ); -} - -#[test] -fn rotations_on_tree(){ - let mut t = Box::new(Node::{key: RangeInclusive::new(1,1), data: vec![1337], height: 1, max: 1, left: None, right: None}); - for i in 2..255 { - t = t.insert(RangeInclusive::new(i,i),1337); - assert!(is_interval_node(&t)); - } - //check that the tree is indeed balanced - assert!(height(&Some(t)) <= 8); -} - -#[test] -fn test_drop_min(){ - let mut t = simple_tree(3); - let (maybe_tree,min) = t.drop_min(); - t = maybe_tree.expect("failure to get tree for first min delete"); - assert!(is_interval_node(&t)); - assert!( min.key == RangeInclusive::new(1,1)); - assert!(!contains::(&RangeInclusive::new(1,1),&t)); - assert!( contains::(&RangeInclusive::new(2,2),&t)); - assert!( contains::(&RangeInclusive::new(3,3),&t)); - - let (maybe_tree,min) = t.drop_min(); - t = maybe_tree.expect("failure to get tree for second min delete"); - assert!(is_interval_node(&t)); - assert!( min.key == RangeInclusive::new(2,2)); - assert!(!contains::(&RangeInclusive::new(1,1),&t)); - assert!(!contains::(&RangeInclusive::new(2,2),&t)); - assert!( contains::(&RangeInclusive::new(3,3),&t)); - - let (maybe_tree,min) = t.drop_min(); - assert!( maybe_tree.is_none() ); - assert!( min.key == RangeInclusive::new(3,3)); -} - -#[test] -fn test_drop_root(){ - let mut t = simple_tree(3); - let maybe_tree = t.delete_root(); - t = maybe_tree.expect("failure to get tree for first root drop"); - assert!(is_interval_node(&t)); - assert!( t.height == 2); - assert!( contains::(&RangeInclusive::new(1,1),&t)); - assert!(!contains::(&RangeInclusive::new(2,2),&t)); - assert!( contains::(&RangeInclusive::new(3,3),&t)); - - let maybe_tree = t.delete_root(); - t = maybe_tree.expect("failure to get tree for second root drop"); - assert!(is_interval_node(&t)); - assert!( contains::(&RangeInclusive::new(1,1),&t)); - assert!(!contains::(&RangeInclusive::new(2,2),&t)); - assert!(!contains::(&RangeInclusive::new(3,3),&t)); - - let maybe_tree = t.delete_root(); - assert!( maybe_tree.is_none() ); -} - -#[test] -fn test_delete(){ - let mut t = simple_tree(10); - for i in 1..10 { - assert!(contains::(&RangeInclusive::new(i,i),&t)); - let maybe_tree = t.delete(RangeInclusive::new(i,i)); - t = maybe_tree.expect("failure to get tree for delete"); - assert!(!contains::(&RangeInclusive::new(i,i),&t)); - assert!(is_interval_node(&t)); - } - assert!(contains::(&RangeInclusive::new(10,10),&t)); - let maybe_tree = t.delete(RangeInclusive::new(10,10)); - assert!(maybe_tree.is_none()); -} - -#[test] -fn test_min_max() { - let t = simple_tree(50); - assert_eq!(min(&t),&[1337]); - assert_eq!(max(&t),&[1337+50-1]); - assert_eq!(t.max_pair().0,&RangeInclusive::new(50,50)); - assert_eq!(t.min_pair().0,&RangeInclusive::new(1,1)); -} - -#[test] -fn test_min_after(){ - let t = simple_tree(50); - for old_key in 0..55 { - println!("trying value: {}", old_key); - match min_after(&RangeInclusive::new(old_key,old_key),&t) { - Some((k,_d)) => assert_eq!(k, &(RangeInclusive::new(old_key+1,old_key+1))), - None => assert!(old_key >= 50) - } - } -} -} diff --git a/crates/interval-tree/src/tests.rs b/crates/interval-tree/src/tests.rs index 3018029e..02848c1d 100644 --- a/crates/interval-tree/src/tests.rs +++ b/crates/interval-tree/src/tests.rs @@ -1,148 +1,154 @@ +use crate::RangeInclusive; use std::cmp; use std::collections::BTreeSet; -use crate::RangeInclusive; type IntervalTree = crate::IntervalTree; #[test] -fn test_getters(){ +fn test_getters() { let data = 1337; let mut t = IntervalTree::::new(); - t.insert(RangeInclusive::new(1,1), data); - t.insert(RangeInclusive::new(2,2), data+1); - t.insert(RangeInclusive::new(3,3), data+2); - assert_eq!(t.get_or(RangeInclusive::new(1,1), &[0]), &[data]); - assert_eq!(t.get_or(RangeInclusive::new(2,2), &[0]), &[data+1]); - assert_eq!(t.get_or(RangeInclusive::new(3,3), &[0]), &[data+2]); - assert_eq!(t.get_or(RangeInclusive::new(4,4), &[0]), &[0]); - assert_eq!(t.get(RangeInclusive::new(4,4)), None); + t.insert(RangeInclusive::new(1, 1), data); + t.insert(RangeInclusive::new(2, 2), data + 1); + t.insert(RangeInclusive::new(3, 3), data + 2); + assert_eq!(t.get_or(RangeInclusive::new(1, 1), &[0]), &[data]); + assert_eq!(t.get_or(RangeInclusive::new(2, 2), &[0]), &[data + 1]); + assert_eq!(t.get_or(RangeInclusive::new(3, 3), &[0]), &[data + 2]); + assert_eq!(t.get_or(RangeInclusive::new(4, 4), &[0]), &[0]); + assert_eq!(t.get(RangeInclusive::new(4, 4)), None); } #[test] -fn test_contains(){ +fn test_contains() { let data = 1337; let mut t = IntervalTree::::new(); - t.insert(RangeInclusive::new(1,1), data); - t.insert(RangeInclusive::new(2,2), data+1); - t.insert(RangeInclusive::new(3,3), data+2); - assert!(!t.contains(RangeInclusive::new(0,0))); - assert!( t.contains(RangeInclusive::new(1,1))); - assert!( t.contains(RangeInclusive::new(2,2))); - assert!( t.contains(RangeInclusive::new(3,3))); - assert!(!t.contains(RangeInclusive::new(4,4))); + t.insert(RangeInclusive::new(1, 1), data); + t.insert(RangeInclusive::new(2, 2), data + 1); + t.insert(RangeInclusive::new(3, 3), data + 2); + assert!(!t.contains(RangeInclusive::new(0, 0))); + assert!(t.contains(RangeInclusive::new(1, 1))); + assert!(t.contains(RangeInclusive::new(2, 2))); + assert!(t.contains(RangeInclusive::new(3, 3))); + assert!(!t.contains(RangeInclusive::new(4, 4))); } #[test] -fn test_empty(){ +fn test_empty() { let data = 1337; let mut t = IntervalTree::::new(); assert!(t.is_empty()); - t.insert(RangeInclusive::new(1,1), data); - t.insert(RangeInclusive::new(2,2), data+1); - t.insert(RangeInclusive::new(3,3), data+2); + t.insert(RangeInclusive::new(1, 1), data); + t.insert(RangeInclusive::new(2, 2), data + 1); + t.insert(RangeInclusive::new(3, 3), data + 2); assert!(!t.is_empty()); } #[test] -fn test_remove(){ +fn test_remove() { let data = 1337; let mut t = IntervalTree::::new(); - t.insert(RangeInclusive::new(1,1), data); - t.insert(RangeInclusive::new(2,2), data+1); - t.insert(RangeInclusive::new(3,3), data+2); - t.remove(RangeInclusive::new(1,1)); - assert!(!t.contains(RangeInclusive::new(1,1))); - assert!( t.contains(RangeInclusive::new(2,2))); - assert!( t.contains(RangeInclusive::new(3,3))); - t.remove(RangeInclusive::new(2,2)); - assert!(!t.contains(RangeInclusive::new(1,1))); - assert!(!t.contains(RangeInclusive::new(2,2))); - assert!( t.contains(RangeInclusive::new(3,3))); - t.remove(RangeInclusive::new(3,3)); - assert!(!t.contains(RangeInclusive::new(1,1))); - assert!(!t.contains(RangeInclusive::new(2,2))); - assert!(!t.contains(RangeInclusive::new(3,3))); + t.insert(RangeInclusive::new(1, 1), data); + t.insert(RangeInclusive::new(2, 2), data + 1); + t.insert(RangeInclusive::new(3, 3), data + 2); + t.remove(RangeInclusive::new(1, 1)); + assert!(!t.contains(RangeInclusive::new(1, 1))); + assert!(t.contains(RangeInclusive::new(2, 2))); + assert!(t.contains(RangeInclusive::new(3, 3))); + t.remove(RangeInclusive::new(2, 2)); + assert!(!t.contains(RangeInclusive::new(1, 1))); + assert!(!t.contains(RangeInclusive::new(2, 2))); + assert!(t.contains(RangeInclusive::new(3, 3))); + t.remove(RangeInclusive::new(3, 3)); + assert!(!t.contains(RangeInclusive::new(1, 1))); + assert!(!t.contains(RangeInclusive::new(2, 2))); + assert!(!t.contains(RangeInclusive::new(3, 3))); assert!(t.is_empty()); } #[test] -fn test_min(){ +fn test_min() { let mut t = IntervalTree::::new(); - assert!{t.min().is_none()}; - t.insert(RangeInclusive::new(50,50), 1337); - assert_eq!{t.min().expect("get 1 min"),(&RangeInclusive::new(50,50),&[1337][..])}; - t.insert(RangeInclusive::new(49,49),1338); - assert_eq!{t.min().expect("get 2 min"),(&RangeInclusive::new(49,49),&[1338][..])}; - t.insert(RangeInclusive::new(47,47),1339); - assert_eq!{t.min().expect("get 3 min"),(&RangeInclusive::new(47,47),&[1339][..])}; - t.insert(RangeInclusive::new(48,48),1340); - assert_eq!{t.min().expect("get 4 min"),(&RangeInclusive::new(47,47),&[1339][..])}; + assert! {t.min().is_none()}; + t.insert(RangeInclusive::new(50, 50), 1337); + assert_eq! {t.min().expect("get 1 min"),(&RangeInclusive::new(50,50),&[1337][..])}; + t.insert(RangeInclusive::new(49, 49), 1338); + assert_eq! {t.min().expect("get 2 min"),(&RangeInclusive::new(49,49),&[1338][..])}; + t.insert(RangeInclusive::new(47, 47), 1339); + assert_eq! {t.min().expect("get 3 min"),(&RangeInclusive::new(47,47),&[1339][..])}; + t.insert(RangeInclusive::new(48, 48), 1340); + assert_eq! {t.min().expect("get 4 min"),(&RangeInclusive::new(47,47),&[1339][..])}; } #[test] -fn test_iter(){ +fn test_iter() { let mut t = IntervalTree::::new(); - t.insert(RangeInclusive::new(32,32),1337); - t.insert(RangeInclusive::new(34,34),1338); - t.insert(RangeInclusive::new(36,36),1339); - t.insert(RangeInclusive::new(38,38),1340); - for (i,pair) in t.iter().enumerate() { - let (k,v) = pair; - println!("{:?}, {}",k,v); - let key = (i as u64)*2 +32; - assert_eq!(k,RangeInclusive::new(key,key)); - assert_eq!(v,&((i as i32)+1337)); + t.insert(RangeInclusive::new(32, 32), 1337); + t.insert(RangeInclusive::new(34, 34), 1338); + t.insert(RangeInclusive::new(36, 36), 1339); + t.insert(RangeInclusive::new(38, 38), 1340); + for (i, pair) in t.iter().enumerate() { + let (k, v) = pair; + println!("{:?}, {}", k, v); + let key = (i as u64) * 2 + 32; + assert_eq!(k, RangeInclusive::new(key, key)); + assert_eq!(v, &((i as i32) + 1337)); } - } #[test] -fn test_range_iter(){ +fn test_range_iter() { let mut t = IntervalTree::::new(); - t.insert(RangeInclusive::new(32,32),1337); - t.insert(RangeInclusive::new(34,34),1338); - t.insert(RangeInclusive::new(36,36),1339); - t.insert(RangeInclusive::new(38,38),1340); - for (i,pair) in t.range(RangeInclusive::new(34, 36)).enumerate() { - let (k,v) = pair; - println!("{:?}, {}",k,v); - let key = (i as u64)*2 +34; - assert_eq!(k,RangeInclusive::new(key,key)); - assert_eq!(v,&((i as i32)+1338)); - assert!(i<2); + t.insert(RangeInclusive::new(32, 32), 1337); + t.insert(RangeInclusive::new(34, 34), 1338); + t.insert(RangeInclusive::new(36, 36), 1339); + t.insert(RangeInclusive::new(38, 38), 1340); + for (i, pair) in t.range(RangeInclusive::new(34, 36)).enumerate() { + let (k, v) = pair; + println!("{:?}, {}", k, v); + let key = (i as u64) * 2 + 34; + assert_eq!(k, RangeInclusive::new(key, key)); + assert_eq!(v, &((i as i32) + 1338)); + assert!(i < 2); } - } #[test] -fn test_range_iter_non_pointwise(){ +fn test_range_iter_non_pointwise() { let mut t = IntervalTree::::new(); - t.insert(RangeInclusive::new(3,8),1337); - t.insert(RangeInclusive::new(6,10),1338); - t.insert(RangeInclusive::new(12,36),1339); - t.insert(RangeInclusive::new(32,40),1340); - assert_eq!(t.range(RangeInclusive::new(9,14)).map(|(k,_)| k.start).collect::>(), vec![6,12]) + t.insert(RangeInclusive::new(3, 8), 1337); + t.insert(RangeInclusive::new(6, 10), 1338); + t.insert(RangeInclusive::new(12, 36), 1339); + t.insert(RangeInclusive::new(32, 40), 1340); + assert_eq!( + t.range(RangeInclusive::new(9, 14)) + .map(|(k, _)| k.start) + .collect::>(), + vec![6, 12] + ) } fn random_range() -> RangeInclusive { let offset = rand::random::(); let len: u64 = if rand::random::() { - cmp::min(rand::random::()%500, 0xff_ff_ff_ff_ff_ff_ff_ff - offset) + cmp::min( + rand::random::() % 500, + 0xff_ff_ff_ff_ff_ff_ff_ff - offset, + ) } else { - rand::random::()%(0xff_ff_ff_ff_ff_ff_ff_ff - offset) + rand::random::() % (0xff_ff_ff_ff_ff_ff_ff_ff - offset) }; - RangeInclusive::new(offset, offset+len) + RangeInclusive::new(offset, offset + len) } #[test] -fn test_range_iter_nontrivial(){ +fn test_range_iter_nontrivial() { let mut set = BTreeSet::>::new(); let mut t = IntervalTree::::new(); for _ in 1..5000 { let decision = rand::random::(); let range = random_range(); - if decision { + if decision { set.insert(range); t.insert(range, 1337); assert!(t.contains(range)); @@ -153,9 +159,16 @@ fn test_range_iter_nontrivial(){ assert!(!t.contains(range)); //assert!(t.test_theban_interval_tree()); }; - let query = random_range(); - let should = set.iter().filter(|r| crate::range::intersect(&query, r)).copied().collect::>>(); - let is = t.range(query).map(|(r,_)| r).collect::>>(); - assert_eq!(should, is); - }; + let query = random_range(); + let should = set + .iter() + .filter(|r| crate::range::intersect(&query, r)) + .copied() + .collect::>>(); + let is = t + .range(query) + .map(|(r, _)| r) + .collect::>>(); + assert_eq!(should, is); + } } diff --git a/crates/interval-tree/src/tree.rs b/crates/interval-tree/src/tree.rs index 9d707dea..9e7e30b8 100644 --- a/crates/interval-tree/src/tree.rs +++ b/crates/interval-tree/src/tree.rs @@ -16,60 +16,62 @@ impl Default for IntervalTree { } impl IntervalTree { -/// This function will construct a new empty IntervalTree. -/// # Examples -/// ``` -/// extern crate interval_tree; -/// let mut t=interval_tree::IntervalTree::::new(); -/// ``` + /// This function will construct a new empty IntervalTree. + /// # Examples + /// ``` + /// extern crate interval_tree; + /// let mut t=interval_tree::IntervalTree::::new(); + /// ``` pub fn new() -> Self { IntervalTree { root: None } } -/// This function will return true if the tree is empty, false otherwise. -/// # Examples -/// ``` -/// extern crate interval_tree; -/// -/// let mut t=interval_tree::IntervalTree::::new(); -/// assert!(t.is_empty()); -/// t.insert(interval_tree::range(2,2),25); -/// assert!(!t.is_empty()); -/// -/// ``` - pub fn is_empty(&self) -> bool { self.root.is_none() } + /// This function will return true if the tree is empty, false otherwise. + /// # Examples + /// ``` + /// extern crate interval_tree; + /// + /// let mut t=interval_tree::IntervalTree::::new(); + /// assert!(t.is_empty()); + /// t.insert(interval_tree::range(2,2),25); + /// assert!(!t.is_empty()); + /// + /// ``` + pub fn is_empty(&self) -> bool { + self.root.is_none() + } -/// This function will return the hieght of the tree. An empty tree hash height 0, one with only -/// one elemente has height 1 etc. -/// # Examples -/// ``` -/// extern crate interval_tree; -/// -/// let mut t=interval_tree::IntervalTree::::new(); -/// assert_eq!(t.height(), 0); -/// t.insert(interval_tree::range(2,2),3); -/// assert_eq!(t.height(), 1); -/// -/// ``` + /// This function will return the hieght of the tree. An empty tree hash height 0, one with only + /// one elemente has height 1 etc. + /// # Examples + /// ``` + /// extern crate interval_tree; + /// + /// let mut t=interval_tree::IntervalTree::::new(); + /// assert_eq!(t.height(), 0); + /// t.insert(interval_tree::range(2,2),3); + /// assert_eq!(t.height(), 1); + /// + /// ``` pub fn height(&self) -> usize { height(&self.root) as usize } } impl IntervalTree { -/// This function will insert the key,value pair into the tree, appending to -/// the old data if the key is already part of the tree. -/// -/// # Examples -/// ``` -/// extern crate interval_tree; -/// -/// let mut t=interval_tree::IntervalTree::::new(); -/// t.insert(interval_tree::range(2,2),25); -/// assert_eq!(t.get(interval_tree::range(2,2)), Some(&[25][..])); -/// t.insert(interval_tree::range(2,2),30); -/// assert_eq!(t.get(interval_tree::range(2,2)), Some(&[25, 30][..])); -/// ``` + /// This function will insert the key,value pair into the tree, appending to + /// the old data if the key is already part of the tree. + /// + /// # Examples + /// ``` + /// extern crate interval_tree; + /// + /// let mut t=interval_tree::IntervalTree::::new(); + /// t.insert(interval_tree::range(2,2),25); + /// assert_eq!(t.get(interval_tree::range(2,2)), Some(&[25][..])); + /// t.insert(interval_tree::range(2,2),30); + /// assert_eq!(t.get(interval_tree::range(2,2)), Some(&[25, 30][..])); + /// ``` pub fn insert(&mut self, key: RangeInclusive, data: V) { self.root = Some(match self.root.take() { Some(box_to_node) => box_to_node.insert(key, data), @@ -77,111 +79,111 @@ impl IntervalTree { }); } -/// This function will remove the key,value pair from the tree, doing nothing if the key is not -/// part of the tree. -/// # Examples -/// ``` -/// extern crate interval_tree; -/// -/// let mut t=interval_tree::IntervalTree::::new(); -/// t.insert(interval_tree::range(2,2),25); -/// t.remove(interval_tree::range(2,2)); -/// assert!(t.is_empty()); -/// // deleting nonexistant keys doesn't do anything -/// t.remove(interval_tree::range(3,3)); -/// assert!(t.is_empty()); -/// ``` + /// This function will remove the key,value pair from the tree, doing nothing if the key is not + /// part of the tree. + /// # Examples + /// ``` + /// extern crate interval_tree; + /// + /// let mut t=interval_tree::IntervalTree::::new(); + /// t.insert(interval_tree::range(2,2),25); + /// t.remove(interval_tree::range(2,2)); + /// assert!(t.is_empty()); + /// // deleting nonexistant keys doesn't do anything + /// t.remove(interval_tree::range(3,3)); + /// assert!(t.is_empty()); + /// ``` pub fn remove(&mut self, key: RangeInclusive) { if let Some(box_to_node) = self.root.take() { self.root = box_to_node.delete(key); } } -/// This function will return the Some(data) stored under the given key or None if the key is not -/// known. -/// # Examples -/// ``` -/// extern crate interval_tree; -/// -/// let mut t=interval_tree::IntervalTree::::new(); -/// t.insert(interval_tree::range(2,2),25); -/// assert_eq!(t.get(interval_tree::range(2,2)), Some(&[25][..])); -/// assert_eq!(t.get(interval_tree::range(3,3)), None); -/// -/// ``` + /// This function will return the Some(data) stored under the given key or None if the key is not + /// known. + /// # Examples + /// ``` + /// extern crate interval_tree; + /// + /// let mut t=interval_tree::IntervalTree::::new(); + /// t.insert(interval_tree::range(2,2),25); + /// assert_eq!(t.get(interval_tree::range(2,2)), Some(&[25][..])); + /// assert_eq!(t.get(interval_tree::range(3,3)), None); + /// + /// ``` pub fn get(&self, key: RangeInclusive) -> Option<&[V]> { match self.root { Some(ref box_to_node) => box_to_node.search(&key), - None => None + None => None, } } -/// This function will return the data stored under the given key or the default if the key is not -/// known. -/// # Examples -/// ``` -/// extern crate interval_tree; -/// -/// let mut t=interval_tree::IntervalTree::::new(); -/// t.insert(interval_tree::range(2,2),25); -/// assert_eq!(t.get_or(interval_tree::range(2,2),&[2000]), &[25]); -/// assert_eq!(t.get_or(interval_tree::range(3,3),&[2000]), &[2000]); -/// -/// ``` + /// This function will return the data stored under the given key or the default if the key is not + /// known. + /// # Examples + /// ``` + /// extern crate interval_tree; + /// + /// let mut t=interval_tree::IntervalTree::::new(); + /// t.insert(interval_tree::range(2,2),25); + /// assert_eq!(t.get_or(interval_tree::range(2,2),&[2000]), &[25]); + /// assert_eq!(t.get_or(interval_tree::range(3,3),&[2000]), &[2000]); + /// + /// ``` pub fn get_or<'a>(&'a self, key: RangeInclusive, default: &'a [V]) -> &'a [V] { self.get(key).unwrap_or(default) } -/// This function will return true if the tree contains the given key, false otherwise -/// # Examples -/// ``` -/// extern crate interval_tree; -/// -/// let mut t=interval_tree::IntervalTree::::new(); -/// t.insert(interval_tree::range(2,2),25); -/// assert!(!t.contains(interval_tree::range(3,3))); -/// assert!(t.contains(interval_tree::range(2,2))); -/// -/// ``` + /// This function will return true if the tree contains the given key, false otherwise + /// # Examples + /// ``` + /// extern crate interval_tree; + /// + /// let mut t=interval_tree::IntervalTree::::new(); + /// t.insert(interval_tree::range(2,2),25); + /// assert!(!t.contains(interval_tree::range(3,3))); + /// assert!(t.contains(interval_tree::range(2,2))); + /// + /// ``` pub fn contains(&self, key: RangeInclusive) -> bool { self.get(key).is_some() } -/// This function will return the key/value pair with the smallest key in the tree, or None if the -/// tree is empty. -/// # Examples -/// ``` -/// extern crate interval_tree; -/// -/// let mut t=interval_tree::IntervalTree::::new(); -/// t.insert(interval_tree::range(2,2),25); -/// t.insert(interval_tree::range(3,3),50); -/// assert_eq!(t.min().unwrap().0, &interval_tree::range(2,2)); -/// assert_eq!(t.min().unwrap().1, &[25]); -/// -/// ``` + /// This function will return the key/value pair with the smallest key in the tree, or None if the + /// tree is empty. + /// # Examples + /// ``` + /// extern crate interval_tree; + /// + /// let mut t=interval_tree::IntervalTree::::new(); + /// t.insert(interval_tree::range(2,2),25); + /// t.insert(interval_tree::range(3,3),50); + /// assert_eq!(t.min().unwrap().0, &interval_tree::range(2,2)); + /// assert_eq!(t.min().unwrap().1, &[25]); + /// + /// ``` pub fn min(&self) -> Option<(&'_ RangeInclusive, &'_ [V])> { self.root.as_ref().map(|n| n.min_pair()) } -/// This function will return the key/value pair with the biggest key in the tree, or None if the -/// tree is empty. -/// # Examples -/// ``` -/// extern crate interval_tree; -/// -/// let mut t=interval_tree::IntervalTree::::new(); -/// t.insert(interval_tree::range(2,2),25); -/// t.insert(interval_tree::range(3,3),50); -/// assert_eq!(t.max().unwrap().0, &interval_tree::range(3,3)); -/// assert_eq!(t.max().unwrap().1, &[50]); -/// -/// ``` + /// This function will return the key/value pair with the biggest key in the tree, or None if the + /// tree is empty. + /// # Examples + /// ``` + /// extern crate interval_tree; + /// + /// let mut t=interval_tree::IntervalTree::::new(); + /// t.insert(interval_tree::range(2,2),25); + /// t.insert(interval_tree::range(3,3),50); + /// assert_eq!(t.max().unwrap().0, &interval_tree::range(3,3)); + /// assert_eq!(t.max().unwrap().1, &[50]); + /// + /// ``` pub fn max(&self) -> Option<(&'_ RangeInclusive, &'_ [V])> { self.root.as_ref().map(|n| n.max_pair()) } -/// Merge all (key, value) pairs from another tree into this one, consuming it. + /// Merge all (key, value) pairs from another tree into this one, consuming it. pub fn merge(&mut self, other: IntervalTree) { for (k, v) in other.into_iter() { self.insert(k, v); @@ -201,30 +203,34 @@ impl IntoIterator for IntervalTree { } impl IntervalTree { -/// This function will return a read only iterator for all (key,value) pairs between the two -/// bounds. -/// # Examples -/// ``` -/// //[...] -/// # let mut t=interval_tree::IntervalTree::::new(); -/// for (key,val) in t.range(interval_tree::range(9, 100)) { -/// println!("{:?} -> {}",key,val) -/// } -/// -/// ``` + /// This function will return a read only iterator for all (key,value) pairs between the two + /// bounds. + /// # Examples + /// ``` + /// //[...] + /// # let mut t=interval_tree::IntervalTree::::new(); + /// for (key,val) in t.range(interval_tree::range(9, 100)) { + /// println!("{:?} -> {}",key,val) + /// } + /// + /// ``` pub fn range(&self, range: RangeInclusive) -> RangePairIter { - RangePairIter::new(self, Bound::Included(range.start), Bound::Included(range.end)) + RangePairIter::new( + self, + Bound::Included(range.start), + Bound::Included(range.end), + ) } -/// This function will return a read only iterator for all (key,value) pairs in the tree. -/// # Examples -/// ``` -/// # let mut t=interval_tree::IntervalTree::::new(); -/// for (key,val) in t.iter() { -/// println!("{:?} -> {}",key,val) -/// } -/// -/// ``` + /// This function will return a read only iterator for all (key,value) pairs in the tree. + /// # Examples + /// ``` + /// # let mut t=interval_tree::IntervalTree::::new(); + /// for (key,val) in t.iter() { + /// println!("{:?} -> {}",key,val) + /// } + /// + /// ``` pub fn iter(&self) -> RangePairIter { RangePairIter::new(self, Bound::Unbounded, Bound::Unbounded) } @@ -233,24 +239,24 @@ impl IntervalTree { #[cfg(test)] mod tests { extern crate rand; - use crate::range::RangeInclusive; use crate::node::tests::is_interval_tree; + use crate::range::RangeInclusive; type IntervalTree = super::IntervalTree; fn random_range() -> RangeInclusive { - let offset = rand::random::()%50; - let len: u64 = rand::random::()%50; - crate::range(offset, offset+len) + let offset = rand::random::() % 50; + let len: u64 = rand::random::() % 50; + crate::range(offset, offset + len) } #[test] - fn test_fuzz(){ + fn test_fuzz() { let mut t = IntervalTree::::new(); for _ in 1..5000 { let decision = rand::random::(); let range = random_range(); - if decision { + if decision { t.insert(range, 1337); assert!(t.contains(range)); assert!(is_interval_tree(&t.root)); @@ -259,6 +265,6 @@ mod tests { assert!(!t.contains(range)); assert!(is_interval_tree(&t.root)); }; - }; + } } } From a97f9b47bb1d1d740a0f70a7f37409879cafd1ef Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Tue, 28 May 2024 23:50:12 -0700 Subject: [PATCH 095/197] rustfmt: Add some #[rustfmt::skip]s for later --- crates/dm-langserver/src/completion.rs | 1 + crates/dreammaker/src/lexer.rs | 3 ++- crates/dreammaker/src/preprocessor.rs | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/dm-langserver/src/completion.rs b/crates/dm-langserver/src/completion.rs index 9812ec50..74a885e4 100644 --- a/crates/dm-langserver/src/completion.rs +++ b/crates/dm-langserver/src/completion.rs @@ -13,6 +13,7 @@ use crate::{is_constructor_name, Engine, Span}; use ahash::RandomState; +#[rustfmt::skip] static PROC_KEYWORDS: &[&str] = &[ // Implicit variables "args", diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index 6a7f8991..cf93b541 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -147,6 +147,7 @@ impl fmt::Display for Punctuation { /// This lookup table is used to keep `read_punct`, called for essentially each /// character in the input, blazing fast. The code to generate it is contained /// in the following test. +#[rustfmt::skip] static SPEEDY_TABLE: [(usize, usize); 127] = [ (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 1), (1, 2), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), @@ -164,7 +165,7 @@ static SPEEDY_TABLE: [(usize, usize); 127] = [ (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (59, 61), (61, 65), (65, 66), (66, 69), - ]; +]; #[test] fn make_speedy_table() { diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index 86565a5b..f52fdc2e 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -722,6 +722,7 @@ impl<'ctx> Preprocessor<'ctx> { } } + #[rustfmt::skip] const ALL_DIRECTIVES: &[&str] = &[ "if", "ifdef", "ifndef", "elif", "else", "endif", "include", "define", "undef", "warn", "error", "pragma", From 5f5236f379ecf9703c4962610829e50fdb1c308d Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 1 Jun 2024 11:52:43 -0700 Subject: [PATCH 096/197] Improve formatting of dreamchecker error tests --- crates/dreamchecker/src/test_helpers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/dreamchecker/src/test_helpers.rs b/crates/dreamchecker/src/test_helpers.rs index b02b68ba..0252c57d 100644 --- a/crates/dreamchecker/src/test_helpers.rs +++ b/crates/dreamchecker/src/test_helpers.rs @@ -32,7 +32,7 @@ pub fn check_errors_match>>(buffer: S, errorlist: &[(u || nexterror.description() != *desc { panic!( - "possible feature regression in dreamchecker, expected {}:{}:{}, found {}:{}:{}", + "possible feature regression in dreamchecker:\nexpected error: {}:{}:{}\nfound error: {}:{}:{}", *line, *column, *desc, From e47fb7c91cb767d6a48fdac6f3d095bbb0c400b9 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 1 Jun 2024 13:49:13 -0700 Subject: [PATCH 097/197] Rewrite parser from next/put_back to peek/take Fixes recent bugs in error message generation. Removes the need to track whether next() has been called multiple times in a row for the purpose of ignoring out-of-place doc comments. --- crates/dreammaker/src/parser.rs | 450 +++++++++++++++----------------- 1 file changed, 216 insertions(+), 234 deletions(-) diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index c895a999..8c8acf7d 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -27,6 +27,11 @@ fn success(t: T) -> Status { Ok(Some(t)) } +#[inline] +fn try_another() -> Status { + Ok(None) +} + const SUCCESS: Status<()> = Ok(Some(())); macro_rules! require { @@ -40,11 +45,48 @@ macro_rules! leading { ($e:expr) => { match $e? { Some(x) => x, - None => return Ok(None), + None => return try_another(), } }; } +macro_rules! take_match { + ( + $self:ident { + $( + $($p:pat)|* $( if $condition:expr )? => $branch:expr, + )* + } + // else mandatory because you should never be matching on every option + else $else:expr + ) => { + // Both $p introduce bindings. The first set are by-ref, the second set + // are by-move. It'd be nice to warn if *both* were unused, but warning + // when just one is unused is too much, so don't warn. + { + #[allow(unused_variables)] + match $self.peek() { + $( + $($p)|* $( if $condition )? => { + // inner match that moves instead of refs + match $self.take() { + // no duplicate `if` because types are different + $($p)|* => { + #[warn(unused_variables)] + $branch + } + // might be unreachable because of missing `if` + #[allow(unreachable_patterns)] + _ => panic!("take_match inner match failed somehow"), + } + } + )* + _ => $else + } + } + } +} + // ---------------------------------------------------------------------------- // Convenience functions @@ -298,7 +340,6 @@ pub struct Parser<'ctx, 'an, 'inp> { expected: Vec>, doc_comments_pending: VecDeque<(Location, DocComment)>, - doc_comments_on_notice: bool, module_docs: BTreeMap>, procs: bool, @@ -329,7 +370,6 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { expected: Vec::new(), doc_comments_pending: Default::default(), - doc_comments_on_notice: false, module_docs: Default::default(), procs: false, @@ -412,24 +452,17 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { if self.eof { return self.error(format!("got EOF, expected one of: {}", expected)); } - match self.next_quiet() { - Ok(got) => { - let message = format!("got '{:#}', expected one of: {}", got, expected); - self.put_back(got); - let mut e = self.error(message); - if self.possible_indentation_error { - let mut loc = e.location(); - loc.line += 1; - loc.column = 1; - e.add_note(loc, "check for extra indentation at the start of the next line"); - self.possible_indentation_error = false; - } - e - } - Err(err) => self - .error(format!("i/o error, expected one of: {}", expected)) - .with_cause(err), + let got = self.peek(); + let message = format!("got '{:#}', expected one of: {}", got, expected); + let mut error = self.error(message); + if self.possible_indentation_error { + let mut loc = error.location(); + loc.line += 1; + loc.column = 1; + error.add_note(loc, "check for extra indentation at the start of the next line"); + self.possible_indentation_error = false; } + error } fn parse_error(&mut self) -> Result { @@ -445,59 +478,48 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } /// Push an alternative to the "got X, expected one of: ..." list. - fn expected(&mut self, expected: Cow<'static, str>) { + fn expected(&mut self, expected: impl Into>) { + let expected = expected.into(); if !expected.is_empty() && !self.expected.contains(&expected) { self.expected.push(expected); } } - /// Get the next token and push something to the "expected" list. - fn next>>(&mut self, expected: S) -> Result { - self.expected(expected.into()); - self.next_quiet() - } - - /// Get the next token without pushing anything to the "expected" list. - fn next_quiet(&mut self) -> Result { + /// Peek next token without consuming it, and update location. + fn peek(&mut self) -> &Token { loop { - if let Some(next) = self.next.take() { - self.doc_comments_on_notice = false; - return Ok(next); + if let Some(ref next) = self.next { + break next; } match self.input.next() { - // To allow comments that look like doc comments in arbitrary - // positions, buffer them until they are specifically read, - // or drop them if we've read TWO non-doc tokens, meaning the - // first non-doc token can no longer be put_back. Some(LocatedToken { location, token: Token::DocComment(comment) }) => { self.doc_comments_pending.push_back((location, comment)); - self.doc_comments_on_notice = false; } - Some(token) => { - self.expected.clear(); - self.location = token.location; - if self.doc_comments_on_notice { - // This is where we would diagnose "doc comment has no - // effect", but it would probably be more annoying than - // useful. - self.doc_comments_pending.clear(); - } else if !self.doc_comments_pending.is_empty() { - self.doc_comments_on_notice = true; - } - return Ok(token.token); + Some(LocatedToken { location, token }) => { + self.location = location; + self.next = Some(token); } None => { if !self.eof { self.eof = true; - return Ok(Token::Eof); + self.next = Some(Token::Eof); } else { - return self.parse_error(); + panic!("internal parser error: kept parsing after EOF"); } } } } } + /// Consume next token unconditionally. Cannot be undone. Try `take_match!` instead. + fn take(&mut self) -> Token { + self.peek(); // Always populates self.next, so .take().unwrap() is OK + //assert_ne!(self.peek(), &Token::Eof, "internal parser error: EOF token was consumed"); + self.doc_comments_pending.clear(); + self.expected.clear(); + self.next.take().unwrap() + } + fn next_comment_of_target(&mut self, target: DocTarget) -> Status { loop { if let Some((location, comment)) = self.doc_comments_pending.pop_front() { @@ -534,17 +556,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } } - fn put_back(&mut self, tok: Token) { - if self.next.is_some() { - panic!("cannot put_back twice") - } - self.next = Some(tok); - } - fn updated_location(&mut self) -> Location { - if let Ok(token) = self.next_quiet() { - self.put_back(token); - } + self.peek(); self.location } @@ -560,69 +573,56 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } } - fn try_another(&mut self, tok: Token) -> Status { - self.put_back(tok); - Ok(None) - } - fn exact(&mut self, tok: Token) -> Status<()> { - let message: Cow<'static, str> = match tok { - Token::Eof => "EOF".into(), - Token::Punct(p) => p.single_quoted().into(), - ref other => format!("'{}'", other).into(), - }; - let next = self.next(message)?; - if next == tok { + match tok { + Token::Eof => self.expected("EOF"), + Token::Punct(p) => self.expected(p.single_quoted()), + ref other => self.expected(format!("'{}'", other)), + } + if self.peek() == &tok { + self.take(); SUCCESS } else { - self.try_another(next) + try_another() } } fn ident(&mut self) -> Status { - match self.next("identifier")? { - Token::Ident(i, _) => Ok(Some(i)), - other => self.try_another(other), - } - } - - fn dot(&mut self) -> Status<()> { - match self.next("'.'")? { - Token::Punct(Punctuation::Dot) => Ok(Some(())), - other => self.try_another(other), - } + self.expected("identifier"); + take_match!(self { + Token::Ident(i, _) => success(i), + } else try_another()) } fn ident_in_seq(&mut self, idx: usize) -> Status { let start = self.updated_location(); - match self.next("identifier")? { + take_match!(self { Token::Ident(i, _) => { self.annotate(start, || Annotation::InSequence(idx)); - Ok(Some(i)) + success(i) }, - other => self.try_another(other), - } + } else try_another()) } fn exact_ident(&mut self, ident: &'static str) -> Status<()> { - match self.next(ident)? { - Token::Ident(ref i, _) if i == ident => SUCCESS, - other => self.try_another(other), - } + self.expected(format!("'{}'", ident)); + take_match!(self { + Token::Ident(i, _) if i == ident => SUCCESS, + } else try_another()) } // ------------------------------------------------------------------------ // Doc comment tracking fn following_doc_comment(&mut self) -> Status { - self.expected("'///'".into()); - self.expected("'/**'".into()); + //self.expected("'///'"); + //self.expected("'/**'"); self.next_comment_of_target(DocTarget::FollowingItem) } fn enclosing_doc_comment(&mut self) -> Status { - self.expected("'//!'".into()); - self.expected("'/*!'".into()); + //self.expected("'//!'"); + //self.expected("'/*!'"); self.next_comment_of_target(DocTarget::EnclosingItem) } @@ -635,14 +635,14 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { fn tree_entries(&mut self, current: NodeIndex, proc_builder: Option, var_type: Option, terminator: Token) -> Status<()> { loop { - self.expected("newline".into()); + self.expected("';'"); if terminator != Token::Eof { - self.expected(format!("'{terminator}'").into()); + self.expected(format!("'{terminator}'")); } if current == self.tree.root_index() { - self.expected("'//!'".into()); - self.expected("'/*!'".into()); + self.expected("'//!'"); + self.expected("'/*!'"); if let Some(module_comment) = self.enclosing_doc_comment()? { // If we're not inside a type, this is where module `//!` comments appear. self.module_docs @@ -653,15 +653,13 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } } - let next = self.next_quiet()?; - if next == terminator || next == Token::Eof { - break; - } else if next == Token::Punct(Punctuation::Semicolon) { - self.doc_comments_on_notice = false; - continue; - } - self.put_back(next); - require!(self.tree_entry(current, proc_builder, var_type.clone())); + take_match!(self { + Token::Eof => break, + tok if tok == &terminator => break, + Token::Punct(Punctuation::Semicolon) => continue, + } else { + require!(self.tree_entry(current, proc_builder, var_type.clone())); + }); } SUCCESS } @@ -709,8 +707,12 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { success((absolute, parts)) } + /// Look for nothing, silently accept `/`, and complain but continue if we see a `.` or `:`. + /// + /// Return: `(absolute, spurious_lead)` fn possible_leading_slash(&mut self) -> Result<(bool, bool), DMError> { - match self.next("'/'")? { + self.expected("'/'"); + take_match!(self { Token::Punct(Punctuation::Slash) => Ok((true, false)), Token::Punct(p @ Punctuation::Dot) | Token::Punct(p @ Punctuation::CloseColon) | @@ -719,17 +721,14 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { .set_severity(Severity::Warning) .register(self.context); Ok((false, true)) - } - t => { - self.put_back(t); - Ok((false, false)) - } - } + }, + } else Ok((false, false))) } - // Look for a `/`, and complain but continue if we see a `.` or `:`. + /// Look for a `/`, and complain but continue if we see a `.` or `:`. fn slash(&mut self) -> Status<()> { - match self.next("'/'")? { + self.expected("'/'"); + take_match!(self { Token::Punct(Punctuation::Slash) => SUCCESS, Token::Punct(p @ Punctuation::Dot) | Token::Punct(p @ Punctuation::CloseColon) | @@ -738,9 +737,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { .set_severity(Severity::Warning) .register(self.context); SUCCESS - } - t => { self.put_back(t); Ok(None) } - } + }, + } else try_another()) } fn tree_entry(&mut self, mut current: NodeIndex, mut proc_builder: Option, mut var_type: Option) -> Status<()> { @@ -849,11 +847,12 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } // read the contents for real - self.expected("'='".into()); - self.expected("'('".into()); - self.expected("'{'".into()); - match self.next_quiet()? { + self.expected("'='"); + self.expected("'('"); + self.expected("'{'"); + match self.peek() { Punct(LBrace) => { + self.take(); // `thing{` - block traverse_tree!(last_part); handle_relative_type_error!(); @@ -878,6 +877,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { SUCCESS } Punct(Assign) => { + self.take(); // `something=` - var handle_relative_type_error!(); let location = self.location; @@ -906,15 +906,13 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { SUCCESS } - t @ Punct(LParen) => { + Punct(LParen) => { // `something(` - proc - self.put_back(t); require!(self.proc_params_and_body(current, proc_builder, last_part, entry_start, absolute, docs)); SUCCESS } - other => { + _ => { // usually `thing;` - a contentless declaration - self.put_back(other); if var_type.is_some() { let _ = require!(self.input_specifier()); // TODO: save to VarType instead of ignoring @@ -1261,24 +1259,27 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } // While loop over self.next, extracting either the first string with from_name OR // if the first string is a slash, continue to extract, and check for a slash again, and finish with from_vec - let return_result: Result = self.next("return type"); - let next_token = return_result?; - if let Token::Ident(text, _) = next_token { - let Some(return_type) = AsType::from_name(text.as_str()) else { - return Err(self.error("Invalid return type")); - }; - return Ok(Some(return_type)); - } - if Token::Punct(Punctuation::Slash) != next_token { - self.put_back(next_token); + self.expected("identifier"); + self.expected("'/'"); + take_match!(self { + Token::Ident(text, _) => { + let Some(return_type) = AsType::from_name(text.as_str()) else { + return Err(self.error("Invalid return type")); + }; + return Ok(Some(return_type)); + }, + Token::Punct(Punctuation::Slash) => {}, + } else { return Err(self.error("Invalid return type")); - } + }); + // We're pulling out just the text, and we go until the end of the text or until we hit something unexpected let mut path_vec = vec![]; let mut slash_last = true; loop { - let path_component = self.next("return type")?; - match path_component { + self.expected("identifier"); + self.expected("'/'"); + take_match!(self { Token::Ident(text, whitespace) if slash_last => { path_vec.push(text); slash_last = false; @@ -1287,12 +1288,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } }, Token::Punct(Punctuation::Slash) if !slash_last => slash_last = true, - _ => { - // If we're done, put back what we just fond so someone else can process it, in case they care - self.put_back(path_component); - break; - }, - } + // If we're done, put back what we just fond so someone else can process it, in case they care + } else break); } if !path_vec.is_empty() { Ok(Some(AsType::from_vec(path_vec))) @@ -1630,21 +1627,22 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } } - // Handle if(1){a=1;b=2} without a trailing semicolon fn statement_terminator(&mut self) -> Status<()> { - match self.next("newline")? { - Token::Punct(Punctuation::Semicolon) => SUCCESS, - p @ Token::Punct(Punctuation::RBrace) => { - self.put_back(p); + self.expected("';'"); + match self.peek() { + Token::Punct(Punctuation::Semicolon) => { + self.take(); SUCCESS - } - p @ Token::Punct(Punctuation::LBrace) => { + }, + // Handle if(1){a=1;b=2} without a trailing semicolon + Token::Punct(Punctuation::RBrace) => { + SUCCESS + }, + Token::Punct(Punctuation::LBrace) => { self.possible_indentation_error = true; - self.try_another(p) - } - other => { - self.try_another(other) - } + try_another() + }, + _ => try_another() } } @@ -1814,12 +1812,11 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // Expressions fn path_separator(&mut self) -> Status { - success(match self.next("path separator")? { - Token::Punct(Punctuation::Slash) => PathOp::Slash, - Token::Punct(Punctuation::Dot) => PathOp::Dot, - Token::Punct(Punctuation::CloseColon) => PathOp::Colon, - other => return self.try_another(other), - }) + take_match!(self { + Token::Punct(Punctuation::Slash) => success(PathOp::Slash), + Token::Punct(Punctuation::Dot) => success(PathOp::Dot), + Token::Punct(Punctuation::CloseColon) => success(PathOp::Colon), + } else try_another()) } // distinct from a tree_path, path must begin with a path separator and can @@ -1892,23 +1889,21 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let mut expr = leading!(self.group(in_ternary)); loop { // try to read the next operator - let next = self.next("operator")?; - let &info = match BINARY_OPS.iter().find(|op| op.matches(&next)) { - Some(info) => info, - None => { - self.put_back(next); - break; - } + self.expected("operator"); + let peek = self.peek(); + let Some(&info) = BINARY_OPS.iter().find(|op| op.matches(peek)) else { + break; }; // If we're a sub-expression within a ternary expression, don't try to read further than our parent's precedence would allow if let Some(strength) = strength { if info.strength > strength { - self.put_back(Token::Punct(info.token)); break; } } + self.take(); + // trampoline high-strength expression parts as the lhs of the newly found op expr = require!(self.expression_part(expr, info, strength, in_ternary || info.strength == Strength::Conditional)); @@ -1925,29 +1920,27 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let mut rhs = require!(self.group(in_ternary)); loop { // try to read the next operator... - let next = self.next("operator")?; - let &info = match BINARY_OPS.iter().find(|op| op.matches(&next)) { - Some(info) => info, - None => { - self.put_back(next); - break; - } + self.expected("operator"); + let peek = self.peek(); + let Some(&info) = BINARY_OPS.iter().find(|op| op.matches(peek)) else { + break; }; // Strength is in reverse order: A < B means A binds tighter match info.strength.cmp(&prev_op.strength) { Ordering::Less => { // the operator is stronger than us... recurse down + self.take(); rhs = require!(self.expression_part(rhs, info, strength, in_ternary || info.strength == Strength::Conditional)); } Ordering::Greater => { // the operator is weaker than us... return up - self.put_back(Token::Punct(info.token)); break; } Ordering::Equal => { // the same strength... push it to the list + self.take(); ops.push(info.oper); bits.push(rhs); rhs = require!(self.group(in_ternary)); @@ -1972,14 +1965,11 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let mut result = rhs; while let Some(lhs) = bits.pop() { // Ensure that the next thing we see is a ':' by now. - match self.next("':'")? { + self.expected("':'"); + take_match!(self { Token::Punct(Punctuation::Colon) | - Token::Punct(Punctuation::CloseColon) => {} - other => { - self.put_back(other); - return self.parse_error() - } - } + Token::Punct(Punctuation::CloseColon) => {}, + } else return self.parse_error()); // Read the else branch. let else_ = match self.expression_ex(Some(Strength::Conditional), true)? { Some(else_) => else_, @@ -2023,7 +2013,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // Read prefix unary ops let mut unary_ops = Vec::new(); loop { - match self.next("operator")? { + self.expected("operator"); + take_match!(self { Token::Punct(Punctuation::Sub) => unary_ops.push(Spanned::new(self.location, Follow::Unary(UnaryOp::Neg))), Token::Punct(Punctuation::Not) => unary_ops.push(Spanned::new(self.location, Follow::Unary(UnaryOp::Not))), Token::Punct(Punctuation::BitNot) => unary_ops.push(Spanned::new(self.location, Follow::Unary(UnaryOp::BitNot))), @@ -2031,11 +2022,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { Token::Punct(Punctuation::MinusMinus) => unary_ops.push(Spanned::new(self.location, Follow::Unary(UnaryOp::PreDecr))), Token::Punct(Punctuation::BitAnd) => unary_ops.push(Spanned::new(self.location, Follow::Unary(UnaryOp::Reference))), Token::Punct(Punctuation::Mul) => unary_ops.push(Spanned::new(self.location, Follow::Unary(UnaryOp::Dereference))), - other => { - self.put_back(other); - break; - } - } + } else break); } let mut belongs_to = Vec::new(); @@ -2048,17 +2035,16 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // Read postfix unary ops and field-access follows let mut follow = Vec::new(); loop { - match self.next("operator")? { + self.expected("operator"); + take_match!(self { Token::Punct(Punctuation::PlusPlus) => follow.push(Spanned::new(self.location, Follow::Unary(UnaryOp::PostIncr))), Token::Punct(Punctuation::MinusMinus) => follow.push(Spanned::new(self.location, Follow::Unary(UnaryOp::PostDecr))), - other => { - self.put_back(other); - match self.follow(&mut belongs_to, in_ternary)? { - Some(f) => follow.push(f), - None => break, - } + } else { + match self.follow(&mut belongs_to, in_ternary)? { + Some(f) => follow.push(f), + None => break, } - } + }); } // Add prefix unary operators to the follows in reverse order @@ -2082,7 +2068,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { use super::lexer::Punctuation::*; let start = self.updated_location(); - let term = match self.next("term")? { + self.expected("term"); // TODO: a better explanation + let term = take_match!(self { // term :: 'new' (prefab | (ident field*))? arglist? Token::Ident(ref i, _) if i == "new" => { // It's not entirely clear what is supposed to be valid here. @@ -2099,7 +2086,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // The following is what seems a reasonable approximation. // Try to read an ident or path, then read the arguments. - if self.dot()?.is_some() { + if let Some(()) = self.exact(Token::Punct(Punctuation::Dot))? { if let Some(ident) = self.ident()? { // prefab // TODO: arrange for this ident to end up in the prefab's annotation @@ -2297,12 +2284,6 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // Go away return self.parse_error() } - } - // term :: path_lit - t @ Token::Punct(Punctuation::Slash) | - t @ Token::Punct(Punctuation::CloseColon) => { - self.put_back(t); - Term::Prefab(require!(self.prefab())) }, // term :: str_lit | num_lit @@ -2332,7 +2313,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let mut parts = Vec::new(); loop { let expr = self.expression()?; - match self.next("']'")? { + self.expected("']'"); + take_match!(self { Token::InterpStringPart(part) => { parts.push((expr, part.into())); }, @@ -2340,14 +2322,18 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { parts.push((expr, end.into())); break; }, - _ => return self.parse_error(), - } + } else return self.parse_error()); } Term::InterpString(begin.into(), parts.into()) }, - - other => return self.try_another(other), - }; + } else match self.peek() { + // term :: prefab + Token::Punct(Punctuation::Slash) | + Token::Punct(Punctuation::CloseColon) => { + Term::Prefab(require!(self.prefab())) + }, + _ => return try_another(), + }); success(Spanned::new(start, term)) } @@ -2355,11 +2341,11 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let first_location = self.updated_location(); // follow :: ('[' | '?[') expression ']' - let kind = match self.next("field access")? { + self.expected("field access"); + let kind = take_match!(self { Token::Punct(Punctuation::LBracket) => ListAccessKind::Normal, Token::Punct(Punctuation::SafeLBracket) => ListAccessKind::Safe, - other => return self.try_another(other), - }; + } else return try_another()); belongs_to.clear(); let expr = require!(self.expression()); @@ -2375,16 +2361,15 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } // follow :: '.' ident arglist? - let kind = match self.next("field access")? { + self.expected("field access"); + let kind = take_match!(self { // TODO: only apply these rules if there is no whitespace around the punctuation Token::Punct(Punctuation::Dot) => PropertyAccessKind::Dot, Token::Punct(Punctuation::CloseColon) if !belongs_to.is_empty() || !in_ternary => PropertyAccessKind::Colon, Token::Punct(Punctuation::SafeDot) => PropertyAccessKind::SafeDot, Token::Punct(Punctuation::SafeColon) => PropertyAccessKind::SafeColon, Token::Punct(Punctuation::Scope) => PropertyAccessKind::Scope, - - other => return self.try_another(other), - }; + } else return try_another()); let mut index_op_loc = self.location; let start = self.updated_location(); @@ -2438,16 +2423,15 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // TODO: somehow fix the fact that this is basically copy-pasted from // follow() above. fn field(&mut self, belongs_to: &mut Vec, in_ternary: bool) -> Status { - let kind = match self.next("field access")? { + self.expected("field access"); + let kind = take_match!(self { // follow :: '.' ident // TODO: only apply these rules if there is no whitespace around the punctuation Token::Punct(Punctuation::Dot) => PropertyAccessKind::Dot, Token::Punct(Punctuation::CloseColon) if !belongs_to.is_empty() || !in_ternary => PropertyAccessKind::Colon, Token::Punct(Punctuation::SafeDot) => PropertyAccessKind::SafeDot, Token::Punct(Punctuation::SafeColon) => PropertyAccessKind::SafeColon, - - other => return self.try_another(other), - }; + } else return try_another()); let mut index_op_loc = self.location; let start = self.updated_location(); @@ -2555,7 +2539,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { fn read_any_tt(&mut self, target: &mut Vec) -> Status<()> { // read a single arbitrary "token tree", either a group or a single token - let start = self.next_quiet()?; + let start = self.take(); let kind = TTKind::from_token(&start); target.push(LocatedToken::new(self.location(), start)); let kind = match kind { @@ -2563,12 +2547,10 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { None => return SUCCESS, }; loop { - let token = self.next_quiet()?; - if kind.is_end(&token) { - target.push(LocatedToken::new(self.location(), token)); + if kind.is_end(self.peek()) { + target.push(LocatedToken::new(self.location(), self.take())); return SUCCESS; } else { - self.put_back(token); require!(self.read_any_tt(target)); } } From fbf6838291c4da54110f2f915d49536cbf3d7a31 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 1 Jun 2024 14:10:14 -0700 Subject: [PATCH 098/197] Expand 'term' in errors to 'literal, variable, proc call' --- crates/dreammaker/src/parser.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 8c8acf7d..490a455f 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -2068,7 +2068,10 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { use super::lexer::Punctuation::*; let start = self.updated_location(); - self.expected("term"); // TODO: a better explanation + // We look for a lot of different words here, so just explain the categories. + self.expected("literal"); + self.expected("variable"); + self.expected("proc call"); let term = take_match!(self { // term :: 'new' (prefab | (ident field*))? arglist? Token::Ident(ref i, _) if i == "new" => { From d704d634859259113cb3a1c6a4f37e420f0f1ce3 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 1 Jun 2024 14:40:24 -0700 Subject: [PATCH 099/197] Fix clippy lints --- crates/dm-langserver/src/debugger/auxtools.rs | 2 +- crates/dm-langserver/src/main.rs | 2 +- crates/dmdoc/src/main.rs | 8 ++++---- crates/dmdoc/src/template.rs | 2 +- crates/dmm-tools/src/minimap.rs | 1 - crates/dmm-tools/src/render_passes/mod.rs | 2 +- crates/dreamchecker/src/lib.rs | 4 ++-- crates/dreamchecker/src/switch_rand_range.rs | 3 +-- crates/dreammaker/src/ast.rs | 4 +--- crates/dreammaker/src/parser.rs | 9 ++------- crates/dreammaker/src/preprocessor.rs | 8 ++++---- crates/interval-tree/src/node.rs | 4 ++-- 12 files changed, 20 insertions(+), 29 deletions(-) diff --git a/crates/dm-langserver/src/debugger/auxtools.rs b/crates/dm-langserver/src/debugger/auxtools.rs index d2fce5ae..beeef165 100644 --- a/crates/dm-langserver/src/debugger/auxtools.rs +++ b/crates/dm-langserver/src/debugger/auxtools.rs @@ -408,7 +408,7 @@ impl AuxtoolsThread { BreakpointReason::Pause => dap_types::StoppedEvent::REASON_PAUSE, BreakpointReason::Breakpoint => dap_types::StoppedEvent::REASON_BREAKPOINT, BreakpointReason::Runtime(error) => { - *(self.last_error.write().unwrap()) = error.clone(); + self.last_error.write().unwrap().clone_from(&error); description = Some(error); dap_types::StoppedEvent::REASON_EXCEPTION } diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index bf9ab3f7..f1f39d9f 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -960,7 +960,7 @@ impl<'a> Engine<'a> { let _ = write!(message, "{}", each); } message.push(')'); - defstring = message.clone(); + defstring.clone_from(&message); } if let Some(ref decl) = proc.declaration { diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index c5651ce6..69476494 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -95,7 +95,7 @@ fn main2() -> Result<(), Box> { println!("collating documented types"); if index_path.is_none() { - index_path = context.config().dmdoc.index_file.clone(); + index_path.clone_from(&context.config().dmdoc.index_file); } let mut code_directories: std::collections::HashSet; @@ -1006,7 +1006,7 @@ fn git_info(git: &mut Git) -> Result<(), git2::Error> { // check that the current revision is an ancestor of its remote let branch = repo.find_branch(req!(head.shorthand()), git2::BranchType::Local)?; if let Ok(Some(name)) = branch.name() { - git.branch = name.to_owned(); + name.clone_into(&mut git.branch); } let upstream = branch.upstream()?; let upstream_oid = upstream.get().peel_to_commit()?.id(); @@ -1020,7 +1020,7 @@ fn git_info(git: &mut Git) -> Result<(), git2::Error> { let mut iter = upstream_name.splitn(2, '/'); let remote_name = req!(iter.next()); if let Some(name) = iter.next() { - git.remote_branch = name.to_owned(); + name.clone_into(&mut git.remote_branch); } let remote = repo.find_remote(remote_name)?; @@ -1035,7 +1035,7 @@ fn git_info(git: &mut Git) -> Result<(), git2::Error> { } } if url.starts_with("https://") || url.starts_with("http://") { - git.web_url = url.to_owned(); + url.clone_into(&mut git.web_url); } else if url.starts_with("ssh://") { git.web_url = url.replace("ssh://", "https://"); } else { diff --git a/crates/dmdoc/src/template.rs b/crates/dmdoc/src/template.rs index 0f5b50fb..d6d3827f 100644 --- a/crates/dmdoc/src/template.rs +++ b/crates/dmdoc/src/template.rs @@ -328,7 +328,7 @@ pub(crate) fn dm_type(ty: &Type) -> Markup { let Type { env, base_href, path, details } = *ty; base( env, - &base_href, + base_href, &display(path), &display(""), &html! { diff --git a/crates/dmm-tools/src/minimap.rs b/crates/dmm-tools/src/minimap.rs index 701902ff..75a6f2d3 100644 --- a/crates/dmm-tools/src/minimap.rs +++ b/crates/dmm-tools/src/minimap.rs @@ -424,7 +424,6 @@ impl Category { const OBJ: Category = Category { raw: 3 }; const MOB: Category = Category { raw: 4 }; - /// pub fn from_path(path: &str) -> Category { if path.starts_with("/area") { Category::AREA diff --git a/crates/dmm-tools/src/render_passes/mod.rs b/crates/dmm-tools/src/render_passes/mod.rs index 3f717160..ba9fbfaa 100644 --- a/crates/dmm-tools/src/render_passes/mod.rs +++ b/crates/dmm-tools/src/render_passes/mod.rs @@ -199,7 +199,7 @@ pub struct HideInvisible { impl RenderPass for HideInvisible { fn configure(&mut self, renderer_config: &dm::config::MapRenderer) { - self.overrides = renderer_config.hide_invisible.clone(); + self.overrides.clone_from(&renderer_config.hide_invisible); // Put longer typepaths earlier in the list so that `/foo/bar` can override `/foo`. self.overrides.sort_unstable_by_key(|k| usize::MAX - k.len()); // Append `/` to each typepath for faster starts_with later. diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index b5d1d3de..d2a470c9 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -440,7 +440,7 @@ impl<'o> ProcDirective<'o> { } fn try_copy_from_parent(&mut self, proc: ProcRef<'o>) { - if self.directive.get(&proc).is_none() { + if !self.directive.contains_key(&proc) { if let Some(parent) = proc.parent_proc() { if let Some((_, true, location)) = self.get_self_or_parent(parent) { let _ = self.insert(proc, true, location); @@ -660,7 +660,7 @@ impl<'o> AnalyzeObjectTree<'o> { if !visited.insert(nextproc) { continue } - if self.waitfor_procs.get(&nextproc).is_some() { + if self.waitfor_procs.contains(&nextproc) { continue } if self.sleep_exempt.get(nextproc).is_some() { diff --git a/crates/dreamchecker/src/switch_rand_range.rs b/crates/dreamchecker/src/switch_rand_range.rs index 764f2de0..3490743c 100644 --- a/crates/dreamchecker/src/switch_rand_range.rs +++ b/crates/dreamchecker/src/switch_rand_range.rs @@ -20,8 +20,7 @@ pub fn check_switch_rand_range( return; }; - let mut case_ranges = vec![]; - case_ranges.reserve(cases.len()); + let mut case_ranges = Vec::with_capacity(cases.len()); for case_block in cases.iter() { let location = case_block.0.location; for case in case_block.0.elem.iter() { diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index fbef071b..2c0cb9ba 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -915,9 +915,7 @@ impl Expression { pub fn is_truthy(&self) -> Option { match self { Expression::Base { term, follow } => { - let Some(mut truthy) = term.elem.is_truthy() else { - return None; - }; + let mut truthy = term.elem.is_truthy()?; for follow in follow.iter() { match follow.elem { Follow::Unary(UnaryOp::Not) => truthy = !truthy, diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 490a455f..fbddd1b1 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -1460,12 +1460,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { Some(Term::Ident(name)) => name, _ => return Err(self.error("for-list must start with variable")), }; - // Explicit move is necessary because rustc becomes - // confused when matching on the *rhs lvalue, thinking - // moving the LHS also moves the RHS. This fails: - // let a: Box<(NonCopy, NonCopy)>; - // let (b, c) = *a; - match {*rhs} { + match *rhs { Expression::BinaryOp { op: BinaryOp::To, lhs, rhs } => { return spanned(require!(self.for_range(None, name, lhs, rhs))); }, @@ -2179,7 +2174,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { Token::Ident(ref i, _) if i == "locate" => match self.arguments(&[], "locate")? { Some(args) => { // warn against this mistake - if let Some(&Expression::BinaryOp { op: BinaryOp::In, .. } ) = args.get(0) { + if let Some(&Expression::BinaryOp { op: BinaryOp::In, .. } ) = args.first() { self.error("bad `locate(X in Y)`, should be `locate(X) in Y`") .set_severity(Severity::Warning) .register(self.context); diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index f52fdc2e..22361329 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -660,7 +660,7 @@ impl<'ctx> Preprocessor<'ctx> { // All DM source is effectively `#pragma once`. let file_id = self.context.register_file(register); if let Some(&loc) = self.include_locations.get(&file_id) { - if self.multiple_locations.get(&file_id).is_none() { + if !self.multiple_locations.contains_key(&file_id) { Err(DMError::new(self.last_input_loc, format!("duplicate #include {:?}", path)) .set_severity(Severity::Warning) .with_note(loc, "previously included here") @@ -868,7 +868,7 @@ impl<'ctx> Preprocessor<'ctx> { let mut params = Vec::new(); let mut subst = Vec::new(); let mut variadic = false; - 'outer: loop { + 'outer: { match next!() { Token::Punct(Punctuation::LParen) if !ws => { loop { @@ -906,7 +906,7 @@ impl<'ctx> Preprocessor<'ctx> { }; self.error(message) .set_severity(Severity::Hint) - .register(&self.context); + .register(self.context); } docs.push(doc); } @@ -925,7 +925,7 @@ impl<'ctx> Preprocessor<'ctx> { }; self.error(message) .set_severity(Severity::Hint) - .register(&self.context); + .register(self.context); } docs.push(doc); } diff --git a/crates/interval-tree/src/node.rs b/crates/interval-tree/src/node.rs index 7b32495e..ecba21ef 100644 --- a/crates/interval-tree/src/node.rs +++ b/crates/interval-tree/src/node.rs @@ -287,7 +287,7 @@ pub mod tests { fn is_sorted_right(node: &Node) -> bool { node.right.as_ref().map_or(true, |succ| succ.key > node.key) } - fn is_interval_node(node: &Box>) -> bool { + fn is_interval_node(node: &Node) -> bool { let sorted = is_sorted_left(node) && is_sorted_right(node); let balanced = node.height == cmp::max(height(&node.left), height(&node.right)) + 1; let proper_max = node.max @@ -299,7 +299,7 @@ pub mod tests { } pub fn is_interval_tree(root: &Option>>) -> bool { - (*root).as_ref().map_or(true, is_interval_node) + (*root).as_ref().map_or(true, |n| is_interval_node(n)) } #[test] From ef9485246d5507433e39948d2bccdaab2983c9a1 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 1 Jun 2024 14:56:01 -0700 Subject: [PATCH 100/197] Improve unexpected-EOF error message --- crates/dreammaker/src/parser.rs | 50 +++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index fbddd1b1..a31dce37 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -5,8 +5,6 @@ use std::collections::{BTreeMap, VecDeque}; use std::ops::Range; use std::str::FromStr; -use crate::ast; - use super::annotation::*; use super::ast::*; use super::docs::*; @@ -299,6 +297,14 @@ impl TTKind { } } + fn end(self) -> &'static str { + match self { + TTKind::Paren => "')'", + TTKind::Brace => "'}'", + TTKind::Bracket => "']'", + } + } + fn is_end(self, token: &Token) -> bool { matches!((self, token), (TTKind::Paren, &Token::Punct(Punctuation::RParen)) @@ -338,6 +344,7 @@ pub struct Parser<'ctx, 'an, 'inp> { next: Option, location: Location, expected: Vec>, + skipping_location: Option, doc_comments_pending: VecDeque<(Location, DocComment)>, module_docs: BTreeMap>, @@ -368,6 +375,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { next: None, location: Default::default(), expected: Vec::new(), + skipping_location: None, doc_comments_pending: Default::default(), module_docs: Default::default(), @@ -450,19 +458,24 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { fn describe_parse_error(&mut self) -> DMError { let expected = self.expected.join(", "); if self.eof { - return self.error(format!("got EOF, expected one of: {}", expected)); + let mut error = self.error(format!("got EOF, expected one of: {}", expected)); + if let Some(loc) = self.skipping_location { + error.add_note(loc, "unmatched pair here"); + } + error + } else { + let got = self.peek(); + let message = format!("got '{:#}', expected one of: {}", got, expected); + let mut error = self.error(message); + if self.possible_indentation_error { + let mut loc = error.location(); + loc.line += 1; + loc.column = 1; + error.add_note(loc, "check for extra indentation at the start of the next line"); + self.possible_indentation_error = false; + } + error } - let got = self.peek(); - let message = format!("got '{:#}', expected one of: {}", got, expected); - let mut error = self.error(message); - if self.possible_indentation_error { - let mut loc = error.location(); - loc.line += 1; - loc.column = 1; - error.add_note(loc, "check for extra indentation at the start of the next line"); - self.possible_indentation_error = false; - } - error } fn parse_error(&mut self) -> Result { @@ -2485,7 +2498,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } } - fn pick_arguments(&mut self) -> Status> { + fn pick_arguments(&mut self) -> Status> { leading!(self.exact(Token::Punct(Punctuation::LParen))); success(require!(self.separated( Punctuation::Comma, @@ -2537,6 +2550,9 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { fn read_any_tt(&mut self, target: &mut Vec) -> Status<()> { // read a single arbitrary "token tree", either a group or a single token + if self.peek() == &Token::Eof { + return try_another(); + } let start = self.take(); let kind = TTKind::from_token(&start); target.push(LocatedToken::new(self.location(), start)); @@ -2544,12 +2560,16 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { Some(k) => k, None => return SUCCESS, }; + let location = self.location; loop { + self.expected(kind.end()); if kind.is_end(self.peek()) { target.push(LocatedToken::new(self.location(), self.take())); return SUCCESS; } else { + self.skipping_location = Some(location); require!(self.read_any_tt(target)); + self.skipping_location = None; } } } From ca9e5a2c8c3b8d2231678088863b1ae7150af4a2 Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Sun, 16 Jun 2024 18:29:17 -0700 Subject: [PATCH 101/197] Add colorspace as an arg to the gradient proc (#391) We need to allow colorspace setting to make HSV gradients possible, which is real powerful. It is technically a bit fucked because byond is ok with passing a value for index after the assoc space value, but we can just pretend that isn't a problem. --- crates/dreammaker/src/builtins.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/dreammaker/src/builtins.rs b/crates/dreammaker/src/builtins.rs index 0a98524f..503d722e 100644 --- a/crates/dreammaker/src/builtins.rs +++ b/crates/dreammaker/src/builtins.rs @@ -467,7 +467,7 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { proc/get_step_rand(Ref); proc/get_step_to(Ref,Trg,Min=0); proc/get_step_towards(Ref,Trg); - proc/gradient(Gradient, index); // unsure how to handle (Item1, Item2, ..., index) form + proc/gradient(Gradient, index, space = COLORSPACE_RGB); // unsure how to handle (Item1, Item2, ..., index) form proc/hascall(Object,ProcName); proc/hearers(Depth=world.view,Center=usr); proc/html_decode(HtmlText); From aec2fc91733faf364a907271a9a2e6728b2bcc69 Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Sun, 16 Jun 2024 20:29:05 -0700 Subject: [PATCH 102/197] Const-evaluate filter() properly (#390) We have a constant for it but nothing actually generates that constant. Should fix that. --- crates/dreammaker/src/constants.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index dc3e5f01..fc12edec 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -788,6 +788,7 @@ impl<'a> ConstantFolder<'a> { "newlist" => Constant::Call(ConstFn::Newlist, self.arguments(args)?), "icon" => Constant::Call(ConstFn::Icon, self.arguments(args)?), "sound" => Constant::Call(ConstFn::Sound, self.arguments(args)?), + "filter" => Constant::Call(ConstFn::Filter, self.arguments(args)?), "file" => Constant::Call(ConstFn::File, self.arguments(args)?), "generator" => Constant::Call(ConstFn::Generator, self.arguments(args)?), // constant-evaluatable functions From 17373dc1d990135ee9827fceb2ba51079eb7ff2b Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 6 Jun 2024 20:10:39 -0700 Subject: [PATCH 103/197] Add sizeof guards for main AST nodes --- crates/dreammaker/src/ast.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 2c0cb9ba..378e42ec 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -1490,3 +1490,9 @@ pub static VALID_FILTER_FLAGS: phf::Map<&'static str, (&str, bool, bool, &[&str] "ripple" => ("flags", false, true, &[ "WAVE_BOUNDED" ]), "wave" => ("flags", false, true, &[ "WAVE_SIDEWAYS", "WAVE_BOUNDED" ]), }; + +// ---------------------------------------------------------------------------- +// Guard against sizeof regression. +const _: [(); 0 - !(std::mem::size_of::() <= 56) as usize] = []; +const _: [(); 0 - !(std::mem::size_of::() <= 32) as usize] = []; +const _: [(); 0 - !(std::mem::size_of::() <= 40) as usize] = []; From d75085266bcd5f5a043761873ee2aff775134f3d Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 20 Jun 2024 21:16:10 -0700 Subject: [PATCH 104/197] Fix parsing of union proc return types Fixes #385. --- crates/dreammaker/src/ast.rs | 53 +++------------------- crates/dreammaker/src/objtree.rs | 8 ++-- crates/dreammaker/src/parser.rs | 67 +++++++++------------------- crates/dreammaker/tests/ast_tests.rs | 16 +++++++ 4 files changed, 48 insertions(+), 96 deletions(-) diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 378e42ec..e2ecf09e 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -298,55 +298,16 @@ impl fmt::Display for PropertyAccessKind { } } -/// Description of the type of an as block, particularly in the context of proc return types +/// Description of a proc's return type (`as` phrase). #[derive(Debug, Clone, PartialEq, Eq, Hash, GetSize)] -pub enum AsType { - // These lummy stole from the InputType spec - // There are more but we will parse them into a typepath/string - Text, - Num, - Null, - List, - File, - Anything, - // Any typepath - Type(Vec), +pub enum ProcReturnType { + InputType(InputType), + TypePath(Vec), } -impl AsType { - pub fn from_name(name: &str) -> Option{ - match name { - // First class pairings - "text" => Some(AsType::Text), - "num" => Some(AsType::Num), - "null" => Some(AsType::Null), - "list" => Some(AsType::List), - "file" => Some(AsType::File), - "anything" => Some(AsType::Anything), - - // Vestiges of input(), we just treat these as text I think - "message" | "command_text" | "password" | "color" | "key" => - Some(AsType::Text), - - // Type handling - "mob" => AsType::from_name("/mob"), - "obj" => AsType::from_name("/obj"), - "turf" => AsType::from_name("/turf"), - "area" => AsType::from_name("/area"), - "icon" => AsType::from_name("/icon"), - "sound" => AsType::from_name("/sound"), - // If it looks like a typepath, we'll process it as a typepath (figure out reality later ya feel?) - _ if name.chars().next().unwrap_or(' ') == '/' => - Some(AsType::from_vec(name.split('/').filter_map(|part| match part { - "" => None, - _ => Some(part.to_string()), - }).collect::>())), - _ => None, - } - } - - pub fn from_vec(vec: Vec) -> AsType{ - AsType::Type(vec) +impl Default for ProcReturnType { + fn default() -> Self { + ProcReturnType::InputType(InputType::empty()) } } diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index c1f86afc..dae9d96d 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -12,7 +12,7 @@ use indexmap::IndexMap; use crate::heap_size_of_index_map; use super::ast::{ - AsType, Block, Expression, Ident, Parameter, PathOp, ProcDeclBuilder, ProcDeclKind, ProcFlags, + ProcReturnType, Block, Expression, Ident, Parameter, PathOp, ProcDeclBuilder, ProcDeclKind, ProcFlags, VarSuffix, VarType, VarTypeBuilder, }; use super::constants::Constant; @@ -86,7 +86,7 @@ pub struct ProcDeclaration { pub location: Location, pub kind: ProcDeclKind, // todo: tie this into our return type, add support for the funky types - pub return_type: AsType, + pub return_type: ProcReturnType, pub flags: ProcFlags, pub id: SymbolId, } @@ -1123,7 +1123,7 @@ impl ObjectTreeBuilder { name: &str, declaration: Option, parameters: Vec, - return_type: AsType, + return_type: ProcReturnType, code: Option, ) -> Result<(usize, &mut ProcValue), DMError> { let node = &mut self.inner.graph[parent.index()]; @@ -1276,7 +1276,7 @@ impl ObjectTreeBuilder { )); } - self.register_proc(context, location, parent, proc_name, declaration, parameters, AsType::Anything, code) + self.register_proc(context, location, parent, proc_name, declaration, parameters, ProcReturnType::default(), code) } } diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index a31dce37..6ad561b7 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -1066,10 +1066,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let location = self.location; let parameters = require!(self.separated(Comma, RParen, None, Parser::proc_parameter)); - let return_type = match self.return_type(proc_builder)? { - Some(type_to_use) => type_to_use, - None => AsType::Anything, - }; + let return_type = self.return_type(proc_builder)?.unwrap_or_default(); // split off a subparser so we can keep parsing the objtree // even when the proc body doesn't parse @@ -1262,53 +1259,31 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } /// Parse an optional as return type signifier (for procs) - fn return_type(&mut self, proc_builder: Option) -> Status { + fn return_type(&mut self, proc_builder: Option) -> Status { if self.exact_ident("as")?.is_none() { - return Ok(None); - }; - if proc_builder.is_none() { - self.error("Cannot specify a return type for a proc override") - .register(self.context); + return try_another(); } - // While loop over self.next, extracting either the first string with from_name OR - // if the first string is a slash, continue to extract, and check for a slash again, and finish with from_vec - self.expected("identifier"); - self.expected("'/'"); - take_match!(self { - Token::Ident(text, _) => { - let Some(return_type) = AsType::from_name(text.as_str()) else { - return Err(self.error("Invalid return type")); - }; - return Ok(Some(return_type)); - }, - Token::Punct(Punctuation::Slash) => {}, - } else { - return Err(self.error("Invalid return type")); - }); - // We're pulling out just the text, and we go until the end of the text or until we hit something unexpected - let mut path_vec = vec![]; - let mut slash_last = true; - loop { - self.expected("identifier"); - self.expected("'/'"); - take_match!(self { - Token::Ident(text, whitespace) if slash_last => { - path_vec.push(text); - slash_last = false; - if whitespace { - break; - } - }, - Token::Punct(Punctuation::Slash) if !slash_last => slash_last = true, - // If we're done, put back what we just fond so someone else can process it, in case they care - } else break); + if proc_builder.is_none() { + self.error("cannot specify a return type for a proc override") + .register(self.context); } - if !path_vec.is_empty() { - Ok(Some(AsType::from_vec(path_vec))) - } else { - Err(self.error("Invalid return type")) + + // Alternative one: a traditional input type as usually follows `as`. + if let Some(input_type) = self.input_type()? { + return success(ProcReturnType::InputType(input_type)); } + + // Option two: a typepath. + require!(self.exact(Token::Punct(Punctuation::Slash))); + let mut path_vec = vec![ + require!(self.ident()), + ]; + while let Some(()) = self.exact(Token::Punct(Punctuation::Slash))? { + path_vec.push(require!(self.ident())); + } + + success(ProcReturnType::TypePath(path_vec)) } /// Parse a verb input type. Used by proc params and the input() form. diff --git a/crates/dreammaker/tests/ast_tests.rs b/crates/dreammaker/tests/ast_tests.rs index 00458945..ea02ea8e 100644 --- a/crates/dreammaker/tests/ast_tests.rs +++ b/crates/dreammaker/tests/ast_tests.rs @@ -237,3 +237,19 @@ var/global/bill = 1 } }) } + +#[test] +fn union_return_types() { + // https://github.com/SpaceManiac/SpacemanDMM/issues/385 + + with_code(" +/proc/returns_num_or_text() as num | text + ", |context, tree| { + context.assert_success(); + + assert_eq!( + tree.root().get_proc("returns_num_or_text").unwrap().get_declaration().unwrap().return_type, + ProcReturnType::InputType(InputType::NUM | InputType::TEXT), + ); + }); +} From 3206ddb261e12ed7458043394bacbd5b1b145790 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 22 Jun 2024 12:59:23 -0700 Subject: [PATCH 105/197] Fix proc return type tests --- crates/dreamchecker/tests/proc_tests.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/dreamchecker/tests/proc_tests.rs b/crates/dreamchecker/tests/proc_tests.rs index c97a5089..1a0e7357 100644 --- a/crates/dreamchecker/tests/proc_tests.rs +++ b/crates/dreamchecker/tests/proc_tests.rs @@ -34,8 +34,8 @@ fn return_type() { } pub const RETURN_TYPE_FAILURE_ERRORS: &[(u32, u16, &str)] = &[ - (4, 13, "Cannot specify a return type for a proc override"), - (7, 22, "Invalid return type"), + (4, 13, "cannot specify a return type for a proc override"), + (7, 22, "bad input type: 'incorrect'"), ]; #[test] @@ -47,7 +47,7 @@ fn return_type_failure() { /mob/test() as /mob return -/mob/proc/test2() as bullshit +/mob/proc/test2() as incorrect return "##.trim(); check_errors_match(code, RETURN_TYPE_FAILURE_ERRORS); From 2d00d0e2d79e5967ff43c221337dca27b856fdf3 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 23 Jun 2024 12:30:06 -0700 Subject: [PATCH 106/197] Allow setting environment variables on DS/DD launch --- crates/dm-langserver/src/debugger/launched.rs | 6 ++++++ crates/dm-langserver/src/debugger/mod.rs | 11 +++++++---- crates/dm-langserver/src/extras.rs | 3 +++ crates/dm-langserver/src/main.rs | 2 +- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/crates/dm-langserver/src/debugger/launched.rs b/crates/dm-langserver/src/debugger/launched.rs index 7ed6279a..8c2c025a 100644 --- a/crates/dm-langserver/src/debugger/launched.rs +++ b/crates/dm-langserver/src/debugger/launched.rs @@ -2,6 +2,7 @@ #![allow(unsafe_code)] use super::SequenceNumber; +use std::collections::HashMap; use std::process::{Command, Stdio}; use std::sync::{Arc, Mutex}; @@ -42,6 +43,7 @@ impl Launched { pub fn new( seq: Arc, dreamseeker_exe: &str, + env: Option<&HashMap>, dmb: &str, params: Option, ) -> std::io::Result { @@ -60,6 +62,10 @@ impl Launched { .stdout(Stdio::piped()) .stderr(Stdio::piped()); + if let Some(env) = env { + command.envs(env); + } + match params { Some(EngineParams::Extools { port, dll }) => { command.env("EXTOOLS_MODE", "LAUNCHED"); diff --git a/crates/dm-langserver/src/debugger/mod.rs b/crates/dm-langserver/src/debugger/mod.rs index c845b954..b731ede4 100644 --- a/crates/dm-langserver/src/debugger/mod.rs +++ b/crates/dm-langserver/src/debugger/mod.rs @@ -62,6 +62,7 @@ pub type LineNumber = (i64, String, String, usize); pub fn start_server( engine: DebugEngine, dreamseeker_exe: String, + env: Option>, db: DebugDatabaseBuilder, ) -> std::io::Result<(u16, std::thread::JoinHandle<()>)> { use std::net::*; @@ -75,7 +76,7 @@ pub fn start_server( let (stream, _) = listener.accept().unwrap(); drop(listener); let mut input = std::io::BufReader::new(stream.try_clone().unwrap()); - let mut debugger = Debugger::new(engine, dreamseeker_exe, db, Box::new(stream)); + let mut debugger = Debugger::new(engine, dreamseeker_exe, env, db, Box::new(stream)); jrpc_io::run_with_read(&mut input, |message| debugger.handle_input(message)); })?; @@ -123,7 +124,7 @@ pub fn debugger_main>(mut args: I) { extools_dll: None, debug_server_dll: None, }; - let mut debugger = Debugger::new(ctx.config().debugger.engine, dreamseeker_exe, db, Box::new(std::io::stdout())); + let mut debugger = Debugger::new(ctx.config().debugger.engine, dreamseeker_exe, None, db, Box::new(std::io::stdout())); jrpc_io::run_until_stdin_eof(|message| debugger.handle_input(message)); } @@ -247,6 +248,7 @@ enum DebugClient { struct Debugger { engine: DebugEngine, dreamseeker_exe: String, + env: Option>, extools_dll: Option, debug_server_dll: Option, db: DebugDatabase, @@ -261,10 +263,11 @@ struct Debugger { } impl Debugger { - fn new(engine: DebugEngine, dreamseeker_exe: String, mut db: DebugDatabaseBuilder, stream: OutStream) -> Self { + fn new(engine: DebugEngine, dreamseeker_exe: String, env: Option>, mut db: DebugDatabaseBuilder, stream: OutStream) -> Self { Debugger { engine, dreamseeker_exe, + env, extools_dll: db.extools_dll.take(), debug_server_dll: db.debug_server_dll.take(), db: db.build(), @@ -480,7 +483,7 @@ handle_request! { }; // Launch the subprocess. - self.launched = Some(Launched::new(self.seq.clone(), &self.dreamseeker_exe, ¶ms.dmb, engine_params)?); + self.launched = Some(Launched::new(self.seq.clone(), &self.dreamseeker_exe, self.env.as_ref(), ¶ms.dmb, engine_params)?); } on AttachVsc(&mut self, params) { diff --git a/crates/dm-langserver/src/extras.rs b/crates/dm-langserver/src/extras.rs index aec4a5bd..60f490a4 100644 --- a/crates/dm-langserver/src/extras.rs +++ b/crates/dm-langserver/src/extras.rs @@ -1,5 +1,7 @@ //! Extensions to the language server protocol. +use std::collections::HashMap; + use lsp_types::notification::*; use lsp_types::request::*; use lsp_types::SymbolKind; @@ -63,6 +65,7 @@ impl Request for StartDebugger { #[derive(Debug, Serialize, Deserialize)] pub struct StartDebuggerParams { pub dreamseeker_exe: String, + pub env: Option>, } #[derive(Debug, Serialize, Deserialize)] pub struct StartDebuggerResult { diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index f1f39d9f..a0d84877 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -2009,7 +2009,7 @@ handle_method_call! { extools_dll: self.extools_dll.clone(), debug_server_dll: self.debug_server_dll.clone(), }; - let (port, handle) = debugger::start_server(self.context.config().debugger.engine, params.dreamseeker_exe, db).map_err(invalid_request)?; + let (port, handle) = debugger::start_server(self.context.config().debugger.engine, params.dreamseeker_exe, params.env, db).map_err(invalid_request)?; self.threads.push(handle); extras::StartDebuggerResult { port } } From c2ed4ed6e16c6abbd2e27577c521947439b3f68e Mon Sep 17 00:00:00 2001 From: jimmyl <70376633+mc-oofert@users.noreply.github.com> Date: Sun, 23 Jun 2024 23:35:32 +0200 Subject: [PATCH 107/197] Change the typepath in the gravitygenerator render pass (#393) /tg/ gravity generators no longer have a /station subtype so the gravity generator pass doesn't do anything. --- crates/dmm-tools/src/render_passes/structures.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/dmm-tools/src/render_passes/structures.rs b/crates/dmm-tools/src/render_passes/structures.rs index a9fb9294..9b9e33bf 100644 --- a/crates/dmm-tools/src/render_passes/structures.rs +++ b/crates/dmm-tools/src/render_passes/structures.rs @@ -43,7 +43,7 @@ impl RenderPass for GravityGen { overlays: &mut Vec>, _: &bumpalo::Bump, ) { - if !atom.istype("/obj/machinery/gravity_generator/main/station/") { + if !atom.istype("/obj/machinery/gravity_generator/main/") { return; } From b80cd15fa25418d1e91a7ab0c8b2b19d23e01061 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 23 Jun 2024 16:37:51 -0700 Subject: [PATCH 108/197] Run cargo update --- Cargo.lock | 327 ++++++++++++++++++++++++++--------------------------- 1 file changed, 160 insertions(+), 167 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a71ac89b..7acd7467 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,9 +29,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -53,47 +53,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys", @@ -108,7 +109,7 @@ dependencies = [ "attribute-derive-macro", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.68", ] [[package]] @@ -124,14 +125,14 @@ dependencies = [ "proc-macro2", "quote", "quote-use", - "syn 2.0.52", + "syn 2.0.68", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "bincode" @@ -150,9 +151,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "builtins-proc-macro" @@ -165,38 +166,39 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.14.3" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.5.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" +checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.68", ] [[package]] name = "cc" -version = "1.0.90" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "c891175c3fb232128f48de6590095e59198bbeb8620c310be349bfc3afd12c7b" dependencies = [ "jobserver", "libc", + "once_cell", ] [[package]] @@ -207,9 +209,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.35" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -221,9 +223,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.2" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" dependencies = [ "clap_builder", "clap_derive", @@ -231,9 +233,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" dependencies = [ "anstream", "anstyle", @@ -243,21 +245,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.68", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "collection_literals" @@ -279,9 +281,9 @@ checksum = "3776b2bcc4e914db501bb9be9572dd706e344b9eb8f882894f3daa651d281381" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "core-foundation-sys" @@ -291,9 +293,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -319,9 +321,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "dap-types" @@ -352,7 +354,7 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.68", ] [[package]] @@ -471,9 +473,9 @@ dependencies = [ [[package]] name = "either" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "fallible_collections" @@ -495,9 +497,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", @@ -568,7 +570,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.68", ] [[package]] @@ -615,7 +617,7 @@ checksum = "13a1bcfb855c1f340d5913ab542e36f25a1c56f57de79022928297632435dec2" dependencies = [ "attribute-derive", "quote", - "syn 2.0.52", + "syn 2.0.68", ] [[package]] @@ -629,9 +631,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -661,11 +663,11 @@ dependencies = [ [[package]] name = "git2" -version = "0.18.2" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b3ba52851e73b46a4c3df1d89343741112003f0f6f13beb0dfac9e457c3fdcd" +checksum = "232e6a7bfe35766bf715e55a88b39a700596c0ccfd88cd3680b4cdb40d66ef70" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "libc", "libgit2-sys", "log", @@ -689,9 +691,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "iana-time-zone" @@ -759,16 +761,22 @@ dependencies = [ ] [[package]] -name = "itoa" -version = "1.0.10" +name = "is_terminal_polyfill" +version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.28" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" dependencies = [ "libc", ] @@ -799,15 +807,15 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libgit2-sys" @@ -823,9 +831,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.15" +version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037731f5d3aaa87a5675e895b63ddff1a87624bc29f77004ea829809654e48f6" +checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e" dependencies = [ "cc", "libc", @@ -899,15 +907,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", "simd-adler32", @@ -928,9 +936,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] @@ -946,9 +954,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -1004,7 +1012,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.68", ] [[package]] @@ -1018,9 +1026,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -1090,9 +1098,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -1103,7 +1111,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "getopts", "memchr", "unicase", @@ -1111,9 +1119,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -1126,7 +1134,7 @@ checksum = "a7b5abe3fe82fdeeb93f44d66a7b444dedf2e4827defb0a8e69c437b2de2ef94" dependencies = [ "quote", "quote-use-macros", - "syn 2.0.52", + "syn 2.0.68", ] [[package]] @@ -1138,7 +1146,7 @@ dependencies = [ "derive-where", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.68", ] [[package]] @@ -1179,9 +1187,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -1199,9 +1207,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.3" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", @@ -1211,9 +1219,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -1222,9 +1230,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rgb" @@ -1237,9 +1245,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -1252,29 +1260,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.197" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.68", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -1283,13 +1291,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.68", ] [[package]] @@ -1315,15 +1323,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" @@ -1338,9 +1346,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.52" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -1412,15 +1420,15 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -1430,9 +1438,9 @@ dependencies = [ [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "vcpkg" @@ -1483,7 +1491,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.68", "wasm-bindgen-shared", ] @@ -1505,7 +1513,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.68", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1522,37 +1530,15 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys", ] -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-core" version = "0.52.0" @@ -1573,13 +1559,14 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -1588,62 +1575,68 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.68", ] From 181067efd1e939e9ca83e71460a95a39a4cb3156 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 23 Jun 2024 16:41:24 -0700 Subject: [PATCH 109/197] Bump versions for suite 1.9 --- Cargo.lock | 8 ++++---- crates/dm-langserver/Cargo.toml | 2 +- crates/dmdoc/Cargo.toml | 2 +- crates/dmm-tools-cli/Cargo.toml | 2 +- crates/dreamchecker/Cargo.toml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7acd7467..2f43c07d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -359,7 +359,7 @@ dependencies = [ [[package]] name = "dm-langserver" -version = "1.8.0" +version = "1.9.0" dependencies = [ "ahash", "bincode", @@ -382,7 +382,7 @@ dependencies = [ [[package]] name = "dmdoc" -version = "1.8.0" +version = "1.9.0" dependencies = [ "chrono", "dreammaker", @@ -414,7 +414,7 @@ dependencies = [ [[package]] name = "dmm-tools-cli" -version = "1.8.0" +version = "1.9.0" dependencies = [ "ahash", "chrono", @@ -439,7 +439,7 @@ dependencies = [ [[package]] name = "dreamchecker" -version = "1.8.0" +version = "1.9.0" dependencies = [ "ahash", "chrono", diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index 413e478b..d0e19cba 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dm-langserver" -version = "1.8.0" +version = "1.9.0" authors = ["Tad Hardesty "] edition = "2018" diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index 340836ca..b69bb488 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dmdoc" -version = "1.8.0" +version = "1.9.0" authors = ["Tad Hardesty "] homepage = "https://github.com/SpaceManiac/SpacemanDMM/blob/master/crates/dmdoc/README.md" edition = "2018" diff --git a/crates/dmm-tools-cli/Cargo.toml b/crates/dmm-tools-cli/Cargo.toml index 080f415d..5f8fafd5 100644 --- a/crates/dmm-tools-cli/Cargo.toml +++ b/crates/dmm-tools-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dmm-tools-cli" -version = "1.8.0" +version = "1.9.0" authors = ["Tad Hardesty "] description = "BYOND map rendering and analysis tools powered by SpacemanDMM" edition = "2018" diff --git a/crates/dreamchecker/Cargo.toml b/crates/dreamchecker/Cargo.toml index a7ea7261..c2e42b52 100644 --- a/crates/dreamchecker/Cargo.toml +++ b/crates/dreamchecker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dreamchecker" -version = "1.8.0" +version = "1.9.0" authors = ["Tad Hardesty "] edition = "2018" From 5919d61c27304f3d6b12a5a5f3aac65b408cc163 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 24 Jun 2024 20:23:55 -0700 Subject: [PATCH 110/197] Remove leftover ConstFn::FileExists --- crates/dreamchecker/src/lib.rs | 1 - crates/dreammaker/src/constants.rs | 3 --- 2 files changed, 4 deletions(-) diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index d2a470c9..aa54aead 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -143,7 +143,6 @@ impl<'o> AssumptionSet<'o> { ConstFn::Newlist => AssumptionSet::from_valid_instance(objtree.expect("/list")), ConstFn::Sound => AssumptionSet::from_valid_instance(objtree.expect("/sound")), ConstFn::Generator => AssumptionSet::from_valid_instance(objtree.expect("/generator")), - ConstFn::FileExists => AssumptionSet::default(), ConstFn::Filter => AssumptionSet::default(), ConstFn::File => AssumptionSet::default(), }, diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index fc12edec..0a0c4aba 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -154,8 +154,6 @@ pub enum ConstFn { File, /// The `generator()` type constructor. Generator, - /// `fexists()`, which can be used in preprocessor expressions. - FileExists, } /// A constant-evaluation error (usually type mismatch). @@ -413,7 +411,6 @@ impl fmt::Display for ConstFn { ConstFn::Filter => "filter", ConstFn::File => "file", ConstFn::Generator => "generator", - ConstFn::FileExists => "fexists" }) } } From ffa13126f9a0bfd7e7f0a1b35bae73241ccc7f8c Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Tue, 25 Jun 2024 16:54:21 -0700 Subject: [PATCH 111/197] Remove unused try_iter! macro --- crates/dreammaker/src/lib.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/crates/dreammaker/src/lib.rs b/crates/dreammaker/src/lib.rs index 86171232..7ec8a8ba 100644 --- a/crates/dreammaker/src/lib.rs +++ b/crates/dreammaker/src/lib.rs @@ -15,16 +15,6 @@ extern crate toml; use std::borrow::Cow; use std::path::Path; -#[allow(unused_macros)] -macro_rules! try_iter { - ($e:expr) => { - match $e { - Ok(x) => x, - Err(e) => return Some(Err(From::from(e))), - } - }; -} - mod error; use ahash::RandomState; pub use error::*; From 8d264957b83a82f22d7f3e37bde2d6e69e316489 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Wed, 26 Jun 2024 19:18:14 -0700 Subject: [PATCH 112/197] Fix broken cross-reference in docs --- crates/dreammaker/src/ast.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index e2ecf09e..3284f5d4 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -13,7 +13,7 @@ use crate::error::Location; /// Arguments for [`Term::Pick`] pub type PickArgs = [(Option, Expression)]; -/// Cases for [`Term::Switch`] +/// Cases for [`Statement::Switch`] pub type SwitchCases = [(Spanned>, Block)]; // ---------------------------------------------------------------------------- From b62b10ce40b514b700c24f4d9c0709aeef2d96a0 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Wed, 26 Jun 2024 23:19:43 -0700 Subject: [PATCH 113/197] Fix some redundant TreePath->TypePath->TreePath conversions --- crates/dreammaker/src/ast.rs | 4 ---- crates/dreammaker/src/constants.rs | 14 +++++++------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 3284f5d4..e92fb985 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -726,10 +726,6 @@ impl<'a, T: fmt::Display> fmt::Display for FormatTreePath<'a, T> { /// A series of identifiers separated by path operators. pub type TypePath = Vec<(PathOp, Ident)>; -pub fn make_typepath(segments: Vec) -> TypePath { - segments.into_iter().fold(vec![], |mut acc, segment| { acc.push((PathOp::Slash, segment)); acc }) -} - pub struct FormatTypePath<'a>(pub &'a [(PathOp, Ident)]); impl<'a> fmt::Display for FormatTypePath<'a> { diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index 0a0c4aba..dde40d51 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -833,8 +833,8 @@ impl<'a> ConstantFolder<'a> { "type" => { if let Some(obj_tree) = &self.tree { let typeval = TypeRef::new(obj_tree, self.ty).get(); - let path = make_typepath(typeval.path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect()); - Constant::Prefab(Box::new(self.prefab(Prefab::from(path))?)) + let pop = Pop::from(typeval.path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect::()); + Constant::Prefab(Box::new(pop)) } else { return Err(self.error("no type context".to_owned())) } @@ -845,8 +845,8 @@ impl<'a> ConstantFolder<'a> { let Some(parent_type) = typeref.parent_type() else { return Err(self.error(format!("no parent type for {}", typeref))) }; - let path = make_typepath(parent_type.path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect()); - Constant::Prefab(Box::new(self.prefab(Prefab::from(path))?)) + let pop = Pop::from(parent_type.path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect::()); + Constant::Prefab(Box::new(pop)) } else { return Err(self.error("no type context".to_owned())) } @@ -861,8 +861,8 @@ impl<'a> ConstantFolder<'a> { Term::__TYPE__ => { if let Some(obj_tree) = &self.tree { let typeval = TypeRef::new(obj_tree, self.ty).get(); - let path = make_typepath(typeval.path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect()); - Constant::Prefab(Box::new(self.prefab(Prefab::from(path))?)) + let pop = Pop::from(typeval.path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect::()); + Constant::Prefab(Box::new(pop)) } else { return Err(self.error("No type context".to_owned())) } @@ -963,7 +963,7 @@ impl<'a> ConstantFolder<'a> { path_elements.push(declaration.kind.name().to_string()); } path_elements.push(proc_ref.name().to_string()); - Ok(Constant::Prefab(Box::new(self.prefab(Prefab::from(make_typepath(path_elements)))?))) + Ok(Constant::Prefab(Box::new(Pop::from(Box::from(path_elements))))) } fn rgb(&mut self, args: Box<[Expression]>) -> Result { From 239ff91947e37bfc3abdd5e7943e5386f8189970 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 27 Jun 2024 00:41:16 -0700 Subject: [PATCH 114/197] Tweak var/proc spans to fix issues with outline view Fixes #394. --- crates/dm-langserver/src/main.rs | 19 ++++++++++++------- crates/dreammaker/src/indents.rs | 4 ++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index a0d84877..9f63fe30 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -1810,10 +1810,12 @@ handle_method_call! { } // recursive traversal - fn find_document_symbols( - iter: &mut std::iter::Peekable, + fn find_document_symbols<'a, I>( + iter: &mut std::iter::Peekable, section_end: dm::Location, - ) -> Vec { + ) -> Vec + where I: Iterator, &'a Annotation)> + { let mut result = Vec::new(); loop { @@ -1823,9 +1825,7 @@ handle_method_call! { } } - let (child_range, annotation) = if let Some(x) = iter.next() { - x - } else { + let Some((child_range, annotation)) = iter.next() else { break; }; @@ -1918,7 +1918,12 @@ handle_method_call! { } else { let start = dm::Location { file: file_id, line: 0, column: 0 }; let end = dm::Location { file: file_id, line: !0, column: !0 }; - let mut iter = annotations.get_range(start..end).peekable(); + let mut vec: Vec<_> = annotations.get_range(start..end).collect(); + // Our traversal is outside-in. TreeBlock and Variable can have the + // same extent if the variable is the only thing in the block, so + // sort TreeBlocks first as well. + vec.sort_by_key(|x| (x.0.start, std::cmp::Reverse(x.0.end), if matches!(x.1, Annotation::TreeBlock(_)) { 0 } else { 1 })); + let mut iter = vec.into_iter().peekable(); Some(DocumentSymbolResponse::Nested(find_document_symbols(&mut iter, end))) } } diff --git a/crates/dreammaker/src/indents.rs b/crates/dreammaker/src/indents.rs index ab8bdafd..0028f4c2 100644 --- a/crates/dreammaker/src/indents.rs +++ b/crates/dreammaker/src/indents.rs @@ -141,11 +141,11 @@ impl<'ctx, I> IndentProcessor<'ctx, I> where } } else if indents == new_indents + 1 { // single unindent - self.push(Token::Punct(Punctuation::RBrace)); + self.push_eol(Token::Punct(Punctuation::RBrace)); } else if indents > new_indents { // multiple unindent for _ in new_indents..indents { - self.push(Token::Punct(Punctuation::RBrace)); + self.push_eol(Token::Punct(Punctuation::RBrace)); } } else { // same indent as before From 9d99263bec6664d25e594915f0836c0afae5bbe5 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 27 Jun 2024 18:08:15 -0700 Subject: [PATCH 115/197] Improve detail notes in document outline --- crates/dm-langserver/src/main.rs | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index 9f63fe30..7dc44a4e 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -1806,13 +1806,22 @@ handle_method_call! { on DocumentSymbolRequest(&mut self, params) { fn name_and_detail(path: &[String]) -> (String, Option) { let (name, rest) = path.split_last().unwrap(); - (name.to_owned(), rest.last().map(ToOwned::to_owned)) + ( + name.to_owned(), + rest.iter().rev().find(|x| + dm::ast::ProcDeclKind::from_name(x).is_none() && + dm::ast::ProcFlags::from_name(x).is_none() && + dm::ast::VarTypeFlags::from_name(x).is_none() && + *x != "var" + ).map(ToOwned::to_owned) + ) } // recursive traversal fn find_document_symbols<'a, I>( iter: &mut std::iter::Peekable, section_end: dm::Location, + skip_front: usize, ) -> Vec where I: Iterator, &'a Annotation)> { @@ -1835,7 +1844,7 @@ handle_method_call! { match annotation { Annotation::TreeBlock(ref path) => { if path.is_empty() { continue } - let (name, detail) = name_and_detail(path); + let (name, detail) = name_and_detail(&path[skip_front..]); result.push(DocumentSymbol { name, detail, @@ -1844,13 +1853,14 @@ handle_method_call! { deprecated: None, range, selection_range, - children: Some(find_document_symbols(iter, end)), + children: Some(find_document_symbols(iter, end, path.len())), }); }, Annotation::Variable(ref path) => { + let (name, detail) = name_and_detail(&path[skip_front..]); result.push(DocumentSymbol { - name: path.last().unwrap().to_owned(), - detail: None, + name: name, + detail: detail, kind: SymbolKind::FIELD, tags: None, deprecated: None, @@ -1861,7 +1871,7 @@ handle_method_call! { }, Annotation::ProcBody(ref path, _) => { if path.is_empty() { continue } - let (name, detail) = name_and_detail(path); + let (name, detail) = name_and_detail(&path[skip_front..]); let kind = if path.len() == 1 || (path.len() == 2 && path[0] == "proc") { SymbolKind::FUNCTION } else if is_constructor_name(&name) { @@ -1877,7 +1887,7 @@ handle_method_call! { tags: None, range, selection_range, - children: Some(find_document_symbols(iter, end)), + children: Some(find_document_symbols(iter, end, 0)), }); }, Annotation::LocalVarScope(_, ref name) => { @@ -1924,7 +1934,7 @@ handle_method_call! { // sort TreeBlocks first as well. vec.sort_by_key(|x| (x.0.start, std::cmp::Reverse(x.0.end), if matches!(x.1, Annotation::TreeBlock(_)) { 0 } else { 1 })); let mut iter = vec.into_iter().peekable(); - Some(DocumentSymbolResponse::Nested(find_document_symbols(&mut iter, end))) + Some(DocumentSymbolResponse::Nested(find_document_symbols(&mut iter, end, 0))) } } From ed98cd63d9ba628670cf547f595c0e3f7dd69545 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Fri, 28 Jun 2024 17:23:01 -0700 Subject: [PATCH 116/197] Fix outline panic on certain definitions in macros Fixed #395. --- crates/dm-langserver/src/main.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index 7dc44a4e..5a629390 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -1804,16 +1804,18 @@ handle_method_call! { #[allow(deprecated)] // DocumentSymbol::deprecated is... deprecated. But we need to provide a `None` anyways. on DocumentSymbolRequest(&mut self, params) { - fn name_and_detail(path: &[String]) -> (String, Option) { + fn name_and_detail(path: &[String], skip_front: usize) -> (String, Option) { let (name, rest) = path.split_last().unwrap(); ( name.to_owned(), - rest.iter().rev().find(|x| - dm::ast::ProcDeclKind::from_name(x).is_none() && - dm::ast::ProcFlags::from_name(x).is_none() && - dm::ast::VarTypeFlags::from_name(x).is_none() && - *x != "var" - ).map(ToOwned::to_owned) + rest.get(skip_front..).and_then(|i| + i.iter().rev().find(|x| + dm::ast::ProcDeclKind::from_name(x).is_none() && + dm::ast::ProcFlags::from_name(x).is_none() && + dm::ast::VarTypeFlags::from_name(x).is_none() && + *x != "var" + ).map(ToOwned::to_owned) + ) ) } @@ -1844,7 +1846,7 @@ handle_method_call! { match annotation { Annotation::TreeBlock(ref path) => { if path.is_empty() { continue } - let (name, detail) = name_and_detail(&path[skip_front..]); + let (name, detail) = name_and_detail(path, skip_front); result.push(DocumentSymbol { name, detail, @@ -1857,7 +1859,7 @@ handle_method_call! { }); }, Annotation::Variable(ref path) => { - let (name, detail) = name_and_detail(&path[skip_front..]); + let (name, detail) = name_and_detail(path, skip_front); result.push(DocumentSymbol { name: name, detail: detail, @@ -1871,7 +1873,7 @@ handle_method_call! { }, Annotation::ProcBody(ref path, _) => { if path.is_empty() { continue } - let (name, detail) = name_and_detail(&path[skip_front..]); + let (name, detail) = name_and_detail(path, skip_front); let kind = if path.len() == 1 || (path.len() == 2 && path[0] == "proc") { SymbolKind::FUNCTION } else if is_constructor_name(&name) { From 367bcdd75f736a91ab046d616ce56f61fb835a94 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Fri, 28 Jun 2024 17:24:52 -0700 Subject: [PATCH 117/197] Update error positions in tests --- crates/dreamchecker/tests/switch_rand_range_tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/dreamchecker/tests/switch_rand_range_tests.rs b/crates/dreamchecker/tests/switch_rand_range_tests.rs index c6685de7..dbcb26ed 100644 --- a/crates/dreamchecker/tests/switch_rand_range_tests.rs +++ b/crates/dreamchecker/tests/switch_rand_range_tests.rs @@ -3,7 +3,7 @@ extern crate dreamchecker as dc; use dc::test_helpers::*; pub const SWITCH_RAND_INCOMPLETE_ERRORS: &[(u32, u16, &str)] = &[ - (5, 9, "Case range '0 to 0' will never trigger as it is outside the rand() range 1 to 3"), + (4, 19, "Case range '0 to 0' will never trigger as it is outside the rand() range 1 to 3"), (2, 5, "Switch branches on rand() with range 1 to 3 but no case branch triggers for 3"), ]; @@ -54,7 +54,7 @@ fn switch_rand_case_ranges() { pub const SWITCH_RAND_DEFAULT_ERRORS: &[(u32, u16, &str)] = &[ - (5, 9, "Case range '5 to 5' will never trigger as it is outside the rand() range 1 to 4"), + (4, 19, "Case range '5 to 5' will never trigger as it is outside the rand() range 1 to 4"), ]; #[test] From 7c188f1f34a15cad4b2d60077a595dedbcc21557 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 7 Jul 2024 18:15:49 -0700 Subject: [PATCH 118/197] Fix dreamchecker and dmdoc not printing config errors --- crates/dmdoc/src/main.rs | 2 +- crates/dreamchecker/src/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 69476494..248ed948 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -82,8 +82,8 @@ fn main2() -> Result<(), Box> { println!("parsing {}", environment.display()); let mut context = dm::Context::default(); - context.autodetect_config(&environment); context.set_print_severity(Some(dm::Severity::Error)); + context.autodetect_config(&environment); let mut pp = dm::preprocessor::Preprocessor::new(&context, environment.clone())?; let (objtree, module_docs) = { let indents = dm::indents::IndentProcessor::new(&context, &mut pp); diff --git a/crates/dreamchecker/src/main.rs b/crates/dreamchecker/src/main.rs index 17e3c314..0b63b77f 100644 --- a/crates/dreamchecker/src/main.rs +++ b/crates/dreamchecker/src/main.rs @@ -50,12 +50,12 @@ fn main() { .expect("no .dme found")); let mut context = dm::Context::default(); + context.set_print_severity(Some(dm::Severity::Info)); if let Some(filepath) = config_file { context.force_config(filepath.as_ref()); } else { context.autodetect_config(&dme); } - context.set_print_severity(Some(dm::Severity::Info)); println!("============================================================"); println!("Parsing {}...\n", dme.display()); From b93a13f6a5f3a8fed43ae339662d0fee2c43a697 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 15 Jul 2024 18:22:46 -0700 Subject: [PATCH 119/197] Handle 'as movable' in proc return types and elsewhere See #399. --- crates/dreammaker/src/ast.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index e92fb985..66ccc511 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -510,6 +510,8 @@ type_table! { "password", PASSWORD, 1 << 15; "command_text", COMMAND_TEXT, 1 << 16; "color", COLOR, 1 << 17; + // Non-primitive combinations that are still valid as(X) calls: + "movable", MOVABLE, (1 << 0) | (1 << 1); } bitflags! { From 49a0f896241cf64840b6ff8bd534cf4313753710 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 15 Jul 2024 18:33:14 -0700 Subject: [PATCH 120/197] Parse 'as atom' See #399. --- crates/dreammaker/src/ast.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 66ccc511..414c7b30 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -511,7 +511,8 @@ type_table! { "command_text", COMMAND_TEXT, 1 << 16; "color", COLOR, 1 << 17; // Non-primitive combinations that are still valid as(X) calls: - "movable", MOVABLE, (1 << 0) | (1 << 1); + "movable", MOVABLE, Self::OBJ.bits | Self::MOB.bits; + "atom", ATOM, Self::AREA.bits | Self::TURF.bits | Self::OBJ.bits | Self::MOB.bits; } bitflags! { From 5de66004a7f5933cd435542824cde4665562448e Mon Sep 17 00:00:00 2001 From: ZeWaka Date: Mon, 15 Jul 2024 23:03:29 -0700 Subject: [PATCH 121/197] Fix preprocessor relative filepath evaluation for fexists (#401) The way I implemented const-eval'd fexists is slightly incorrect. It's evaulating the existence of the path relative to the working directory, instead of relative to the current file. This is causing errors in StrongDMM, because it's checking paths relative to the application exe file. I tested by building StrongDMM and using this fixed version, and it worked correctly. --- crates/dreammaker/src/constants.rs | 20 ++++++++++++++++---- crates/dreammaker/src/preprocessor.rs | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index dde40d51..b9559b92 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -2,6 +2,7 @@ use std::fmt; use std::ops; use std::path::Path; +use std::path::PathBuf; use get_size::GetSize; use get_size_derive::GetSize; @@ -435,6 +436,7 @@ impl Expression { /// Evaluate this expression in the absence of any surrounding context. pub fn simple_evaluate(self, location: Location) -> Result { ConstantFolder { + context: None, tree: None, location, ty: NodeIndex::new(0), @@ -444,8 +446,9 @@ impl Expression { } /// Evaluate an expression in the preprocessor, with `defined()` available. -pub fn preprocessor_evaluate(location: Location, expr: Expression, defines: &DefineMap) -> Result { +pub fn preprocessor_evaluate(location: Location, expr: Expression, defines: &DefineMap, context: Option<&Context>) -> Result { ConstantFolder { + context, tree: None, location, ty: NodeIndex::new(0), @@ -466,7 +469,7 @@ pub(crate) fn evaluate_all(context: &Context, tree: &mut ObjectTree) { { continue; // skip non-constant-evaluable vars } - match constant_ident_lookup(tree, ty, &key, false) { + match constant_ident_lookup(tree, ty, &key, false, Some(context)) { Err(err) => context.register_error(err), Ok(ConstLookup::Found(_)) => {} Ok(ConstLookup::Continue(_)) => { @@ -494,6 +497,7 @@ fn constant_ident_lookup( ty: NodeIndex, ident: &str, must_be_const: bool, + context: Option<&Context>, ) -> Result { // try to read the currently-set value if we can and // substitute that in, otherwise try to evaluate it. @@ -544,6 +548,7 @@ fn constant_ident_lookup( }; // evaluate full_value let value = ConstantFolder { + context, tree: Some(tree), defines: None, location, @@ -557,6 +562,7 @@ fn constant_ident_lookup( } struct ConstantFolder<'a> { + context: Option<&'a Context>, tree: Option<&'a mut ObjectTree>, defines: Option<&'a DefineMap>, location: Location, @@ -818,7 +824,13 @@ impl<'a> ConstantFolder<'a> { return Err(self.error(format!("malformed fexists() call, must have 1 argument and instead has {}", args.len()))); } match args[0].as_term() { - Some(Term::String(ref path)) => Constant::from(std::path::Path::new(path).exists()), + Some(Term::String(passed_path)) => { + let current_file = self.location().file; + let path = self.context + .map(|ctx| ctx.file_path(current_file).parent().unwrap().join(passed_path)) + .unwrap_or_else(|| PathBuf::from(passed_path)); + Constant::from(path.exists()) + }, _ => return Err(self.error("malformed fexists() call, argument given isn't a string.")), } } @@ -940,7 +952,7 @@ impl<'a> ConstantFolder<'a> { return Err(self.error(format!("cannot reference variable {:?} in this context", ident))); } let tree = self.tree.as_mut().unwrap(); - match constant_ident_lookup(tree, ty, ident, must_be_const) + match constant_ident_lookup(tree, ty, ident, must_be_const, self.context) .map_err(|e| e.with_location(location))? { ConstLookup::Found(v) => return Ok(v), diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index 22361329..83d703f3 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -616,7 +616,7 @@ impl<'ctx> Preprocessor<'ctx> { start, self.output.drain(..), )?; - Ok(crate::constants::preprocessor_evaluate(start, expr, &self.defines)?.to_bool()) + Ok(crate::constants::preprocessor_evaluate(start, expr, &self.defines, Some(self.context))?.to_bool()) } fn evaluate(&mut self) -> bool { From e72dd6074664b4277985f473f59fe5d2390d2bc8 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 15 Jul 2024 19:30:11 -0700 Subject: [PATCH 122/197] Fix extra blank line on #warn and #error messages --- crates/dreammaker/src/preprocessor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index 83d703f3..27954542 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -971,14 +971,14 @@ impl<'ctx> Preprocessor<'ctx> { "warn" if disabled => {} "warn" => { expect_token!((text) = Token::String(text)); - DMError::new(self.last_input_loc, format!("#{} {}", ident, text)) + DMError::new(self.last_input_loc, format!("#{} {}", ident, text.trim_end_matches(['\r', '\n']))) .set_severity(Severity::Warning) .register(self.context); } "error" if disabled => {} "error" => { expect_token!((text) = Token::String(text)); - self.context.register_error(DMError::new(self.last_input_loc, format!("#{} {}", ident, text))); + self.context.register_error(DMError::new(self.last_input_loc, format!("#{} {}", ident, text.trim_end_matches(['\r', '\n'])))); } "pragma" if disabled => {} "pragma" => { From afc817e66821b71f528145d3248908dde3cade64 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 15 Jul 2024 23:06:27 -0700 Subject: [PATCH 123/197] Improve fexists() error handling Treat the call as invalid if no context is set, and error instead of evaluating the existence of the wrong path if the current file has no known parent. --- crates/dreammaker/src/constants.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index b9559b92..c757a65e 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -2,7 +2,6 @@ use std::fmt; use std::ops; use std::path::Path; -use std::path::PathBuf; use get_size::GetSize; use get_size_derive::GetSize; @@ -819,18 +818,21 @@ impl<'a> ConstantFolder<'a> { None => return Err(self.error("malformed nameof() call, expression appears to have no name")), } } - "fexists" if self.defines.is_some() => { + "fexists" if self.defines.is_some() && self.context.is_some() => { if args.len() != 1 { return Err(self.error(format!("malformed fexists() call, must have 1 argument and instead has {}", args.len()))); } match args[0].as_term() { Some(Term::String(passed_path)) => { - let current_file = self.location().file; - let path = self.context - .map(|ctx| ctx.file_path(current_file).parent().unwrap().join(passed_path)) - .unwrap_or_else(|| PathBuf::from(passed_path)); - Constant::from(path.exists()) - }, + let current_file_path = self.context.unwrap(/* is_some checked above */).file_path(self.location.file); + let Some(current_dir) = current_file_path.parent() else { + return Err(self.error(format!( + "fexists() file has no parent: {:?}", + current_file_path + ))); + }; + current_dir.join(passed_path).exists().into() + } _ => return Err(self.error("malformed fexists() call, argument given isn't a string.")), } } From 58258e60138fa0e0efeb1676a18ee8e64d508a83 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 21 Jul 2024 19:45:18 -0700 Subject: [PATCH 124/197] Remove old .travis.yml --- .travis.yml | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9ba3de64..00000000 --- a/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -language: rust -rust: - - stable -branches: - only: - - master -cache: cargo -before_cache: - - cargo-cache -install: - - rustc -Vv - - cargo -V - - cargo install cargo-cache --no-default-features --features ci-autoclean cargo-cache -script: - - cargo build --verbose --all - - cargo test --verbose --all From 47643caae18baa2c9a1ab57cf9788b653a62f82d Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 21 Jul 2024 19:52:53 -0700 Subject: [PATCH 125/197] Fix Clippy lints --- crates/dm-langserver/src/main.rs | 4 ++-- crates/dmm-tools/src/dmm.rs | 2 +- crates/dmm-tools/src/render_passes/mod.rs | 4 ++-- crates/dreammaker/src/objtree.rs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index 5a629390..c54b4edf 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -1861,8 +1861,8 @@ handle_method_call! { Annotation::Variable(ref path) => { let (name, detail) = name_and_detail(path, skip_front); result.push(DocumentSymbol { - name: name, - detail: detail, + name, + detail, kind: SymbolKind::FIELD, tags: None, deprecated: None, diff --git a/crates/dmm-tools/src/dmm.rs b/crates/dmm-tools/src/dmm.rs index 4b9420f7..1a8e917b 100644 --- a/crates/dmm-tools/src/dmm.rs +++ b/crates/dmm-tools/src/dmm.rs @@ -306,7 +306,7 @@ impl fmt::Display for Coord3 { impl Key { pub fn invalid() -> Key { - Key(KeyType::max_value()) + Key(KeyType::MAX) } pub fn next(self) -> Key { diff --git a/crates/dmm-tools/src/render_passes/mod.rs b/crates/dmm-tools/src/render_passes/mod.rs index ba9fbfaa..7e4063f1 100644 --- a/crates/dmm-tools/src/render_passes/mod.rs +++ b/crates/dmm-tools/src/render_passes/mod.rs @@ -382,7 +382,7 @@ impl RenderPass for Pretty { } else if atom.istype("/obj/structure/tank_dispenser/") { if let &Constant::Float(oxygen) = atom.get_var("oxygentanks", objtree) { match oxygen as i32 { - 4..=std::i32::MAX => add_to(overlays, atom, "oxygen-4"), + 4..=i32::MAX => add_to(overlays, atom, "oxygen-4"), 3 => add_to(overlays, atom, "oxygen-3"), 2 => add_to(overlays, atom, "oxygen-2"), 1 => add_to(overlays, atom, "oxygen-1"), @@ -391,7 +391,7 @@ impl RenderPass for Pretty { } if let &Constant::Float(plasma) = atom.get_var("plasmatanks", objtree) { match plasma as i32 { - 5..=std::i32::MAX => add_to(overlays, atom, "plasma-5"), + 5..=i32::MAX => add_to(overlays, atom, "plasma-5"), 4 => add_to(overlays, atom, "plasma-4"), 3 => add_to(overlays, atom, "plasma-3"), 2 => add_to(overlays, atom, "plasma-2"), diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index dae9d96d..9936aad2 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -1312,7 +1312,7 @@ impl NodeIndex { #[inline] pub fn end() -> Self { - NodeIndex(std::u32::MAX) + NodeIndex(u32::MAX) } } From 9d988a11014dfd8eca5864ff25132b89f95ce0df Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 8 Aug 2024 17:24:33 -0700 Subject: [PATCH 126/197] Parse `as list` return type Fixes #399. --- crates/dreammaker/src/ast.rs | 2 ++ crates/dreammaker/tests/ast_tests.rs | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 414c7b30..c338b561 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -513,6 +513,8 @@ type_table! { // Non-primitive combinations that are still valid as(X) calls: "movable", MOVABLE, Self::OBJ.bits | Self::MOB.bits; "atom", ATOM, Self::AREA.bits | Self::TURF.bits | Self::OBJ.bits | Self::MOB.bits; + // Placeholder value for `as list` that's technically only legal as a proc return type, but whatever. + "list", LIST, 1 << 31; } bitflags! { diff --git a/crates/dreammaker/tests/ast_tests.rs b/crates/dreammaker/tests/ast_tests.rs index ea02ea8e..dcbb08e2 100644 --- a/crates/dreammaker/tests/ast_tests.rs +++ b/crates/dreammaker/tests/ast_tests.rs @@ -239,9 +239,8 @@ var/global/bill = 1 } #[test] -fn union_return_types() { +fn return_type_union() { // https://github.com/SpaceManiac/SpacemanDMM/issues/385 - with_code(" /proc/returns_num_or_text() as num | text ", |context, tree| { @@ -253,3 +252,18 @@ fn union_return_types() { ); }); } + +#[test] +fn return_type_list() { + // https://github.com/SpaceManiac/SpacemanDMM/issues/399 + with_code(" +/proc/returns_list() as list + ", |context, tree| { + context.assert_success(); + + assert_eq!( + tree.root().get_proc("returns_list").unwrap().get_declaration().unwrap().return_type, + ProcReturnType::InputType(InputType::LIST), + ); + }); +} From 0a003dfd4646aa0dc7d562534606f3db4ea27743 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 8 Aug 2024 17:54:28 -0700 Subject: [PATCH 127/197] Show parameter `as` types in dmdoc --- crates/dmdoc/src/main.rs | 3 +++ crates/dmdoc/src/template.rs | 49 ++++++++++++++++++++++++++++++++++++ crates/dreammaker/src/ast.rs | 6 +++++ 3 files changed, 58 insertions(+) diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 248ed948..65775eea 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -8,6 +8,7 @@ extern crate walkdir; mod markdown; mod template; +use dm::ast::InputType; use dm::objtree::ObjectTree; use maud::{Markup, PreEscaped}; use pulldown_cmark::{BrokenLink, CowStr}; @@ -404,6 +405,7 @@ fn main2() -> Result<(), Box> { params: proc_value.parameters.iter().map(|p| Param { name: p.name.clone(), type_path: format_type_path(&p.var_type.type_path), + input_type: p.input_type, }).collect(), decl: match proc.declaration { Some(ref decl) => decl.kind.name(), @@ -1298,6 +1300,7 @@ struct Proc { struct Param { name: String, type_path: String, + input_type: Option, } /// Module struct exposed to templates. diff --git a/crates/dmdoc/src/template.rs b/crates/dmdoc/src/template.rs index d6d3827f..734fd94f 100644 --- a/crates/dmdoc/src/template.rs +++ b/crates/dmdoc/src/template.rs @@ -2,6 +2,7 @@ use std::path::Path; +use dm::ast::InputType; use maud::{display, html, Markup, PreEscaped, Render, DOCTYPE}; use crate::{markdown::DocBlock, Environment, Index, IndexTree, ModuleArgs, ModuleItem, Type}; @@ -443,6 +444,12 @@ pub(crate) fn dm_type(ty: &Type) -> Markup { "/" } (param.name) + @if let Some(input_type) = param.input_type { + @if !input_type.is_empty() { + i { " as " } + (render_input_type(env, input_type)) + } + } } ") " (git_link(env, &proc.file.to_string_lossy(), proc.line)) @@ -455,6 +462,48 @@ pub(crate) fn dm_type(ty: &Type) -> Markup { ) } +pub fn render_input_type(env: &Environment, input_type: InputType) -> Markup { + html! { + @for (i, &name) in matching_names(input_type).iter().enumerate() { + @if i > 0 { " | " } + @match name { + "mob" => (linkify_input_type(env, "mob", "/mob")), + "obj" => (linkify_input_type(env, "obj", "/obj")), + "turf" => (linkify_input_type(env, "turf", "/turf")), + "area" => (linkify_input_type(env, "area", "/area")), + //"icon" => (linkify_input_type(env, "icon", "/icon")), + //"sound" => (linkify_input_type(env, "sound", "/sound")), + "movable" => (linkify_input_type(env, "movable", "/atom/movable")), + "atom" => (linkify_input_type(env, "atom", "/atom")), + "list" => (linkify_input_type(env, "list", "/list")), + _ => (name), + } + } + } +} + +fn linkify_input_type(env: &Environment, show: &str, typepath: &str) -> Markup { + if env.all_type_names.contains(typepath) { + html! { + a href=(format!("{}.html", &typepath[1..])) { (show) } + } + } else { + html! { (show) } + } +} + +fn matching_names(mut input_type: InputType) -> Vec<&'static str> { + let mut result = Vec::with_capacity(input_type.bits().count_ones() as usize); + for &(name, value) in InputType::ENTRIES.iter().rev() { + if input_type.contains(value) { + input_type.remove(value); + result.push(name); + } + } + result.reverse(); + result +} + pub fn save_resources(output_path: &Path) -> std::io::Result<()> { #[cfg(debug_assertions)] macro_rules! resources { diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index c338b561..bbdeca0c 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -456,6 +456,12 @@ macro_rules! type_table { } } + impl $name { + pub const ENTRIES: &'static [(&'static str, $name)] = &[ + $(($txt, $name::$i),)* + ]; + } + impl std::str::FromStr for $name { type Err = (); From 8df23f779394a48314a744931b5a7bbb08d5b1ba Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 8 Aug 2024 18:29:33 -0700 Subject: [PATCH 128/197] Show proc return `as` types in dmdoc --- crates/dmdoc/src/main.rs | 8 +++++--- crates/dmdoc/src/template.rs | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 65775eea..494fff04 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -8,7 +8,7 @@ extern crate walkdir; mod markdown; mod template; -use dm::ast::InputType; +use dm::ast::{InputType, ProcReturnType}; use dm::objtree::ObjectTree; use maud::{Markup, PreEscaped}; use pulldown_cmark::{BrokenLink, CowStr}; @@ -413,6 +413,7 @@ fn main2() -> Result<(), Box> { }, file: context.file_path(proc_value.location.file), line: proc_value.location.line, + return_type: proc.declaration.as_ref().map(|d| &d.return_type), parent, }); anything = true; @@ -1263,7 +1264,7 @@ struct ParsedType<'a> { docs: Option, substance: bool, vars: BTreeMap<&'a str, Var<'a>>, - procs: BTreeMap<&'a str, Proc>, + procs: BTreeMap<&'a str, Proc<'a>>, htmlname: &'a str, file: PathBuf, line: u32, @@ -1288,13 +1289,14 @@ struct VarType<'a> { path: &'a [String], } -struct Proc { +struct Proc<'a> { docs: DocBlock, decl: &'static str, params: Vec, file: PathBuf, line: u32, parent: Option, + return_type: Option<&'a ProcReturnType>, } struct Param { diff --git a/crates/dmdoc/src/template.rs b/crates/dmdoc/src/template.rs index 734fd94f..901d2927 100644 --- a/crates/dmdoc/src/template.rs +++ b/crates/dmdoc/src/template.rs @@ -2,7 +2,7 @@ use std::path::Path; -use dm::ast::InputType; +use dm::ast::{InputType, ProcReturnType}; use maud::{display, html, Markup, PreEscaped, Render, DOCTYPE}; use crate::{markdown::DocBlock, Environment, Index, IndexTree, ModuleArgs, ModuleItem, Type}; @@ -446,12 +446,24 @@ pub(crate) fn dm_type(ty: &Type) -> Markup { (param.name) @if let Some(input_type) = param.input_type { @if !input_type.is_empty() { - i { " as " } + small { " as " } (render_input_type(env, input_type)) } } } ") " + @match proc.return_type { + Some(ProcReturnType::InputType(i)) if !i.is_empty() => { + small { " as " } + ({ eprintln!("{:?}", proc.file); "" }) + (render_input_type(env, *i)) + }, + Some(ProcReturnType::TypePath(p)) => { + small { " as " } + (env.linkify_type_array(p)) + }, + _ => {}, + } (git_link(env, &proc.file.to_string_lossy(), proc.line)) } } From 20dabdca3ab4cd1d6ca12b08f7b809c7faa47cc0 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 8 Aug 2024 18:47:07 -0700 Subject: [PATCH 129/197] Show proc `set SpacemanDMM_return_type` in dmdoc --- crates/dmdoc/src/main.rs | 35 ++++++++++++++++++++++++++++++----- crates/dmdoc/src/template.rs | 2 +- crates/dreammaker/src/ast.rs | 6 ++++++ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 494fff04..dc7e03b4 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -88,7 +88,8 @@ fn main2() -> Result<(), Box> { let mut pp = dm::preprocessor::Preprocessor::new(&context, environment.clone())?; let (objtree, module_docs) = { let indents = dm::indents::IndentProcessor::new(&context, &mut pp); - let parser = dm::parser::Parser::new(&context, indents); + let mut parser = dm::parser::Parser::new(&context, indents); + parser.enable_procs(); // for `set SpacemanDMM_return_type` parser.parse_with_module_docs() }; let define_history = pp.finalize(); @@ -399,6 +400,14 @@ fn main2() -> Result<(), Box> { )); } + let return_type = proc.declaration.as_ref() + .map(|decl| &decl.return_type) + .filter(|ret| !ret.is_empty()) + .cloned() // could use Cow maybe + .or_else(|| { + proc_value.code.as_ref().and_then(find_return_type).map(ProcReturnType::TypePath) + }); + // add the proc to the type containing it parsed_type.procs.insert(name, Proc { docs: block, @@ -413,7 +422,7 @@ fn main2() -> Result<(), Box> { }, file: context.file_path(proc_value.location.file), line: proc_value.location.line, - return_type: proc.declaration.as_ref().map(|d| &d.return_type), + return_type, parent, }); anything = true; @@ -707,6 +716,22 @@ fn main2() -> Result<(), Box> { Ok(()) } +fn find_return_type(code: &dm::ast::Block) -> Option> { + for stmt in code { + if let dm::ast::Statement::Setting { name, mode: dm::ast::SettingMode::Assign, value } = &stmt.elem { + if name.as_str() == "SpacemanDMM_return_type" { + if let Some(dm::ast::Term::Prefab(fab)) = value.as_term() { + let bits: Vec<_> = fab.path.iter().map(|(_, name)| name.to_owned()).collect(); + return Some(bits); + } + } + } else { + break; + } + } + None +} + // reference & other captures -> (href, tooltip) // this function's purpose is to prevent code copying in above closures #[allow(clippy::too_many_arguments)] @@ -1264,7 +1289,7 @@ struct ParsedType<'a> { docs: Option, substance: bool, vars: BTreeMap<&'a str, Var<'a>>, - procs: BTreeMap<&'a str, Proc<'a>>, + procs: BTreeMap<&'a str, Proc>, htmlname: &'a str, file: PathBuf, line: u32, @@ -1289,14 +1314,14 @@ struct VarType<'a> { path: &'a [String], } -struct Proc<'a> { +struct Proc { docs: DocBlock, decl: &'static str, params: Vec, file: PathBuf, line: u32, parent: Option, - return_type: Option<&'a ProcReturnType>, + return_type: Option, } struct Param { diff --git a/crates/dmdoc/src/template.rs b/crates/dmdoc/src/template.rs index 901d2927..b963c63e 100644 --- a/crates/dmdoc/src/template.rs +++ b/crates/dmdoc/src/template.rs @@ -452,7 +452,7 @@ pub(crate) fn dm_type(ty: &Type) -> Markup { } } ") " - @match proc.return_type { + @match &proc.return_type { Some(ProcReturnType::InputType(i)) if !i.is_empty() => { small { " as " } ({ eprintln!("{:?}", proc.file); "" }) diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index bbdeca0c..9432894f 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -305,6 +305,12 @@ pub enum ProcReturnType { TypePath(Vec), } +impl ProcReturnType { + pub fn is_empty(&self) -> bool { + matches!(self, ProcReturnType::InputType(InputType { bits: 0 })) + } +} + impl Default for ProcReturnType { fn default() -> Self { ProcReturnType::InputType(InputType::empty()) From a24a15a0fe755043d39f3c3e3b77718a45861902 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 8 Aug 2024 18:53:52 -0700 Subject: [PATCH 130/197] Fix dmdoc linkification of types like `/list/datum` --- crates/dmdoc/src/main.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index dc7e03b4..570f9224 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -993,6 +993,11 @@ fn linkify_type<'a, I: Iterator>(all_type_names: &BTreeSet &progress[1..] ); progress.clear(); + } else if all_progress == "/list" { + // Let `/list/datum` resolve to `/list/datum`. + output.push_str("/list"); + all_progress.clear(); + progress.clear(); } } output.push_str(&progress); From 568f4f417fbe80176d2c6a7ce6836a6dfc423381 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 8 Aug 2024 19:45:23 -0700 Subject: [PATCH 131/197] Permit 'operator' in type names again Fixes #374. --- crates/dreammaker/src/parser.rs | 19 +++++++++++++------ crates/dreammaker/tests/ast_tests.rs | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 6ad561b7..294b4c56 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -704,11 +704,18 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } } // followed by ('/' ident)* - while parts.last().unwrap() != "operator" && self.slash()?.is_some() { + while self.slash()?.is_some() { let mut slash_loc = self.location; if let Some(i) = self.ident_in_seq(parts.len())? { parts.push(i); } else { + // .../operator/ = ... / "operator/" + // but .../operator/ident = ... / "operator" / "ident" + let last = parts.last_mut().unwrap(); + if last == "operator" { + last.push('/'); + } + slash_loc.column += 1; self.annotate_precise(slash_loc..slash_loc, || { Annotation::IncompleteTreePath(absolute || always_absolute, parts.clone()) @@ -789,7 +796,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let (last_part, traverse) = match path.split_last_mut() { Some(x) => x, None => { - self.error("what?") + self.error("tree entry appears to have no name") .register(self.context); return SUCCESS; } @@ -844,7 +851,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // parse operator overloading definitions if last_part == "operator" { - self.try_read_operator_name(last_part)?; + let () = self.try_read_operator_name(last_part)?; } let var_suffix = if var_type.is_some() { @@ -956,7 +963,6 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { .set_severity(Severity::Warning) .register(self.context); } else if proc_builder.is_some() { - eprintln!("-- {:?}", last_part); self.error("child of `proc/` without body") .register(self.context); } else { @@ -977,7 +983,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // ------------------------------------------------------------------------ // Object tree - Procs - fn try_read_operator_name(&mut self, last_part: &mut String) -> Status<()> { + fn try_read_operator_name(&mut self, last_part: &mut String) -> Result<(), DMError> { use super::lexer::Token::Punct; use super::lexer::Punctuation::*; @@ -1000,6 +1006,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } else if self.exact(Punct(MulAssign))?.is_some() { last_part.push_str("*="); } else if self.exact(Punct(Slash))?.is_some() { + // Here for completeness, but REALLY handled in tree_path(). last_part.push('/'); } else if self.exact(Punct(DivAssign))?.is_some() { last_part.push_str("/="); @@ -1055,7 +1062,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } else if self.exact(Token::String("".to_string()))?.is_some() { last_part.push_str("\"\"") } - SUCCESS + Ok(()) } fn proc_params_and_body(&mut self, current: NodeIndex, proc_builder: Option, name: &str, entry_start: Location, absolute: bool, mut docs: DocCollection) -> Status<()> { diff --git a/crates/dreammaker/tests/ast_tests.rs b/crates/dreammaker/tests/ast_tests.rs index dcbb08e2..ac582d63 100644 --- a/crates/dreammaker/tests/ast_tests.rs +++ b/crates/dreammaker/tests/ast_tests.rs @@ -267,3 +267,24 @@ fn return_type_list() { ); }); } + +#[test] +fn proc_operator_slash() { + // https://github.com/SpaceManiac/SpacemanDMM/issues/399 + with_code(" +/datum/operator/proc/foo() +/datum/operator/() +/datum/operator/=() +/datum/operator + proc/bar() + ", |context, tree| { + context.assert_success(); + + eprintln!("{:#?}", tree.expect("/datum").procs); + + tree.expect("/datum/operator").get_proc("foo").unwrap(); + tree.expect("/datum").get_proc("operator/").unwrap(); + tree.expect("/datum").get_proc("operator/=").unwrap(); + tree.expect("/datum/operator").get_proc("bar").unwrap(); + }); +} From d423f00f784436625403a5dce26d7a0ba8d9cc42 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 8 Aug 2024 20:06:39 -0700 Subject: [PATCH 132/197] Fix dm-langserver warnings about unknown #[cfg] names --- crates/dm-langserver/Cargo.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index d0e19cba..dd6308b8 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -24,3 +24,9 @@ ahash = "0.8.0" [build-dependencies] chrono = "0.4.22" git2 = { version = "0.18.2", default-features = false } + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = [ + 'cfg(auxtools_bundle)', + 'cfg(extools_bundle)', +] } From 6cae59f0ef4dc83a84ada20c67e71bb5d4653771 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 8 Aug 2024 20:27:25 -0700 Subject: [PATCH 133/197] Bundle extools and auxtools in all builds, not just releases --- Cargo.lock | 204 ++++++++++++++++++ crates/dm-langserver/Cargo.toml | 2 + crates/dm-langserver/build.rs | 43 +++- .../src/debugger/auxtools_bundle.rs | 2 +- .../src/debugger/extools_bundle.rs | 2 +- crates/dm-langserver/src/main.rs | 4 +- scripts/build-langserver-release.sh | 5 - scripts/build-suite-release.sh | 5 - scripts/download-auxtools.sh | 21 -- scripts/download-extools.sh | 21 -- scripts/update-auxtools.sh | 10 +- 11 files changed, 249 insertions(+), 70 deletions(-) delete mode 100755 scripts/download-auxtools.sh delete mode 100755 scripts/download-extools.sh diff --git a/Cargo.lock b/Cargo.lock index 2f43c07d..44bf9055 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,6 +100,17 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "async-trait" +version = "0.1.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "attribute-derive" version = "0.6.1" @@ -134,6 +145,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bincode" version = "1.3.3" @@ -155,6 +172,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "builtins-proc-macro" version = "0.0.0" @@ -190,6 +216,12 @@ dependencies = [ "syn 2.0.68", ] +[[package]] +name = "bytes" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" + [[package]] name = "cc" version = "1.0.100" @@ -291,6 +323,15 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.4.2" @@ -325,6 +366,16 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "dap-types" version = "0.0.0" @@ -357,6 +408,16 @@ dependencies = [ "syn 2.0.68", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "dm-langserver" version = "1.9.0" @@ -377,6 +438,8 @@ dependencies = [ "serde", "serde_derive", "serde_json", + "sha256", + "ureq", "url", ] @@ -603,6 +666,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "get-size" version = "0.1.4" @@ -695,6 +768,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -1243,6 +1322,53 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys", +] + +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" + +[[package]] +name = "rustls-webpki" +version = "0.102.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "ryu" version = "1.0.18" @@ -1300,6 +1426,29 @@ dependencies = [ "syn 2.0.68", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha256" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18278f6a914fa3070aa316493f7d2ddfb9ac86ebc06fa3b83bffda487e9065b0" +dependencies = [ + "async-trait", + "bytes", + "hex", + "sha2", +] + [[package]] name = "simd-adler32" version = "0.3.7" @@ -1327,12 +1476,24 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "1.0.109" @@ -1388,6 +1549,12 @@ dependencies = [ "serde", ] +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicase" version = "2.7.0" @@ -1424,6 +1591,28 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" +dependencies = [ + "base64", + "flate2", + "log", + "once_cell", + "rustls", + "rustls-pki-types", + "url", + "webpki-roots", +] + [[package]] name = "url" version = "2.5.2" @@ -1524,6 +1713,15 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "weezl" version = "0.1.8" @@ -1640,3 +1838,9 @@ dependencies = [ "quote", "syn 2.0.68", ] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index dd6308b8..29a02e88 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -24,6 +24,8 @@ ahash = "0.8.0" [build-dependencies] chrono = "0.4.22" git2 = { version = "0.18.2", default-features = false } +sha256 = { version = "1.5.0", default-features = false } +ureq = "2.10.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = [ diff --git a/crates/dm-langserver/build.rs b/crates/dm-langserver/build.rs index d37a7a2c..78ed1bca 100644 --- a/crates/dm-langserver/build.rs +++ b/crates/dm-langserver/build.rs @@ -4,7 +4,7 @@ extern crate git2; use std::env; use std::fs::File; use std::io::Write; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; fn main() { // build info @@ -18,16 +18,24 @@ fn main() { writeln!(f, "build date: {}", chrono::Utc::now().date_naive()).unwrap(); // extools bundling - println!("cargo:rerun-if-env-changed=EXTOOLS_BUNDLE_DLL"); - if env::var_os("EXTOOLS_BUNDLE_DLL").is_some() { - println!("cargo:rustc-cfg=extools_bundle"); - } + println!("cargo:rustc-cfg=extools_bundle"); + download_dll( + &out_dir, + "extools.dll", + "v0.0.7", // EXTOOLS_TAG + "https://github.com/tgstation/tgstation/raw/34f0cc6394a064b87cbd1d6cb225f1d3df444ba7/byond-extools.dll", // EXTOOLS_DLL_URL + "073dd08790a13580bae71758e9217917700dd85ce8d35cb030cef0cf5920fca8", // EXTOOLS_DLL_SHA256 + ); // auxtools bundling - println!("cargo:rerun-if-env-changed=AUXTOOLS_BUNDLE_DLL"); - if env::var_os("AUXTOOLS_BUNDLE_DLL").is_some() { - println!("cargo:rustc-cfg=auxtools_bundle"); - } + println!("cargo:rustc-cfg=auxtools_bundle"); + download_dll( + &out_dir, + "debug_server.dll", + "v2.3.3", // DEBUG_SERVER_TAG + "https://github.com/willox/auxtools/releases/download/v2.3.3/debug_server.dll", // DEBUG_SERVER_DLL_URL + "8c3633d8237738be39a8c8f34bbd3d819cdaa270d1f30774c5007481fc32418c", // DEBUG_SERVER_DLL_SHA256 + ); } fn read_commit() -> Result { @@ -60,3 +68,20 @@ fn read_commit() -> Result { Ok(head.to_string()) } + +fn download_dll(out_dir: &Path, fname: &str, tag: &str, url: &str, sha256: &str) { + let full_path = out_dir.join(fname); + println!("cargo:rustc-env=BUNDLE_PATH_{}={}", fname, full_path.display()); + println!("cargo:rustc-env=BUNDLE_VERSION_{}={}", fname, tag); + + if let Ok(digest) = sha256::try_digest(&full_path) { + if digest == sha256 { + return; + } + } + + std::io::copy( + &mut ureq::get(url).call().expect("Error downloading DLL to bundle").into_reader(), + &mut std::fs::File::create(full_path).unwrap(), + ).unwrap(); +} diff --git a/crates/dm-langserver/src/debugger/auxtools_bundle.rs b/crates/dm-langserver/src/debugger/auxtools_bundle.rs index 3eb1e2a6..2f01b681 100644 --- a/crates/dm-langserver/src/debugger/auxtools_bundle.rs +++ b/crates/dm-langserver/src/debugger/auxtools_bundle.rs @@ -3,7 +3,7 @@ use std::fs::File; use std::io::{Result, Write}; use std::path::{Path, PathBuf}; -const BYTES: &[u8] = include_bytes!(env!("AUXTOOLS_BUNDLE_DLL")); +const BYTES: &[u8] = include_bytes!(env!("BUNDLE_PATH_debug_server.dll")); fn write(path: &Path) -> Result<()> { File::create(path)?.write_all(BYTES) diff --git a/crates/dm-langserver/src/debugger/extools_bundle.rs b/crates/dm-langserver/src/debugger/extools_bundle.rs index 04c631c8..29755dcc 100644 --- a/crates/dm-langserver/src/debugger/extools_bundle.rs +++ b/crates/dm-langserver/src/debugger/extools_bundle.rs @@ -3,7 +3,7 @@ use std::fs::File; use std::io::{Result, Write}; use std::path::{Path, PathBuf}; -const BYTES: &[u8] = include_bytes!(env!("EXTOOLS_BUNDLE_DLL")); +const BYTES: &[u8] = include_bytes!(env!("BUNDLE_PATH_extools.dll")); fn write(path: &Path) -> Result<()> { File::create(path)?.write_all(BYTES) diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index c54b4edf..cc1ece39 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -68,10 +68,10 @@ fn main() { } eprint!("{}", include_str!(concat!(env!("OUT_DIR"), "/build-info.txt"))); #[cfg(extools_bundle)] { - eprintln!("extools commit: {}", env!("EXTOOLS_COMMIT_HASH")); + eprintln!("extools commit: {}", env!("BUNDLE_VERSION_extools.dll")); } #[cfg(auxtools_bundle)] { - eprintln!("auxtools commit: {}", env!("AUXTOOLS_COMMIT_HASH")); + eprintln!("auxtools commit: {}", env!("BUNDLE_VERSION_debug_server.dll")); } match std::env::current_dir() { Ok(path) => eprintln!("directory: {}", path.display()), diff --git a/scripts/build-langserver-release.sh b/scripts/build-langserver-release.sh index bf610ed5..a2eb6027 100755 --- a/scripts/build-langserver-release.sh +++ b/scripts/build-langserver-release.sh @@ -4,11 +4,6 @@ set -euo pipefail cd "$(dirname "${BASH_SOURCE[0]}")" cd .. -# ----------------------------------------------------------------------------- -# Prepare dependency DLLs -eval "$(scripts/download-extools.sh)" -eval "$(scripts/download-auxtools.sh)" - # ----------------------------------------------------------------------------- # Cargo build touch crates/dm-langserver/build.rs diff --git a/scripts/build-suite-release.sh b/scripts/build-suite-release.sh index b3629b7e..84e128d4 100755 --- a/scripts/build-suite-release.sh +++ b/scripts/build-suite-release.sh @@ -9,11 +9,6 @@ cd .. relname=$(git describe --tags --exact) echo "Using tag name: $relname" -# ----------------------------------------------------------------------------- -# Prepare dependency DLLs -eval "$(scripts/download-extools.sh)" -eval "$(scripts/download-auxtools.sh)" - # ----------------------------------------------------------------------------- # Cargo build touch crates/*/build.rs diff --git a/scripts/download-auxtools.sh b/scripts/download-auxtools.sh deleted file mode 100755 index 92738f06..00000000 --- a/scripts/download-auxtools.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# Settings -DEBUG_SERVER_TAG=v2.3.3 -DEBUG_SERVER_DLL_URL=https://github.com/willox/auxtools/releases/download/v2.3.3/debug_server.dll -DEBUG_SERVER_DLL_SHA256=8c3633d8237738be39a8c8f34bbd3d819cdaa270d1f30774c5007481fc32418c - -# ----------------------------------------------------------------------------- -cd "$(dirname "${BASH_SOURCE[0]}")" -mkdir -p "../target/deps" -cd "../target/deps" - -AUXTOOLS_BUNDLE_DLL="$PWD/debug_server.dll" -echo "export AUXTOOLS_BUNDLE_DLL=$AUXTOOLS_BUNDLE_DLL" -echo "export AUXTOOLS_COMMIT_HASH=$DEBUG_SERVER_TAG" - -if ! test -f "$AUXTOOLS_BUNDLE_DLL" || ! sha256sum -c <<<"$DEBUG_SERVER_DLL_SHA256 $AUXTOOLS_BUNDLE_DLL" >/dev/null 2>/dev/null; then - wget -q -O "$AUXTOOLS_BUNDLE_DLL" "$DEBUG_SERVER_DLL_URL" >&2 - sha256sum -c <<<"$DEBUG_SERVER_DLL_SHA256 $AUXTOOLS_BUNDLE_DLL" >&2 -fi diff --git a/scripts/download-extools.sh b/scripts/download-extools.sh deleted file mode 100755 index 81d3f432..00000000 --- a/scripts/download-extools.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# Settings -EXTOOLS_TAG=v0.0.7 -EXTOOLS_DLL_URL=https://github.com/tgstation/tgstation/raw/34f0cc6394a064b87cbd1d6cb225f1d3df444ba7/byond-extools.dll -EXTOOLS_DLL_SHA256=073dd08790a13580bae71758e9217917700dd85ce8d35cb030cef0cf5920fca8 - -# ----------------------------------------------------------------------------- -cd "$(dirname "${BASH_SOURCE[0]}")" -mkdir -p "../target/deps" -cd "../target/deps" - -EXTOOLS_BUNDLE_DLL="$PWD/extools.dll" -echo "export EXTOOLS_BUNDLE_DLL=$EXTOOLS_BUNDLE_DLL" -echo "export EXTOOLS_COMMIT_HASH=$EXTOOLS_TAG" - -if ! test -f "$EXTOOLS_BUNDLE_DLL" || ! sha256sum -c <<<"$EXTOOLS_DLL_SHA256 $EXTOOLS_BUNDLE_DLL" >/dev/null 2>/dev/null; then - wget -q -O "$EXTOOLS_BUNDLE_DLL" "$EXTOOLS_DLL_URL" >&2 - sha256sum -c <<<"$EXTOOLS_DLL_SHA256 $EXTOOLS_BUNDLE_DLL" >&2 -fi diff --git a/scripts/update-auxtools.sh b/scripts/update-auxtools.sh index 528519e9..feb967b4 100755 --- a/scripts/update-auxtools.sh +++ b/scripts/update-auxtools.sh @@ -12,11 +12,11 @@ DEBUG_SERVER_DLL_URL=https://github.com/willox/auxtools/releases/download/$DEBUG DEBUG_SERVER_DLL_SHA256=$(curl -L -s "$DEBUG_SERVER_DLL_URL" | sha256sum | cut -d' ' -f1) sed \ - -e "/^DEBUG_SERVER_TAG=/c DEBUG_SERVER_TAG=$DEBUG_SERVER_TAG" \ - -e "/^DEBUG_SERVER_DLL_URL=/c DEBUG_SERVER_DLL_URL=$DEBUG_SERVER_DLL_URL" \ - -e "/^DEBUG_SERVER_DLL_SHA256=/c DEBUG_SERVER_DLL_SHA256=$DEBUG_SERVER_DLL_SHA256" \ + -e "/DEBUG_SERVER_TAG$/c\\ \"$DEBUG_SERVER_TAG\", // DEBUG_SERVER_TAG" \ + -e "/DEBUG_SERVER_DLL_URL$/c\\ \"$DEBUG_SERVER_DLL_URL\", // DEBUG_SERVER_DLL_URL" \ + -e "/DEBUG_SERVER_DLL_SHA256$/c\\ \"$DEBUG_SERVER_DLL_SHA256\", // DEBUG_SERVER_DLL_SHA256" \ --in-place \ - download-auxtools.sh + ../crates/dm-langserver/build.rs # Prepare the commit -git commit -m "Update to auxtools debug server $DEBUG_SERVER_TAG" -- download-auxtools.sh +git commit -m "Update to auxtools debug server $DEBUG_SERVER_TAG" -- ../crates/dm-langserver/build.rs From 4ca3cdf670c42cde9e62cec34283ec62631eba3e Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Fri, 9 Aug 2024 15:12:04 -0700 Subject: [PATCH 134/197] Remove leftover proc return debugging in dmdoc --- crates/dmdoc/src/template.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/dmdoc/src/template.rs b/crates/dmdoc/src/template.rs index b963c63e..75e1f656 100644 --- a/crates/dmdoc/src/template.rs +++ b/crates/dmdoc/src/template.rs @@ -455,7 +455,6 @@ pub(crate) fn dm_type(ty: &Type) -> Markup { @match &proc.return_type { Some(ProcReturnType::InputType(i)) if !i.is_empty() => { small { " as " } - ({ eprintln!("{:?}", proc.file); "" }) (render_input_type(env, *i)) }, Some(ProcReturnType::TypePath(p)) => { From 8c06700a4a9951d263404db776481a68beba23b0 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Fri, 9 Aug 2024 16:15:37 -0700 Subject: [PATCH 135/197] Make 'as' italic instead of small in dmdoc --- crates/dmdoc/src/template.rs | 6 +++--- crates/dmdoc/src/template/dmdoc.css | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/dmdoc/src/template.rs b/crates/dmdoc/src/template.rs index 75e1f656..06bdc4ff 100644 --- a/crates/dmdoc/src/template.rs +++ b/crates/dmdoc/src/template.rs @@ -446,7 +446,7 @@ pub(crate) fn dm_type(ty: &Type) -> Markup { (param.name) @if let Some(input_type) = param.input_type { @if !input_type.is_empty() { - small { " as " } + span class="as" { " as " } (render_input_type(env, input_type)) } } @@ -454,11 +454,11 @@ pub(crate) fn dm_type(ty: &Type) -> Markup { ") " @match &proc.return_type { Some(ProcReturnType::InputType(i)) if !i.is_empty() => { - small { " as " } + span class="as" { " as " } (render_input_type(env, *i)) }, Some(ProcReturnType::TypePath(p)) => { - small { " as " } + span class="as" { " as " } (env.linkify_type_array(p)) }, _ => {}, diff --git a/crates/dmdoc/src/template/dmdoc.css b/crates/dmdoc/src/template/dmdoc.css index 367f005d..8307e907 100644 --- a/crates/dmdoc/src/template/dmdoc.css +++ b/crates/dmdoc/src/template/dmdoc.css @@ -45,7 +45,7 @@ aside.declaration, aside.parent { margin-right: -100px; right: 105px; } -aside.declaration { +aside.declaration, span.as { font-style: italic; } table.summary tr:first-child > td > :first-child { From cb9444dc9e57bfcb77437332c53e35a9f89c1b15 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Fri, 9 Aug 2024 18:35:53 -0700 Subject: [PATCH 136/197] Show var `as` types in dmdoc --- crates/dmdoc/src/main.rs | 2 ++ crates/dmdoc/src/template.rs | 22 ++++++++++++++-------- crates/dreammaker/src/ast.rs | 10 ++++++++++ crates/dreammaker/src/objtree.rs | 1 + crates/dreammaker/src/parser.rs | 14 ++++++++++---- 5 files changed, 37 insertions(+), 12 deletions(-) diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 570f9224..fee3af28 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -350,6 +350,7 @@ fn main2() -> Result<(), Box> { //is_private: decl.var_type.flags.is_private(), //is_protected: decl.var_type.flags.is_protected(), path: &decl.var_type.type_path, + input_type: decl.var_type.input_type, }); parsed_type.vars.insert(name, Var { docs: block, @@ -1317,6 +1318,7 @@ struct VarType<'a> { //is_private: bool, //is_protected: bool, path: &'a [String], + input_type: InputType, } struct Proc { diff --git a/crates/dmdoc/src/template.rs b/crates/dmdoc/src/template.rs index 06bdc4ff..5d5cd724 100644 --- a/crates/dmdoc/src/template.rs +++ b/crates/dmdoc/src/template.rs @@ -405,14 +405,20 @@ pub(crate) fn dm_type(ty: &Type) -> Markup { } (name) @if let Some(ref ty) = var.type_ { - " " - aside { - "\u{2013} " // – - @if ty.is_static { "/static" } - @if ty.is_const { "/const" } - @if ty.is_tmp { "/tmp" } - @if ty.is_final { "/final" } - (env.linkify_type_array(ty.path)) + @if ty.is_static || ty.is_const || ty.is_tmp || ty.is_final || !ty.path.is_empty() || !ty.input_type.is_empty() { + " " + aside { + "\u{2013} " // – + @if ty.is_static { "/static" } + @if ty.is_const { "/const" } + @if ty.is_tmp { "/tmp" } + @if ty.is_final { "/final" } + (env.linkify_type_array(ty.path)) + @if !ty.input_type.is_empty() { + span class="as" { " as " } + (render_input_type(env, ty.input_type)) + } + } } } (git_link(env, &var.file.to_string_lossy(), var.line)) diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 9432894f..a1309a3f 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -529,6 +529,12 @@ type_table! { "list", LIST, 1 << 31; } +impl Default for InputType { + fn default() -> Self { + Self::empty() + } +} + bitflags! { #[derive(Default, GetSize)] pub struct VarTypeFlags: u8 { @@ -1218,6 +1224,7 @@ impl fmt::Display for Parameter { pub struct VarType { pub flags: VarTypeFlags, pub type_path: TreePath, + pub input_type: InputType, } impl VarType { @@ -1254,6 +1261,7 @@ impl fmt::Display for VarType { pub struct VarTypeBuilder { pub flags: VarTypeFlags, pub type_path: Vec, + pub input_type: Option, } impl VarTypeBuilder { @@ -1267,6 +1275,7 @@ impl VarTypeBuilder { VarType { flags: self.flags, type_path: self.type_path.into_boxed_slice(), + input_type: self.input_type.unwrap_or_default(), } } } @@ -1288,6 +1297,7 @@ impl FromIterator for VarTypeBuilder { VarTypeBuilder { flags, type_path, + input_type: None, } } } diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index 9936aad2..6aa2f374 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -1087,6 +1087,7 @@ impl ObjectTreeBuilder { let mut var_type = VarTypeBuilder { flags, type_path, + input_type: None, }; var_type.suffix(&suffix); diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 294b4c56..def602fc 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -903,7 +903,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let location = self.location; let expression = require!(self.expression()); - let _ = require!(self.input_specifier()); // TODO: save to VarType instead of ignoring + // TODO: save `in` expression? + let (input_type, _) = require!(self.input_specifier()); // We have to annotate prior to consuming the statement terminator, as we // will otherwise consume following whitespace resulting in a bad annotation range @@ -919,6 +920,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { if let Some(mut var_type) = var_type { var_type.suffix(&var_suffix); + var_type.input_type = input_type; self.tree.declare_var(current, last_part, location, docs, var_type.build(), Some(expression)); } else { self.tree.override_var(current, last_part, location, docs, expression); @@ -934,9 +936,12 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { _ => { // usually `thing;` - a contentless declaration - if var_type.is_some() { - let _ = require!(self.input_specifier()); // TODO: save to VarType instead of ignoring - } + let input_type = if var_type.is_some() { + // TODO: save `in` expression? + require!(self.input_specifier()).0 + } else { + None + }; // Same-line `//!` comment AFTER while let Some(comment) = self.enclosing_doc_comment()? { @@ -954,6 +959,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { .register(self.context); } else { var_type.suffix(&var_suffix); + var_type.input_type = input_type; let node = self.tree.get_path(current).to_owned(); self.annotate(entry_start, || Annotation::Variable(reconstruct_path(&node, proc_builder, Some(&var_type), last_part))); self.tree.declare_var(current, last_part, self.location, docs, var_type.build(), var_suffix.into_initializer()); From a7649bdce1ac91acf6f8930168295d80de5d0c14 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Fri, 9 Aug 2024 20:50:33 -0700 Subject: [PATCH 137/197] Fix module git links in dmdoc --- crates/dmdoc/src/template.rs | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/crates/dmdoc/src/template.rs b/crates/dmdoc/src/template.rs index 5d5cd724..89949326 100644 --- a/crates/dmdoc/src/template.rs +++ b/crates/dmdoc/src/template.rs @@ -84,21 +84,36 @@ fn teaser(block: &DocBlock, prefix: &str) -> Markup { } fn git_link(env: &Environment, file: &str, line: u32) -> Markup { + let title = if line == 0 { + file + } else { + &format!("{} {}", file, line) + }; let icon = html! { - img src="git.png" width="16" height="16" title=(format!("{}{}{}", file, if line != 0 { " " } else { "" }, line)); + img src="git.png" width="16" height="16" title=(title); }; html! { - @if !file.is_empty() { + @if !file.is_empty() && file != "(builtins)" { " " @if !env.git.web_url.is_empty() && !env.git.revision.is_empty() { - a href=(format!( - "{}/blob/{}/{}{}{}", - env.git.web_url, - env.git.revision, - file, - if line != 0 { "#L" } else { "" }, - line - )) { + a href=( + if line == 0 { + format!( + "{}/blob/{}/{}", + env.git.web_url, + env.git.revision, + file + ) + } else { + format!( + "{}/blob/{}/{}#L{}", + env.git.web_url, + env.git.revision, + file, + line + ) + } + ) { (icon) } } @else { From 86172de96511aa8d10508fb3bf6a6df36bf9d311 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Wed, 21 Aug 2024 21:22:29 -0700 Subject: [PATCH 138/197] Handle 'as' return types in dreamchecker Fixes #406. --- crates/dreamchecker/src/lib.rs | 19 +++++++++++++++++++ crates/dreammaker/src/ast.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index aa54aead..1f3e12b9 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -753,6 +753,7 @@ impl<'o> AnalyzeObjectTree<'o> { /// Gather and store set directives for the given proc using the provided code body and already existing flags pub fn gather_settings(&mut self, proc: ProcRef<'o>, code: &'o [Spanned]) { let proc_location = proc.get().location; + // Need to extract OUR declaration, and not our parent's. so we do the stupid if let Some(proc_type) = proc.ty().get().procs.get(proc.name()) { if let Some(declaration) = &proc_type.declaration { @@ -765,6 +766,24 @@ impl<'o> AnalyzeObjectTree<'o> { } } } + + if let Some(decl) = proc.get_declaration() { + match &decl.return_type { + ProcReturnType::InputType(input_type) => { + if let Some(path) = input_type.to_typepath() { + if let Some(ty) = self.objtree.find(path) { + self.return_type.insert(proc, TypeExpr::from(StaticType::Type(ty))); + } + } + } + ProcReturnType::TypePath(bits) => { + if let Ok(ty) = crate::static_type(self.objtree, proc_location, bits) { + self.return_type.insert(proc, TypeExpr::from(ty)); + } + } + } + } + for statement in code.iter() { if let Statement::Setting { ref name, ref value, .. } = statement.elem { if name == "SpacemanDMM_return_type" { diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index a1309a3f..6f35aa1f 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -535,6 +535,33 @@ impl Default for InputType { } } +impl InputType { + /// Get a typepath that approximates this input type, if possible. + pub fn to_typepath(&self) -> Option<&'static str> { + if self.is_empty() { + None + } else if *self == InputType::MOB { + Some("/mob") + } else if *self == InputType::OBJ { + Some("/obj") + } else if *self == InputType::TURF { + Some("/turf") + } else if *self == InputType::AREA { + Some("/area") + } else if *self == InputType::LIST { + Some("/list") + } else if self.difference(InputType::MOVABLE).is_empty() { + // Only applies to exactly movable = mob | obj + Some("/atom/movable") + } else if self.difference(InputType::ATOM).is_empty() { + // Might apply to area|turf or turf|mob or similar combos + Some("/atom") + } else { + None + } + } +} + bitflags! { #[derive(Default, GetSize)] pub struct VarTypeFlags: u8 { From 88a9fd048c1c6065d7f6ca0552ce685c60a4925b Mon Sep 17 00:00:00 2001 From: ZeWaka Date: Fri, 25 Oct 2024 21:07:11 -0700 Subject: [PATCH 139/197] Upgrade packages to Rust 2021 (#412) More modern edition of the compiler --- Cargo.toml | 1 + crates/builtins-proc-macro/Cargo.toml | 2 +- crates/dap-types/Cargo.toml | 2 +- crates/dm-langserver/Cargo.toml | 2 +- crates/dm-langserver/src/macros.rs | 2 +- crates/dmdoc/Cargo.toml | 2 +- crates/dmm-tools-cli/Cargo.toml | 2 +- crates/dmm-tools/Cargo.toml | 2 +- crates/dreamchecker/Cargo.toml | 2 +- crates/dreammaker/Cargo.toml | 2 +- crates/dreammaker/src/parser.rs | 2 +- crates/dreammaker/tests/format_tests.rs | 4 ++-- crates/interval-tree/Cargo.toml | 2 +- crates/spaceman-dmm/Cargo.toml | 2 +- 14 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 03658aa4..db15750d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ members = [ "crates/interval-tree", #"crates/spaceman-dmm", ] +resolver = "2" [profile.dev] opt-level = 2 diff --git a/crates/builtins-proc-macro/Cargo.toml b/crates/builtins-proc-macro/Cargo.toml index 5d4cb9ea..33188b43 100644 --- a/crates/builtins-proc-macro/Cargo.toml +++ b/crates/builtins-proc-macro/Cargo.toml @@ -2,7 +2,7 @@ name = "builtins-proc-macro" version = "0.0.0" authors = ["Tad Hardesty "] -edition = "2018" +edition = "2021" [lib] proc-macro = true diff --git a/crates/dap-types/Cargo.toml b/crates/dap-types/Cargo.toml index 72f995c4..06608f38 100644 --- a/crates/dap-types/Cargo.toml +++ b/crates/dap-types/Cargo.toml @@ -2,7 +2,7 @@ name = "dap-types" version = "0.0.0" authors = ["Tad Hardesty "] -edition = "2018" +edition = "2021" [dependencies] serde = "1.0.144" diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index 29a02e88..c6e52424 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -2,7 +2,7 @@ name = "dm-langserver" version = "1.9.0" authors = ["Tad Hardesty "] -edition = "2018" +edition = "2021" [dependencies] url = "2.3.1" diff --git a/crates/dm-langserver/src/macros.rs b/crates/dm-langserver/src/macros.rs index e7d25ea1..46eb05da 100644 --- a/crates/dm-langserver/src/macros.rs +++ b/crates/dm-langserver/src/macros.rs @@ -142,7 +142,7 @@ macro_rules! if_annotation { } macro_rules! match_annotation { - ($a:expr; $($($p:pat)|* => $b:block,)*) => { + ($a:expr; $($($p:pat_param)|* => $b:block,)*) => { for (_, thing) in $a.clone() { match thing { $($($p)|* => $b,)* diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index b69bb488..47879959 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -3,7 +3,7 @@ name = "dmdoc" version = "1.9.0" authors = ["Tad Hardesty "] homepage = "https://github.com/SpaceManiac/SpacemanDMM/blob/master/crates/dmdoc/README.md" -edition = "2018" +edition = "2021" [dependencies] dreammaker = { path = "../dreammaker" } diff --git a/crates/dmm-tools-cli/Cargo.toml b/crates/dmm-tools-cli/Cargo.toml index 5f8fafd5..d106d2b9 100644 --- a/crates/dmm-tools-cli/Cargo.toml +++ b/crates/dmm-tools-cli/Cargo.toml @@ -3,7 +3,7 @@ name = "dmm-tools-cli" version = "1.9.0" authors = ["Tad Hardesty "] description = "BYOND map rendering and analysis tools powered by SpacemanDMM" -edition = "2018" +edition = "2021" [[bin]] name = "dmm-tools" diff --git a/crates/dmm-tools/Cargo.toml b/crates/dmm-tools/Cargo.toml index 77a65471..4be0c6c3 100644 --- a/crates/dmm-tools/Cargo.toml +++ b/crates/dmm-tools/Cargo.toml @@ -2,7 +2,7 @@ name = "dmm-tools" version = "0.1.0" authors = ["Tad Hardesty "] -edition = "2018" +edition = "2021" [dependencies] inflate = "0.4.5" diff --git a/crates/dreamchecker/Cargo.toml b/crates/dreamchecker/Cargo.toml index c2e42b52..54dc0170 100644 --- a/crates/dreamchecker/Cargo.toml +++ b/crates/dreamchecker/Cargo.toml @@ -2,7 +2,7 @@ name = "dreamchecker" version = "1.9.0" authors = ["Tad Hardesty "] -edition = "2018" +edition = "2021" [dependencies] dreammaker = { path = "../dreammaker" } diff --git a/crates/dreammaker/Cargo.toml b/crates/dreammaker/Cargo.toml index bdd4b8c0..f93bdf83 100644 --- a/crates/dreammaker/Cargo.toml +++ b/crates/dreammaker/Cargo.toml @@ -2,7 +2,7 @@ name = "dreammaker" version = "0.1.0" authors = ["Tad Hardesty "] -edition = "2018" +edition = "2021" [dependencies] interval-tree = { path = "../interval-tree" } diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index def602fc..5a188663 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -52,7 +52,7 @@ macro_rules! take_match { ( $self:ident { $( - $($p:pat)|* $( if $condition:expr )? => $branch:expr, + $($p:pat_param)|* $( if $condition:expr )? => $branch:expr, )* } // else mandatory because you should never be matching on every option diff --git a/crates/dreammaker/tests/format_tests.rs b/crates/dreammaker/tests/format_tests.rs index 6a1c3aea..0b69e0bb 100644 --- a/crates/dreammaker/tests/format_tests.rs +++ b/crates/dreammaker/tests/format_tests.rs @@ -26,8 +26,8 @@ fn floats() { assert_eq!(FormatFloat(0.000500001).to_string(), "0.000500001"); assert_eq!(FormatFloat(0.0000500001).to_string(), "5.00001e-005"); - assert_eq!(FormatFloat(std::f32::INFINITY).to_string(), "1.#INF"); - assert_eq!(FormatFloat(-std::f32::INFINITY).to_string(), "-1.#INF"); + assert_eq!(FormatFloat(f32::INFINITY).to_string(), "1.#INF"); + assert_eq!(FormatFloat(-f32::INFINITY).to_string(), "-1.#INF"); assert_eq!(FormatFloat(2.9).to_string(), "2.9"); assert_eq!(FormatFloat(2.4).to_string(), "2.4"); diff --git a/crates/interval-tree/Cargo.toml b/crates/interval-tree/Cargo.toml index b6b08922..57c71494 100644 --- a/crates/interval-tree/Cargo.toml +++ b/crates/interval-tree/Cargo.toml @@ -6,7 +6,7 @@ description = "A simple Interval Tree implementation" repository = "https://github.com/SpaceManiac/SpacemanDMM/tree/master/crates/interval-tree" keywords = ["datastructure", "interval", "tree", "map"] license-file = "LICENSE" -edition = "2018" +edition = "2021" [dev-dependencies] rand = "0.8.5" diff --git a/crates/spaceman-dmm/Cargo.toml b/crates/spaceman-dmm/Cargo.toml index bb75a549..36ca7fb9 100644 --- a/crates/spaceman-dmm/Cargo.toml +++ b/crates/spaceman-dmm/Cargo.toml @@ -2,7 +2,7 @@ name = "spaceman-dmm" version = "0.1.0" authors = ["Tad Hardesty "] -edition = "2018" +edition = "2021" [[bin]] name = "editor" From 63f43a1afc2a05e896db9bfd73873ac435666d9d Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Fri, 25 Oct 2024 19:45:09 -0700 Subject: [PATCH 140/197] Use new :pat to simplify relevant macros --- crates/dm-langserver/src/macros.rs | 4 ++-- crates/dreammaker/src/parser.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/dm-langserver/src/macros.rs b/crates/dm-langserver/src/macros.rs index 46eb05da..833fb066 100644 --- a/crates/dm-langserver/src/macros.rs +++ b/crates/dm-langserver/src/macros.rs @@ -142,10 +142,10 @@ macro_rules! if_annotation { } macro_rules! match_annotation { - ($a:expr; $($($p:pat_param)|* => $b:block,)*) => { + ($a:expr; $($p:pat => $b:block,)*) => { for (_, thing) in $a.clone() { match thing { - $($($p)|* => $b,)* + $($p => $b,)* _ => {} } } diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 5a188663..c87184e6 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -52,7 +52,7 @@ macro_rules! take_match { ( $self:ident { $( - $($p:pat_param)|* $( if $condition:expr )? => $branch:expr, + $p:pat $( if $condition:expr )? => $branch:expr, )* } // else mandatory because you should never be matching on every option @@ -65,11 +65,11 @@ macro_rules! take_match { #[allow(unused_variables)] match $self.peek() { $( - $($p)|* $( if $condition )? => { + $p $( if $condition )? => { // inner match that moves instead of refs match $self.take() { // no duplicate `if` because types are different - $($p)|* => { + $p => { #[warn(unused_variables)] $branch } From 7c3593538bfe6f81c0b6915223d5ee420571dfd1 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Fri, 25 Oct 2024 21:04:08 -0700 Subject: [PATCH 141/197] Update Rust version in Dockerfile to actually work --- dockerfile => Dockerfile | 2 +- crates/dmdoc/src/main.rs | 2 +- crates/dmdoc/src/template.rs | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) rename dockerfile => Dockerfile (92%) diff --git a/dockerfile b/Dockerfile similarity index 92% rename from dockerfile rename to Dockerfile index 9547bf27..49fce654 100644 --- a/dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.54 +FROM rust:1.74 WORKDIR /usr/src/myapp COPY . . diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index fee3af28..253ee52e 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -718,7 +718,7 @@ fn main2() -> Result<(), Box> { } fn find_return_type(code: &dm::ast::Block) -> Option> { - for stmt in code { + for stmt in code.iter() { if let dm::ast::Statement::Setting { name, mode: dm::ast::SettingMode::Assign, value } = &stmt.elem { if name.as_str() == "SpacemanDMM_return_type" { if let Some(dm::ast::Term::Prefab(fab)) = value.as_term() { diff --git a/crates/dmdoc/src/template.rs b/crates/dmdoc/src/template.rs index 89949326..e465c81b 100644 --- a/crates/dmdoc/src/template.rs +++ b/crates/dmdoc/src/template.rs @@ -84,10 +84,12 @@ fn teaser(block: &DocBlock, prefix: &str) -> Markup { } fn git_link(env: &Environment, file: &str, line: u32) -> Markup { + let z; let title = if line == 0 { file } else { - &format!("{} {}", file, line) + z = format!("{} {}", file, line); + &z }; let icon = html! { img src="git.png" width="16" height="16" title=(title); From 6ede21716e5f3eb2b792b2774200a2b3266634b0 Mon Sep 17 00:00:00 2001 From: ZeWaka Date: Sat, 26 Oct 2024 22:31:05 -0700 Subject: [PATCH 142/197] Run `cargo upgrade` (#413) It's free, easy, and keeps us up-to-date. ### Changes * Upgrades packages via `cargo upgrade` and then `cargo upgrades` to make the cargo.toml versions match. * Manually upgrades the git2 versions and implements better error handling (if you weren't on a tag, say you had uncommitted changes to the spacemandmm repo, it would error. now it just continues searching for the nearest tag). ### Testing Tested using dm-langserver on the goonstation codebase in release. ![image](https://github.com/user-attachments/assets/7dd2e777-2814-49b9-b735-de58e7f85afb) --- Cargo.lock | 457 +++++++++++++------------- crates/builtins-proc-macro/Cargo.toml | 2 +- crates/dap-types/Cargo.toml | 8 +- crates/dm-langserver/Cargo.toml | 22 +- crates/dm-langserver/build.rs | 22 +- crates/dmdoc/Cargo.toml | 12 +- crates/dmm-tools-cli/Cargo.toml | 16 +- crates/dmm-tools/Cargo.toml | 16 +- crates/dreamchecker/Cargo.toml | 6 +- crates/dreammaker/Cargo.toml | 22 +- crates/spaceman-dmm/Cargo.toml | 2 +- 11 files changed, 296 insertions(+), 289 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44bf9055..01f83a24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,10 +3,10 @@ version = 3 [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "adler32" @@ -53,9 +53,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" dependencies = [ "anstyle", "anstyle-parse", @@ -68,47 +68,47 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.85", ] [[package]] @@ -120,7 +120,7 @@ dependencies = [ "attribute-derive-macro", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.85", ] [[package]] @@ -136,14 +136,14 @@ dependencies = [ "proc-macro2", "quote", "quote-use", - "syn 2.0.68", + "syn 2.0.85", ] [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "base64" @@ -168,9 +168,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -198,39 +198,45 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.16.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" +checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.85", ] [[package]] -name = "bytes" -version = "1.7.1" +name = "byteorder" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "cc" -version = "1.0.100" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c891175c3fb232128f48de6590095e59198bbeb8620c310be349bfc3afd12c7b" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "jobserver", "libc", - "once_cell", + "shlex", ] [[package]] @@ -255,9 +261,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.7" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -265,9 +271,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.7" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -277,21 +283,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.5" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.85", ] [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "collection_literals" @@ -307,27 +313,27 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "color_space" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3776b2bcc4e914db501bb9be9572dd706e344b9eb8f882894f3daa651d281381" +checksum = "52fdfaf2bee6357023bf7f95b15a8ef0b82759d2bce705cc45efcae9ae10f0ff" [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -405,7 +411,7 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.85", ] [[package]] @@ -536,33 +542,24 @@ dependencies = [ [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" - -[[package]] -name = "fallible_collections" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88c69768c0a15262df21899142bc6df9b9b823546d4b4b9a7bc2d6c448ec6fd" -dependencies = [ - "hashbrown 0.13.2", -] +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "fdeflate" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab" dependencies = [ "simd-adler32", ] [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide", @@ -579,9 +576,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -594,9 +591,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -604,15 +601,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -621,38 +618,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.85", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -690,7 +687,7 @@ checksum = "13a1bcfb855c1f340d5913ab542e36f25a1c56f57de79022928297632435dec2" dependencies = [ "attribute-derive", "quote", - "syn 2.0.68", + "syn 2.0.85", ] [[package]] @@ -736,11 +733,11 @@ dependencies = [ [[package]] name = "git2" -version = "0.18.3" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "232e6a7bfe35766bf715e55a88b39a700596c0ccfd88cd3680b4cdb40d66ef70" +checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", "libgit2-sys", "log", @@ -753,15 +750,6 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash", -] - [[package]] name = "heck" version = "0.5.0" @@ -776,9 +764,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -814,7 +802,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown 0.12.3", + "hashbrown", ] [[package]] @@ -841,9 +829,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" @@ -853,18 +841,18 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -892,15 +880,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libgit2-sys" -version = "0.16.2+1.7.2" +version = "0.17.0+1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee4126d8b4ee5c9d9ea891dd875cfdc1e9d0950437179104b183d7d8a74d24e8" +checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224" dependencies = [ "cc", "libc", @@ -910,9 +898,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.18" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" dependencies = [ "cc", "libc", @@ -922,12 +910,11 @@ dependencies = [ [[package]] name = "lodepng" -version = "3.10.1" +version = "3.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a42d298694b14401847de29abd44adf278b42e989e516deac7b72018400002d8" +checksum = "7b2dea7cda68e381418c985fd8f32a9c279a21ae8c715f2376adb20c27a0fad3" dependencies = [ "crc32fast", - "fallible_collections", "flate2", "libc", "rgb", @@ -935,9 +922,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lsp-types" @@ -954,9 +941,9 @@ dependencies = [ [[package]] name = "matrixmultiply" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2" +checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" dependencies = [ "autocfg", "rawpointer", @@ -992,11 +979,11 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", "simd-adler32", ] @@ -1042,9 +1029,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "ordered-float" @@ -1091,7 +1078,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.85", ] [[package]] @@ -1105,9 +1092,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -1117,15 +1104,15 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "png" -version = "0.17.13" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -1136,9 +1123,12 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro-error" @@ -1177,9 +1167,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -1190,7 +1180,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "getopts", "memchr", "unicase", @@ -1198,9 +1188,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -1213,7 +1203,7 @@ checksum = "a7b5abe3fe82fdeeb93f44d66a7b444dedf2e4827defb0a8e69c437b2de2ef94" dependencies = [ "quote", "quote-use-macros", - "syn 2.0.68", + "syn 2.0.85", ] [[package]] @@ -1225,7 +1215,7 @@ dependencies = [ "derive-where", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.85", ] [[package]] @@ -1286,9 +1276,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.5" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -1298,9 +1288,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", @@ -1309,15 +1299,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rgb" -version = "0.8.37" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" dependencies = [ "bytemuck", ] @@ -1334,14 +1324,14 @@ dependencies = [ "libc", "spin", "untrusted", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" dependencies = [ "log", "once_cell", @@ -1354,15 +1344,15 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-webpki" -version = "0.102.6" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -1386,31 +1376,32 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.203" +version = "1.0.213" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.213" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.85", ] [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -1423,7 +1414,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.85", ] [[package]] @@ -1449,6 +1440,12 @@ dependencies = [ "sha2", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "simd-adler32" version = "0.3.7" @@ -1507,9 +1504,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.68" +version = "2.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" dependencies = [ "proc-macro2", "quote", @@ -1527,9 +1524,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -1557,39 +1554,36 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "untrusted" @@ -1639,9 +1633,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" @@ -1661,34 +1655,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.85", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1696,28 +1691,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.85", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "webpki-roots" -version = "0.26.3" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" dependencies = [ "rustls-pki-types", ] @@ -1730,11 +1725,11 @@ checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -1756,10 +1751,19 @@ dependencies = [ ] [[package]] -name = "windows-targets" -version = "0.52.5" +name = "windows-sys" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -1773,70 +1777,71 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.85", ] [[package]] diff --git a/crates/builtins-proc-macro/Cargo.toml b/crates/builtins-proc-macro/Cargo.toml index 33188b43..4f9b7b8e 100644 --- a/crates/builtins-proc-macro/Cargo.toml +++ b/crates/builtins-proc-macro/Cargo.toml @@ -10,4 +10,4 @@ proc-macro = true [dependencies] syn = { version = "1.0", features = ["full"] } quote = "1.0" -proc-macro2 = "1.0.43" +proc-macro2 = "1.0.89" diff --git a/crates/dap-types/Cargo.toml b/crates/dap-types/Cargo.toml index 06608f38..f87f3692 100644 --- a/crates/dap-types/Cargo.toml +++ b/crates/dap-types/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Tad Hardesty "] edition = "2021" [dependencies] -serde = "1.0.144" -serde_json = "1.0.85" -serde_derive = "1.0.144" -ahash = "0.8.0" +serde = "1.0.213" +serde_json = "1.0.132" +serde_derive = "1.0.213" +ahash = "0.8.11" diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index c6e52424..77d52ddc 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -5,25 +5,25 @@ authors = ["Tad Hardesty "] edition = "2021" [dependencies] -url = "2.3.1" -serde = "1.0.144" -serde_json = "1.0.85" -serde_derive = "1.0.144" +url = "2.5.2" +serde = "1.0.213" +serde_json = "1.0.132" +serde_derive = "1.0.213" bincode = "1.3.3" jsonrpc-core = "18.0.0" -lsp-types = "0.93.1" +lsp-types = "0.93.2" dap-types = { path = "../dap-types" } dreammaker = { path = "../dreammaker" } dreamchecker = { path = "../dreamchecker" } interval-tree = { path = "../interval-tree" } -libc = "0.2.132" -regex = "1.6.0" -lazy_static = "1.4" -ahash = "0.8.0" +libc = "0.2.161" +regex = "1.11.1" +lazy_static = "1.5" +ahash = "0.8.11" [build-dependencies] -chrono = "0.4.22" -git2 = { version = "0.18.2", default-features = false } +chrono = "0.4.38" +git2 = { version = "0.19.0", default-features = false } sha256 = { version = "1.5.0", default-features = false } ureq = "2.10.1" diff --git a/crates/dm-langserver/build.rs b/crates/dm-langserver/build.rs index 78ed1bca..8e8c2ff5 100644 --- a/crates/dm-langserver/build.rs +++ b/crates/dm-langserver/build.rs @@ -47,17 +47,19 @@ fn read_commit() -> Result { let mut best = None; for tag_id in all_tags { - let tag_commit = repo.find_tag(tag_id)?.as_object().peel_to_commit()?.id(); - let (ahead, behind) = repo.graph_ahead_behind(head, tag_commit)?; - if behind == 0 { - match best { - None => best = Some(ahead), - Some(prev) if ahead < prev => best = Some(ahead), - _ => {} + if let Ok(possible_tag) = repo.find_tag(tag_id) { + let tag_commit = possible_tag.as_object().peel_to_commit()?.id(); + let (ahead, behind) = repo.graph_ahead_behind(head, tag_commit)?; + if behind == 0 { + match best { + None => best = Some(ahead), + Some(prev) if ahead < prev => best = Some(ahead), + _ => {} + } + } + if ahead == 0 { + break; } - } - if ahead == 0 { - break; } } diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index 47879959..ee13a81c 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -7,14 +7,14 @@ edition = "2021" [dependencies] dreammaker = { path = "../dreammaker" } -pulldown-cmark = "0.9.2" -walkdir = "2.3.2" -git2 = { version = "0.18.2", default-features = false } +pulldown-cmark = "0.9.6" +walkdir = "2.5.0" +git2 = { version = "0.19.0", default-features = false } maud = "0.25.0" [dev-dependencies] -walkdir = "2.3.2" +walkdir = "2.5.0" [build-dependencies] -chrono = "0.4.22" -git2 = { version = "0.18.2", default-features = false } +chrono = "0.4.38" +git2 = { version = "0.19.0", default-features = false } diff --git a/crates/dmm-tools-cli/Cargo.toml b/crates/dmm-tools-cli/Cargo.toml index d106d2b9..012b6f0a 100644 --- a/crates/dmm-tools-cli/Cargo.toml +++ b/crates/dmm-tools-cli/Cargo.toml @@ -10,15 +10,15 @@ name = "dmm-tools" path = "src/main.rs" [dependencies] -clap = { version = "4.3.17", features = ["derive"] } -serde = "1.0.144" -serde_derive = "1.0.144" -serde_json = "1.0.85" -rayon = "1.5.3" +clap = { version = "4.5.20", features = ["derive"] } +serde = "1.0.213" +serde_derive = "1.0.213" +serde_json = "1.0.132" +rayon = "1.10.0" dreammaker = { path = "../dreammaker" } dmm-tools = { path = "../dmm-tools", features = ["png"] } -ahash = "0.8.0" +ahash = "0.8.11" [build-dependencies] -chrono = "0.4.22" -git2 = { version = "0.18.2", default-features = false } +chrono = "0.4.38" +git2 = { version = "0.19.0", default-features = false } diff --git a/crates/dmm-tools/Cargo.toml b/crates/dmm-tools/Cargo.toml index 4be0c6c3..c1ffa7b8 100644 --- a/crates/dmm-tools/Cargo.toml +++ b/crates/dmm-tools/Cargo.toml @@ -9,21 +9,21 @@ inflate = "0.4.5" ndarray = "0.15.6" rand = "0.8.5" dreammaker = { path = "../dreammaker" } -lodepng = "3.7.0" -indexmap = "1.9.1" -ahash = "0.8.0" -either = "1.8.0" +lodepng = "3.10.7" +indexmap = "1.9.3" +ahash = "0.8.11" +either = "1.13.0" [dependencies.bytemuck] -version = "1.12.1" +version = "1.19.0" features = ["derive"] [dependencies.bumpalo] -version = "3.11.1" +version = "3.16.0" features = ["collections"] [dependencies.png] -version = "0.17.6" +version = "0.17.14" optional = true [dependencies.gfx_core] @@ -35,4 +35,4 @@ version = "0.11.4" optional = true [dev-dependencies] -walkdir = "2.3.2" +walkdir = "2.5.0" diff --git a/crates/dreamchecker/Cargo.toml b/crates/dreamchecker/Cargo.toml index 54dc0170..68439416 100644 --- a/crates/dreamchecker/Cargo.toml +++ b/crates/dreamchecker/Cargo.toml @@ -7,8 +7,8 @@ edition = "2021" [dependencies] dreammaker = { path = "../dreammaker" } serde_json = "1.0" -ahash = "0.8.0" +ahash = "0.8.11" [build-dependencies] -chrono = "0.4.22" -git2 = { version = "0.18.2", default-features = false } +chrono = "0.4.38" +git2 = { version = "0.19.0", default-features = false } diff --git a/crates/dreammaker/Cargo.toml b/crates/dreammaker/Cargo.toml index f93bdf83..8c432d60 100644 --- a/crates/dreammaker/Cargo.toml +++ b/crates/dreammaker/Cargo.toml @@ -7,20 +7,20 @@ edition = "2021" [dependencies] interval-tree = { path = "../interval-tree" } builtins-proc-macro = { path = "../builtins-proc-macro" } -lodepng = "3.7.0" +lodepng = "3.10.7" bitflags = "1.3.2" -termcolor = "1.1.3" -ordered-float = "3.0.0" -serde = { version = "1.0.144", features = ["derive"] } -serde_derive = "1.0.144" -toml = "0.5.9" -phf = { version = "0.11.1", features = ["macros"] } -color_space = "0.5.3" -ahash = "0.8.0" -indexmap = "1.9.1" +termcolor = "1.4.1" +ordered-float = "3.9.2" +serde = { version = "1.0.213", features = ["derive"] } +serde_derive = "1.0.213" +toml = "0.5.11" +phf = { version = "0.11.2", features = ["macros"] } +color_space = "0.5.4" +ahash = "0.8.11" +indexmap = "1.9.3" derivative = "2.2.0" get-size = "0.1.4" get-size-derive = "0.1.3" [dev-dependencies] -walkdir = "2.3.2" +walkdir = "2.5.0" diff --git a/crates/spaceman-dmm/Cargo.toml b/crates/spaceman-dmm/Cargo.toml index 36ca7fb9..84e1becb 100644 --- a/crates/spaceman-dmm/Cargo.toml +++ b/crates/spaceman-dmm/Cargo.toml @@ -35,4 +35,4 @@ branch = "zenity" [build-dependencies] chrono = "0.4.19" -git2 = { version = "0.18.2", default-features = false } +git2 = { version = "0.19.0", default-features = false } From d19602a6f081e6877bb5de291b160000fdbd2aaa Mon Sep 17 00:00:00 2001 From: ZeWaka Date: Fri, 8 Nov 2024 17:49:06 -0800 Subject: [PATCH 143/197] Change the hasher used for HashMap/Sets (#414) I chose to use [foldhash](https://docs.rs/foldhash/0.1.3/foldhash/index.html) since we're not needing cryptographically secure hashing, nor are we concerned with people reverse-engineering application state. Basically just changing the RandomState or the HashMap/Set import everywhere. The *Ext types provide the `::new()` interface. Tested dm-langserver, all works well: ![image](https://github.com/user-attachments/assets/957e9db8-eb99-4970-82e0-a3ca1434e178) --- Cargo.lock | 48 +++++++++---------- crates/dap-types/Cargo.toml | 2 +- crates/dap-types/src/lib.rs | 5 +- crates/dm-langserver/Cargo.toml | 2 +- crates/dm-langserver/src/completion.rs | 14 +++--- crates/dm-langserver/src/debugger/extools.rs | 10 ++-- .../src/debugger/extools_types.rs | 5 +- crates/dm-langserver/src/debugger/launched.rs | 2 +- crates/dm-langserver/src/debugger/mod.rs | 16 +++---- crates/dm-langserver/src/document.rs | 6 +-- crates/dm-langserver/src/extras.rs | 2 +- crates/dm-langserver/src/find_references.rs | 14 +++--- crates/dm-langserver/src/main.rs | 17 ++++--- crates/dmdoc/Cargo.toml | 1 + crates/dmdoc/src/main.rs | 3 +- crates/dmm-tools-cli/Cargo.toml | 2 +- crates/dmm-tools-cli/src/main.rs | 11 ++--- crates/dmm-tools/Cargo.toml | 4 +- .../examples/duplicate_icon_states.rs | 2 +- crates/dmm-tools/src/dmm.rs | 2 +- crates/dmm-tools/src/icon_cache.rs | 3 +- crates/dmm-tools/src/minimap.rs | 8 ++-- .../src/render_passes/icon_smoothing_2020.rs | 5 +- crates/dreamchecker/Cargo.toml | 2 +- crates/dreamchecker/src/lib.rs | 37 +++++++------- crates/dreamchecker/src/type_expr.rs | 8 ++-- crates/dreammaker/Cargo.toml | 4 +- crates/dreammaker/src/config.rs | 9 ++-- crates/dreammaker/src/constants.rs | 2 +- crates/dreammaker/src/dmi.rs | 3 +- crates/dreammaker/src/error.rs | 6 +-- crates/dreammaker/src/lib.rs | 3 +- crates/dreammaker/src/objtree.rs | 2 +- crates/dreammaker/src/preprocessor.rs | 15 +++--- 34 files changed, 129 insertions(+), 146 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 01f83a24..795bafea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,19 +14,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "getrandom", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "aho-corasick" version = "1.1.3" @@ -386,7 +373,7 @@ dependencies = [ name = "dap-types" version = "0.0.0" dependencies = [ - "ahash", + "foldhash", "serde", "serde_derive", "serde_json", @@ -428,12 +415,12 @@ dependencies = [ name = "dm-langserver" version = "1.9.0" dependencies = [ - "ahash", "bincode", "chrono", "dap-types", "dreamchecker", "dreammaker", + "foldhash", "git2", "interval-tree", "jsonrpc-core", @@ -455,6 +442,7 @@ version = "1.9.0" dependencies = [ "chrono", "dreammaker", + "foldhash", "git2", "maud", "pulldown-cmark", @@ -465,11 +453,11 @@ dependencies = [ name = "dmm-tools" version = "0.1.0" dependencies = [ - "ahash", "bumpalo", "bytemuck", "dreammaker", "either", + "foldhash", "gfx_core", "gif", "indexmap", @@ -485,11 +473,11 @@ dependencies = [ name = "dmm-tools-cli" version = "1.9.0" dependencies = [ - "ahash", "chrono", "clap", "dmm-tools", "dreammaker", + "foldhash", "git2", "rayon", "serde", @@ -510,9 +498,9 @@ dependencies = [ name = "dreamchecker" version = "1.9.0" dependencies = [ - "ahash", "chrono", "dreammaker", + "foldhash", "git2", "serde_json", ] @@ -521,11 +509,11 @@ dependencies = [ name = "dreammaker" version = "0.1.0" dependencies = [ - "ahash", "bitflags 1.3.2", "builtins-proc-macro", "color_space", "derivative", + "foldhash", "get-size", "get-size-derive", "indexmap", @@ -546,6 +534,12 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "fdeflate" version = "0.3.5" @@ -565,6 +559,12 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -746,9 +746,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "heck" @@ -797,11 +797,11 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.3" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "autocfg", + "equivalent", "hashbrown", ] diff --git a/crates/dap-types/Cargo.toml b/crates/dap-types/Cargo.toml index f87f3692..406a77e0 100644 --- a/crates/dap-types/Cargo.toml +++ b/crates/dap-types/Cargo.toml @@ -8,4 +8,4 @@ edition = "2021" serde = "1.0.213" serde_json = "1.0.132" serde_derive = "1.0.213" -ahash = "0.8.11" +foldhash = "0.1.3" diff --git a/crates/dap-types/src/lib.rs b/crates/dap-types/src/lib.rs index e254f20b..14b4b33e 100644 --- a/crates/dap-types/src/lib.rs +++ b/crates/dap-types/src/lib.rs @@ -4,10 +4,9 @@ #![deny(unsafe_code)] #![allow(non_snake_case)] -use ahash::RandomState; use serde_derive::{Deserialize, Serialize}; use serde_json::Value; -use std::collections::HashMap; +use foldhash::HashMap; pub trait Request { type Params; @@ -1530,7 +1529,7 @@ pub struct Message { /** * An object used as a dictionary for looking up the variables in the format string. */ - pub variables: Option>, + pub variables: Option>, /** * If true send to telemetry. diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index 77d52ddc..a833b16e 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -19,7 +19,7 @@ interval-tree = { path = "../interval-tree" } libc = "0.2.161" regex = "1.11.1" lazy_static = "1.5" -ahash = "0.8.11" +foldhash = "0.1.3" [build-dependencies] chrono = "0.4.38" diff --git a/crates/dm-langserver/src/completion.rs b/crates/dm-langserver/src/completion.rs index 74a885e4..8f7e6f8b 100644 --- a/crates/dm-langserver/src/completion.rs +++ b/crates/dm-langserver/src/completion.rs @@ -1,6 +1,6 @@ //! Supporting functions for completion and go-to-definition. -use std::collections::HashSet; +use foldhash::{HashSet, HashSetExt}; use lsp_types::*; @@ -11,8 +11,6 @@ use dm::objtree::{ProcValue, TypeProc, TypeRef, TypeVar}; use crate::symbol_search::contains; use crate::{is_constructor_name, Engine, Span}; -use ahash::RandomState; - #[rustfmt::skip] static PROC_KEYWORDS: &[&str] = &[ // Implicit variables @@ -103,7 +101,7 @@ fn item_documentation(docs: &dm::docs::DocCollection) -> Option { fn items_ty<'a>( results: &mut Vec, - skip: &mut HashSet<(&str, &'a String), RandomState>, + skip: &mut HashSet<(&str, &'a String)>, ty: TypeRef<'a>, query: &str, ) { @@ -256,7 +254,7 @@ impl<'a> Engine<'a> { } let mut next = Some(ty).filter(|ty| !ty.is_root()); - let mut skip = HashSet::with_hasher(RandomState::default()); + let mut skip = HashSet::new(); while let Some(ty) = next { // override a parent's var for (name, var) in ty.get().vars.iter() { @@ -350,7 +348,7 @@ impl<'a> Engine<'a> { proc: None, }) => { let mut next = Some(ty); - let mut skip = HashSet::with_hasher(RandomState::default()); + let mut skip = HashSet::new(); while let Some(ty) = next { // reference a declared proc for (name, proc) in ty.get().procs.iter() { @@ -446,7 +444,7 @@ impl<'a> Engine<'a> { // fields let mut next = Some(ty); - let mut skip = HashSet::with_hasher(RandomState::default()); + let mut skip = HashSet::new(); while let Some(ty) = next { items_ty(results, &mut skip, ty, query); next = ty.parent_type(); @@ -463,7 +461,7 @@ impl<'a> Engine<'a> { I: Iterator + Clone, { let mut next = self.find_scoped_type(iter, priors); - let mut skip = HashSet::with_hasher(RandomState::default()); + let mut skip = HashSet::new(); while let Some(ty) = next { items_ty(results, &mut skip, ty, query); next = ty.parent_type_without_root(); diff --git a/crates/dm-langserver/src/debugger/extools.rs b/crates/dm-langserver/src/debugger/extools.rs index 15829474..24aee362 100644 --- a/crates/dm-langserver/src/debugger/extools.rs +++ b/crates/dm-langserver/src/debugger/extools.rs @@ -1,14 +1,12 @@ //! Client for the Extools debugger protocol. -use std::collections::HashMap; +use foldhash::{HashMap, HashMapExt}; use std::error::Error; use std::io::{Read, Write}; use std::net::{Ipv4Addr, SocketAddr, TcpListener, TcpStream}; use std::sync::{mpsc, Arc, Mutex}; use std::time::Duration; -use ahash::RandomState; - use super::extools_types::*; use super::SequenceNumber; @@ -141,7 +139,7 @@ pub struct Extools { seq: Arc, sender: ExtoolsSender, threads: Arc>>, - bytecode: HashMap<(String, usize), Vec, RandomState>, + bytecode: HashMap<(String, usize), Vec>, get_type_rx: mpsc::Receiver, bytecode_rx: mpsc::Receiver, get_field_rx: mpsc::Receiver, @@ -173,7 +171,7 @@ impl Extools { seq, sender, threads: Arc::new(Mutex::new(HashMap::new())), - bytecode: HashMap::with_hasher(RandomState::default()), + bytecode: HashMap::new(), bytecode_rx, get_type_rx, get_field_rx, @@ -300,7 +298,7 @@ impl Extools { Ok(self.get_type_rx.recv_timeout(RECV_TIMEOUT)?.0) } - pub fn get_all_fields(&self, reference: Ref) -> Result, Box> { + pub fn get_all_fields(&self, reference: Ref) -> Result, Box> { self.sender.send(GetAllFields(reference)); Ok(self.get_field_rx.recv_timeout(RECV_TIMEOUT)?.0) } diff --git a/crates/dm-langserver/src/debugger/extools_types.rs b/crates/dm-langserver/src/debugger/extools_types.rs index e580adb2..72b0ca29 100644 --- a/crates/dm-langserver/src/debugger/extools_types.rs +++ b/crates/dm-langserver/src/debugger/extools_types.rs @@ -4,9 +4,8 @@ //! //! > All communication happens over a TCP socket using a JSON-based protocol. //! > A null byte signifies the end of a message. -use ahash::RandomState; use serde_json::Value as Json; -use std::collections::HashMap; +use foldhash::HashMap; // ---------------------------------------------------------------------------- // Extools data structures @@ -328,7 +327,7 @@ impl Request for GetAllFields { } #[derive(Deserialize, Debug)] -pub struct GetAllFieldsResponse(pub HashMap); +pub struct GetAllFieldsResponse(pub HashMap); impl Response for GetAllFieldsResponse { const TYPE: &'static str = "get all fields"; diff --git a/crates/dm-langserver/src/debugger/launched.rs b/crates/dm-langserver/src/debugger/launched.rs index 8c2c025a..4ffd3dbc 100644 --- a/crates/dm-langserver/src/debugger/launched.rs +++ b/crates/dm-langserver/src/debugger/launched.rs @@ -2,7 +2,7 @@ #![allow(unsafe_code)] use super::SequenceNumber; -use std::collections::HashMap; +use foldhash::HashMap; use std::process::{Command, Stdio}; use std::sync::{Arc, Mutex}; diff --git a/crates/dm-langserver/src/debugger/mod.rs b/crates/dm-langserver/src/debugger/mod.rs index b731ede4..1159e784 100644 --- a/crates/dm-langserver/src/debugger/mod.rs +++ b/crates/dm-langserver/src/debugger/mod.rs @@ -38,7 +38,7 @@ mod extools_bundle; mod extools_types; mod launched; -use std::collections::{HashMap, HashSet}; +use foldhash::{HashMap, HashMapExt, HashSet, HashSetExt}; use std::error::Error; use std::sync::{atomic, Arc, Mutex}; @@ -48,8 +48,6 @@ use dreammaker::config::DebugEngine; use auxtools::Auxtools; -use ahash::RandomState; - use self::auxtools::AuxtoolsScopes; use self::extools::ExtoolsHolder; use self::launched::{EngineParams, Launched}; @@ -145,8 +143,8 @@ impl DebugDatabaseBuilder { extools_dll: _, debug_server_dll: _, } = self; - let mut line_numbers: HashMap, RandomState> = - HashMap::with_hasher(RandomState::default()); + let mut line_numbers: HashMap> = + HashMap::new(); objtree.root().recurse(&mut |ty| { for (name, proc) in ty.procs.iter() { @@ -186,7 +184,7 @@ pub struct DebugDatabase { root_dir: std::path::PathBuf, files: dm::FileList, objtree: Arc, - line_numbers: HashMap, RandomState>, + line_numbers: HashMap>, } fn get_proc<'o>( @@ -1158,7 +1156,7 @@ handle_request! { if mod2 == 1 { // arguments let mut variables = Vec::with_capacity(2 + frame.args.len()); - let mut seen = std::collections::HashMap::with_hasher(RandomState::default()); + let mut seen = HashMap::new(); seen.insert("src", 0); variables.push(Variable { @@ -1203,7 +1201,7 @@ handle_request! { // If VSC receives two Variables with the same name, it only // displays the first one. Avert this by adding suffixes. - let mut seen = std::collections::HashMap::with_hasher(RandomState::default()); + let mut seen = HashMap::new(); variables.extend(frame.locals.iter().enumerate().map(|(i, vt)| Variable { name: match frame.local_names.get(i) { Some(local) => { @@ -1230,7 +1228,7 @@ handle_request! { // If VSC receives two Variables with the same name, it only // displays the first one. Avert this by adding suffixes. - let mut seen = std::collections::HashMap::with_hasher(RandomState::default()); + let mut seen = HashMap::new(); for aux_var in aux_variables { let name = match seen.entry(aux_var.name.clone()).and_modify(|e| *e += 1).or_default() { diff --git a/crates/dm-langserver/src/document.rs b/crates/dm-langserver/src/document.rs index 98407555..f3b80501 100644 --- a/crates/dm-langserver/src/document.rs +++ b/crates/dm-langserver/src/document.rs @@ -3,7 +3,7 @@ #![allow(dead_code)] use std::borrow::Cow; -use std::collections::HashMap; +use foldhash::HashMap; use std::io::{self, BufRead, Read}; use std::rc::Rc; use url::Url; @@ -15,13 +15,11 @@ use lsp_types::{ use super::{invalid_request, url_to_path}; -use ahash::RandomState; - /// A store for the contents of currently-open documents, with appropriate /// fallback for documents which are not currently open. #[derive(Default)] pub struct DocumentStore { - map: HashMap, + map: HashMap, } impl DocumentStore { diff --git a/crates/dm-langserver/src/extras.rs b/crates/dm-langserver/src/extras.rs index 60f490a4..180c3430 100644 --- a/crates/dm-langserver/src/extras.rs +++ b/crates/dm-langserver/src/extras.rs @@ -1,6 +1,6 @@ //! Extensions to the language server protocol. -use std::collections::HashMap; +use foldhash::HashMap; use lsp_types::notification::*; use lsp_types::request::*; diff --git a/crates/dm-langserver/src/find_references.rs b/crates/dm-langserver/src/find_references.rs index 49291475..075a554a 100644 --- a/crates/dm-langserver/src/find_references.rs +++ b/crates/dm-langserver/src/find_references.rs @@ -1,15 +1,13 @@ //! The symbol table used for "Find References" support. -use std::collections::HashMap; +use foldhash::{HashMap, HashMapExt}; use dm::ast::*; use dm::objtree::*; use dm::Location; -use ahash::RandomState; - pub struct ReferencesTable { - uses: HashMap, + uses: HashMap, symbols: SymbolIdSource, } @@ -22,7 +20,7 @@ struct References { impl ReferencesTable { pub fn new(objtree: &ObjectTree) -> Self { let mut tab = ReferencesTable { - uses: HashMap::with_hasher(RandomState::default()), + uses: HashMap::new(), symbols: SymbolIdSource::new(SymbolIdCategory::LocalVars), }; @@ -134,12 +132,12 @@ struct WalkProc<'o> { objtree: &'o ObjectTree, ty: TypeRef<'o>, proc: Option>, - local_vars: HashMap, RandomState>, + local_vars: HashMap>, } impl<'o> WalkProc<'o> { fn from_proc(tab: &'o mut ReferencesTable, objtree: &'o ObjectTree, proc: ProcRef<'o>) -> Self { - let mut local_vars = HashMap::with_hasher(RandomState::default()); + let mut local_vars = HashMap::new(); local_vars.insert("global".to_owned(), Local { ty: StaticType::Type(objtree.root()), symbol: objtree.root().id, @@ -175,7 +173,7 @@ impl<'o> WalkProc<'o> { } fn from_ty(tab: &'o mut ReferencesTable, objtree: &'o ObjectTree, ty: TypeRef<'o>) -> Self { - let mut local_vars = HashMap::with_hasher(RandomState::default()); + let mut local_vars = HashMap::new(); local_vars.insert("global".to_owned(), Local { ty: StaticType::Type(objtree.root()), symbol: objtree.root().id, diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index cc1ece39..ffa6bb3e 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -36,7 +36,8 @@ mod symbol_search; mod debugger; use std::collections::hash_map::Entry; -use std::collections::{HashMap, HashSet, VecDeque}; +use std::collections::VecDeque; +use foldhash::{HashMap, HashMapExt, HashSet, HashSetExt}; use std::path::PathBuf; use std::rc::Rc; use std::sync::{Arc, Mutex}; @@ -49,8 +50,6 @@ use dm::annotation::{Annotation, AnnotationTree}; use dm::objtree::TypeRef; use dm::FileId; -use ahash::RandomState; - fn main() { std::env::set_var("RUST_BACKTRACE", "1"); @@ -149,7 +148,7 @@ impl ClientCaps { #[derive(Default)] struct DiagnosticsTracker { - sent: HashSet, + sent: HashSet, } impl DiagnosticsTracker { @@ -162,8 +161,8 @@ impl DiagnosticsTracker { } } - fn build(root: Option<&Url>, file_list: &dm::FileList, errors: &[dm::DMError], related_info: bool) -> HashMap, RandomState> { - let mut map: HashMap<_, Vec<_>, RandomState> = HashMap::with_hasher(RandomState::default()); + fn build(root: Option<&Url>, file_list: &dm::FileList, errors: &[dm::DMError], related_info: bool) -> HashMap> { + let mut map: HashMap<_, Vec<_>> = HashMap::new(); for error in errors.iter() { let loc = error.location(); let related_information = if !related_info || error.notes().is_empty() { @@ -216,8 +215,8 @@ impl DiagnosticsTracker { map } - fn send(&mut self, map: HashMap, RandomState>) { - let mut new_sent = HashSet::with_capacity_and_hasher(map.len(), RandomState::default()); + fn send(&mut self, map: HashMap>) { + let mut new_sent = HashSet::with_capacity(map.len()); for (url, diagnostics) in map { self.sent.remove(&url); // don't erase below new_sent.insert(url.clone()); @@ -256,7 +255,7 @@ struct Engine<'a> { objtree: Arc, references_table: background::Background, - annotations: HashMap), RandomState>, + annotations: HashMap)>, diagnostics_tracker: Arc>, client_caps: ClientCaps, diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index ee13a81c..19ae9200 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -11,6 +11,7 @@ pulldown-cmark = "0.9.6" walkdir = "2.5.0" git2 = { version = "0.19.0", default-features = false } maud = "0.25.0" +foldhash = "0.1.3" [dev-dependencies] walkdir = "2.5.0" diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 253ee52e..c339226a 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -13,6 +13,7 @@ use dm::objtree::ObjectTree; use maud::{Markup, PreEscaped}; use pulldown_cmark::{BrokenLink, CowStr}; use std::collections::{BTreeMap, BTreeSet}; +use foldhash::HashSet; use std::fs::{self, File}; use std::io::{self, Write}; use std::path::{Path, PathBuf}; @@ -100,7 +101,7 @@ fn main2() -> Result<(), Box> { index_path.clone_from(&context.config().dmdoc.index_file); } - let mut code_directories: std::collections::HashSet; + let mut code_directories: HashSet; if context.config().dmdoc.module_directories.is_empty() { // Any top-level directory which is `#include`d in the `.dme` (most // importantly "code", but also "_maps", "interface", and any downstream diff --git a/crates/dmm-tools-cli/Cargo.toml b/crates/dmm-tools-cli/Cargo.toml index 012b6f0a..676580e8 100644 --- a/crates/dmm-tools-cli/Cargo.toml +++ b/crates/dmm-tools-cli/Cargo.toml @@ -17,7 +17,7 @@ serde_json = "1.0.132" rayon = "1.10.0" dreammaker = { path = "../dreammaker" } dmm-tools = { path = "../dmm-tools", features = ["png"] } -ahash = "0.8.11" +foldhash = "0.1.3" [build-dependencies] chrono = "0.4.38" diff --git a/crates/dmm-tools-cli/src/main.rs b/crates/dmm-tools-cli/src/main.rs index 119decf0..ab538084 100644 --- a/crates/dmm-tools-cli/src/main.rs +++ b/crates/dmm-tools-cli/src/main.rs @@ -13,8 +13,7 @@ extern crate serde_derive; extern crate dmm_tools; extern crate dreammaker as dm; -use std::collections::HashMap; -use std::collections::HashSet; +use foldhash::{HashMap, HashMapExt, HashSet}; use std::fmt; use std::io::Write; use std::path::{Path, PathBuf}; @@ -27,8 +26,6 @@ use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterato use dm::objtree::ObjectTree; use dmm_tools::*; -use ahash::RandomState; - // ---------------------------------------------------------------------------- // Main driver @@ -242,7 +239,7 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { let render_passes = &dmm_tools::render_passes::configure(&context.dm_context.config().map_renderer, enable, disable); let paths: Vec<&Path> = files.iter().map(|p| p.as_ref()).collect(); - let errors: RwLock> = Default::default(); + let errors: RwLock> = Default::default(); let perform_job = move |path: &Path| { let mut filename; @@ -391,7 +388,7 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { num_keys: usize, } - let mut report = HashMap::with_hasher(RandomState::default()); + let mut report = HashMap::new(); for path in files.iter() { let path = std::path::Path::new(path); let map = dmm::Map::from_file(path).unwrap(); @@ -561,7 +558,7 @@ fn render_many(context: &Context, command: RenderManyCommand) -> RenderManyComma .. } = *context; let render_passes = &dmm_tools::render_passes::configure_list(&context.dm_context.config().map_renderer, &command.enable, &command.disable); - let errors: RwLock> = Default::default(); + let errors: RwLock> = Default::default(); // Prepare output directory. let output_directory = command.output_directory; diff --git a/crates/dmm-tools/Cargo.toml b/crates/dmm-tools/Cargo.toml index c1ffa7b8..9f43cafd 100644 --- a/crates/dmm-tools/Cargo.toml +++ b/crates/dmm-tools/Cargo.toml @@ -10,8 +10,8 @@ ndarray = "0.15.6" rand = "0.8.5" dreammaker = { path = "../dreammaker" } lodepng = "3.10.7" -indexmap = "1.9.3" -ahash = "0.8.11" +indexmap = "2.6.0" +foldhash = "0.1.3" either = "1.13.0" [dependencies.bytemuck] diff --git a/crates/dmm-tools/examples/duplicate_icon_states.rs b/crates/dmm-tools/examples/duplicate_icon_states.rs index 4fe90fca..ff54e878 100644 --- a/crates/dmm-tools/examples/duplicate_icon_states.rs +++ b/crates/dmm-tools/examples/duplicate_icon_states.rs @@ -5,7 +5,7 @@ extern crate walkdir; use dmm_tools::dmi::*; use ndarray::s; -use std::collections::HashMap; +use foldhash::{HashMap, HashMapExt}; use std::path::Path; use walkdir::{DirEntry, WalkDir}; diff --git a/crates/dmm-tools/src/dmm.rs b/crates/dmm-tools/src/dmm.rs index 1a8e917b..b6dc1859 100644 --- a/crates/dmm-tools/src/dmm.rs +++ b/crates/dmm-tools/src/dmm.rs @@ -4,7 +4,7 @@ use std::fs::File; use std::io; use std::path::Path; -use ahash::RandomState; +use foldhash::fast::RandomState; use indexmap::IndexMap; use ndarray::{self, Array3, Axis}; diff --git a/crates/dmm-tools/src/icon_cache.rs b/crates/dmm-tools/src/icon_cache.rs index 24b2e80f..63b63d16 100644 --- a/crates/dmm-tools/src/icon_cache.rs +++ b/crates/dmm-tools/src/icon_cache.rs @@ -1,4 +1,5 @@ use std::collections::{hash_map, HashMap}; +use foldhash::fast::RandomState; use std::path::{Path, PathBuf}; use std::sync::{Arc, RwLock}; @@ -6,7 +7,7 @@ use super::dmi::IconFile; #[derive(Default)] pub struct IconCache { - lock: RwLock>>>, + lock: RwLock>, RandomState>>, icons_root: Option, } diff --git a/crates/dmm-tools/src/minimap.rs b/crates/dmm-tools/src/minimap.rs index 75a6f2d3..93e2a0ab 100644 --- a/crates/dmm-tools/src/minimap.rs +++ b/crates/dmm-tools/src/minimap.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeMap, HashSet}; +use std::collections::BTreeMap; use std::sync::RwLock; use ndarray::Axis; @@ -10,7 +10,7 @@ use crate::render_passes::RenderPass; use dm::constants::Constant; use dm::objtree::*; -use ahash::RandomState; +use foldhash::HashSet; const TILE_SIZE: u32 = 32; @@ -25,7 +25,7 @@ pub struct Context<'a> { pub min: (usize, usize), pub max: (usize, usize), pub render_passes: &'a [Box], - pub errors: &'a RwLock>, + pub errors: &'a RwLock>, pub bump: &'a bumpalo::Bump, } @@ -201,7 +201,7 @@ fn get_atom_list<'a>( objtree: &'a ObjectTree, prefabs: &'a [Prefab], render_passes: &[Box], - errors: &RwLock>, + errors: &RwLock>, ) -> Vec> { let mut result = Vec::new(); diff --git a/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs b/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs index 1b39662a..3373d45e 100644 --- a/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs +++ b/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs @@ -8,6 +8,7 @@ use crate::dmi::Dir; use crate::minimap::{Atom, GetVar, Neighborhood, Sprite}; use dm::constants::Constant; use dm::objtree::ObjectTree; +use foldhash::HashSet; use super::RenderPass; @@ -132,10 +133,10 @@ fn find_type_in_direction(objtree: &ObjectTree, adjacency: &Neighborhood, source match source.get_var("canSmoothWith", objtree) { Constant::List(elements) => { // smooth with anything for which their smoothing_groups overlaps our canSmoothWith - let set: std::collections::HashSet<_> = elements.iter().map(|x| &x.0).collect(); + let set: HashSet<_> = elements.iter().map(|x| &x.0).collect(); for atom in atom_list { if let Constant::List(elements2) = atom.get_var("smoothing_groups", objtree) { - let set2: std::collections::HashSet<_> = elements2.iter().map(|x| &x.0).collect(); + let set2: HashSet<_> = elements2.iter().map(|x| &x.0).collect(); if set.intersection(&set2).next().is_some() { return true; } diff --git a/crates/dreamchecker/Cargo.toml b/crates/dreamchecker/Cargo.toml index 68439416..24c4f62c 100644 --- a/crates/dreamchecker/Cargo.toml +++ b/crates/dreamchecker/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] dreammaker = { path = "../dreammaker" } serde_json = "1.0" -ahash = "0.8.11" +foldhash = "0.1.3" [build-dependencies] chrono = "0.4.38" diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 1f3e12b9..f25887b1 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -8,9 +8,8 @@ use dm::constants::{ConstFn, Constant}; use dm::objtree::{ObjectTree, ProcRef, TypeRef}; use dm::{Context, DMError, Location, Severity}; -use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; - -use ahash::RandomState; +use std::collections::{BTreeMap, VecDeque}; +use foldhash::{HashMap, HashMapExt, HashSet, HashSetExt}; mod type_expr; use type_expr::TypeExpr; @@ -1157,7 +1156,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } pub fn run(&mut self, block: &'o [Spanned]) { - let mut local_vars = HashMap::::with_hasher(RandomState::default()); + let mut local_vars = HashMap::::new(); local_vars.insert(".".to_owned(), Analysis::empty().into()); local_vars.insert("args".to_owned(), Analysis::from_static_type_impure(self.objtree.expect("/list")).into()); local_vars.insert("usr".to_owned(), Analysis::from_static_type(self.objtree.expect("/mob")).into()); @@ -1222,7 +1221,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } - fn visit_block(&mut self, block: &'o [Spanned], local_vars: &mut HashMap, RandomState>) -> ControlFlow { + fn visit_block(&mut self, block: &'o [Spanned], local_vars: &mut HashMap>) -> ControlFlow { let mut term = ControlFlow::allfalse(); for stmt in block.iter() { if term.terminates() { @@ -1268,7 +1267,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } - fn visit_statement(&mut self, location: Location, statement: &'o Statement, local_vars: &mut HashMap, RandomState>) -> ControlFlow { + fn visit_statement(&mut self, location: Location, statement: &'o Statement, local_vars: &mut HashMap>) -> ControlFlow { match statement { Statement::Expr(expr) => { match expr { @@ -1564,11 +1563,11 @@ impl<'o, 's> AnalyzeProc<'o, 's> { ControlFlow::allfalse() } - fn visit_var_stmt(&mut self, location: Location, var: &'o VarStatement, local_vars: &mut HashMap, RandomState>) { + fn visit_var_stmt(&mut self, location: Location, var: &'o VarStatement, local_vars: &mut HashMap>) { self.visit_var(location, &var.var_type, &var.name, var.value.as_ref(), local_vars) } - fn visit_var(&mut self, location: Location, var_type: &VarType, name: &str, value: Option<&'o Expression>, local_vars: &mut HashMap, RandomState>) { + fn visit_var(&mut self, location: Location, var_type: &VarType, name: &str, value: Option<&'o Expression>, local_vars: &mut HashMap>) { // Calculate type hint let static_type = self.env.static_type(location, &var_type.type_path); // Visit the expression if it's there @@ -1582,7 +1581,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { local_vars.insert(name.to_owned(), LocalVar { location, analysis }); } - fn visit_expression(&mut self, location: Location, expression: &'o Expression, type_hint: Option>, local_vars: &mut HashMap, RandomState>) -> Analysis<'o> { + fn visit_expression(&mut self, location: Location, expression: &'o Expression, type_hint: Option>, local_vars: &mut HashMap>) -> Analysis<'o> { match expression { Expression::Base { term, follow } => { let base_type_hint = if follow.is_empty() { @@ -1691,7 +1690,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } - fn visit_term(&mut self, location: Location, term: &'o Term, type_hint: Option>, local_vars: &mut HashMap, RandomState>) -> Analysis<'o> { + fn visit_term(&mut self, location: Location, term: &'o Term, type_hint: Option>, local_vars: &mut HashMap>) -> Analysis<'o> { match term { Term::Null => Analysis::null(), Term::Int(number) => Analysis::from_value(self.objtree, Constant::from(*number), type_hint), @@ -1956,7 +1955,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } - fn visit_new(&mut self, location: Location, typepath: TypeRef<'o>, args: &'o Option>, local_vars: &mut HashMap, RandomState>) -> Analysis<'o> { + fn visit_new(&mut self, location: Location, typepath: TypeRef<'o>, args: &'o Option>, local_vars: &mut HashMap>) -> Analysis<'o> { if let Some(new_proc) = typepath.get_proc("New") { self.visit_call( location, @@ -1990,7 +1989,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } - fn visit_follow(&mut self, location: Location, lhs: Analysis<'o>, rhs: &'o Follow, local_vars: &mut HashMap, RandomState>) -> Analysis<'o> { + fn visit_follow(&mut self, location: Location, lhs: Analysis<'o>, rhs: &'o Follow, local_vars: &mut HashMap>) -> Analysis<'o> { match rhs { Follow::Unary(op) => self.visit_unary(lhs, op, location, local_vars), @@ -2190,7 +2189,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } // checks operatorX overloads on types - fn check_operator_overload(&mut self, rhs: Analysis<'o>, location: Location, operator: &str, local_vars: &mut HashMap, RandomState>) -> Analysis<'o> { + fn check_operator_overload(&mut self, rhs: Analysis<'o>, location: Location, operator: &str, local_vars: &mut HashMap>) -> Analysis<'o> { if let Some(impurity) = rhs.is_impure { if impurity { self.env.impure_procs.insert_violator(self.proc_ref, &format!("{} done on non-local var", operator), location); @@ -2217,7 +2216,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Analysis::empty() } - fn visit_unary(&mut self, rhs: Analysis<'o>, op: &UnaryOp, location: Location, local_vars: &mut HashMap, RandomState>) -> Analysis<'o> { + fn visit_unary(&mut self, rhs: Analysis<'o>, op: &UnaryOp, location: Location, local_vars: &mut HashMap>) -> Analysis<'o> { match op { // !x just evaluates the "truthiness" of x and negates it, returning 1 or 0 UnaryOp::Not => Analysis::from(assumption_set![Assumption::IsNum(true)]), @@ -2311,7 +2310,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } - fn visit_call(&mut self, location: Location, src: TypeRef<'o>, proc: ProcRef<'o>, args: &'o [Expression], is_exact: bool, local_vars: &mut HashMap, RandomState>) -> Analysis<'o> { + fn visit_call(&mut self, location: Location, src: TypeRef<'o>, proc: ProcRef<'o>, args: &'o [Expression], is_exact: bool, local_vars: &mut HashMap>) -> Analysis<'o> { self.env.call_tree.entry(self.proc_ref).or_default().push((proc, location, self.inside_newcontext != 0)); if let Some((privateproc, true, decllocation)) = self.env.private.get_self_or_parent(proc) { if self.ty != privateproc.ty() { @@ -2325,9 +2324,9 @@ impl<'o, 's> AnalyzeProc<'o, 's> { // identify and register kwargs used let mut any_kwargs_yet = false; - let mut param_name_map = HashMap::with_hasher(RandomState::default()); - let mut param_expr_map = HashMap::with_hasher(RandomState::default()); - let mut param_idx_map = HashMap::with_hasher(RandomState::default()); + let mut param_name_map = HashMap::new(); + let mut param_expr_map = HashMap::new(); + let mut param_idx_map = HashMap::new(); let mut param_idx = 0; let mut arglist_used = false; @@ -2466,7 +2465,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } - fn visit_arguments(&mut self, location: Location, args: &'o [Expression], local_vars: &mut HashMap, RandomState>) { + fn visit_arguments(&mut self, location: Location, args: &'o [Expression], local_vars: &mut HashMap>) { for arg in args { let mut argument_value = arg; if let Expression::AssignOp { op: AssignOp::Assign, lhs, rhs } = arg { diff --git a/crates/dreamchecker/src/type_expr.rs b/crates/dreamchecker/src/type_expr.rs index 6e9c1430..8fabae3e 100644 --- a/crates/dreamchecker/src/type_expr.rs +++ b/crates/dreamchecker/src/type_expr.rs @@ -1,21 +1,19 @@ //! Support for "type expressions", used in evaluating dynamic/generic return //! types. -use std::collections::HashMap; +use foldhash::HashMap; use dm::ast::*; use dm::constants::Constant; use dm::objtree::{ObjectTree, ProcRef}; use dm::{DMError, Location}; -use ahash::RandomState; - use crate::{Analysis, StaticType}; pub struct TypeExprContext<'o, 't> { pub objtree: &'o ObjectTree, - pub param_name_map: HashMap<&'t str, Analysis<'o>, RandomState>, - pub param_idx_map: HashMap, RandomState>, + pub param_name_map: HashMap<&'t str, Analysis<'o>>, + pub param_idx_map: HashMap>, } impl<'o, 't> TypeExprContext<'o, 't> { diff --git a/crates/dreammaker/Cargo.toml b/crates/dreammaker/Cargo.toml index 8c432d60..bdbdd80e 100644 --- a/crates/dreammaker/Cargo.toml +++ b/crates/dreammaker/Cargo.toml @@ -16,8 +16,8 @@ serde_derive = "1.0.213" toml = "0.5.11" phf = { version = "0.11.2", features = ["macros"] } color_space = "0.5.4" -ahash = "0.8.11" -indexmap = "1.9.3" +foldhash = "0.1.3" +indexmap = "2.6.0" derivative = "2.2.0" get-size = "0.1.4" get-size-derive = "0.1.3" diff --git a/crates/dreammaker/src/config.rs b/crates/dreammaker/src/config.rs index 2c1e9424..7c949069 100644 --- a/crates/dreammaker/src/config.rs +++ b/crates/dreammaker/src/config.rs @@ -1,11 +1,10 @@ //! Configuration file for diagnostics. -use std::collections::HashMap; +use foldhash::HashMap; use std::fs::File; use std::io::Read; use std::path::{Path, PathBuf}; -use ahash::RandomState; use serde::Deserialize; use crate::error::Severity; @@ -19,7 +18,7 @@ pub struct Config { // diagnostic configuration display: WarningDisplay, - diagnostics: HashMap, + diagnostics: HashMap, pub code_standards: CodeStandards, // tool-specific configuration @@ -101,10 +100,10 @@ pub struct MapRenderer { /// Map from render pass name to whether it should be enabled/disabled. /// /// Priority is: CLI arguments > config > defaults. - pub render_passes: HashMap, + pub render_passes: HashMap, /// Map from typepath to layer number. - pub fancy_layers: HashMap, + pub fancy_layers: HashMap, /// List of typepath to just hide pub hide_invisible: Vec, diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index c757a65e..53663178 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -6,7 +6,7 @@ use std::path::Path; use get_size::GetSize; use get_size_derive::GetSize; -use ahash::RandomState; +use foldhash::fast::RandomState; use color_space::{Hsl, Hsv, Lch, Rgb}; use indexmap::IndexMap; use ordered_float::OrderedFloat; diff --git a/crates/dreammaker/src/dmi.rs b/crates/dreammaker/src/dmi.rs index 4ced6159..61abaa8d 100644 --- a/crates/dreammaker/src/dmi.rs +++ b/crates/dreammaker/src/dmi.rs @@ -1,6 +1,7 @@ //! DMI metadata parsing and representation. -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; +use foldhash::{HashMap, HashMapExt}; use std::fmt::Display; use std::io; use std::path::Path; diff --git a/crates/dreammaker/src/error.rs b/crates/dreammaker/src/error.rs index 5c2ffafe..752a8e6f 100644 --- a/crates/dreammaker/src/error.rs +++ b/crates/dreammaker/src/error.rs @@ -1,12 +1,10 @@ //! Error, warning, and other diagnostics handling. use std::cell::{Ref, RefCell, RefMut}; -use std::collections::HashMap; +use foldhash::HashMap; use std::path::{Path, PathBuf}; use std::{error, fmt, io}; -use ahash::RandomState; - use get_size::GetSize; use get_size_derive::GetSize; use termcolor::{Color, ColorSpec}; @@ -36,7 +34,7 @@ pub struct FileList { /// The list of loaded files. files: RefCell>, /// Reverse mapping from paths to file numbers. - reverse_files: RefCell>, + reverse_files: RefCell>, } /// A diagnostics context, tracking loaded files and any observed errors. diff --git a/crates/dreammaker/src/lib.rs b/crates/dreammaker/src/lib.rs index 7ec8a8ba..ab506b5d 100644 --- a/crates/dreammaker/src/lib.rs +++ b/crates/dreammaker/src/lib.rs @@ -16,9 +16,10 @@ use std::borrow::Cow; use std::path::Path; mod error; -use ahash::RandomState; pub use error::*; use get_size::GetSize; + +use foldhash::fast::RandomState; use indexmap::IndexMap; // roughly in order of stage diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index 6aa2f374..b644d477 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -6,8 +6,8 @@ use std::fmt; use get_size::GetSize; use get_size_derive::GetSize; -use ahash::RandomState; use indexmap::IndexMap; +use foldhash::fast::RandomState; use crate::heap_size_of_index_map; diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index 27954542..d8c7cf3b 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -1,12 +1,12 @@ //! The preprocessor. use std::borrow::Cow; -use std::collections::{HashMap, VecDeque}; +use std::collections::VecDeque; use std::fs::File; use std::path::{Path, PathBuf}; use std::rc::Rc; use std::{fmt, io}; -use ahash::RandomState; +use foldhash::HashMap; use interval_tree::{range, IntervalTree}; @@ -169,7 +169,7 @@ impl std::ops::DerefMut for DefineHistory { /// stack is exhausted. #[derive(Debug, Clone, Default)] pub struct DefineMap { - inner: HashMap, RandomState>, + inner: HashMap>, } impl DefineMap { @@ -384,10 +384,10 @@ pub struct Preprocessor<'ctx> { env_file: PathBuf, include_stack: IncludeStack<'ctx>, - include_locations: HashMap, + include_locations: HashMap, // list of files with #pragma multiple to allow for more then one include // should this be done as an enum in include_locations instead? - multiple_locations: HashMap, + multiple_locations: HashMap, last_input_loc: Location, output: VecDeque, ifdef_stack: Vec, @@ -401,7 +401,7 @@ pub struct Preprocessor<'ctx> { scripts: Vec, last_printable_input_loc: Location, - danger_idents: HashMap, + danger_idents: HashMap, in_interp_string: u32, docs_in: VecDeque<(Location, DocComment)>, @@ -583,9 +583,8 @@ impl<'ctx> Preprocessor<'ctx> { } fn pop_ifdef(&mut self) -> Option { - self.ifdef_stack.pop().map(|ifdef| { + self.ifdef_stack.pop().inspect(|ifdef| { self.ifdef_history.insert(range(ifdef.location, self.last_input_loc), ifdef.active); - ifdef }) } From e22ff4757f29dbcf01e1aac9ad29ce8bf668f235 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 25 Nov 2024 11:14:52 -0800 Subject: [PATCH 144/197] Add and use Token::single_quoted --- crates/dreammaker/src/lexer.rs | 8 ++++++++ crates/dreammaker/src/parser.rs | 8 ++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index cf93b541..92ea37ce 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -348,6 +348,14 @@ impl Token { _ => false, } } + + pub fn single_quoted(&self) -> Cow<'static, str> { + match self { + Token::Eof => Cow::Borrowed("EOF"), + Token::Punct(p) => Cow::Borrowed(p.single_quoted()), + _ => Cow::Owned(format!("'{}'", self)), + } + } } impl fmt::Display for Token { diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index c87184e6..23cee7e4 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -587,11 +587,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } fn exact(&mut self, tok: Token) -> Status<()> { - match tok { - Token::Eof => self.expected("EOF"), - Token::Punct(p) => self.expected(p.single_quoted()), - ref other => self.expected(format!("'{}'", other)), - } + self.expected(tok.single_quoted()); if self.peek() == &tok { self.take(); SUCCESS @@ -650,7 +646,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { loop { self.expected("';'"); if terminator != Token::Eof { - self.expected(format!("'{terminator}'")); + self.expected(terminator.single_quoted()); } if current == self.tree.root_index() { From a026dc6c09960a7268ee99a9777a7d415cca2e74 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 20:50:11 -0800 Subject: [PATCH 145/197] Bump rustls from 0.23.15 to 0.23.18 (#415) Bumps [rustls](https://github.com/rustls/rustls) from 0.23.15 to 0.23.18. - [Release notes](https://github.com/rustls/rustls/releases) - [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md) - [Commits](rustls/rustls@v/0.23.15...v/0.23.18) --- updated-dependencies: - dependency-name: rustls dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 795bafea..5fa45bb1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1329,9 +1329,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.15" +version = "0.23.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" +checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f" dependencies = [ "log", "once_cell", From 4c8b80ec36165d87debd7680886ba9b591ddb1b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 19:46:34 -0800 Subject: [PATCH 146/197] Bump hashbrown from 0.15.0 to 0.15.2 (#417) Bumps [hashbrown](https://github.com/rust-lang/hashbrown) from 0.15.0 to 0.15.2. - [Changelog](https://github.com/rust-lang/hashbrown/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/hashbrown/commits) --- updated-dependencies: - dependency-name: hashbrown dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5fa45bb1..fed32276 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -746,9 +746,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" From c7448ea917a0c35c91742729bff990acf665dc0b Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 8 Dec 2024 23:17:40 -0800 Subject: [PATCH 147/197] Require &mut Context to modify config --- crates/dm-langserver/src/completion.rs | 4 +-- crates/dm-langserver/src/debugger/mod.rs | 2 +- crates/dm-langserver/src/macros.rs | 4 +-- crates/dm-langserver/src/main.rs | 42 +++++++++++------------- crates/dreammaker/src/error.rs | 16 ++++----- 5 files changed, 33 insertions(+), 35 deletions(-) diff --git a/crates/dm-langserver/src/completion.rs b/crates/dm-langserver/src/completion.rs index 8f7e6f8b..e4010b5c 100644 --- a/crates/dm-langserver/src/completion.rs +++ b/crates/dm-langserver/src/completion.rs @@ -164,10 +164,10 @@ pub fn combine_tree_path<'a, I>(iter: &I, mut absolute: bool, mut parts: &'a [St prefix_parts.iter().chain(parts).map(|x| &**x) } -impl<'a> Engine<'a> { +impl Engine { pub fn follow_type_path<'b, I>(&'b self, iter: &I, mut parts: &'b [(PathOp, String)]) -> Option> where - I: Iterator + Clone, + I: Iterator + Clone, { // cut off the part of the path we haven't selected if_annotation! { Annotation::InSequence(idx) in iter; { diff --git a/crates/dm-langserver/src/debugger/mod.rs b/crates/dm-langserver/src/debugger/mod.rs index 1159e784..7b2045df 100644 --- a/crates/dm-langserver/src/debugger/mod.rs +++ b/crates/dm-langserver/src/debugger/mod.rs @@ -105,7 +105,7 @@ pub fn debugger_main>(mut args: I) { let environment = dm::detect_environment_default() .expect("detect .dme error") .expect("did not detect a .dme"); - let ctx = dm::Context::default(); + let mut ctx = dm::Context::default(); ctx.autodetect_config(&environment); let mut pp = dm::preprocessor::Preprocessor::new(&ctx, environment).unwrap(); let objtree = { diff --git a/crates/dm-langserver/src/macros.rs b/crates/dm-langserver/src/macros.rs index 833fb066..66800e2b 100644 --- a/crates/dm-langserver/src/macros.rs +++ b/crates/dm-langserver/src/macros.rs @@ -12,7 +12,7 @@ pub mod all_notifications { macro_rules! handle_method_call { ($($(#[$attr:meta])* on $what:ident(&mut $self:ident, $p:pat) $b:block)*) => { - impl<'a> Engine<'a> { + impl Engine { fn handle_method_call_table(method: &str) -> Option Result> { use macros::all_methods::*; $(if method == <$what>::METHOD { @@ -46,7 +46,7 @@ macro_rules! handle_method_call { macro_rules! handle_notification { ($(on $what:ident(&mut $self:ident, $p:pat) $b:block)*) => { - impl<'a> Engine<'a> { + impl Engine { fn handle_notification_table(method: &str) -> Option Result<(), jsonrpc::Error>> { use macros::all_notifications::*; $(if method == <$what>::METHOD { diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index ffa6bb3e..4d346851 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -89,8 +89,7 @@ fn main() { } } - let context = dm::Context::default(); - let mut engine = Engine::new(&context); + let mut engine = Engine::new(); jrpc_io::run_until_stdin_eof(|message| engine.handle_input(message)); engine.exit(0); } @@ -242,7 +241,7 @@ impl DiagnosticsTracker { } } -struct Engine<'a> { +struct Engine { docs: document::DocumentStore, status: InitStatus, @@ -250,7 +249,7 @@ struct Engine<'a> { threads: Vec>, root: Option, - context: &'a dm::Context, + context: dm::Context, defines: Option, objtree: Arc, references_table: background::Background, @@ -263,8 +262,8 @@ struct Engine<'a> { debug_server_dll: Option, } -impl<'a> Engine<'a> { - fn new(context: &'a dm::Context) -> Self { +impl Engine { + fn new() -> Self { Engine { docs: Default::default(), @@ -273,7 +272,7 @@ impl<'a> Engine<'a> { threads: Default::default(), root: None, - context, + context: dm::Context::default(), defines: None, objtree: Default::default(), references_table: Default::default(), @@ -448,10 +447,9 @@ impl<'a> Engine<'a> { }; // Set up the preprocessor. - let ctx = self.context; - ctx.reset_io_time(); - ctx.autodetect_config(&environment); - let mut pp = match dm::preprocessor::Preprocessor::new(ctx, environment.clone()) { + self.context.reset_io_time(); + self.context.autodetect_config(&environment); + let mut pp = match dm::preprocessor::Preprocessor::new(&self.context, environment.clone()) { Ok(pp) => pp, Err(err) => { self.issue_notification::( @@ -477,7 +475,7 @@ impl<'a> Engine<'a> { // Parse the environment. let fatal_errored; { - let mut parser = dm::parser::Parser::new(ctx, dm::indents::IndentProcessor::new(ctx, &mut pp)); + let mut parser = dm::parser::Parser::new(&self.context, dm::indents::IndentProcessor::new(&self.context, &mut pp)); parser.enable_procs(); let (fatal_errored_2, objtree) = parser.parse_object_tree_2(); fatal_errored = fatal_errored_2; @@ -485,7 +483,7 @@ impl<'a> Engine<'a> { } let elapsed = start.elapsed(); start += elapsed; { - let disk = ctx.get_io_time(); + let disk = self.context.get_io_time(); let parse = elapsed.saturating_sub(disk); eprint!("disk {}.{:03}s - parse {}.{:03}s", disk.as_secs(), disk.subsec_millis(), parse.as_secs(), parse.subsec_millis()); } @@ -504,7 +502,7 @@ impl<'a> Engine<'a> { let mut diagnostics_lock = self.diagnostics_tracker.lock().unwrap(); // Background thread: If enabled, and parse was OK, run dreamchecker. - if ctx.config().langserver.dreamchecker && !fatal_errored { + if self.context.config().langserver.dreamchecker && !fatal_errored { self.show_status("checking"); let context = self.context.clone(); let objtree = self.objtree.clone(); @@ -582,16 +580,16 @@ impl<'a> Engine<'a> { Err(_) => "".as_ref(), }; let (real_file_id, mut preprocessor) = match self.context.get_file(stripped) { - Some(id) => (id, defines.branch_at_file(id, self.context)), - None => (FileId::default(), defines.branch_at_end(self.context)), + Some(id) => (id, defines.branch_at_file(id, &self.context)), + None => (FileId::default(), defines.branch_at_end(&self.context)), }; let contents = self.docs.read(url).map_err(invalid_request)?; let file_id = preprocessor.push_file(stripped.to_owned(), contents).map_err(invalid_request)?; preprocessor.enable_annotations(); let mut annotations = AnnotationTree::default(); { - let indent = dm::indents::IndentProcessor::new(self.context, &mut preprocessor); - let parser = dm::parser::Parser::new(self.context, indent); + let indent = dm::indents::IndentProcessor::new(&self.context, &mut preprocessor); + let parser = dm::parser::Parser::new(&self.context, indent); parser.parse_annotations_only(&mut annotations); } annotations.merge(preprocessor.take_annotations().unwrap()); @@ -602,7 +600,7 @@ impl<'a> Engine<'a> { let filename = url.to_string(); let contents = self.docs.get_contents(url).map_err(invalid_request)?.into_owned(); - let mut pp = dm::preprocessor::Preprocessor::from_buffer(self.context, filename.clone().into(), contents); + let mut pp = dm::preprocessor::Preprocessor::from_buffer(&self.context, filename.clone().into(), contents); let file_id = self.context.get_file(filename.as_ref()).expect("file didn't exist?"); // Clear old errors for this file. Hacky, but it will work for now. self.context.errors_mut().retain(|error| error.location().file != file_id); @@ -610,8 +608,8 @@ impl<'a> Engine<'a> { pp.enable_annotations(); let mut annotations = AnnotationTree::default(); { - let indent = dm::indents::IndentProcessor::new(self.context, &mut pp); - let mut parser = dm::parser::Parser::new(self.context, indent); + let indent = dm::indents::IndentProcessor::new(&self.context, &mut pp); + let mut parser = dm::parser::Parser::new(&self.context, indent); parser.annotate_to(&mut annotations); // Every time anyone types anything the object tree is replaced. // This is probably really inefficient, but it will do until @@ -619,7 +617,7 @@ impl<'a> Engine<'a> { self.objtree = Arc::new(parser.parse_object_tree()); } pp.finalize(); - dreamchecker::run(self.context, &self.objtree); + dreamchecker::run(&self.context, &self.objtree); // Perform a diagnostics pump on this file only. // Assume all errors are in this file. diff --git a/crates/dreammaker/src/error.rs b/crates/dreammaker/src/error.rs index 752a8e6f..b3f8e718 100644 --- a/crates/dreammaker/src/error.rs +++ b/crates/dreammaker/src/error.rs @@ -44,7 +44,7 @@ pub struct Context { /// A list of errors, warnings, and other diagnostics generated. errors: RefCell>, /// Warning config - config: RefCell, + config: Config, print_severity: Option, io_time: std::cell::Cell, @@ -124,9 +124,9 @@ impl Context { // ------------------------------------------------------------------------ // Configuration - pub fn force_config(&self, toml: &Path) { + pub fn force_config(&mut self, toml: &Path) { match Config::read_toml(toml) { - Ok(config) => *self.config.borrow_mut() = config, + Ok(config) => self.config = config, Err(io_error) => { let file = self.register_file(toml); let (line, column) = io_error.line_col().unwrap_or((1, 1)); @@ -137,15 +137,15 @@ impl Context { } } - pub fn autodetect_config(&self, dme: &Path) { + pub fn autodetect_config(&mut self, dme: &Path) { let toml = dme.parent().unwrap().join("SpacemanDMM.toml"); if toml.exists() { self.force_config(&toml); } } - pub fn config(&self) -> Ref { - self.config.borrow() + pub fn config(&self) -> &Config { + &self.config } /// Set a severity at and above which errors will be printed immediately. @@ -173,11 +173,11 @@ impl Context { /// Push an error or other diagnostic to the context. pub fn register_error(&self, error: DMError) { - let Some(error) = self.config.borrow().set_configured_severity(error) else { + let Some(error) = self.config.set_configured_severity(error) else { return // errortype is disabled }; // ignore errors with severity above configured level - if !self.config.borrow().registerable_error(&error) { + if !self.config.registerable_error(&error) { return } if let Some(print_severity) = self.print_severity { From 844ca6395ad2339ded7dc5dc58f39f04ab685029 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Fri, 10 Jan 2025 23:37:04 -0800 Subject: [PATCH 148/197] Run cargo update --- Cargo.lock | 540 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 387 insertions(+), 153 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fed32276..5a5fa516 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,9 +40,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.17" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -55,9 +55,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" @@ -89,13 +89,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.83" +version = "0.1.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.96", ] [[package]] @@ -107,7 +107,7 @@ dependencies = [ "attribute-derive-macro", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.96", ] [[package]] @@ -123,7 +123,7 @@ dependencies = [ "proc-macro2", "quote", "quote-use", - "syn 2.0.85", + "syn 2.0.96", ] [[package]] @@ -155,9 +155,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" [[package]] name = "block-buffer" @@ -185,22 +185,22 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.19.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" +checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.96", ] [[package]] @@ -211,15 +211,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" -version = "1.1.31" +version = "1.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "ad0cf6e91fde44c773c6ee7ec6bba798504641a8bc2eb7e37a04ffbf4dfaa55a" dependencies = [ "jobserver", "libc", @@ -234,9 +234,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -248,9 +248,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" dependencies = [ "clap_builder", "clap_derive", @@ -258,9 +258,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" dependencies = [ "anstream", "anstyle", @@ -270,21 +270,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.96", ] [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "collection_literals" @@ -318,9 +318,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -336,9 +336,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -355,9 +355,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crypto-common" @@ -398,7 +398,7 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.96", ] [[package]] @@ -411,6 +411,17 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "dm-langserver" version = "1.9.0" @@ -542,18 +553,18 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "fdeflate" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" dependencies = [ "simd-adler32", ] [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide", @@ -561,9 +572,9 @@ dependencies = [ [[package]] name = "foldhash" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" [[package]] name = "form_urlencoded" @@ -630,7 +641,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.96", ] [[package]] @@ -687,7 +698,7 @@ checksum = "13a1bcfb855c1f340d5913ab542e36f25a1c56f57de79022928297632435dec2" dependencies = [ "attribute-derive", "quote", - "syn 2.0.85", + "syn 2.0.96", ] [[package]] @@ -737,7 +748,7 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "libc", "libgit2-sys", "log", @@ -786,20 +797,149 @@ dependencies = [ ] [[package]] -name = "idna" -version = "0.5.0" +name = "icu_collections" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown", @@ -835,9 +975,9 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" @@ -850,10 +990,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -880,9 +1021,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libgit2-sys" @@ -898,9 +1039,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.20" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +checksum = "df9b68e50e6e0b26f672573834882eb57759f6db9b3be2ea3c35c91188bb4eaa" dependencies = [ "cc", "libc", @@ -908,6 +1049,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + [[package]] name = "lodepng" version = "3.10.7" @@ -922,9 +1069,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "3d6ea2a48c204030ee31a7d7fc72c93294c92fe87ecb1789881c9543516e1a0d" [[package]] name = "lsp-types" @@ -979,9 +1126,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" dependencies = [ "adler2", "simd-adler32", @@ -1050,9 +1197,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_macros", "phf_shared", @@ -1060,9 +1207,9 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", "rand", @@ -1070,31 +1217,31 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ "phf_generator", "phf_shared", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.96", ] [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -1110,9 +1257,9 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "png" -version = "0.17.14" +version = "0.17.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -1167,9 +1314,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -1180,7 +1327,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "getopts", "memchr", "unicase", @@ -1188,9 +1335,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -1203,7 +1350,7 @@ checksum = "a7b5abe3fe82fdeeb93f44d66a7b444dedf2e4827defb0a8e69c437b2de2ef94" dependencies = [ "quote", "quote-use-macros", - "syn 2.0.85", + "syn 2.0.96", ] [[package]] @@ -1215,7 +1362,7 @@ dependencies = [ "derive-where", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.96", ] [[package]] @@ -1288,9 +1435,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -1329,9 +1476,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.18" +version = "0.23.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f" +checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8" dependencies = [ "log", "once_cell", @@ -1344,9 +1491,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" [[package]] name = "rustls-webpki" @@ -1376,29 +1523,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.213" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.213" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.96", ] [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ "itoa", "memchr", @@ -1414,7 +1561,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.96", ] [[package]] @@ -1454,9 +1601,9 @@ checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "siphasher" -version = "0.3.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" @@ -1479,6 +1626,12 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "strsim" version = "0.11.1" @@ -1504,15 +1657,26 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.85" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -1523,20 +1687,15 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.8.0" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "toml" version = "0.5.11" @@ -1554,30 +1713,15 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicase" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" - -[[package]] -name = "unicode-bidi" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" - -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-width" @@ -1593,9 +1737,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.10.1" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" dependencies = [ "base64", "flate2", @@ -1609,9 +1753,9 @@ dependencies = [ [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -1619,6 +1763,18 @@ dependencies = [ "serde", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -1655,9 +1811,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", @@ -1666,24 +1822,23 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.96", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1691,28 +1846,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.96", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "webpki-roots" -version = "0.26.6" +version = "0.26.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" dependencies = [ "rustls-pki-types", ] @@ -1823,6 +1978,42 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -1841,7 +2032,28 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.96", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", + "synstructure", ] [[package]] @@ -1849,3 +2061,25 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] From b3eb12c1285e26ed2616489a1ee5d2c10d80985a Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 11 Jan 2025 13:08:11 -0800 Subject: [PATCH 149/197] Reduce allocation in FileList::get_path --- crates/dm-langserver/src/debugger/mod.rs | 4 ++-- crates/dmdoc/src/main.rs | 6 +++--- crates/dreammaker/src/error.rs | 12 ++++++------ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/dm-langserver/src/debugger/mod.rs b/crates/dm-langserver/src/debugger/mod.rs index 7b2045df..9530afb2 100644 --- a/crates/dm-langserver/src/debugger/mod.rs +++ b/crates/dm-langserver/src/debugger/mod.rs @@ -924,7 +924,7 @@ handle_request! { .unwrap_or_default() .to_string_lossy() .into_owned()), - path: Some(self.db.root_dir.join(path).to_string_lossy().into_owned()), + path: Some(self.db.root_dir.join(&*path).to_string_lossy().into_owned()), .. Default::default() }); dap_frame.line = i64::from(proc.location.line); @@ -990,7 +990,7 @@ handle_request! { .unwrap_or_default() .to_string_lossy() .into_owned()), - path: Some(self.db.root_dir.join(path).to_string_lossy().into_owned()), + path: Some(self.db.root_dir.join(&*path).to_string_lossy().into_owned()), .. Default::default() }); dap_frame.line = i64::from(proc.location.line); diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index c339226a..d6994177 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -358,7 +358,7 @@ fn main2() -> Result<(), Box> { type_, // but `decl` is only used if it's on this type decl: if var.declaration.is_some() { "var" } else { "" }, - file: context.file_path(var.value.location.file), + file: context.file_path(var.value.location.file).to_owned(), line: var.value.location.line, parent, }); @@ -422,7 +422,7 @@ fn main2() -> Result<(), Box> { Some(ref decl) => decl.kind.name(), None => "", }, - file: context.file_path(proc_value.location.file), + file: context.file_path(proc_value.location.file).to_owned(), line: proc_value.location.line, return_type, parent, @@ -446,7 +446,7 @@ fn main2() -> Result<(), Box> { } if anything { - parsed_type.file = context.file_path(ty.location.file); + parsed_type.file = context.file_path(ty.location.file).to_owned(); parsed_type.line = ty.location.line; parsed_type.substance = substance; if substance { diff --git a/crates/dreammaker/src/error.rs b/crates/dreammaker/src/error.rs index b3f8e718..ce6b9001 100644 --- a/crates/dreammaker/src/error.rs +++ b/crates/dreammaker/src/error.rs @@ -73,16 +73,16 @@ impl FileList { } /// Look up a file path by its index returned from `register_file`. - pub fn get_path(&self, file: FileId) -> PathBuf { + pub fn get_path(&self, file: FileId) -> Ref { + let files = self.files.borrow(); if file == FILEID_BUILTINS { - return "(builtins)".into(); + return Ref::map(files, |_| Path::new("(builtins)")); } let idx = (file.0 - FILEID_MIN.0) as usize; - let files = self.files.borrow(); if idx > files.len() { - "(unknown)".into() + Ref::map(files, |_| Path::new("(unknown)")) } else { - files[idx].to_owned() + Ref::map(files, |files| files[idx].as_path()) } } @@ -108,7 +108,7 @@ impl Context { } /// Look up a file path by its index returned from `register_file`. - pub fn file_path(&self, file: FileId) -> PathBuf { + pub fn file_path(&self, file: FileId) -> Ref { self.files.get_path(file) } From db59a080030e41c5f929a358f397726c6831537c Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 11 Jan 2025 14:01:20 -0800 Subject: [PATCH 150/197] Add LocationTracker::count_location helper --- crates/dreammaker/src/lexer.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index 92ea37ce..e59f3902 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -500,9 +500,8 @@ fn buffer_read(file: FileId, mut read: R) -> Result, DMError> { let mut buffer = Vec::new(); if let Err(error) = read.read_to_end(&mut buffer) { - let mut tracker = LocationTracker::new(file, buffer.as_slice().into()); - tracker.by_ref().count(); - return Err(DMError::new(tracker.location(), "i/o error reading file").with_cause(error)); + let location = LocationTracker::count_location(file, &buffer); + return Err(DMError::new(location, "i/o error reading file").with_cause(error)); } Ok(buffer) @@ -524,9 +523,8 @@ pub fn buffer_file(file: FileId, path: &std::path::Path) -> Result, DMEr }; if let Err(error) = read.read_to_end(&mut buffer) { - let mut tracker = LocationTracker::new(file, buffer.as_slice().into()); - tracker.by_ref().count(); - return Err(DMError::new(tracker.location(), "i/o error reading file").with_cause(error)); + let location = LocationTracker::count_location(file, &buffer); + return Err(DMError::new(location, "i/o error reading file").with_cause(error)); } Ok(buffer) @@ -559,6 +557,12 @@ impl<'a> LocationTracker<'a> { } } + pub fn count_location(file: FileId, content: &[u8]) -> Location { + let mut tracker = LocationTracker::new(file, content.into()); + tracker.by_ref().count(); + tracker.location() + } + pub fn new(file: FileId, inner: Cow<'a, [u8]>) -> LocationTracker<'a> { LocationTracker { inner, From c5e4b0b1e3227ef4f5219971bc4c06197d2ffec5 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 11 Jan 2025 15:04:19 -0800 Subject: [PATCH 151/197] Simplify skipping of UTF-8 BOM --- crates/dreammaker/src/lexer.rs | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index e59f3902..1c8a0dc4 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -545,18 +545,6 @@ pub struct LocationTracker<'a> { } impl<'a> LocationTracker<'a> { - pub fn skip_utf8_bom(input: Cow<'a, [u8]>) -> Cow<'a, [u8]> { - const BOM: &[u8] = b"\xEF\xBB\xBF"; - if input.starts_with(BOM) { - match input { - Cow::Borrowed(b) => Cow::Borrowed(&b[BOM.len()..]), - Cow::Owned(mut o) => { o.drain(..BOM.len()); Cow::Owned(o) } - } - } else { - input - } - } - pub fn count_location(file: FileId, content: &[u8]) -> Location { let mut tracker = LocationTracker::new(file, content.into()); tracker.by_ref().count(); @@ -564,7 +552,7 @@ impl<'a> LocationTracker<'a> { } pub fn new(file: FileId, inner: Cow<'a, [u8]>) -> LocationTracker<'a> { - LocationTracker { + let mut this = LocationTracker { inner, offset: 0, location: Location { @@ -573,7 +561,12 @@ impl<'a> LocationTracker<'a> { column: 0, }, at_line_end: true, + }; + // Skip UTF-8 BOM + if this.inner.starts_with(b"\xEF\xBB\xBF") { + this.offset += 3; } + this } /// `location` will be taken as the location of the first character of `inner`. @@ -686,8 +679,7 @@ impl<'ctx> Lexer<'ctx> { /// Create a new lexer from a byte stream. pub fn new>>(context: &'ctx Context, file_number: FileId, input: I) -> Self { - let inner = LocationTracker::skip_utf8_bom(input.into()); - Lexer::from_input(context, LocationTracker::new(file_number, inner)) + Lexer::from_input(context, LocationTracker::new(file_number, input.into())) } /// Create a new lexer from a reader. From 76725c56819e3fae76d35c405bbf9fbe9abe4b6d Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 11 Jan 2025 15:04:41 -0800 Subject: [PATCH 152/197] Check for 'in' keyword directly, not by looping Best case 4% speedup on lint example. --- crates/dreammaker/src/lexer.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index 1c8a0dc4..1040992e 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -1259,10 +1259,8 @@ impl<'ctx> Iterator for Lexer<'ctx> { } } // check keywords - for &(name, value) in PUNCT_TABLE.iter() { - if name == ident { - return Some(locate(Punct(value))); - } + if ident == "in" { + return Some(locate(Punct(In))); } self.close_allowed = true; Some(locate(Ident(ident, ws))) From fa715c91944b87bced55b34e10399538d552014a Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 11 Jan 2025 15:11:58 -0800 Subject: [PATCH 153/197] Allocate exact amount in read_ident --- crates/dreammaker/src/lexer.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index 1040992e..8983cf7f 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -931,20 +931,25 @@ impl<'ctx> Lexer<'ctx> { } } - fn read_ident(&mut self, first: u8) -> String { - // 12 is ~89% of idents, 24 is ~99.5%, 48 is ~100% - let mut ident = Vec::with_capacity(12); - ident.push(first); + fn read_ident(&mut self, first: u8) -> (String, bool) { + let start = self.input.offset - 1; + let mut end = start + 1; + assert_eq!(first, self.input.inner[start]); + let ws; loop { match self.next() { - Some(ch) if is_ident(ch) || is_digit(ch) => ident.push(ch), + Some(ch) if is_ident(ch) || is_digit(ch) => { + end += 1; + }, ch => { + ws = ch == Some(b' ') || ch == Some(b'\t'); self.put_back(ch); break; } } } - from_utf8_or_latin1(ident) + let ident = &self.input.inner[start..end]; + (from_utf8_or_latin1_borrowed(ident).into_owned(), ws) } fn read_resource(&mut self) -> String { @@ -1247,10 +1252,7 @@ impl<'ctx> Iterator for Lexer<'ctx> { None => match first { b'0'..=b'9' => Some(locate(self.read_number(first))), b'_' | b'a'..=b'z' | b'A'..=b'Z' => { - let ident = self.read_ident(first); - let next = self.next(); - self.put_back(next); - let ws = next == Some(b' ') || next == Some(b'\t'); + let (ident, ws) = self.read_ident(first); if self.directive == Directive::Hash { if ident == "warn" || ident == "error" { self.directive = Directive::Stringy; From 9fd698e2d63ec86534c81ef1dd82f652cbe6109c Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 23 Feb 2025 14:36:22 -0800 Subject: [PATCH 154/197] Update to auxtools debug server v2.3.4 --- crates/dm-langserver/build.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/dm-langserver/build.rs b/crates/dm-langserver/build.rs index 8e8c2ff5..dc21b05b 100644 --- a/crates/dm-langserver/build.rs +++ b/crates/dm-langserver/build.rs @@ -32,9 +32,9 @@ fn main() { download_dll( &out_dir, "debug_server.dll", - "v2.3.3", // DEBUG_SERVER_TAG - "https://github.com/willox/auxtools/releases/download/v2.3.3/debug_server.dll", // DEBUG_SERVER_DLL_URL - "8c3633d8237738be39a8c8f34bbd3d819cdaa270d1f30774c5007481fc32418c", // DEBUG_SERVER_DLL_SHA256 + "v2.3.4", // DEBUG_SERVER_TAG + "https://github.com/willox/auxtools/releases/download/v2.3.4/debug_server.dll", // DEBUG_SERVER_DLL_URL + "06547804cf39c74d6a74aa1663a47f438871ea8fa85deb7dcb0c8d772747db7c", // DEBUG_SERVER_DLL_SHA256 ); } From 18a5d84ba5f8611c0842dd9102740741edc12e5a Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 23 Feb 2025 19:06:40 -0800 Subject: [PATCH 155/197] Update copyright years for 2025 --- crates/dm-langserver/src/main.rs | 2 +- crates/dmdoc/src/main.rs | 2 +- crates/dmm-tools-cli/src/main.rs | 2 +- crates/dreamchecker/src/main.rs | 2 +- crates/spaceman-dmm/src/main.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index 4d346851..1b5414b9 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -54,7 +54,7 @@ fn main() { std::env::set_var("RUST_BACKTRACE", "1"); eprintln!( - "dm-langserver {} Copyright (C) 2017-2024 Tad Hardesty", + "dm-langserver {} Copyright (C) 2017-2025 Tad Hardesty", env!("CARGO_PKG_VERSION") ); eprintln!("This program comes with ABSOLUTELY NO WARRANTY. This is free software,"); diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index d6994177..a35293d2 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -24,7 +24,7 @@ use dm::docs::*; use markdown::DocBlock; const BUILD_INFO: &str = concat!( - "dmdoc ", env!("CARGO_PKG_VERSION"), " Copyright (C) 2017-2024 Tad Hardesty\n", + "dmdoc ", env!("CARGO_PKG_VERSION"), " Copyright (C) 2017-2025 Tad Hardesty\n", include_str!(concat!(env!("OUT_DIR"), "/build-info.txt")), "\n", "This program comes with ABSOLUTELY NO WARRANTY. This is free software,\n", "and you are welcome to redistribute it under the conditions of the GNU\n", diff --git a/crates/dmm-tools-cli/src/main.rs b/crates/dmm-tools-cli/src/main.rs index ab538084..614e5d9b 100644 --- a/crates/dmm-tools-cli/src/main.rs +++ b/crates/dmm-tools-cli/src/main.rs @@ -89,7 +89,7 @@ impl Context { env!("CARGO_PKG_VERSION"), "\n", include_str!(concat!(env!("OUT_DIR"), "/build-info.txt")) ), - author="Copyright (C) 2017-2024 Tad Hardesty", + author="Copyright (C) 2017-2025 Tad Hardesty", about="This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under the conditions of the GNU General Public License version 3.", diff --git a/crates/dreamchecker/src/main.rs b/crates/dreamchecker/src/main.rs index 0b63b77f..174b292e 100644 --- a/crates/dreamchecker/src/main.rs +++ b/crates/dreamchecker/src/main.rs @@ -21,7 +21,7 @@ fn main() { while let Some(arg) = args.next() { if arg == "-V" || arg == "--version" { println!( - "dreamchecker {} Copyright (C) 2017-2024 Tad Hardesty", + "dreamchecker {} Copyright (C) 2017-2025 Tad Hardesty", env!("CARGO_PKG_VERSION") ); println!("{}", include_str!(concat!(env!("OUT_DIR"), "/build-info.txt"))); diff --git a/crates/spaceman-dmm/src/main.rs b/crates/spaceman-dmm/src/main.rs index 04a0434c..09de2d4c 100644 --- a/crates/spaceman-dmm/src/main.rs +++ b/crates/spaceman-dmm/src/main.rs @@ -590,7 +590,7 @@ impl EditorScene { ui.menu(im_str!("Help"), true, || { ui.menu(im_str!("About SpacemanDMM"), true, || { ui.text(&im_str!( - "{} {} Copyright (C) 2017-2024 Tad Hardesty", + "{} {} Copyright (C) 2017-2025 Tad Hardesty", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"), )); From 039e8208c21212cad5611cedc701b9eb1d3f8519 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Mar 2025 17:24:09 -0800 Subject: [PATCH 156/197] Bump ring from 0.17.8 to 0.17.13 (#422) Bumps [ring](https://github.com/briansmith/ring) from 0.17.8 to 0.17.13. - [Changelog](https://github.com/briansmith/ring/blob/main/RELEASES.md) - [Commits](https://github.com/briansmith/ring/commits) --- updated-dependencies: - dependency-name: ring dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Cargo.lock | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5a5fa516..bb78af3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "adler2" @@ -1461,15 +1461,14 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.8" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" dependencies = [ "cc", "cfg-if", "getrandom", "libc", - "spin", "untrusted", "windows-sys 0.52.0", ] @@ -1620,12 +1619,6 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - [[package]] name = "stable_deref_trait" version = "1.2.0" From 4b77cd487d0a7b6a069df20356b701af5b20489d Mon Sep 17 00:00:00 2001 From: Waterpig <49160555+Majkl-J@users.noreply.github.com> Date: Tue, 18 Mar 2025 04:06:30 +0100 Subject: [PATCH 157/197] Add pixel_w and pixel_z to image() (#424) The image constructor accepts pixel_w and pixel_z as arguments. This is not documented anywhere but seemingly works completely fine, as shown below. ![image](https://github.com/user-attachments/assets/ea30e0bd-bf03-4092-86f6-77105818e332) So I added it to lints --- crates/dreammaker/src/builtins.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/dreammaker/src/builtins.rs b/crates/dreammaker/src/builtins.rs index 503d722e..cd40f077 100644 --- a/crates/dreammaker/src/builtins.rs +++ b/crates/dreammaker/src/builtins.rs @@ -474,7 +474,7 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { proc/html_encode(PlainText); proc/icon(icon,icon_state,dir,frame,moving); // SNA proc/icon_states(Icon, mode=0); - proc/image(icon,loc,icon_state,layer,dir,pixel_x,pixel_y); // SNA + proc/image(icon,loc,icon_state,layer,dir,pixel_x,pixel_y,pixel_w,pixel_z); // SNA proc/initial(Var); // special form proc/input(Usr=usr,Message,Title,Default)/*as Type in List*/; // special form proc/isarea(Loc1, Loc2/*,...*/); From e447107f6cb9b9ef68e85b4ee9fcece8624f635a Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Wed, 26 Mar 2025 18:27:06 -0700 Subject: [PATCH 158/197] Update to auxtools debug server v2.3.5 --- crates/dm-langserver/build.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/dm-langserver/build.rs b/crates/dm-langserver/build.rs index dc21b05b..b84b50f7 100644 --- a/crates/dm-langserver/build.rs +++ b/crates/dm-langserver/build.rs @@ -32,9 +32,9 @@ fn main() { download_dll( &out_dir, "debug_server.dll", - "v2.3.4", // DEBUG_SERVER_TAG - "https://github.com/willox/auxtools/releases/download/v2.3.4/debug_server.dll", // DEBUG_SERVER_DLL_URL - "06547804cf39c74d6a74aa1663a47f438871ea8fa85deb7dcb0c8d772747db7c", // DEBUG_SERVER_DLL_SHA256 + "v2.3.5", // DEBUG_SERVER_TAG + "https://github.com/willox/auxtools/releases/download/v2.3.5/debug_server.dll", // DEBUG_SERVER_DLL_URL + "dfcaa1086608047559103b55396f99504320f2b0ec1695baa3dc34dbd41695b2", // DEBUG_SERVER_DLL_SHA256 ); } From fcc814dfbd66a7e39d1135e334aba2832808a69b Mon Sep 17 00:00:00 2001 From: harry Date: Fri, 4 Apr 2025 08:31:13 +0100 Subject: [PATCH 159/197] Add 516 compatibility stubs + astype (#420) we still need to do `for (k, v in list()/alist())` and `pragma syntax c` but it'll do for now --- crates/dm-langserver/src/completion.rs | 2 + crates/dreamchecker/src/lib.rs | 19 ++++++ crates/dreammaker/src/builtins.rs | 92 +++++++++++++++++++++++++- crates/dreammaker/src/objtree.rs | 2 +- crates/dreammaker/src/parser.rs | 6 +- 5 files changed, 116 insertions(+), 5 deletions(-) diff --git a/crates/dm-langserver/src/completion.rs b/crates/dm-langserver/src/completion.rs index e4010b5c..65967cd5 100644 --- a/crates/dm-langserver/src/completion.rs +++ b/crates/dm-langserver/src/completion.rs @@ -18,6 +18,8 @@ static PROC_KEYWORDS: &[&str] = &[ "global", "src", "usr", + "caller", + "callee", // Term "null", diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index f25887b1..3d7809b4 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -1160,6 +1160,8 @@ impl<'o, 's> AnalyzeProc<'o, 's> { local_vars.insert(".".to_owned(), Analysis::empty().into()); local_vars.insert("args".to_owned(), Analysis::from_static_type_impure(self.objtree.expect("/list")).into()); local_vars.insert("usr".to_owned(), Analysis::from_static_type(self.objtree.expect("/mob")).into()); + local_vars.insert("callee".to_owned(), Analysis::from_static_type(self.objtree.expect("/callee")).into()); + local_vars.insert("caller".to_owned(), Analysis::from_static_type(self.objtree.expect("/callee")).into()); if !self.ty.is_root() { local_vars.insert("src".to_owned(), Analysis::from_static_type(self.ty).into()); } @@ -1925,6 +1927,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { self.visit_arguments(location, args, local_vars); Analysis::empty() // TODO }, + Term::__TYPE__ => { let pop = dm::constants::Pop::from(self.ty.path.split('/').skip(1).map(ToOwned::to_owned).collect::>().into_boxed_slice()); Analysis { @@ -2405,6 +2408,22 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } + if proc.ty().is_root() && proc.name() == "astype" { + if let Some(type_val) = param_idx_map.get(&1) { + if let Some(Constant::Prefab(path)) = type_val.clone().value { + let type_val = path.path.iter().map(|x| "/".to_owned() + x).collect::>().join(""); + + if let Some(path) = self.objtree.find(&type_val) { + return Analysis::from_static_type(path); + } + } + } + + if let Some(type_val) = param_idx_map.get(&0) { + return Analysis::from(type_val.clone().static_ty); + } + } + // filter call checking // TODO: some filters have limits for their numerical params // eg "rays" type "threshold" param defaults to 0.5, can be 0 to 1 diff --git a/crates/dreammaker/src/builtins.rs b/crates/dreammaker/src/builtins.rs index cd40f077..c44a73e4 100644 --- a/crates/dreammaker/src/builtins.rs +++ b/crates/dreammaker/src/builtins.rs @@ -13,8 +13,8 @@ const DM_BUILD: i32 = 1619; /// Register BYOND builtin macros to the given define map. pub fn default_defines(defines: &mut DefineMap) { - use super::lexer::*; use super::lexer::Token::*; + use super::lexer::*; let location = Location::builtins(); // #define EXCEPTION(value) new /exception(value) @@ -149,6 +149,7 @@ pub fn default_defines(defines: &mut DefineMap) { ANIMATION_LINEAR_TRANSFORM = Int(2); ANIMATION_PARALLEL = Int(4); ANIMATION_SLICE = Int(8); // 515 + ANIMATION_END_LOOP = Int(16); // 516 ANIMATION_RELATIVE = Int(256); ANIMATION_CONTINUE = Int(512); // 515 @@ -403,7 +404,7 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { proc/abs(A); proc/addtext(Arg1, Arg2/*, ...*/); proc/alert(Usr/*=usr*/,Message,Title,Button1/*="Ok"*/,Button2,Button3); - proc/animate(Object, time, loop, easing, flags, delay, // +2 forms + proc/animate(Object, time, loop, easing, flags, delay, tag, command, // +2 forms // these kwargs alpha, color, infra_luminosity, layer, maptext_width, maptext_height, maptext_x, maptext_y, luminosity, pixel_x, pixel_y, pixel_w, pixel_z, @@ -451,7 +452,8 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { repeat, radius, falloff, - alpha + alpha, + name // 516 ); proc/findlasttext(Haystack,Needle,Start=0,End=1); proc/findlasttextEx(Haystack,Needle,Start=0,End=1); @@ -576,6 +578,12 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { proc/winshow(player, window, show=1); proc/CRASH(message); // kind of special, but let's pretend + proc/values_cut_over(Alist, Max, inclusive=0); + proc/values_cut_under(Alist, Max, inclusive=0); + proc/values_dot(A, B); + proc/values_product(Alist); + proc/values_sum(Alist); + // database builtin procs proc/_dm_db_new_query(); proc/_dm_db_execute(db_query, sql_query, db_connection, cursor_handler, unknown); @@ -629,6 +637,22 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { list/proc/Swap(Index1, Index2); list/var/len; + // 516 + alist; + alist/var/const/type; + alist/var/const/parent_type; + alist/var/tag; + alist/proc/Add(Item1, Item2/*,...*/); + alist/proc/Copy(Start=1, End=0); + alist/proc/Cut(Start=1, End=0); + alist/proc/Find(Elem, Start=1, End=0); + alist/proc/Insert(Index, Item1, Item2/*,...*/); + alist/proc/Join(Glue, Start=1, End=0); + alist/proc/Remove(Item1, Item2/*,...*/); + alist/proc/Splice(Start=1, End=0, Item1, Item2/*,...*/); + alist/proc/Swap(Index1, Index2); + alist/var/len; + atom/parent_type = path!(/datum); atom/var/alpha = int!(255); atom/var/tmp/appearance; // not editable @@ -666,6 +690,12 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { atom/var/pixel_y = int!(0); atom/var/pixel_w = int!(0); atom/var/pixel_z = int!(0); + + // 516 + atom/var/icon_w = int!(0); + atom/var/icon_z = int!(0); + atom/var/pixloc/pixloc; + atom/var/plane = int!(0); atom/var/suffix; atom/var/text; @@ -913,6 +943,11 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { // only used by client.SoundQuery() for now: sound/var/offset = int!(0); sound/var/len = int!(0); + + // 516 + sound/var/tmp/atom/atom; + sound/var/transform; + sound/New(file, repeat, wait, channel, volume); icon; @@ -1015,6 +1050,11 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { image/var/pixel_y; image/var/pixel_w; image/var/pixel_z; + + // 516 + image/var/icon_w; + image/var/icon_z; + image/var/plane; image/var/render_source; image/var/render_target; @@ -1200,6 +1240,52 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { list/proc/RemoveAll(Item1/*, ...*/); world/proc/Tick(); + + // 516 + proc/lerp(A, B, factor); + proc/sign(A); + proc/astype(Val, Type); + proc/alist(A/* =a */,B/* =b */,C/* =c */); + + proc/load_ext(LibName, FuncName); + + callee; + callee/var/args; + callee/var/callee/caller; + callee/var/category; + callee/var/desc; + callee/var/file; + callee/var/name; + callee/var/line; + callee/var/proc; + callee/var/src; + callee/var/type; + callee/var/usr; + + proc/pixloc(x, y, z); + + pixloc; + pixloc/var/atom/loc; + pixloc/var/step_x; + pixloc/var/step_y; + pixloc/x; + pixloc/y; + pixloc/z; + + proc/vector(x, y, z); + + vector; + vector/var/len; + vector/var/size; + vector/var/x; + vector/var/y; + vector/var/z; + + vector/proc/Cross(B); + vector/proc/Dot(B); + vector/proc/Interpolate(B, t); + vector/proc/Normalize(); + vector/proc/Turn(B); }; } diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index b644d477..646a85fe 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -825,7 +825,7 @@ impl ObjectTreeBuilder { fn assign_parent_types(&mut self, context: &Context) { for (path, &type_idx) in self.inner.types.iter() { let mut location = self.inner[type_idx].location; - let idx = if path == "/datum" || path == "/list" || path == "/savefile" || path == "/world" { + let idx = if path == "/datum" || path == "/list" || path == "/alist" || path == "/savefile" || path == "/world" || path == "/vector" || path == "/pixloc" { // These types have no parent and cannot have one added. In the official compiler: // - setting list or savefile/parent_type is denied with the same error as setting something's parent type to them; // - setting datum/parent_type infinite loops the compiler; diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 23cee7e4..bc7db303 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -1754,7 +1754,6 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // for(var/a = 1 to 20 // for(var/a in 1 to 20 // This... isn't a boxed local, it's method arguments. Clippy?? - #[allow(clippy::boxed_local)] fn for_range( &mut self, var_type: Option, @@ -2133,6 +2132,11 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { None => Term::Ident(i.to_owned()), }, + Token::Ident(ref i, _) if i == "alist" => match self.arguments(&[], "alist")? { + Some(args) => Term::List(args), + None => Term::Ident(i.to_owned()), + }, + // term :: 'call' arglist arglist Token::Ident(ref i, _) if i == "call" => Term::DynamicCall( require!(self.arguments(&[], "call")), From d6bcdd50d1532571715e24b006482094d78c1ba5 Mon Sep 17 00:00:00 2001 From: harry Date: Sat, 5 Apr 2025 23:24:16 +0100 Subject: [PATCH 160/197] Add <=>, update new(), stub bound_pixloc() (#425) new() is updated for /alist, /vector, and /pixloc. Co-authored-by: harryob <55142896+harryob@users.noreply.github.com> --- crates/dreamchecker/src/lib.rs | 2 +- crates/dreammaker/src/ast.rs | 2 ++ crates/dreammaker/src/builtins.rs | 1 + crates/dreammaker/src/lexer.rs | 7 ++++--- crates/dreammaker/src/parser.rs | 3 +++ 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 3d7809b4..947f3cd4 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -1969,7 +1969,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { // `/datum/New()` and never an override. true, local_vars); - } else if typepath.path != "/list" { + } else if typepath.path != "/list" && typepath.path != "/alist" && typepath.path != "/vector" && typepath.path != "/pixloc" { error(location, format!("couldn't find {}/proc/New", typepath.path)) .register(self.context); } diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 6f35aa1f..a5c3db03 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -123,6 +123,7 @@ pub enum BinaryOp { Greater, LessEq, GreaterEq, + LessOrGreater, Equiv, NotEquiv, BitAnd, @@ -152,6 +153,7 @@ impl fmt::Display for BinaryOp { Less => "<", Greater => ">", LessEq => "<=", + LessOrGreater => "<=>", GreaterEq => ">=", Equiv => "~=", NotEquiv => "~!", diff --git a/crates/dreammaker/src/builtins.rs b/crates/dreammaker/src/builtins.rs index c44a73e4..3fb95b7d 100644 --- a/crates/dreammaker/src/builtins.rs +++ b/crates/dreammaker/src/builtins.rs @@ -1227,6 +1227,7 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { proc/refcount(Object); proc/trimtext(Text); proc/trunc(A); + proc/bound_pixloc(Atom, Dir); client/proc/RenderIcon(object); diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index 8983cf7f..c1553f8d 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -109,6 +109,7 @@ table! { "<<", LShift; "<<=", LShiftAssign; "<=", LessEq; + "<=>", LessOrGreater; "<>", LessGreater; "=", Assign; "==", Eq; @@ -156,15 +157,15 @@ static SPEEDY_TABLE: [(usize, usize); 127] = [ (2, 3), (3, 5), (5, 6), (6, 8), (0, 0), (8, 12), (12, 16), (16, 17), (17, 18), (18, 19), (19, 22), (22, 25), (25, 26), (26, 29), (29, 32), (32, 36), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (36, 39), (39, 40), (40, 45), (45, 47), (47, 51), (51, 55), + (0, 0), (0, 0), (36, 39), (39, 40), (40, 46), (46, 48), (48, 52), (52, 56), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (55, 56), (0, 0), (56, 57), (57,59), (0, 0), + (0, 0), (0, 0), (0, 0), (56, 57), (0, 0), (57, 58), (58, 60), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (59, 61), (61, 65), (65, 66), (66, 69), + (0, 0), (0, 0), (0, 0), (60, 62), (62, 66), (66, 67), (67, 70) ]; #[test] diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index bc7db303..a4c929ce 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -208,6 +208,7 @@ oper_table! { BINARY_OPS; (BinaryOp, Greater), (BinaryOp, LessEq), (BinaryOp, GreaterEq), + (BinaryOp, LessOrGreater), } // << >> Shift { @@ -1032,6 +1033,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { last_part.push_str("<<="); } else if self.exact(Punct(LessEq))?.is_some() { last_part.push_str("<=") + } else if self.exact(Punct(LessOrGreater))?.is_some() { + last_part.push_str("<=>"); } else if self.exact(Punct(Greater))?.is_some() { last_part.push('>'); } else if self.exact(Punct(GreaterEq))?.is_some() { From a58420e0b73b2c3f1289461b289cbe4f9a4639e1 Mon Sep 17 00:00:00 2001 From: Lucy Date: Thu, 1 May 2025 18:06:02 -0400 Subject: [PATCH 161/197] Fix `dreammaker.debugServerDll` accepting empty strings (#428) This makes it so blank strings are filtered out of `dreammaker.debugServerDll` (and also `dreammaker.extoolsDLL`, but I highly doubt that is still in use at all), so the config option being a blank string will just be treated as if said config option were unset. --- crates/dm-langserver/src/main.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index 1b5414b9..3f1b74b1 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -2080,10 +2080,16 @@ handle_notification! { } on DidChangeConfiguration(&mut self, params) { - if let Some(extools_dll) = params.settings["dreammaker"]["extoolsDLL"].as_str() { + if let Some(extools_dll) = params.settings["dreammaker"]["extoolsDLL"] + .as_str() + .filter(|path| !path.trim().is_empty()) + { self.extools_dll = Some(extools_dll.to_owned()); } - if let Some(debug_server_dll) = params.settings["dreammaker"]["debugServerDll"].as_str() { + if let Some(debug_server_dll) = params.settings["dreammaker"]["debugServerDll"] + .as_str() + .filter(|path| !path.trim().is_empty()) + { self.debug_server_dll = Some(debug_server_dll.to_owned()); } } From c1101fb3ad7971f3d19d6b81911fbd94d98fbad4 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sun, 11 May 2025 22:48:05 -0700 Subject: [PATCH 162/197] Bump versions for suite 1.10 --- Cargo.lock | 8 ++++---- crates/dm-langserver/Cargo.toml | 2 +- crates/dmdoc/Cargo.toml | 2 +- crates/dmm-tools-cli/Cargo.toml | 2 +- crates/dreamchecker/Cargo.toml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bb78af3d..f4579f1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -424,7 +424,7 @@ dependencies = [ [[package]] name = "dm-langserver" -version = "1.9.0" +version = "1.10.0" dependencies = [ "bincode", "chrono", @@ -449,7 +449,7 @@ dependencies = [ [[package]] name = "dmdoc" -version = "1.9.0" +version = "1.10.0" dependencies = [ "chrono", "dreammaker", @@ -482,7 +482,7 @@ dependencies = [ [[package]] name = "dmm-tools-cli" -version = "1.9.0" +version = "1.10.0" dependencies = [ "chrono", "clap", @@ -507,7 +507,7 @@ dependencies = [ [[package]] name = "dreamchecker" -version = "1.9.0" +version = "1.10.0" dependencies = [ "chrono", "dreammaker", diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index a833b16e..6a951ee3 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dm-langserver" -version = "1.9.0" +version = "1.10.0" authors = ["Tad Hardesty "] edition = "2021" diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index 19ae9200..a6f3c3e1 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dmdoc" -version = "1.9.0" +version = "1.10.0" authors = ["Tad Hardesty "] homepage = "https://github.com/SpaceManiac/SpacemanDMM/blob/master/crates/dmdoc/README.md" edition = "2021" diff --git a/crates/dmm-tools-cli/Cargo.toml b/crates/dmm-tools-cli/Cargo.toml index 676580e8..f104963c 100644 --- a/crates/dmm-tools-cli/Cargo.toml +++ b/crates/dmm-tools-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dmm-tools-cli" -version = "1.9.0" +version = "1.10.0" authors = ["Tad Hardesty "] description = "BYOND map rendering and analysis tools powered by SpacemanDMM" edition = "2021" diff --git a/crates/dreamchecker/Cargo.toml b/crates/dreamchecker/Cargo.toml index 24c4f62c..722c073e 100644 --- a/crates/dreamchecker/Cargo.toml +++ b/crates/dreamchecker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dreamchecker" -version = "1.9.0" +version = "1.10.0" authors = ["Tad Hardesty "] edition = "2021" From 68a0d9d5f85279ec723aa96d27d04379f23980ac Mon Sep 17 00:00:00 2001 From: Lucy Date: Thu, 19 Jun 2025 00:52:55 -0400 Subject: [PATCH 163/197] Update `git2` to 0.20.2 (#434) This updates the `git2` crate to 0.20.2, as linking on Windows (except win7) is broken in Rust 1.87+ due to https://github.com/rust-lang/rust/pull/138233, which https://github.com/rust-lang/git2-rs/pull/1143 fixed in `git2` 0.20.1. I'd try to convert everything to gitoxide instead, but that's easier said than done. --- Cargo.lock | 8 ++++---- crates/dm-langserver/Cargo.toml | 7 ++----- crates/dmdoc/Cargo.toml | 4 ++-- crates/dmm-tools-cli/Cargo.toml | 2 +- crates/dreamchecker/Cargo.toml | 2 +- crates/spaceman-dmm/Cargo.toml | 2 +- 6 files changed, 11 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f4579f1f..b2a5643a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -744,9 +744,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.19.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" +checksum = "2deb07a133b1520dc1a5690e9bd08950108873d7ed5de38dcc74d3b5ebffa110" dependencies = [ "bitflags 2.7.0", "libc", @@ -1027,9 +1027,9 @@ checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libgit2-sys" -version = "0.17.0+1.8.1" +version = "0.18.1+1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224" +checksum = "e1dcb20f84ffcdd825c7a311ae347cce604a6f084a767dec4a4929829645290e" dependencies = [ "cc", "libc", diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index 6a951ee3..f14a7d02 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -23,12 +23,9 @@ foldhash = "0.1.3" [build-dependencies] chrono = "0.4.38" -git2 = { version = "0.19.0", default-features = false } +git2 = { version = "0.20.2", default-features = false } sha256 = { version = "1.5.0", default-features = false } ureq = "2.10.1" [lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = [ - 'cfg(auxtools_bundle)', - 'cfg(extools_bundle)', -] } +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(auxtools_bundle)', 'cfg(extools_bundle)'] } diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index a6f3c3e1..bb82d6b6 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" dreammaker = { path = "../dreammaker" } pulldown-cmark = "0.9.6" walkdir = "2.5.0" -git2 = { version = "0.19.0", default-features = false } +git2 = { version = "0.20.2", default-features = false } maud = "0.25.0" foldhash = "0.1.3" @@ -18,4 +18,4 @@ walkdir = "2.5.0" [build-dependencies] chrono = "0.4.38" -git2 = { version = "0.19.0", default-features = false } +git2 = { version = "0.20.2", default-features = false } diff --git a/crates/dmm-tools-cli/Cargo.toml b/crates/dmm-tools-cli/Cargo.toml index f104963c..c7f62faa 100644 --- a/crates/dmm-tools-cli/Cargo.toml +++ b/crates/dmm-tools-cli/Cargo.toml @@ -21,4 +21,4 @@ foldhash = "0.1.3" [build-dependencies] chrono = "0.4.38" -git2 = { version = "0.19.0", default-features = false } +git2 = { version = "0.20.2", default-features = false } diff --git a/crates/dreamchecker/Cargo.toml b/crates/dreamchecker/Cargo.toml index 722c073e..466fc90f 100644 --- a/crates/dreamchecker/Cargo.toml +++ b/crates/dreamchecker/Cargo.toml @@ -11,4 +11,4 @@ foldhash = "0.1.3" [build-dependencies] chrono = "0.4.38" -git2 = { version = "0.19.0", default-features = false } +git2 = { version = "0.20.2", default-features = false } diff --git a/crates/spaceman-dmm/Cargo.toml b/crates/spaceman-dmm/Cargo.toml index 84e1becb..f8e44e50 100644 --- a/crates/spaceman-dmm/Cargo.toml +++ b/crates/spaceman-dmm/Cargo.toml @@ -35,4 +35,4 @@ branch = "zenity" [build-dependencies] chrono = "0.4.19" -git2 = { version = "0.19.0", default-features = false } +git2 = { version = "0.20.2", default-features = false } From 7f2641466b0afe06acf6c22bb78b8f318ffda633 Mon Sep 17 00:00:00 2001 From: Drathek <76988376+Drulikar@users.noreply.github.com> Date: Mon, 23 Jun 2025 02:14:56 -0500 Subject: [PATCH 164/197] Lint for set SpacemanDMM_ statements that have no effect (#435) Currently when a spaceman setting like `SHOULD_CALL_PARENT` comes after some other statement other than possibly another setting, it is silently ignored. This PR now errors in that situation. The checking is only performed on spaceman settings and not built in settings (e.g. `background`) because those can situationally be allowed in control statements so long as they otherwise would be at the top of the proc, but dreammaker will already warn for them if they would have no effect. See below where red lined are the new lints, and yellow lined are the existing dreammaker warnings. ![image](https://github.com/user-attachments/assets/4fe70a7f-819b-458a-9960-557b7c5bf6ab) --- crates/dreamchecker/src/lib.rs | 46 ++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 947f3cd4..e83af6e9 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -1183,7 +1183,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { //println!("adding parameters {:#?}", self.local_vars); } - self.visit_block(block, &mut local_vars); + self.visit_block(block, &mut local_vars, true); //println!("purity {}", self.is_pure); @@ -1223,7 +1223,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } - fn visit_block(&mut self, block: &'o [Spanned], local_vars: &mut HashMap>) -> ControlFlow { + fn visit_block(&mut self, block: &'o [Spanned], local_vars: &mut HashMap>, mut setting_allowed : bool) -> ControlFlow { let mut term = ControlFlow::allfalse(); for stmt in block.iter() { if term.terminates() { @@ -1232,6 +1232,20 @@ impl<'o, 's> AnalyzeProc<'o, 's> { .register(self.context); return term // stop evaluating } + match &stmt.elem { + Statement::Setting { name, mode, value } => { + // Defines like SHOULD_CALL_PARENT currently only work at the top + // Built in settings like background can situationally work in control blocks but are already warned by dreammaker + if !setting_allowed && name.starts_with("SpacemanDMM_") { + error(stmt.location, "set statement not at the top of the proc") + .with_errortype("set_has_no_effect") + .register(self.context); + } + } + _ => { + setting_allowed = false; + } + } let state = self.visit_statement(stmt.location, &stmt.elem, local_vars); term.merge(state); } @@ -1321,13 +1335,13 @@ impl<'o, 's> AnalyzeProc<'o, 's> { let mut scoped_locals = local_vars.clone(); // We don't check for static/determine conditions because while(TRUE) is so common. self.visit_expression(location, condition, None, &mut scoped_locals); - let mut state = self.visit_block(block, &mut scoped_locals); + let mut state = self.visit_block(block, &mut scoped_locals, false); state.end_loop(); return state }, Statement::DoWhile { block, condition } => { let mut scoped_locals = local_vars.clone(); - let mut state = self.visit_block(block, &mut scoped_locals); + let mut state = self.visit_block(block, &mut scoped_locals, false); if state.terminates_loop() { error(location,"do while terminates without ever reaching condition") .register(self.context); @@ -1350,7 +1364,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { .register(self.context); } self.visit_expression(condition.location, &condition.elem, None, &mut scoped_locals); - let state = self.visit_block(block, &mut scoped_locals); + let state = self.visit_block(block, &mut scoped_locals, false); match condition.elem.is_truthy() { Some(true) => { error(condition.location,"if condition is always true") @@ -1375,7 +1389,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { .register(self.context); } } - let state = self.visit_block(else_arm, &mut local_vars.clone()); + let state = self.visit_block(else_arm, &mut local_vars.clone(), false); allterm.merge_false(state); } else { allterm.no_else(); @@ -1386,7 +1400,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { }, Statement::ForInfinite { block } => { let mut scoped_locals = local_vars.clone(); - let mut state = self.visit_block(block, &mut scoped_locals); + let mut state = self.visit_block(block, &mut scoped_locals, false); state.end_loop(); return state } @@ -1403,7 +1417,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { if let Some(inc) = inc { self.visit_statement(location, inc, &mut scoped_locals); } - let mut state = self.visit_block(block, &mut scoped_locals); + let mut state = self.visit_block(block, &mut scoped_locals, false); state.end_loop(); return state }, @@ -1442,7 +1456,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { if let Some(var_type) = var_type { self.visit_var(location, var_type, name, None, &mut scoped_locals); } - let mut state = self.visit_block(block, &mut scoped_locals); + let mut state = self.visit_block(block, &mut scoped_locals, false); state.end_loop(); return state }, @@ -1456,7 +1470,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { if let Some(var_type) = var_type { self.visit_var(location, var_type, name, Some(start), &mut scoped_locals); } - let mut state = self.visit_block(block, &mut scoped_locals); + let mut state = self.visit_block(block, &mut scoped_locals, false); if let Some(startterm) = start.as_term() { if let Some(endterm) = end.as_term() { if let Some(validity) = startterm.valid_for_range(endterm, step.as_ref()) { @@ -1497,7 +1511,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { if let Some(delay) = delay { self.visit_expression(location, delay, None, &mut scoped_locals); } - self.visit_block(block, &mut scoped_locals); + self.visit_block(block, &mut scoped_locals, false); self.inside_newcontext = self.inside_newcontext.wrapping_sub(1); }, Statement::Switch { input, cases, default } => { @@ -1521,11 +1535,11 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } } - let state = self.visit_block(block, &mut scoped_locals); + let state = self.visit_block(block, &mut scoped_locals, false); allterm.merge_false(state); } if let Some(default) = default { - let state = self.visit_block(default, &mut local_vars.clone()); + let state = self.visit_block(default, &mut local_vars.clone(), false); allterm.merge_false(state); } else { allterm.no_else(); @@ -1535,7 +1549,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { return allterm }, Statement::TryCatch { try_block, catch_params, catch_block } => { - self.visit_block(try_block, &mut local_vars.clone()); + self.visit_block(try_block, &mut local_vars.clone(), false); if catch_params.len() > 1 { error(location, format!("Expected 0 or 1 catch parameters, got {}", catch_params.len())) .set_severity(Severity::Warning) @@ -1554,12 +1568,12 @@ impl<'o, 's> AnalyzeProc<'o, 's> { let var_type: VarType = type_path.iter().map(ToOwned::to_owned).collect(); self.visit_var(location, &var_type, var_name, None, &mut catch_locals); } - self.visit_block(catch_block, &mut catch_locals); + self.visit_block(catch_block, &mut catch_locals, false); }, Statement::Continue(_) => { return ControlFlow { returns: false, continues: true, breaks: false, fuzzy: true } }, Statement::Break(_) => { return ControlFlow { returns: false, continues: false, breaks: true, fuzzy: true } }, Statement::Goto(_) => {}, - Statement::Label { name: _, block } => { self.visit_block(block, &mut local_vars.clone()); }, + Statement::Label { name: _, block } => { self.visit_block(block, &mut local_vars.clone(), false); }, Statement::Del(expr) => { self.visit_expression(location, expr, None, local_vars); }, } ControlFlow::allfalse() From 56a699be348973a721f811fae7597f654d2a4c03 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 26 Jun 2025 19:00:26 -0700 Subject: [PATCH 165/197] Remove Dockerfile It's slightly annoying to have to bump the Rust version here to keep it working, and it rarely gets noticed when it's out of date anyways because it isn't really used. --- Dockerfile | 9 --------- README.md | 15 --------------- 2 files changed, 24 deletions(-) delete mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 49fce654..00000000 --- a/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM rust:1.74 - -WORKDIR /usr/src/myapp -COPY . . - -RUN cargo build -p dmm-tools-cli --release -RUN ln -s /usr/src/myapp/target/release/dmm-tools /usr/src/myapp/dmm-tools -ENTRYPOINT ["./dmm-tools"] -CMD ["help"] diff --git a/README.md b/README.md index 890f8bb3..10386c6a 100644 --- a/README.md +++ b/README.md @@ -93,21 +93,6 @@ the individual packages. [rust]: https://www.rust-lang.org/en-US/install.html [source readme]: ./crates/README.md -### Docker - -A `dockerfile` is provided for the map generator binary. To build the docker -image, enter the SpacemanDMM directory and run: - -```shell -docker build -t spacemandmm . -``` - -To use the image, switch to the codebase you want to generate maps for and invoke the container: - -```shell -docker run -v "$PWD":/usr/src/codebase --rm -it spacemandmm -e /usr/src/codebase/tgstation.dme minimap /usr/src/codebase/_maps/map_files/BoxStation/BoxStation.dmm -``` - ## License SpacemanDMM is free software: you can redistribute it and/or modify From ed90d86e8fd5c6a326c1322d8faa430c5aa6adb3 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 26 Jun 2025 18:59:01 -0700 Subject: [PATCH 166/197] Run cargo clippy --fix --- crates/dm-langserver/build.rs | 6 +- crates/dm-langserver/src/color.rs | 8 +- crates/dm-langserver/src/completion.rs | 8 +- crates/dm-langserver/src/debugger/auxtools.rs | 24 +-- .../src/debugger/auxtools_bundle.rs | 2 +- crates/dm-langserver/src/debugger/extools.rs | 6 +- .../src/debugger/extools_bundle.rs | 2 +- .../src/debugger/extools_types.rs | 14 +- crates/dm-langserver/src/debugger/launched.rs | 4 +- crates/dm-langserver/src/debugger/mod.rs | 20 +-- crates/dm-langserver/src/document.rs | 8 +- crates/dm-langserver/src/jrpc_io.rs | 4 +- crates/dm-langserver/src/main.rs | 32 ++-- crates/dmdoc/build.rs | 2 +- crates/dmdoc/src/main.rs | 50 +++---- crates/dmdoc/src/markdown.rs | 2 +- crates/dmdoc/src/template.rs | 2 +- crates/dmm-tools-cli/build.rs | 2 +- crates/dmm-tools-cli/src/main.rs | 18 +-- .../examples/duplicate_icon_states.rs | 2 +- crates/dmm-tools/src/dmi.rs | 2 +- crates/dmm-tools/src/dmm.rs | 4 +- crates/dmm-tools/src/dmm/read.rs | 5 +- crates/dmm-tools/src/dmm/save_tgm.rs | 4 +- crates/dmm-tools/src/minimap.rs | 4 +- crates/dmm-tools/src/render_passes/random.rs | 2 +- crates/dmm-tools/tests/parse_codebase.rs | 2 +- crates/dreamchecker/build.rs | 2 +- crates/dreamchecker/src/lib.rs | 138 +++++++++--------- crates/dreamchecker/src/main.rs | 4 +- crates/dreamchecker/src/switch_rand_range.rs | 5 +- crates/dreamchecker/src/type_expr.rs | 4 +- crates/dreamchecker/tests/proc_tests.rs | 2 +- crates/dreammaker/examples/flags.rs | 6 +- crates/dreammaker/src/ast.rs | 8 +- crates/dreammaker/src/constants.rs | 65 ++++----- crates/dreammaker/src/dmi.rs | 2 +- crates/dreammaker/src/indents.rs | 3 +- crates/dreammaker/src/lexer.rs | 33 ++--- crates/dreammaker/src/lib.rs | 4 +- crates/dreammaker/src/objtree.rs | 12 +- crates/dreammaker/src/parser.rs | 18 +-- crates/dreammaker/src/preprocessor.rs | 35 +++-- crates/dreammaker/tests/annotation_tests.rs | 2 +- crates/dreammaker/tests/ast_tests.rs | 2 +- crates/dreammaker/tests/lexer_tests.rs | 4 +- crates/dreammaker/tests/location_tests.rs | 4 +- crates/interval-tree/src/iterators.rs | 7 +- crates/interval-tree/src/node.rs | 8 +- crates/interval-tree/src/tests.rs | 4 +- 50 files changed, 300 insertions(+), 311 deletions(-) diff --git a/crates/dm-langserver/build.rs b/crates/dm-langserver/build.rs index b84b50f7..54309c45 100644 --- a/crates/dm-langserver/build.rs +++ b/crates/dm-langserver/build.rs @@ -12,8 +12,8 @@ fn main() { let mut f = File::create(out_dir.join("build-info.txt")).unwrap(); match read_commit() { - Ok(commit) => writeln!(f, "commit: {}", commit).unwrap(), - Err(err) => println!("cargo:warning=Failed to fetch commit info: {}", err) + Ok(commit) => writeln!(f, "commit: {commit}").unwrap(), + Err(err) => println!("cargo:warning=Failed to fetch commit info: {err}") } writeln!(f, "build date: {}", chrono::Utc::now().date_naive()).unwrap(); @@ -74,7 +74,7 @@ fn read_commit() -> Result { fn download_dll(out_dir: &Path, fname: &str, tag: &str, url: &str, sha256: &str) { let full_path = out_dir.join(fname); println!("cargo:rustc-env=BUNDLE_PATH_{}={}", fname, full_path.display()); - println!("cargo:rustc-env=BUNDLE_VERSION_{}={}", fname, tag); + println!("cargo:rustc-env=BUNDLE_VERSION_{fname}={tag}"); if let Ok(digest) = sha256::try_digest(&full_path) { if digest == sha256 { diff --git a/crates/dm-langserver/src/color.rs b/crates/dm-langserver/src/color.rs index 1634b86b..8426202e 100644 --- a/crates/dm-langserver/src/color.rs +++ b/crates/dm-langserver/src/color.rs @@ -58,14 +58,14 @@ impl ColorFormat { let short = short && r % 0x11 == 0 && g % 0x11 == 0 && b % 0x11 == 0 && a % 0x11 == 0; let alpha = alpha || a != 255; match (short, alpha) { - (false, false) => format!("{}#{:02x}{:02x}{:02x}{}", q, r, g, b, q), - (false, true) => format!("{}#{:02x}{:02x}{:02x}{:02x}{}", q, r, g, b, a, q), + (false, false) => format!("{q}#{r:02x}{g:02x}{b:02x}{q}"), + (false, true) => format!("{q}#{r:02x}{g:02x}{b:02x}{a:02x}{q}"), (true, false) => format!("{}#{:x}{:x}{:x}{}", q, r / 0x11, g / 0x11, b / 0x11, q), (true, true) => format!("{}#{:x}{:x}{:x}{:x}{}", q, r / 0x11, g / 0x11, b / 0x11, a / 0x11, q), } }, - ColorFormat::Rgb { alpha } if alpha || a != 255 => format!("rgb({}, {}, {}, {})", r, g, b, a), - ColorFormat::Rgb { alpha: _ } => format!("rgb({}, {}, {})", r, g, b), + ColorFormat::Rgb { alpha } if alpha || a != 255 => format!("rgb({r}, {g}, {b}, {a})"), + ColorFormat::Rgb { alpha: _ } => format!("rgb({r}, {g}, {b})"), } } } diff --git a/crates/dm-langserver/src/completion.rs b/crates/dm-langserver/src/completion.rs index 65967cd5..2311c283 100644 --- a/crates/dm-langserver/src/completion.rs +++ b/crates/dm-langserver/src/completion.rs @@ -59,7 +59,7 @@ fn item_var(ty: TypeRef, name: &str, var: &TypeVar) -> CompletionItem { if ty.is_root() { detail = constant.to_string(); } else { - detail = format!("{} - {}", constant, detail); + detail = format!("{constant} - {detail}"); } } } @@ -265,7 +265,7 @@ impl Engine { } if contains(name, query) { results.push(CompletionItem { - insert_text: Some(format!("{} = ", name)), + insert_text: Some(format!("{name} = ")), .. item_var(ty, name, var) }); } @@ -279,11 +279,11 @@ impl Engine { if contains(name, query) { use std::fmt::Write; - let mut completion = format!("{}(", name); + let mut completion = format!("{name}("); let mut sep = ""; for param in proc.main_value().parameters.iter() { for each in param.var_type.type_path.iter() { - let _ = write!(completion, "{}{}", sep, each); + let _ = write!(completion, "{sep}{each}"); sep = "/"; } let _ = write!(completion, "{}{}", sep, param.name); diff --git a/crates/dm-langserver/src/debugger/auxtools.rs b/crates/dm-langserver/src/debugger/auxtools.rs index beeef165..69685205 100644 --- a/crates/dm-langserver/src/debugger/auxtools.rs +++ b/crates/dm-langserver/src/debugger/auxtools.rs @@ -156,7 +156,7 @@ impl Auxtools { self.send_or_disconnect(Request::Configured)?; match self.read_response_or_disconnect()? { - Response::Ack { .. } => Ok(()), + Response::Ack => Ok(()), response => Err(Box::new(UnexpectedResponse::new("Ack", response))), } } @@ -251,7 +251,7 @@ impl Auxtools { })?; match self.read_response_or_disconnect()? { - Response::Ack { .. } => Ok(()), + Response::Ack => Ok(()), response => Err(Box::new(UnexpectedResponse::new("Ack", response))), } } @@ -262,7 +262,7 @@ impl Auxtools { })?; match self.read_response_or_disconnect()? { - Response::Ack { .. } => Ok(()), + Response::Ack => Ok(()), response => Err(Box::new(UnexpectedResponse::new("Ack", response))), } } @@ -273,7 +273,7 @@ impl Auxtools { })?; match self.read_response_or_disconnect()? { - Response::Ack { .. } => Ok(()), + Response::Ack => Ok(()), response => Err(Box::new(UnexpectedResponse::new("Ack", response))), } } @@ -284,7 +284,7 @@ impl Auxtools { })?; match self.read_response_or_disconnect()? { - Response::Ack { .. } => Ok(()), + Response::Ack => Ok(()), response => Err(Box::new(UnexpectedResponse::new("Ack", response))), } } @@ -293,7 +293,7 @@ impl Auxtools { self.send_or_disconnect(Request::Pause)?; match self.read_response_or_disconnect()? { - Response::Ack { .. } => Ok(()), + Response::Ack => Ok(()), response => Err(Box::new(UnexpectedResponse::new("Ack", response))), } } @@ -375,7 +375,7 @@ impl AuxtoolsThread { match connection_sender.send(stream.try_clone().unwrap()) { Ok(_) => {} Err(e) => { - eprintln!("Debug client thread failed to pass cloned TcpStream: {}", e); + eprintln!("Debug client thread failed to pass cloned TcpStream: {e}"); return; } } @@ -384,7 +384,7 @@ impl AuxtoolsThread { } Err(e) => { - eprintln!("Debug client failed to accept connection: {}", e); + eprintln!("Debug client failed to accept connection: {e}"); } }) } @@ -444,7 +444,7 @@ impl AuxtoolsThread { Ok(_) => u32::from_le_bytes(len_bytes), Err(e) => { - eprintln!("Debug server thread read error: {}", e); + eprintln!("Debug server thread read error: {e}"); break; } }; @@ -454,7 +454,7 @@ impl AuxtoolsThread { Ok(_) => (), Err(e) => { - eprintln!("Debug server thread read error: {}", e); + eprintln!("Debug server thread read error: {e}"); break; } }; @@ -468,7 +468,7 @@ impl AuxtoolsThread { } Err(e) => { - eprintln!("Debug server thread failed to handle request: {}", e); + eprintln!("Debug server thread failed to handle request: {e}"); break; } } @@ -483,7 +483,7 @@ pub struct UnexpectedResponse(String); impl UnexpectedResponse { fn new(expected: &'static str, received: Response) -> Self { - Self(format!("received unexpected response: expected {}, got {:?}", expected, received)) + Self(format!("received unexpected response: expected {expected}, got {received:?}")) } } diff --git a/crates/dm-langserver/src/debugger/auxtools_bundle.rs b/crates/dm-langserver/src/debugger/auxtools_bundle.rs index 2f01b681..3790d296 100644 --- a/crates/dm-langserver/src/debugger/auxtools_bundle.rs +++ b/crates/dm-langserver/src/debugger/auxtools_bundle.rs @@ -13,7 +13,7 @@ pub fn extract() -> Result { let exe = std::env::current_exe()?; let directory = exe.parent().unwrap(); for i in 0..9 { - let dll = directory.join(format!("auxtools_debug_server{}.dll", i)); + let dll = directory.join(format!("auxtools_debug_server{i}.dll")); if let Ok(()) = write(&dll) { return Ok(dll); } diff --git a/crates/dm-langserver/src/debugger/extools.rs b/crates/dm-langserver/src/debugger/extools.rs index 24aee362..172d03c4 100644 --- a/crates/dm-langserver/src/debugger/extools.rs +++ b/crates/dm-langserver/src/debugger/extools.rs @@ -57,7 +57,7 @@ impl ExtoolsHolder { let (conn_tx, conn_rx) = mpsc::channel(); std::thread::Builder::new() - .name(format!("extools listening on port {}", port)) + .name(format!("extools listening on port {port}")) .spawn(move || { let stream = match listener.accept() { Ok((stream, _)) => stream, @@ -84,7 +84,7 @@ impl ExtoolsHolder { let (cancel_tx, cancel_rx) = mpsc::channel(); std::thread::Builder::new() - .name(format!("extools attaching on port {}", port)) + .name(format!("extools attaching on port {port}")) .spawn(move || { while let Err(mpsc::TryRecvError::Empty) = cancel_rx.try_recv() { if let Ok(stream) = TcpStream::connect_timeout(&addr, std::time::Duration::from_secs(5)) { @@ -372,7 +372,7 @@ impl ExtoolsThread { } buffer.extend_from_slice(slice); } - Err(e) => panic!("extools read error: {:?}", e), + Err(e) => panic!("extools read error: {e:?}"), } // chop off as many full messages from the buffer as we can diff --git a/crates/dm-langserver/src/debugger/extools_bundle.rs b/crates/dm-langserver/src/debugger/extools_bundle.rs index 29755dcc..713029c7 100644 --- a/crates/dm-langserver/src/debugger/extools_bundle.rs +++ b/crates/dm-langserver/src/debugger/extools_bundle.rs @@ -13,7 +13,7 @@ pub fn extract() -> Result { let exe = std::env::current_exe()?; let directory = exe.parent().unwrap(); for i in 0..9 { - let dll = directory.join(format!("extools{}.dll", i)); + let dll = directory.join(format!("extools{i}.dll")); if let Ok(()) = write(&dll) { return Ok(dll); } diff --git a/crates/dm-langserver/src/debugger/extools_types.rs b/crates/dm-langserver/src/debugger/extools_types.rs index 72b0ca29..ce9f382e 100644 --- a/crates/dm-langserver/src/debugger/extools_types.rs +++ b/crates/dm-langserver/src/debugger/extools_types.rs @@ -151,7 +151,7 @@ impl std::fmt::Display for Ref { match *self { Ref::NULL => fmt.write_str("null"), Ref::WORLD => fmt.write_str("world"), - Ref(v) => write!(fmt, "[0x{:08x}]", v), + Ref(v) => write!(fmt, "[0x{v:08x}]"), } } } @@ -159,15 +159,15 @@ impl std::fmt::Display for Ref { impl std::fmt::Display for Literal { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { match self { - Literal::Ref(v) => write!(fmt, "{}", v), - Literal::Number(n) => write!(fmt, "{}", n), - Literal::String(s) => write!(fmt, "{:?}", s), - Literal::Typepath(t) => write!(fmt, "{}", t), - Literal::Resource(f) => write!(fmt, "'{}'", f), + Literal::Ref(v) => write!(fmt, "{v}"), + Literal::Number(n) => write!(fmt, "{n}"), + Literal::String(s) => write!(fmt, "{s:?}"), + Literal::Typepath(t) => write!(fmt, "{t}"), + Literal::Resource(f) => write!(fmt, "'{f}'"), Literal::Proc(p) => { match p.rfind('/') { Some(idx) => write!(fmt, "{}/proc/{}", &p[..idx], &p[idx + 1..]), - None => write!(fmt, "{}", p), + None => write!(fmt, "{p}"), } } } diff --git a/crates/dm-langserver/src/debugger/launched.rs b/crates/dm-langserver/src/debugger/launched.rs index 4ffd3dbc..5e486e25 100644 --- a/crates/dm-langserver/src/debugger/launched.rs +++ b/crates/dm-langserver/src/debugger/launched.rs @@ -166,7 +166,7 @@ impl Launched { fn pipe_output(seq: Arc, keyword: &'static str, stream: Option) -> std::io::Result<()> { let Some(stream2) = stream else { return Ok(()); }; std::thread::Builder::new() - .name(format!("launched debuggee {} relay", keyword)) + .name(format!("launched debuggee {keyword} relay")) .spawn(move || { use std::io::BufRead; @@ -185,7 +185,7 @@ fn pipe_output(seq: Arc, keyw } Err(e) => { seq.issue_event(dap_types::OutputEvent { - output: format!("[launched {}] {}", keyword, e), + output: format!("[launched {keyword}] {e}"), category: Some("console".to_owned()), ..Default::default() }); diff --git a/crates/dm-langserver/src/debugger/mod.rs b/crates/dm-langserver/src/debugger/mod.rs index 9530afb2..5a0e0412 100644 --- a/crates/dm-langserver/src/debugger/mod.rs +++ b/crates/dm-langserver/src/debugger/mod.rs @@ -69,7 +69,7 @@ pub fn start_server( let port = listener.local_addr()?.port(); let handle = std::thread::Builder::new() - .name(format!("DAP listener on port {}", port)) + .name(format!("DAP listener on port {port}")) .spawn(move || { let (stream, _) = listener.accept().unwrap(); drop(listener); @@ -92,13 +92,13 @@ pub fn debugger_main>(mut args: I) { .expect("must specify a value for --dreamseeker-exe"), ); } else { - panic!("unknown argument {:?}", arg); + panic!("unknown argument {arg:?}"); } } let dreamseeker_exe = dreamseeker_exe.expect("must provide argument `--dreamseeker-exe path/to/dreamseeker.exe`"); - eprintln!("dreamseeker: {}", dreamseeker_exe); + eprintln!("dreamseeker: {dreamseeker_exe}"); // This isn't the preferred way to run the DAP server so it's okay for it // to be kind of sloppy. @@ -324,7 +324,7 @@ impl Debugger { self.seq .send_raw(&serde_json::to_string(&response).expect("response encode error")) } - other => return Err(format!("unknown `type` field {:?}", other).into()), + other => return Err(format!("unknown `type` field {other:?}").into()), } Ok(()) } @@ -623,7 +623,7 @@ handle_request! { for sbp in inputs { if let Some((typepath, name, override_id)) = self.db.location_to_proc_ref(file_id, sbp.line) { // TODO: better discipline around format!("{}/{}") and so on - let proc = format!("{}/{}", typepath, name); + let proc = format!("{typepath}/{name}"); if let Some(offset) = extools.line_to_offset(&proc, override_id, sbp.line) { let tup = (proc, override_id, offset); if saved.insert(tup.clone()) { @@ -677,7 +677,7 @@ handle_request! { for sbp in inputs { if let Some((typepath, name, override_id)) = self.db.location_to_proc_ref(file_id, sbp.line) { // TODO: better discipline around format!("{}/{}") and so on - let proc = format!("{}/{}", typepath, name); + let proc = format!("{typepath}/{name}"); if let Some(offset) = auxtools.get_offset(proc.as_str(), override_id as u32, sbp.line as u32)? { saved.insert((proc.clone(), override_id, offset as i64)); @@ -795,7 +795,7 @@ handle_request! { }); } else { breakpoints.push(Breakpoint { - message: Some(format!("Unknown proc {}#{}", proc, override_id)), + message: Some(format!("Unknown proc {proc}#{override_id}")), verified: false, .. Default::default() }); @@ -1024,7 +1024,7 @@ handle_request! { let frame_no = frame_id / threads.len(); let Some(frame) = threads[&thread_id].call_stack.get(frame_no) else { - return Err(Box::new(GenericError2(format!("Stack frame out of range: {} (thread {}, depth {})", frameId, thread_id, frame_no)))); + return Err(Box::new(GenericError2(format!("Stack frame out of range: {frameId} (thread {thread_id}, depth {frame_no})")))); }; ScopesResponse { @@ -1178,7 +1178,7 @@ handle_request! { Some(param) => { match seen.entry(param).and_modify(|e| *e += 1).or_default() { 0 => param.clone(), - n => format!("{} #{}", param, n), + n => format!("{param} #{n}"), } } None => format!("args[{}]", i + 1), @@ -1207,7 +1207,7 @@ handle_request! { Some(local) => { match seen.entry(local).and_modify(|e| *e += 1).or_default() { 0 => local.clone(), - n => format!("{} #{}", local, n), + n => format!("{local} #{n}"), } } None => i.to_string(), diff --git a/crates/dm-langserver/src/document.rs b/crates/dm-langserver/src/document.rs index f3b80501..83069c3c 100644 --- a/crates/dm-langserver/src/document.rs +++ b/crates/dm-langserver/src/document.rs @@ -78,7 +78,7 @@ impl DocumentStore { } Err(io::Error::new(io::ErrorKind::NotFound, - format!("URL not opened and schema is not 'file': {}", url))) + format!("URL not opened and schema is not 'file': {url}"))) } pub fn read(&self, url: &Url) -> io::Result> { @@ -92,7 +92,7 @@ impl DocumentStore { } Err(io::Error::new(io::ErrorKind::NotFound, - format!("URL not opened and schema is not 'file': {}", url))) + format!("URL not opened and schema is not 'file': {url}"))) } } @@ -193,7 +193,7 @@ pub fn find_word(text: &str, offset: usize) -> &str { while !text.is_char_boundary(start_next) { start_next -= 1; } - if !text[start_next..start].chars().next().map_or(false, is_ident) { + if !text[start_next..start].chars().next().is_some_and(is_ident) { break; } start = start_next; @@ -206,7 +206,7 @@ pub fn find_word(text: &str, offset: usize) -> &str { while !text.is_char_boundary(end_next) { end_next += 1; } - if !text[end..end_next].chars().next().map_or(false, is_ident) { + if !text[end..end_next].chars().next().is_some_and(is_ident) { break; } end = end_next; diff --git a/crates/dm-langserver/src/jrpc_io.rs b/crates/dm-langserver/src/jrpc_io.rs index d3ff6a42..ff83caef 100644 --- a/crates/dm-langserver/src/jrpc_io.rs +++ b/crates/dm-langserver/src/jrpc_io.rs @@ -28,11 +28,11 @@ fn read(input: &mut R) -> Result, Box = buffer.split(' ').collect(); if parts.len() != 2 { - eprintln!("JSON-RPC read error: parts.len() != 2\n{:?}", parts); + eprintln!("JSON-RPC read error: parts.len() != 2\n{parts:?}"); return Ok(None); } if !parts[0].eq_ignore_ascii_case("content-length:") { - eprintln!("JSON-RPC read error: !parts[0].eq_ignore_ascii_case(\"content-length:\")\n{:?}", parts); + eprintln!("JSON-RPC read error: !parts[0].eq_ignore_ascii_case(\"content-length:\")\n{parts:?}"); return Ok(None); } parts[1].trim().parse::()? diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index 3f1b74b1..6ef5cd70 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -63,7 +63,7 @@ fn main() { eprintln!(); match std::env::current_exe() { Ok(path) => eprintln!("executable: {}", path.display()), - Err(e) => eprintln!("exe check failure: {}", e), + Err(e) => eprintln!("exe check failure: {e}"), } eprint!("{}", include_str!(concat!(env!("OUT_DIR"), "/build-info.txt"))); #[cfg(extools_bundle)] { @@ -74,7 +74,7 @@ fn main() { } match std::env::current_dir() { Ok(path) => eprintln!("directory: {}", path.display()), - Err(e) => eprintln!("dir check failure: {}", e), + Err(e) => eprintln!("dir check failure: {e}"), } let mut args = std::env::args(); @@ -85,7 +85,7 @@ fn main() { } else if arg == "--version" { return; } else { - panic!("unknown argument {:?}", arg); + panic!("unknown argument {arg:?}"); } } @@ -301,7 +301,7 @@ impl Engine { S: Into { let message = message.into(); - eprintln!("{:?}: {}", typ, message); + eprintln!("{typ:?}: {message}"); self.issue_notification::( lsp_types::ShowMessageParams { typ, message } ) @@ -319,10 +319,10 @@ impl Engine { fn file_url(&self, file: dm::FileId) -> Result { if let Some(ref root) = self.root { root.join(&self.context.file_path(file).display().to_string()) - .map_err(|e| invalid_request(format!("error in file_url: {}", e))) + .map_err(|e| invalid_request(format!("error in file_url: {e}"))) } else { Url::parse(&self.context.file_path(file).display().to_string()) - .map_err(|e| invalid_request(format!("error in rootless file_url {}", e))) + .map_err(|e| invalid_request(format!("error in rootless file_url {e}"))) } } @@ -462,7 +462,7 @@ impl Engine { version: None, }, ); - eprintln!("{:?}", err); + eprintln!("{err:?}"); return Ok(()); } }; @@ -945,7 +945,7 @@ impl Engine { // form the markdown text to be used once the proc's declaration is reached if defstring.is_empty() { proclink = format!("[{}]({})", ty.pretty_path(), self.location_link(proc_value.location)?); - let mut message = format!("{}(", proc_name); + let mut message = format!("{proc_name}("); let mut first = true; for each in proc_value.parameters.iter() { use std::fmt::Write; @@ -954,7 +954,7 @@ impl Engine { } else { message.push_str(", "); } - let _ = write!(message, "{}", each); + let _ = write!(message, "{each}"); } message.push(')'); defstring.clone_from(&message); @@ -1127,7 +1127,7 @@ handle_method_call! { let path = format!("{}/", url.path()); url.set_path(&path); } - eprintln!("workspace root: {}", url); + eprintln!("workspace root: {url}"); if let Ok(root_path) = url_to_path(&url) { let config_path = root_path.join("SpacemanDMM.toml"); @@ -1147,7 +1147,7 @@ handle_method_call! { if let (Some(start), Some(end)) = (debug.find('{'), debug.rfind('}')) { eprintln!("client capabilities: {}", &debug[start + 2..end - 1]); } else { - eprintln!("client capabilities: {}", debug); + eprintln!("client capabilities: {debug}"); } eprintln!(); @@ -1289,7 +1289,7 @@ handle_method_call! { let iter = annotations.get_location(location); for (_range, annotation) in iter.clone() { #[cfg(debug_assertions)] { - results.push(format!("{:?}", annotation)); + results.push(format!("{annotation:?}")); } match annotation { Annotation::Variable(path) if !path.is_empty() => { @@ -1311,7 +1311,7 @@ handle_method_call! { while let Some(current) = next { if let Some(var) = current.vars.get(last) { let constant = if let Some(ref constant) = var.value.constant { - format!("\n```dm\n= {}\n```", constant) + format!("\n```dm\n= {constant}\n```") } else { String::new() }; @@ -1362,7 +1362,7 @@ handle_method_call! { } else { message.push_str(", "); } - let _ = write!(message, "{}", each); + let _ = write!(message, "{each}"); } message.push_str(")\n```"); infos.push_front(message); @@ -1752,7 +1752,7 @@ handle_method_call! { let mut sep = ""; for param in proc.main_value().parameters.iter() { for each in param.var_type.type_path.iter() { - let _ = write!(label, "{}{}", sep, each); + let _ = write!(label, "{sep}{each}"); sep = "/"; } label.push_str(sep); @@ -2133,7 +2133,7 @@ fn url_to_path(url: &Url) -> Result { fn path_to_url(path: PathBuf) -> Result { let formatted = path.display().to_string(); Url::from_file_path(path).map_err(|_| invalid_request(format!( - "bad file path: {}", formatted, + "bad file path: {formatted}", ))) } diff --git a/crates/dmdoc/build.rs b/crates/dmdoc/build.rs index d9951a53..df81ad5a 100644 --- a/crates/dmdoc/build.rs +++ b/crates/dmdoc/build.rs @@ -11,7 +11,7 @@ fn main() { let mut f = File::create(out_dir.join("build-info.txt")).unwrap(); if let Ok(commit) = read_commit() { - writeln!(f, "commit: {}", commit).unwrap(); + writeln!(f, "commit: {commit}").unwrap(); } writeln!(f, "build date: {}", chrono::Utc::now().date_naive()).unwrap(); } diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index a35293d2..8298a4a9 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -38,7 +38,7 @@ const DM_REFERENCE_BASE: &str = "https://www.byond.com/docs/ref/#"; fn main() { if let Err(e) = main2() { - eprintln!("{}", e); + eprintln!("{e}"); std::process::exit(1); } } @@ -54,7 +54,7 @@ fn main2() -> Result<(), Box> { let _ = args.next(); // skip executable name while let Some(arg) = args.next() { if arg == "-V" || arg == "--version" { - println!("{}", BUILD_INFO); + println!("{BUILD_INFO}"); return Ok(()); } else if arg == "-e" { environment = Some(args.next().expect("must specify a value for -e")); @@ -65,7 +65,7 @@ fn main2() -> Result<(), Box> { } else if arg == "--dry-run" { dry_run = true; } else { - return Err(format!("unknown argument: {}", arg).into()); + return Err(format!("unknown argument: {arg}").into()); } } @@ -205,7 +205,7 @@ fn main2() -> Result<(), Box> { if docs.is_empty() { continue; } - error_entity_put(format!("#define {}", name)); + error_entity_put(format!("#define {name}")); let broken_link_callback = &mut |link: BrokenLink| -> Option<(CowStr, CowStr)> { broken_link_fixer(link, ¯o_to_module_map, ¯o_exists, &diagnostic_count, &error_entity, &modules_which_exist, &objtree, &types_with_docs) }; @@ -621,7 +621,7 @@ fn main2() -> Result<(), Box> { .unwrap_or(world_name); let mut git = Default::default(); if let Err(e) = git_info(&mut git) { - println!("incomplete git info: {}", e); + println!("incomplete git info: {e}"); } let env = &Environment { all_type_names: &all_type_names, @@ -753,20 +753,20 @@ fn broken_link_fixer<'str>( let error_entity_print = || { diagnostic_count.set(diagnostic_count.get() + 1); if let Some(name) = error_entity.take() { - eprintln!("{}:", name); + eprintln!("{name}:"); } }; // macros if let Some(module) = macro_to_module_map.get(reference) { - return Some((format!("{}.html#define/{}", module, reference).into(), reference.to_owned().into())); + return Some((format!("{module}.html#define/{reference}").into(), reference.to_owned().into())); } else if macro_exists.contains(reference) { error_entity_print(); - eprintln!(" [{}]: macro not documented", reference); + eprintln!(" [{reference}]: macro not documented"); return None; } else if reference.ends_with(".dm") || reference.ends_with(".txt") || reference.ends_with(".md") { let mod_path = module_path(reference.as_ref()); if modules_which_exist.contains(&mod_path) { - return Some((format!("{}.html", mod_path).into(), reference.to_owned().into())); + return Some((format!("{mod_path}.html").into(), reference.to_owned().into())); } error_entity_print(); eprintln!(" [{}]: module {}", reference, if Path::new(reference).exists() { "not documented" } else { "does not exist" }); @@ -813,14 +813,14 @@ fn broken_link_fixer<'str>( proc_name = Some(rest); ty_path = parent; error_entity_print(); - eprintln!(" [{}]: correcting to [{}/proc/{}]", reference, parent, rest); + eprintln!(" [{reference}]: correcting to [{parent}/proc/{rest}]"); entity_exists = true; } else if ty.vars.contains_key(rest) { // correct `[/ty/varname]` to `[/ty/var/varname]` var_name = Some(rest); ty_path = parent; error_entity_print(); - eprintln!(" [{}]: correcting to [{}/var/{}]", reference, parent, rest); + eprintln!(" [{reference}]: correcting to [{parent}/var/{rest}]"); entity_exists = true; } } @@ -828,7 +828,7 @@ fn broken_link_fixer<'str>( ty_path = ""; var_name = Some(reference); error_entity_print(); - eprintln!(" [{0}]: correcting to [/var/{0}]", reference); + eprintln!(" [{reference}]: correcting to [/var/{reference}]"); entity_exists = true; } // else `[/ty]` @@ -844,7 +844,7 @@ fn broken_link_fixer<'str>( if var.location.is_builtins() { external_url = Some(match var.docs.builtin_docs { BuiltinDocs::None => format!("{}{}/var/{}", DM_REFERENCE_BASE, ty.path, var_name), - BuiltinDocs::ReferenceHash(hash) => format!("{}{}", DM_REFERENCE_BASE, hash), + BuiltinDocs::ReferenceHash(hash) => format!("{DM_REFERENCE_BASE}{hash}"), }) } } @@ -853,14 +853,14 @@ fn broken_link_fixer<'str>( if proc.location.is_builtins() { external_url = Some(match proc.docs.builtin_docs { BuiltinDocs::None => format!("{}{}/proc/{}", DM_REFERENCE_BASE, ty.path, proc_name), - BuiltinDocs::ReferenceHash(hash) => format!("{}{}", DM_REFERENCE_BASE, hash), + BuiltinDocs::ReferenceHash(hash) => format!("{DM_REFERENCE_BASE}{hash}"), }) } } } else if ty.location.is_builtins() { external_url = Some(match ty.docs.builtin_docs { BuiltinDocs::None => format!("{}{}", DM_REFERENCE_BASE, ty.path), - BuiltinDocs::ReferenceHash(hash) => format!("{}{}", DM_REFERENCE_BASE, hash), + BuiltinDocs::ReferenceHash(hash) => format!("{DM_REFERENCE_BASE}{hash}"), }) } } @@ -915,9 +915,9 @@ fn broken_link_fixer<'str>( eprint!(" [{}]: unknown crosslink, guessing [{}", reference, &progress[..best]); } if let Some(proc_name) = proc_name { - eprint!("/proc/{}", proc_name); + eprint!("/proc/{proc_name}"); } else if let Some(var_name) = var_name { - eprint!("/var/{}", var_name); + eprint!("/var/{var_name}"); } eprintln!("]"); progress.truncate(best); @@ -925,9 +925,9 @@ fn broken_link_fixer<'str>( let mut href = format!("{}.html", &progress[1..]); if let Some(proc_name) = proc_name { - let _ = write!(href, "#proc/{}", proc_name); + let _ = write!(href, "#proc/{proc_name}"); } else if let Some(var_name) = var_name { - let _ = write!(href, "#var/{}", var_name); + let _ = write!(href, "#var/{var_name}"); } Some((href.into(), progress.into())) } else if let Some(external) = external_url { @@ -935,9 +935,9 @@ fn broken_link_fixer<'str>( } else { error_entity_print(); if entity_exists { - eprintln!(" [{}]: not documented", reference); + eprintln!(" [{reference}]: not documented"); } else { - eprintln!(" [{}]: unknown crosslink", reference); + eprintln!(" [{reference}]: unknown crosslink"); } None } @@ -948,7 +948,7 @@ fn broken_link_fixer<'str>( fn module_path(path: &Path) -> String { let mut path = path.with_extension(""); - if path.file_name().map_or(false, |x| x.to_string_lossy().eq_ignore_ascii_case("README")) { + if path.file_name().is_some_and(|x| x.to_string_lossy().eq_ignore_ascii_case("README")) { path.pop(); } path.display().to_string().replace('\\', "/") @@ -1047,7 +1047,7 @@ fn git_info(git: &mut Git) -> Result<(), git2::Error> { let upstream_oid = upstream.get().peel_to_commit()?.id(); let upstream_name = req!(upstream.name()?); if repo.merge_base(head_oid, upstream_oid)? != head_oid { - println!("incomplete git info: HEAD is not an ancestor of {}", upstream_name); + println!("incomplete git info: HEAD is not an ancestor of {upstream_name}"); return Ok(()); } @@ -1079,7 +1079,7 @@ fn git_info(git: &mut Git) -> Result<(), git2::Error> { if colon >= at { git.web_url = format!("https://{}/{}", &url[at + 1..colon], &url[colon + 1..]); } else { - println!("incomplete git info: weird SSH path: {}", url); + println!("incomplete git info: weird SSH path: {url}"); } } Ok(()) @@ -1197,7 +1197,7 @@ fn combine(stack: &mut Vec, to: usize) { } fn last_element(path: &str) -> &str { - path.split('/').last().unwrap_or("") + path.split('/').next_back().unwrap_or("") } // ---------------------------------------------------------------------------- diff --git a/crates/dmdoc/src/markdown.rs b/crates/dmdoc/src/markdown.rs index e0eab5a0..c6501d06 100644 --- a/crates/dmdoc/src/markdown.rs +++ b/crates/dmdoc/src/markdown.rs @@ -129,7 +129,7 @@ impl<'a, I: Iterator>> Iterator for HeadingLinker<'a, I> { self.output.push_back(event); } - self.output.push_back(Event::Html(format!("", heading).into())); + self.output.push_back(Event::Html(format!("").into())); return Some(Event::Html(format!("<{} id=\"{}\">", heading, slugify(&text_buf)).into())); } original diff --git a/crates/dmdoc/src/template.rs b/crates/dmdoc/src/template.rs index e465c81b..6b1bcd5b 100644 --- a/crates/dmdoc/src/template.rs +++ b/crates/dmdoc/src/template.rs @@ -88,7 +88,7 @@ fn git_link(env: &Environment, file: &str, line: u32) -> Markup { let title = if line == 0 { file } else { - z = format!("{} {}", file, line); + z = format!("{file} {line}"); &z }; let icon = html! { diff --git a/crates/dmm-tools-cli/build.rs b/crates/dmm-tools-cli/build.rs index 31ff1307..f827f259 100644 --- a/crates/dmm-tools-cli/build.rs +++ b/crates/dmm-tools-cli/build.rs @@ -11,7 +11,7 @@ fn main() { let mut f = File::create(out_dir.join("build-info.txt")).unwrap(); if let Ok(commit) = read_commit() { - writeln!(f, "commit: {}", commit).unwrap(); + writeln!(f, "commit: {commit}").unwrap(); } write!(f, "build date: {}", chrono::Utc::now().date_naive()).unwrap(); } diff --git a/crates/dmm-tools-cli/src/main.rs b/crates/dmm-tools-cli/src/main.rs index 614e5d9b..1bed6380 100644 --- a/crates/dmm-tools-cli/src/main.rs +++ b/crates/dmm-tools-cli/src/main.rs @@ -72,7 +72,7 @@ impl Context { let pp = match dm::preprocessor::Preprocessor::new(&self.dm_context, environment) { Ok(pp) => pp, Err(e) => { - eprintln!("i/o error opening environment:\n{}", e); + eprintln!("i/o error opening environment:\n{e}"); std::process::exit(1); } }; @@ -275,7 +275,7 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { max.x = clamp(max.x, min.x, dim_x); max.y = clamp(max.y, min.y, dim_y); max.z = clamp(max.z, min.z, dim_z); - println!("{}rendering from {} to {}", prefix, min, max); + println!("{prefix}rendering from {min} to {max}"); let do_z_level = |z| { println!("{}generating z={}", prefix, 1 + z); @@ -292,7 +292,7 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { }; let image = minimap::generate(minimap_context, icon_cache).unwrap(); if let Err(e) = std::fs::create_dir_all(output) { - eprintln!("Failed to create output directory {}:\n{}", output, e); + eprintln!("Failed to create output directory {output}:\n{e}"); exit_status.fetch_add(1, Ordering::Relaxed); return; } @@ -302,11 +302,11 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { path.file_stem().unwrap().to_string_lossy(), 1 + z ); - println!("{}saving {}", prefix, outfile); + println!("{prefix}saving {outfile}"); image.to_file(outfile.as_ref()).unwrap(); if pngcrush { - println!(" pngcrush {}", outfile); - let temp = format!("{}.temp", outfile); + println!(" pngcrush {outfile}"); + let temp = format!("{outfile}.temp"); assert!(std::process::Command::new("pngcrush") .arg("-ow") .arg(&outfile) @@ -317,7 +317,7 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { .success(), "pngcrush failed"); } if optipng { - println!("{}optipng {}", prefix, outfile); + println!("{prefix}optipng {outfile}"); assert!(std::process::Command::new("optipng") .arg(&outfile) .stderr(std::process::Stdio::null()) @@ -358,7 +358,7 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { let left_dims = left_map.dim_xyz(); let right_dims = right_map.dim_xyz(); if left_dims != right_dims { - println!(" different size: {:?} {:?}", left_dims, right_dims); + println!(" different size: {left_dims:?} {right_dims:?}"); } for z in 0..min(left_dims.2, right_dims.2) { @@ -586,7 +586,7 @@ fn render_many(context: &Context, command: RenderManyCommand) -> RenderManyComma }).collect()); let result_chunks: Vec<_> = chunks.into_par_iter().enumerate().map(|(chunk_idx, chunk)| { - eprintln!("{}/{}: render {:?}", file_idx, chunk_idx, chunk); + eprintln!("{file_idx}/{chunk_idx}: render {chunk:?}"); // Render the image. let bump = Default::default(); diff --git a/crates/dmm-tools/examples/duplicate_icon_states.rs b/crates/dmm-tools/examples/duplicate_icon_states.rs index ff54e878..859a70d5 100644 --- a/crates/dmm-tools/examples/duplicate_icon_states.rs +++ b/crates/dmm-tools/examples/duplicate_icon_states.rs @@ -23,7 +23,7 @@ fn files_with_extension(ext: &str, mut f: F) { let dir = match std::env::var_os("TEST_DME") { Some(dme) => Path::new(&dme).parent().unwrap().to_owned(), None => { - println!("Set TEST_DME to check .{} files", ext); + println!("Set TEST_DME to check .{ext} files"); return; } }; diff --git a/crates/dmm-tools/src/dmi.rs b/crates/dmm-tools/src/dmi.rs index 499575c6..1a309099 100644 --- a/crates/dmm-tools/src/dmi.rs +++ b/crates/dmm-tools/src/dmi.rs @@ -65,7 +65,7 @@ impl IconFile { self.metadata.get_icon_state(icon_state).ok_or_else(|| { io::Error::new( io::ErrorKind::NotFound, - format!("icon_state {} not found", icon_state), + format!("icon_state {icon_state} not found"), ) }) } diff --git a/crates/dmm-tools/src/dmm.rs b/crates/dmm-tools/src/dmm.rs index b6dc1859..1ba025d5 100644 --- a/crates/dmm-tools/src/dmm.rs +++ b/crates/dmm-tools/src/dmm.rs @@ -146,7 +146,7 @@ impl std::hash::Hash for Prefab { impl Map { pub fn new(x: usize, y: usize, z: usize, turf: String, area: String) -> Map { - assert!(x > 0 && y > 0 && z > 0, "({}, {}, {})", x, y, z); + assert!(x > 0 && y > 0 && z > 0, "({x}, {y}, {z})"); let mut dictionary = BTreeMap::new(); dictionary.insert(Key(0), vec![ @@ -281,7 +281,7 @@ impl fmt::Display for Prefab { if f.alternate() { f.write_str("\n ")?; } - write!(f, "{} = {}", k, v)?; + write!(f, "{k} = {v}")?; } if f.alternate() { f.write_str("\n")?; diff --git a/crates/dmm-tools/src/dmm/read.rs b/crates/dmm-tools/src/dmm/read.rs index 13f86c2c..eb7f5916 100644 --- a/crates/dmm-tools/src/dmm/read.rs +++ b/crates/dmm-tools/src/dmm/read.rs @@ -222,7 +222,7 @@ pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { } else { match (ch as char).to_digit(10) { Some(x) => curr_num = 10 * curr_num + x as usize, - None => return Err(DMError::new(chars.location(), format!("bad digit {:?} in map coordinate", ch))), + None => return Err(DMError::new(chars.location(), format!("bad digit {ch:?} in map coordinate"))), } } } else if in_map_string { @@ -247,8 +247,7 @@ pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { curr_key_length = 0; if grid.insert((curr_x, curr_y, curr_z), Key(key)).is_some() { return Err(DMError::new(chars.location(), format!( - "multiple entries for ({}, {}, {})", - curr_x, curr_y, curr_z))) + "multiple entries for ({curr_x}, {curr_y}, {curr_z})"))) } max_x = max(max_x, curr_x); curr_x += 1; diff --git a/crates/dmm-tools/src/dmm/save_tgm.rs b/crates/dmm-tools/src/dmm/save_tgm.rs index 98cee5e8..b3f2996c 100644 --- a/crates/dmm-tools/src/dmm/save_tgm.rs +++ b/crates/dmm-tools/src/dmm/save_tgm.rs @@ -11,7 +11,7 @@ const TGM_HEADER: &str = "//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREV // If that changes, this will break. pub fn save_tgm(map: &Map, w: &mut impl Write) -> io::Result<()> { let mut f = BufWriter::new(w); - writeln!(f, "{}", TGM_HEADER)?; + writeln!(f, "{TGM_HEADER}")?; // dictionary for (&key, prefabs) in map.dictionary.iter() { @@ -21,7 +21,7 @@ pub fn save_tgm(map: &Map, w: &mut impl Write) -> io::Result<()> { if !fab.vars.is_empty() { write!(f, "{{")?; for (i, (var, value)) in fab.vars.iter().enumerate() { - write!(f, "\n\t{} = {}", var, value)?; + write!(f, "\n\t{var} = {value}")?; if i + 1 != fab.vars.len() { write!(f, ";")?; } diff --git a/crates/dmm-tools/src/minimap.rs b/crates/dmm-tools/src/minimap.rs index 93e2a0ab..41dc2c05 100644 --- a/crates/dmm-tools/src/minimap.rs +++ b/crates/dmm-tools/src/minimap.rs @@ -155,7 +155,7 @@ pub fn generate(ctx: Context, icon_cache: &IconCache) -> Result { } else { let key = format!("bad icon: {:?}, state: {:?}", sprite.icon, sprite.icon_state); if !ctx.errors.read().unwrap().contains(&key) { - eprintln!("{}", key); + eprintln!("{key}"); ctx.errors.write().unwrap().insert(key); } } @@ -218,7 +218,7 @@ fn get_atom_list<'a>( None => { let key = format!("bad path: {}", fab.path); if !errors.read().unwrap().contains(&key) { - println!("{}", key); + println!("{key}"); errors.write().unwrap().insert(key); } continue; diff --git a/crates/dmm-tools/src/render_passes/random.rs b/crates/dmm-tools/src/render_passes/random.rs index d773efe7..3ca1bbec 100644 --- a/crates/dmm-tools/src/render_passes/random.rs +++ b/crates/dmm-tools/src/render_passes/random.rs @@ -123,7 +123,7 @@ impl RenderPass for Random { let mut signs = Vec::new(); for child in root.children() { if let Some(v) = child.vars.get("hidden") { - if !v.value.constant.as_ref().map_or(false, |c| c.to_bool()) { + if !v.value.constant.as_ref().is_some_and(|c| c.to_bool()) { continue; } } diff --git a/crates/dmm-tools/tests/parse_codebase.rs b/crates/dmm-tools/tests/parse_codebase.rs index c28abf9a..e2e3d7ba 100644 --- a/crates/dmm-tools/tests/parse_codebase.rs +++ b/crates/dmm-tools/tests/parse_codebase.rs @@ -19,7 +19,7 @@ fn files_with_extension(ext: &str, mut f: F) { let dir = match std::env::var_os("TEST_DME") { Some(dme) => Path::new(&dme).parent().unwrap().to_owned(), None => { - println!("Set TEST_DME to check .{} files", ext); + println!("Set TEST_DME to check .{ext} files"); return; } }; diff --git a/crates/dreamchecker/build.rs b/crates/dreamchecker/build.rs index d9951a53..df81ad5a 100644 --- a/crates/dreamchecker/build.rs +++ b/crates/dreamchecker/build.rs @@ -11,7 +11,7 @@ fn main() { let mut f = File::create(out_dir.join("build-info.txt")).unwrap(); if let Ok(commit) = read_commit() { - writeln!(f, "commit: {}", commit).unwrap(); + writeln!(f, "commit: {commit}").unwrap(); } writeln!(f, "build date: {}", chrono::Utc::now().date_naive()).unwrap(); } diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index e83af6e9..3cb6d8e6 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -259,7 +259,7 @@ trait WithFilterArgs { impl WithFilterArgs for DMError { fn with_filter_args(mut self, loc: Location, filtertype: &str) -> Self { // luckily lummox has made the anchor url match the type= value for each filter - self.add_note(loc, format!("See: http://www.byond.com/docs/ref/#/{{notes}}/filters/{} for the permitted arguments", filtertype)); + self.add_note(loc, format!("See: http://www.byond.com/docs/ref/#/{{notes}}/filters/{filtertype} for the permitted arguments")); self } } @@ -456,7 +456,7 @@ pub fn directive_value_to_truthy(expr: &Expression, location: Location) -> Resul Some(Term::Int(1)) => Ok(true), Some(Term::Ident(i)) if i == "FALSE" => Ok(false), Some(Term::Ident(i)) if i == "TRUE" => Ok(true), - _ => Err(error(location, format!("invalid value for set {:?}", expr)) + _ => Err(error(location, format!("invalid value for set {expr:?}")) .set_severity(Severity::Warning)), } } @@ -482,21 +482,21 @@ trait DMErrorExt { impl DMErrorExt for DMError { fn with_callstack(mut self, stack: &CallStack) -> DMError { for (procref, location, new_context) in stack.call_stack.iter() { - self.add_note(*location, format!("{}() called here", procref)); + self.add_note(*location, format!("{procref}() called here")); } self } fn with_blocking_builtins(mut self, blockers: &[(String, Location)]) -> DMError { for (procname, location) in blockers.iter() { - self.add_note(*location, format!("{}() called here", procname)); + self.add_note(*location, format!("{procname}() called here")); } self } fn with_impure_operations(mut self, impures: &[(String, Location)]) -> DMError { for (impure, location) in impures.iter() { - self.add_note(*location, format!("{} happens here", impure)); + self.add_note(*location, format!("{impure} happens here")); } self } @@ -607,7 +607,7 @@ impl<'o> AnalyzeObjectTree<'o> { "SpacemanDMM_should_be_pure" => &mut self.must_be_pure, "SpacemanDMM_can_be_redefined" => &mut self.can_be_redefined, other => { - error(location, format!("unknown linter setting {:?}", directive)) + error(location, format!("unknown linter setting {directive:?}")) .with_errortype("unknown_linter_setting") .set_severity(Severity::Warning) .register(self.context); @@ -618,7 +618,7 @@ impl<'o> AnalyzeObjectTree<'o> { if procdirective.set_at_definition { if let Some(procdef) = &mut proc.get_declaration() { if procdef.location != proc.get().location { - error(location, format!("Can't define procs {} outside their initial definition", directive)) + error(location, format!("Can't define procs {directive} outside their initial definition")) .set_severity(Severity::Warning) .register(self.context); return @@ -639,7 +639,7 @@ impl<'o> AnalyzeObjectTree<'o> { pub fn check_proc_call_tree(&mut self) { for (procref, &(_, location)) in self.must_not_sleep.directive.iter() { if let Some(sleepvec) = self.sleeping_procs.get_violators(*procref) { - error(procref.get().location, format!("{} sets SpacemanDMM_should_not_sleep but calls blocking built-in(s)", procref)) + error(procref.get().location, format!("{procref} sets SpacemanDMM_should_not_sleep but calls blocking built-in(s)")) .with_note(location, "SpacemanDMM_should_not_sleep set here") .with_errortype("must_not_sleep") .with_blocking_builtins(sleepvec) @@ -668,7 +668,7 @@ impl<'o> AnalyzeObjectTree<'o> { continue } if let Some(sleepvec) = self.sleeping_procs.get_violators(nextproc) { - error(procref.get().location, format!("{} sets SpacemanDMM_should_not_sleep but calls blocking proc {}", procref, nextproc)) + error(procref.get().location, format!("{procref} sets SpacemanDMM_should_not_sleep but calls blocking proc {nextproc}")) .with_note(location, "SpacemanDMM_should_not_sleep set here") .with_errortype("must_not_sleep") .with_callstack(&callstack) @@ -679,7 +679,7 @@ impl<'o> AnalyzeObjectTree<'o> { if procref.ty().is_subtype_of(&nextproc.ty()) && !child_violator.ty().is_subtype_of(&procref.ty()) { continue } - error(procref.get().location, format!("{} calls {} which has override child proc that sleeps {}", procref, nextproc, child_violator)) + error(procref.get().location, format!("{procref} calls {nextproc} which has override child proc that sleeps {child_violator}")) .with_note(location, "SpacemanDMM_should_not_sleep set here") .with_errortype("must_not_sleep") .with_callstack(&callstack) @@ -699,7 +699,7 @@ impl<'o> AnalyzeObjectTree<'o> { for (procref, (_, location)) in self.must_be_pure.directive.iter() { if let Some(impurevec) = self.impure_procs.get_violators(*procref) { - error(procref.get().location, format!("{} does impure operations", procref)) + error(procref.get().location, format!("{procref} does impure operations")) .with_errortype("must_be_pure") .with_note(*location, "SpacemanDMM_should_be_pure set here") .with_impure_operations(impurevec) @@ -719,7 +719,7 @@ impl<'o> AnalyzeObjectTree<'o> { continue } if let Some(impurevec) = self.impure_procs.get_violators(nextproc) { - error(procref.get().location, format!("{} sets SpacemanDMM_should_be_pure but calls a {} that does impure operations", procref, nextproc)) + error(procref.get().location, format!("{procref} sets SpacemanDMM_should_be_pure but calls a {nextproc} that does impure operations")) .with_note(*location, "SpacemanDMM_should_be_pure set here") .with_errortype("must_be_pure") .with_callstack(&callstack) @@ -730,7 +730,7 @@ impl<'o> AnalyzeObjectTree<'o> { if procref.ty().is_subtype_of(&nextproc.ty()) && !child_violator.ty().is_subtype_of(&procref.ty()) { continue } - error(procref.get().location, format!("{} calls {} which has override child proc that does impure operations {}", procref, nextproc, child_violator)) + error(procref.get().location, format!("{procref} calls {nextproc} which has override child proc that does impure operations {child_violator}")) .with_note(*location, "SpacemanDMM_should_not_pure set here") .with_errortype("must_be_pure") .with_callstack(&callstack) @@ -801,7 +801,7 @@ impl<'o> AnalyzeObjectTree<'o> { } else if name.starts_with("SpacemanDMM_") { self.add_directive_or_error(proc, name.as_str(), value, statement.location); } else if !KNOWN_SETTING_NAMES.contains(&name.as_str()) { - error(statement.location, format!("unknown setting {:?}", name)) + error(statement.location, format!("unknown setting {name:?}")) .set_severity(Severity::Warning) .register(self.context); } else { @@ -907,8 +907,8 @@ impl<'o> AnalyzeObjectTree<'o> { // List out the child procs that are missing overrides. let msg = match kwarg_info.bad_overrides_at.len() { - 1 => format!("an override of {} is missing keyword args", base_procname), - len => format!("{} overrides of {} are missing keyword args", len, base_procname), + 1 => format!("an override of {base_procname} is missing keyword args"), + len => format!("{len} overrides of {base_procname} are missing keyword args"), }; let mut error = error(kwarg_info.location, msg) .with_errortype("override_missing_keyword_arg"); @@ -931,7 +931,7 @@ impl<'o> AnalyzeObjectTree<'o> { error.add_note(called_at.location, format!("called with {:?} here, and {} other places", arg_name, called_at.others)); } else { - error.add_note(called_at.location, format!("called with {:?} here", arg_name)); + error.add_note(called_at.location, format!("called with {arg_name:?} here")); } } @@ -1007,20 +1007,20 @@ pub fn check_var_defs(objtree: &ObjectTree, context: &Context) { if typevar.value.location.is_builtins() { continue; } - DMError::new(mydecl.location, format!("{} redeclares var {:?}", path, varname)) + DMError::new(mydecl.location, format!("{path} redeclares var {varname:?}")) .with_note(decl.location, format!("declared on {} here", parent.path)) .register(context); } if decl.var_type.flags.is_final() { - DMError::new(typevar.value.location, format!("{} overrides final var {:?}", path, varname)) + DMError::new(typevar.value.location, format!("{path} overrides final var {varname:?}")) .with_errortype("final_var") .with_note(decl.location, format!("declared final on {} here", parent.path)) .register(context); } if decl.var_type.flags.is_private() { - DMError::new(typevar.value.location, format!("{} overrides private var {:?}", path, varname)) + DMError::new(typevar.value.location, format!("{path} overrides private var {varname:?}")) .with_errortype("private_var") .with_note(decl.location, format!("declared private on {} here", parent.path)) .register(context); @@ -1190,7 +1190,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { if let Some(parent) = self.proc_ref.parent_proc() { if let Some((proc, true, location)) = self.env.private.get_self_or_parent(self.proc_ref) { if proc != self.proc_ref { - error(self.proc_ref.location, format!("proc overrides private parent, prohibited by {}", proc)) + error(self.proc_ref.location, format!("proc overrides private parent, prohibited by {proc}")) .with_note(location, "prohibited by this private_proc annotation") .with_errortype("private_proc") .register(self.context); @@ -1198,7 +1198,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } if let Some((proc, true, location)) = self.env.must_not_override.get_self_or_parent(self.proc_ref) { if proc != self.proc_ref { - error(self.proc_ref.location, format!("proc overrides parent, prohibited by {}", proc)) + error(self.proc_ref.location, format!("proc overrides parent, prohibited by {proc}")) .with_note(location, "prohibited by this must_not_override annotation") .with_errortype("must_not_override") .register(self.context); @@ -1206,7 +1206,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } if !self.calls_parent { if let Some((proc, true, location)) = self.env.must_call_parent.get_self_or_parent(self.proc_ref) { - error(self.proc_ref.location, format!("proc never calls parent, required by {}", proc)) + error(self.proc_ref.location, format!("proc never calls parent, required by {proc}")) .with_note(location, "required by this must_call_parent annotation") .with_errortype("must_call_parent") .register(self.context); @@ -1292,7 +1292,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { if !follow.iter().any(|f| matches!(f.elem, Follow::Call(..))) { if let Some(proc) = self.ty.get_proc(call) { if let Some((_, _, loc)) = self.env.must_be_pure.get_self_or_parent(proc) { - error(location, format!("call to pure proc {} discards return value", call)) + error(location, format!("call to pure proc {call} discards return value")) .with_note(loc, "prohibited by this must_be_pure annotation") .register(self.context); } @@ -1642,19 +1642,19 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } }, Expression::BinaryOp { op, lhs, rhs } => { - error(location, format!("ambiguous `{}` on left side of an `in`", op)) + error(location, format!("ambiguous `{op}` on left side of an `in`")) .set_severity(Severity::Warning) .with_errortype("ambiguous_in_lhs") - .with_note(location, format!("add parentheses to fix: `a {} (b in c)`", op)) - .with_note(location, format!("add parentheses to disambiguate: `(a {} b) in c`", op)) + .with_note(location, format!("add parentheses to fix: `a {op} (b in c)`")) + .with_note(location, format!("add parentheses to disambiguate: `(a {op} b) in c`")) .register(self.context); }, Expression::AssignOp { op, lhs, rhs } => { - error(location, format!("ambiguous `{}` on left side of an `in`", op)) + error(location, format!("ambiguous `{op}` on left side of an `in`")) .set_severity(Severity::Warning) .with_errortype("ambiguous_in_lhs") - .with_note(location, format!("add parentheses to fix: `a {} (b in c)`", op)) - .with_note(location, format!("add parentheses to disambiguate: `(a {} b) in c`", op)) + .with_note(location, format!("add parentheses to fix: `a {op} (b in c)`")) + .with_note(location, format!("add parentheses to disambiguate: `(a {op} b) in c`")) .register(self.context); }, Expression::TernaryOp { cond, if_, else_ } => { @@ -1737,7 +1737,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { ana.is_impure = Some(true); ana } else { - error(location, format!("undefined var: {:?}", unscoped_name)) + error(location, format!("undefined var: {unscoped_name:?}")) .register(self.context); Analysis::empty() } @@ -1749,7 +1749,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { ana.is_impure = Some(true); ana } else { - error(location, format!("undefined global var: {:?}", global_name)) + error(location, format!("undefined global var: {global_name:?}")) .register(self.context); Analysis::empty() } @@ -1837,7 +1837,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { if let Some(proc) = self.objtree.root().get_proc(global_name) { self.visit_call(location, self.objtree.root(), proc, args, true, local_vars) } else { - error(location, format!("undefined global proc: {:?}", global_name)) + error(location, format!("undefined global proc: {global_name:?}")) .register(self.context); Analysis::empty() } @@ -1995,12 +1995,12 @@ impl<'o, 's> AnalyzeProc<'o, 's> { "/client" => if self.inside_newcontext == 0 && matches!(unscoped_name, "SoundQuery" | "MeasureText") { - self.env.sleeping_procs.insert_violator(self.proc_ref, format!("client.{}", unscoped_name).as_str(), location); + self.env.sleeping_procs.insert_violator(self.proc_ref, format!("client.{unscoped_name}").as_str(), location); }, "/world" => if self.inside_newcontext == 0 && matches!(unscoped_name, "Import" | "Export") { - self.env.sleeping_procs.insert_violator(self.proc_ref, format!("world.{}", unscoped_name).as_str(), location); + self.env.sleeping_procs.insert_violator(self.proc_ref, format!("world.{unscoped_name}").as_str(), location); }, _ => {}, } @@ -2050,13 +2050,13 @@ impl<'o, 's> AnalyzeProc<'o, 's> { if let Some(ty) = lhs.static_ty.basic_type() { if let Some(decl) = ty.get_var_declaration(name) { if ty != self.ty && decl.var_type.flags.is_private() { - error(location, format!("field {:?} on {} is declared as private", name, ty)) + error(location, format!("field {name:?} on {ty} is declared as private")) .with_errortype("private_var") .set_severity(Severity::Warning) .with_note(decl.location, "definition is here") .register(self.context); } else if !self.ty.is_subtype_of(ty.get()) && decl.var_type.flags.is_protected() { - error(location, format!("field {:?} on {} is declared as protected", name, ty)) + error(location, format!("field {name:?} on {ty} is declared as protected")) .with_errortype("protected_var") .set_severity(Severity::Warning) .with_note(decl.location, "definition is here") @@ -2065,12 +2065,12 @@ impl<'o, 's> AnalyzeProc<'o, 's> { self.static_type(location, &decl.var_type.type_path) .with_fix_hint(decl.location, "add additional type info here") } else { - error(location, format!("undefined field: {:?} on {}", name, ty)) + error(location, format!("undefined field: {name:?} on {ty}")) .register(self.context); Analysis::empty() } } else { - error(location, format!("field access requires static type: {:?}", name)) + error(location, format!("field access requires static type: {name:?}")) .set_severity(Severity::Warning) .with_errortype("field_access_static_type") .with_fix_hint(&lhs) @@ -2083,23 +2083,23 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Some(existing_type) => existing_type, None => { let Some(to_our_side) = lhs.value else { - error(location, format!("no typepath found for: {:?}", name)) + error(location, format!("no typepath found for: {name:?}")) .register(self.context); return Analysis::empty() }; let Constant::Prefab(typepop) = to_our_side else { - error(location, format!("static access requires a static typepath, {} found instead", to_our_side)) + error(location, format!("static access requires a static typepath, {to_our_side} found instead")) .register(self.context); return Analysis::empty() }; if !typepop.vars.is_empty() { - error(location, format!("static access requires a static typepath, {} found instead", typepop)) + error(location, format!("static access requires a static typepath, {typepop} found instead")) .register(self.context); return Analysis::empty() } let typepath = dm::ast::FormatTreePath(&typepop.path).to_string(); let Some(found_type) = self.objtree.find(typepath.as_str()) else { - error(location, format!("static access requires an existing typepath, {} found instead", typepath)) + error(location, format!("static access requires an existing typepath, {typepath} found instead")) .register(self.context); return Analysis::empty() }; @@ -2107,7 +2107,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } }; let Some(decl) = real_type.get_var_declaration(name) else { - error(location, format!("undefined field: {:?} on {}", name, real_type)) + error(location, format!("undefined field: {name:?} on {real_type}")) .register(self.context); return Analysis::empty() }; @@ -2139,12 +2139,12 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } self.visit_call(location, ty, proc, arguments, false, local_vars) } else { - error(location, format!("undefined proc: {:?} on {}", name, ty)) + error(location, format!("undefined proc: {name:?} on {ty}")) .register(self.context); Analysis::empty() } } else { - error(location, format!("proc call requires static type: {:?}", name)) + error(location, format!("proc call requires static type: {name:?}")) .set_severity(Severity::Warning) .with_errortype("proc_call_static_type") .with_fix_hint(&lhs) @@ -2157,23 +2157,23 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Some(existing_type) => existing_type, None => { let Some(to_our_side) = lhs.value else { - error(location, format!("no typepath found for: {:?}", name)) + error(location, format!("no typepath found for: {name:?}")) .register(self.context); return Analysis::empty() }; let Constant::Prefab(typepop) = to_our_side else { - error(location, format!("static proc reference requires a static typepath, {} found instead", to_our_side)) + error(location, format!("static proc reference requires a static typepath, {to_our_side} found instead")) .register(self.context); return Analysis::empty() }; if !&typepop.vars.is_empty() { - error(location, format!("static proc reference requires a static typepath, {} found instead", typepop)) + error(location, format!("static proc reference requires a static typepath, {typepop} found instead")) .register(self.context); return Analysis::empty() } let typepath = dm::ast::FormatTreePath(&typepop.path).to_string(); let Some(found_type) = self.objtree.find(typepath.as_str()) else { - error(location, format!("static proc reference requires an existing typepath, {} found instead", typepath)) + error(location, format!("static proc reference requires an existing typepath, {typepath} found instead")) .register(self.context); return Analysis::empty() }; @@ -2181,7 +2181,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } }; let Some(decl) = real_type.get_proc(name) else { - error(location, format!("undefined proc: {:?} on {}", name, real_type)) + error(location, format!("undefined proc: {name:?} on {real_type}")) .register(self.context); return Analysis::empty() }; @@ -2209,7 +2209,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { fn check_operator_overload(&mut self, rhs: Analysis<'o>, location: Location, operator: &str, local_vars: &mut HashMap>) -> Analysis<'o> { if let Some(impurity) = rhs.is_impure { if impurity { - self.env.impure_procs.insert_violator(self.proc_ref, &format!("{} done on non-local var", operator), location); + self.env.impure_procs.insert_violator(self.proc_ref, &format!("{operator} done on non-local var"), location); } } let typeerror; @@ -2228,7 +2228,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { typeerror = "list"; }, }; - error(location, format!("Attempting {} on a {} which does not overload {}", operator, typeerror, operator)) + error(location, format!("Attempting {operator} on a {typeerror} which does not overload {operator}")) .register(self.context); Analysis::empty() } @@ -2256,12 +2256,12 @@ impl<'o, 's> AnalyzeProc<'o, 's> { let Expression::Base { follow, .. } = lhs else { return }; let any_not = follow.iter().any(|f| matches!(f.elem, Follow::Unary(UnaryOp::Not))); if any_not { - error(location, format!("Ambiguous `!` on left side of bitwise `{}` operator", bit_op)) + error(location, format!("Ambiguous `!` on left side of bitwise `{bit_op}` operator")) .with_errortype("ambiguous_not_bitwise") .set_severity(Severity::Warning) - .with_note(location, format!("Did you mean `!(x {} y)`?", bit_op)) - .with_note(location, format!("Did you mean `!x {} y`?", bool_op)) - .with_note(location, format!("Did you mean `~x {} y`?", bit_op)) + .with_note(location, format!("Did you mean `!(x {bit_op} y)`?")) + .with_note(location, format!("Did you mean `!x {bool_op} y`?")) + .with_note(location, format!("Did you mean `~x {bit_op} y`?")) .register(self.context); } } @@ -2288,7 +2288,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { match expr { Expression::BinaryOp{ op: BinaryOp::BitOr, lhs, rhs } => { if exclusive { - error(location, format!("filter(type=\"{}\") '{}' parameter must have one value, found bitwise OR", typevalue, flagfieldname)) + error(location, format!("filter(type=\"{typevalue}\") '{flagfieldname}' parameter must have one value, found bitwise OR")) .with_filter_args(location, typevalue) .register(self.context); return @@ -2298,7 +2298,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { self.check_filter_flag(rhs, can_be_zero, location, typevalue, valid_flags, flagfieldname, exclusive); }, Expression::Base{ term, follow } => { - if follow.len() > 0 { + if !follow.is_empty() { error(location, "filter() flag fields cannot have unary ops or field accesses") .register(self.context); return @@ -2306,21 +2306,21 @@ impl<'o, 's> AnalyzeProc<'o, 's> { match &term.elem { Term::Ident(flagname) => { if !valid_flags.iter().any(|&x| x == flagname) { - error(location, format!("filter(type=\"{}\") called with invalid '{}' flag '{}'", typevalue, flagfieldname, flagname)) + error(location, format!("filter(type=\"{typevalue}\") called with invalid '{flagfieldname}' flag '{flagname}'")) .with_filter_args(location, typevalue) .register(self.context); } }, Term::Int(0) if can_be_zero => {}, other => { - error(location, format!("filter(type=\"{}\") called with invalid '{}' value '{:?}'", typevalue, flagfieldname, other)) + error(location, format!("filter(type=\"{typevalue}\") called with invalid '{flagfieldname}' value '{other:?}'")) .with_filter_args(location, typevalue) .register(self.context); }, } }, _ => { - error(location, format!("filter(type=\"{}\"), extremely invalid value passed to '{}' field", typevalue, flagfieldname)) + error(location, format!("filter(type=\"{typevalue}\"), extremely invalid value passed to '{flagfieldname}' field")) .with_filter_args(location, typevalue) .register(self.context); } @@ -2364,11 +2364,11 @@ impl<'o, 's> AnalyzeProc<'o, 's> { if !proc.parameters.iter().any(|p| p.name == *name) { // Search for a child proc that does have this keyword argument. let mut error = error(location, - format!("bad keyword argument {:?} to {}", name, proc)); + format!("bad keyword argument {name:?} to {proc}")); proc.recurse_children(&mut |child_proc| { if child_proc.ty() == proc.ty() { return } if child_proc.parameters.iter().any(|p| p.name == *name) { - error.add_note(child_proc.location, format!("an override has this parameter: {}", child_proc)); + error.add_note(child_proc.location, format!("an override has this parameter: {child_proc}")); } }); error.register(self.context); @@ -2455,13 +2455,13 @@ impl<'o, 's> AnalyzeProc<'o, 's> { return Analysis::empty() }; let Some(arglist) = VALID_FILTER_TYPES.get(typevalue) else { - error(location, format!("filter() called with invalid type keyword parameter value '{}'", typevalue)) + error(location, format!("filter() called with invalid type keyword parameter value '{typevalue}'")) .register(self.context); return Analysis::empty() }; for arg in param_name_map.keys() { - if *arg != "type" && !arglist.iter().any(|&x| x == *arg) { - error(location, format!("filter(type=\"{}\") called with invalid keyword parameter '{}'", typevalue, arg)) + if *arg != "type" && !arglist.contains(arg) { + error(location, format!("filter(type=\"{typevalue}\") called with invalid keyword parameter '{arg}'")) .with_filter_args(location, typevalue) .register(self.context); } @@ -2483,7 +2483,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { }; match return_type.evaluate(location, &ec) { Ok(st) => { - let hint = format!("return type evaluated to {:?}", st); + let hint = format!("return type evaluated to {st:?}"); Analysis::from(st).with_fix_hint(location, hint) }, Err(err) => { @@ -2494,7 +2494,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } else { Analysis::empty() - .with_fix_hint(proc.location, format!("add a return type annotation to {}", proc)) + .with_fix_hint(proc.location, format!("add a return type annotation to {proc}")) } } diff --git a/crates/dreamchecker/src/main.rs b/crates/dreamchecker/src/main.rs index 174b292e..4f1fd5e0 100644 --- a/crates/dreamchecker/src/main.rs +++ b/crates/dreamchecker/src/main.rs @@ -38,7 +38,7 @@ fn main() { } else if arg == "--parse-only" { parse_only = true; } else { - eprintln!("unknown argument: {}", arg); + eprintln!("unknown argument: {arg}"); return; } } @@ -72,7 +72,7 @@ fn main() { println!("============================================================"); let errors = context.errors().iter().filter(|each| each.severity() <= dm::Severity::Info).count(); - println!("Found {} diagnostics", errors); + println!("Found {errors} diagnostics"); if json { serde_json::to_writer(std::io::stdout().lock(), &json! {{ diff --git a/crates/dreamchecker/src/switch_rand_range.rs b/crates/dreamchecker/src/switch_rand_range.rs index 3490743c..f898797c 100644 --- a/crates/dreamchecker/src/switch_rand_range.rs +++ b/crates/dreamchecker/src/switch_rand_range.rs @@ -30,7 +30,7 @@ pub fn check_switch_rand_range( if start <= rand_end && end >= rand_start { case_ranges.push((start, end)); } else { - DMError::new(location, format!("Case range '{} to {}' will never trigger as it is outside the rand() range {} to {}", start, end, rand_start, rand_end)) + DMError::new(location, format!("Case range '{start} to {end}' will never trigger as it is outside the rand() range {rand_start} to {rand_end}")) .with_component(dm::Component::DreamChecker) .set_severity(Severity::Warning) .register(context); @@ -58,8 +58,7 @@ pub fn check_switch_rand_range( DMError::new( location, format!( - "Switch branches on rand() with range {} to {} but no case branch triggers for {}", - rand_start, rand_end, first_uncovered + "Switch branches on rand() with range {rand_start} to {rand_end} but no case branch triggers for {first_uncovered}" ), ) .with_component(dm::Component::DreamChecker) diff --git a/crates/dreamchecker/src/type_expr.rs b/crates/dreamchecker/src/type_expr.rs index 8fabae3e..cd7ce2ac 100644 --- a/crates/dreamchecker/src/type_expr.rs +++ b/crates/dreamchecker/src/type_expr.rs @@ -198,7 +198,7 @@ impl<'o> TypeExprCompiler<'o> { } Err(DMError::new( location, - format!("type expr: no such parameter {:?}", unscoped_name), + format!("type expr: no such parameter {unscoped_name:?}"), )) } @@ -261,7 +261,7 @@ impl<'o> TypeExprCompiler<'o> { )), }, - _ => Err(DMError::new(location, format!("type expr: bad follow node {:?}", rhs))), + _ => Err(DMError::new(location, format!("type expr: bad follow node {rhs:?}"))), } } } diff --git a/crates/dreamchecker/tests/proc_tests.rs b/crates/dreamchecker/tests/proc_tests.rs index 1a0e7357..8edca7a2 100644 --- a/crates/dreamchecker/tests/proc_tests.rs +++ b/crates/dreamchecker/tests/proc_tests.rs @@ -27,7 +27,7 @@ fn return_type() { return "##.trim(); let context = parse_a_file_for_test(code); - let error_text: Vec = context.errors().iter().map(|error| format!("{}", error)).collect(); + let error_text: Vec = context.errors().iter().map(|error| format!("{error}")).collect(); if !error_text.is_empty() { panic!("\n{}", error_text.join("\n")) } diff --git a/crates/dreammaker/examples/flags.rs b/crates/dreammaker/examples/flags.rs index d32c6d1c..8a13026f 100644 --- a/crates/dreammaker/examples/flags.rs +++ b/crates/dreammaker/examples/flags.rs @@ -44,8 +44,7 @@ fn main() { let crossover = if rhs != 0 && lhs != 0 { panic!( - "flags_1={}, item_flags={}, lhs={}, rhs={}", - flags_1, item_flags, lhs, rhs + "flags_1={flags_1}, item_flags={item_flags}, lhs={lhs}, rhs={rhs}" ); } else if lhs != 0 { lhs @@ -54,8 +53,7 @@ fn main() { }; println!( - "flags_1={}, item_flags={}, crossover={}", - flags_1, item_flags, crossover + "flags_1={flags_1}, item_flags={item_flags}, crossover={crossover}" ); }); diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index a5c3db03..f10fd4ea 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -736,7 +736,7 @@ impl fmt::Debug for Ident2 { impl GetSize for Ident2 { fn get_heap_size(&self) -> usize { - self.inner.as_bytes().len() + self.inner.len() } } @@ -769,7 +769,7 @@ pub struct FormatTreePath<'a, T>(pub &'a [T]); impl<'a, T: fmt::Display> fmt::Display for FormatTreePath<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for each in self.0.iter() { - write!(f, "/{}", each)?; + write!(f, "/{each}")?; } Ok(()) } @@ -944,7 +944,7 @@ impl Expression { }, Expression::AssignOp { op, lhs: _, rhs } => { if let AssignOp::Assign = op { - return match rhs.as_term() { + match rhs.as_term() { Some(term) => term.is_truthy(), _ => None, } @@ -1242,7 +1242,7 @@ impl fmt::Display for Parameter { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "{}{}", self.var_type, self.name)?; if let Some(input_type) = self.input_type { - write!(fmt, " as {}", input_type)?; + write!(fmt, " as {input_type}")?; } Ok(()) } diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index 53663178..cb67c96b 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -323,7 +323,7 @@ impl ops::Not for Constant { } } -impl<'a> ops::Not for &'a Constant { +impl ops::Not for &Constant { type Output = Constant; fn not(self) -> Constant { @@ -338,7 +338,7 @@ impl fmt::Display for Constant { Constant::New { ref type_, ref args } => { f.write_str("new")?; if let Some(prefab) = type_ { - write!(f, " {}", prefab)?; + write!(f, " {prefab}")?; } if let Some(args) = args.as_ref() { write!(f, "(")?; @@ -350,7 +350,7 @@ impl fmt::Display for Constant { first = false; write!(f, "{}", each.0)?; if let Some(val) = each.1.as_ref() { - write!(f, " = {}", val)?; + write!(f, " = {val}")?; } } write!(f, ")")?; @@ -370,32 +370,32 @@ impl fmt::Display for Constant { } first = false; previous_assoc = false; - write!(f, "{}", key)?; + write!(f, "{key}")?; if let Some(val) = val.as_ref() { - write!(f, " = {}", val)?; + write!(f, " = {val}")?; previous_assoc = true; } } write!(f, ")") }, Constant::Call(const_fn, ref list) => { - write!(f, "{}(", const_fn)?; + write!(f, "{const_fn}(")?; let mut first = true; for (key, val) in list.iter() { if !first { write!(f, ", ")?; } first = false; - write!(f, "{}", key)?; + write!(f, "{key}")?; if let Some(val) = val { - write!(f, " = {}", val)?; + write!(f, " = {val}")?; } } write!(f, ")") }, - Constant::Prefab(ref val) => write!(f, "{}", val), + Constant::Prefab(ref val) => write!(f, "{val}"), Constant::String(ref val) => crate::lexer::Quote(val).fmt(f), - Constant::Resource(ref val) => write!(f, "'{}'", val), + Constant::Resource(ref val) => write!(f, "'{val}'"), Constant::Float(val) => crate::lexer::FormatFloat(val).fmt(f), } } @@ -462,7 +462,7 @@ pub(crate) fn evaluate_all(context: &Context, tree: &mut ObjectTree) { for key in keys { if !tree[ty] .get_var_declaration(&key, tree) - .map_or(true, |x| { + .is_none_or(|x| { x.var_type.is_const_evaluable() && (x.var_type.flags.is_const() || ty != NodeIndex::new(0)) }) { @@ -520,17 +520,17 @@ fn constant_ident_lookup( if var.value.being_evaluated { return Err(DMError::new( var.value.location, - format!("recursive constant reference: {}", ident), + format!("recursive constant reference: {ident}"), )); } else if !decl.var_type.is_const_evaluable() { return Err(DMError::new( var.value.location, - format!("non-const-evaluable variable: {}", ident), + format!("non-const-evaluable variable: {ident}"), )); } else if !decl.var_type.flags.is_const() && must_be_const { return Err(DMError::new( var.value.location, - format!("non-const variable: {}", ident), + format!("non-const variable: {ident}"), )); } var.value.being_evaluated = true; @@ -653,16 +653,16 @@ impl<'a> ConstantFolder<'a> { } match self.tree.as_mut().and_then(|t| t.find(&full_path)).map(|t| t.index()) { Some(idx) => self.recursive_lookup(idx, &field_name, true), - None => Err(self.error(format!("unknown typepath {}", full_path))), + None => Err(self.error(format!("unknown typepath {full_path}"))), } } (term, Follow::Unary(op)) => self.unary(term, op), (term, Follow::StaticField(field)) => { let Constant::Prefab(read_from) = term else { - return Err(self.error(format!("non typepath {} used with ::", term))) + return Err(self.error(format!("non typepath {term} used with ::"))) }; if !read_from.vars.is_empty() { - return Err(self.error(format!("non typepath {} used with ::", read_from))) + return Err(self.error(format!("non typepath {read_from} used with ::"))) } let Some(ref tree) = self.tree else { return Err(self.error("no type tree available")) @@ -674,10 +674,10 @@ impl<'a> ConstantFolder<'a> { }, (term, Follow::ProcReference(field)) => { let Constant::Prefab(read_from) = term else { - return Err(self.error(format!("non typepath {} used with ::", term))) + return Err(self.error(format!("non typepath {term} used with ::"))) }; if !read_from.vars.is_empty() { - return Err(self.error(format!("non typepath {} used with ::", read_from))) + return Err(self.error(format!("non typepath {read_from} used with ::"))) } let Some(ref tree) = self.tree else { return Err(self.error("no type tree available")) @@ -687,7 +687,7 @@ impl<'a> ConstantFolder<'a> { }; self.proc_ref_lookup(real_type.index(), &field) }, - (term, follow) => Err(self.error(format!("non-constant expression follower: {} {:?}", term, follow))), + (term, follow) => Err(self.error(format!("non-constant expression follower: {term} {follow:?}"))), } } @@ -761,7 +761,7 @@ impl<'a> ConstantFolder<'a> { (BinaryOp::NotEq, lhs, rhs) => Ok(Constant::from(lhs != rhs)), (BinaryOp::And, lhs, rhs) => Ok(if lhs.to_bool() { rhs } else { lhs }), (BinaryOp::Or, lhs, rhs) => Ok(if lhs.to_bool() { lhs } else { rhs }), - (op, lhs, rhs) => Err(self.error(format!("non-constant {:?}: {} {} {}", op, lhs, op, rhs))), + (op, lhs, rhs) => Err(self.error(format!("non-constant {op:?}: {lhs} {op} {rhs}"))), } } @@ -827,8 +827,7 @@ impl<'a> ConstantFolder<'a> { let current_file_path = self.context.unwrap(/* is_some checked above */).file_path(self.location.file); let Some(current_dir) = current_file_path.parent() else { return Err(self.error(format!( - "fexists() file has no parent: {:?}", - current_file_path + "fexists() file has no parent: {current_file_path:?}" ))); }; current_dir.join(passed_path).exists().into() @@ -837,7 +836,7 @@ impl<'a> ConstantFolder<'a> { } } // other functions are no-goes - _ => return Err(self.error(format!("non-constant function call: {}", ident))), + _ => return Err(self.error(format!("non-constant function call: {ident}"))), }, Term::Prefab(prefab) => Constant::Prefab(Box::new(self.prefab(*prefab)?)), Term::Ident(ident) => match ident.as_str() { @@ -857,7 +856,7 @@ impl<'a> ConstantFolder<'a> { if let Some(obj_tree) = &self.tree { let typeref = TypeRef::new(obj_tree, self.ty); let Some(parent_type) = typeref.parent_type() else { - return Err(self.error(format!("no parent type for {}", typeref))) + return Err(self.error(format!("no parent type for {typeref}"))) }; let pop = Pop::from(parent_type.path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect::()); Constant::Prefab(Box::new(pop)) @@ -951,7 +950,7 @@ impl<'a> ConstantFolder<'a> { while let Some(ty) = idx { let location = self.location; if self.tree.is_none() { - return Err(self.error(format!("cannot reference variable {:?} in this context", ident))); + return Err(self.error(format!("cannot reference variable {ident:?} in this context"))); } let tree = self.tree.as_mut().unwrap(); match constant_ident_lookup(tree, ty, ident, must_be_const, self.context) @@ -961,14 +960,14 @@ impl<'a> ConstantFolder<'a> { ConstLookup::Continue(i) => idx = i, } } - Err(self.error(format!("unknown variable: {}", ident))) + Err(self.error(format!("unknown variable: {ident}"))) } fn proc_ref_lookup(&mut self, ty: NodeIndex, name: &str) -> Result { let tree = self.tree.as_mut().unwrap(); let proc_type = TypeRef::new(tree, ty); let Some(proc_ref) = proc_type.get_proc(name) else { - return Err(self.error(format!("unknown proc: {}", name))) + return Err(self.error(format!("unknown proc: {name}"))) }; // Gonna build the proc's path let mut path_elements: Vec = proc_type.get().path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect(); @@ -1032,15 +1031,15 @@ impl<'a> ConstantFolder<'a> { Some(2) => space = Some(ColorSpace::Hsl), Some(3) => space = Some(ColorSpace::Hcy), _ => { - return Err(self.error(format!("malformed rgb() call, bad color space: {}", kwarg_value))) + return Err(self.error(format!("malformed rgb() call, bad color space: {kwarg_value}"))) } } _ => { - return Err(self.error(format!("malformed rgb() call, bad kwarg passed: {}", kwarg))) + return Err(self.error(format!("malformed rgb() call, bad kwarg passed: {kwarg}"))) } } } else { - return Err(self.error(format!("malformed rgb() call, kwarg is not string: {}", value))); + return Err(self.error(format!("malformed rgb() call, kwarg is not string: {value}"))); } } } @@ -1112,11 +1111,11 @@ impl<'a> ConstantFolder<'a> { "a" | "alpha" => 0..=255, "space" => continue, // Don't range-check the value of the space _ => { - return Err(self.error(format!("malformed rgb() call, bad kwarg passed: {}", kwarg))) + return Err(self.error(format!("malformed rgb() call, bad kwarg passed: {kwarg}"))) } }; } else { - return Err(self.error(format!("malformed rgb() call, kwarg is not string: {}", value))); + return Err(self.error(format!("malformed rgb() call, kwarg is not string: {value}"))); } } diff --git a/crates/dreammaker/src/dmi.rs b/crates/dreammaker/src/dmi.rs index 61abaa8d..dcbce34a 100644 --- a/crates/dreammaker/src/dmi.rs +++ b/crates/dreammaker/src/dmi.rs @@ -408,7 +408,7 @@ fn parse_metadata(data: &str) -> io::Result { return Err( io::Error::new( io::ErrorKind::InvalidData, - format!("Wrong dmi metadata header. Expected {:?}, got {:?}", expected_header, header ) + format!("Wrong dmi metadata header. Expected {expected_header:?}, got {header:?}" ) ) ); } diff --git a/crates/dreammaker/src/indents.rs b/crates/dreammaker/src/indents.rs index 0028f4c2..06a0760e 100644 --- a/crates/dreammaker/src/indents.rs +++ b/crates/dreammaker/src/indents.rs @@ -117,8 +117,7 @@ impl<'ctx, I> IndentProcessor<'ctx, I> where // hope that truncating division will approximate // a sane situation. DMError::new(self.last_input_loc, format!( - "inconsistent indentation: {} % {} != 0", - spaces, spaces_per_indent, + "inconsistent indentation: {spaces} % {spaces_per_indent} != 0", )).register(self.context) } new_indents = spaces / spaces_per_indent; diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index c1553f8d..b96df3a3 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -178,8 +178,7 @@ fn make_speedy_table() { for each in everything.iter() { assert!( each.len() == 1 || everything.contains(&&each[..each.len() - 1]), - "no prefix: {}", - each + "no prefix: {each}" ); } @@ -191,7 +190,7 @@ fn make_speedy_table() { } if let Some(prev) = prev { - assert!(each > prev, "out-of-order: {:?} is not greater than {:?}", each, prev); + assert!(each > prev, "out-of-order: {each:?} is not greater than {prev:?}"); } prev = Some(each); @@ -204,7 +203,7 @@ fn make_speedy_table() { table[b].1 = i + 1; } else { assert!(i >= table[b].0); - assert_eq!(i, table[b].1, "{}", each); + assert_eq!(i, table[b].1, "{each}"); table[b].1 = i + 1; } } @@ -354,7 +353,7 @@ impl Token { match self { Token::Eof => Cow::Borrowed("EOF"), Token::Punct(p) => Cow::Borrowed(p.single_quoted()), - _ => Cow::Owned(format!("'{}'", self)), + _ => Cow::Owned(format!("'{self}'")), } } } @@ -367,10 +366,10 @@ impl fmt::Display for Token { Punct(p) => p.fmt(f), Ident(ref i, _) => f.write_str(i), String(ref i) => Quote(i).fmt(f), - InterpStringBegin(ref i) => write!(f, "\"{}[", i), - InterpStringPart(ref i) => write!(f, "]{}[", i), - InterpStringEnd(ref i) => write!(f, "]{}\"", i), - Resource(ref i) => write!(f, "'{}'", i), + InterpStringBegin(ref i) => write!(f, "\"{i}["), + InterpStringPart(ref i) => write!(f, "]{i}["), + InterpStringEnd(ref i) => write!(f, "]{i}\""), + Resource(ref i) => write!(f, "'{i}'"), Int(i) => FormatFloat(i as f32).fmt(f), Float(i) => FormatFloat(i).fmt(f), DocComment(ref c) => c.fmt(f), @@ -387,11 +386,11 @@ impl<'a> fmt::Display for Quote<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s = self.0; if s.contains("\"}") { - write!(f, "@@{}@", s) + write!(f, "@@{s}@") } else if s.contains('"') || s.contains('\n') { - write!(f, "{{\"{}\"}}", s) + write!(f, "{{\"{s}\"}}") } else { - write!(f, "\"{}\"", s) + write!(f, "\"{s}\"") } } } @@ -428,7 +427,7 @@ impl fmt::Display for FormatFloat { write!(f, "{:.*}e{:+04}", precision as usize, n2, exp) } else { let n2 = (n * factor).round() / factor; - write!(f, "{}", n2) + write!(f, "{n2}") } } } @@ -908,7 +907,7 @@ impl<'ctx> Lexer<'ctx> { if let Ok(val) = f32::from_str(&buf) { let val_str = val.to_string(); if val_str != buf { - self.error(format!("precision loss of integer constant: \"{}\" to {}", buf, val)) + self.error(format!("precision loss of integer constant: \"{buf}\" to {val}")) .set_severity(Severity::Warning) .with_errortype("integer_precision_loss") .register(self.context); @@ -917,7 +916,7 @@ impl<'ctx> Lexer<'ctx> { } } self.context.register_error(self.error( - format!("bad base-{} integer \"{}\": {}", radix, buf, original_error))); + format!("bad base-{radix} integer \"{buf}\": {original_error}"))); Token::Int(0) // fallback } else { // ignore radix @@ -925,7 +924,7 @@ impl<'ctx> Lexer<'ctx> { Ok(val) => Token::Float(val), Err(e) => { self.context.register_error(self.error( - format!("bad float \"{}\": {}", buf, e))); + format!("bad float \"{buf}\": {e}"))); Token::Float(0.0) // fallback } } @@ -1276,7 +1275,7 @@ impl<'ctx> Iterator for Lexer<'ctx> { b'@' => Some(locate(self.read_raw_string())), _ => { if !found_illegal { - let mut msg = format!("illegal byte 0x{:x}", first); + let mut msg = format!("illegal byte 0x{first:x}"); if (b' '..=b'~').contains(&first) { use std::fmt::Write; let _ = write!(msg, " ({:?})", first as char); diff --git a/crates/dreammaker/src/lib.rs b/crates/dreammaker/src/lib.rs index ab506b5d..b893d941 100644 --- a/crates/dreammaker/src/lib.rs +++ b/crates/dreammaker/src/lib.rs @@ -95,7 +95,7 @@ pub fn pretty_print(w: &mut W, input: I, show_ws: bool) -> std::fmt::Resul let spaces = 2 * indents; writeln!(w)?; for _ in 0..(spaces / SPACES.len()) { - write!(w, "{}", SPACES)?; + write!(w, "{SPACES}")?; } write!(w, "{}", &SPACES[..spaces % SPACES.len()])?; needs_newline = false; @@ -104,7 +104,7 @@ pub fn pretty_print(w: &mut W, input: I, show_ws: bool) -> std::fmt::Resul write!(w, " ")?; } } - write!(w, "{}", other)?; + write!(w, "{other}")?; prev = Some(other); } } diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index 646a85fe..a4633b66 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -675,7 +675,7 @@ impl ObjectTree { pub fn expect(&self, path: &str) -> TypeRef { match self.types.get(path) { Some(&ix) => TypeRef::new(self, ix), - None => panic!("type not found: {:?}", path), + None => panic!("type not found: {path:?}"), } } @@ -837,7 +837,7 @@ impl ObjectTreeBuilder { if var.value.expression.is_some() { context.register_error(DMError::new( var.value.location, - format!("not allowed to change {}/parent_type", path), + format!("not allowed to change {path}/parent_type"), )); } } @@ -879,7 +879,7 @@ impl ObjectTreeBuilder { Ok(&empty_string) } else { // A weird situation which should not happen. - Err(DMError::new(location, format!("missing {}/parent_type", path))) + Err(DMError::new(location, format!("missing {path}/parent_type"))) }; match constant { @@ -895,7 +895,7 @@ impl ObjectTreeBuilder { parent_type = &parent_type_buf; } Ok(other) => { - context.register_error(DMError::new(location, format!("value of {}/parent_type must be a string or typepath, got {}", path, other))); + context.register_error(DMError::new(location, format!("value of {path}/parent_type must be a string or typepath, got {other}"))); } Err(e) => { context.register_error(e); @@ -913,7 +913,7 @@ impl ObjectTreeBuilder { } else { context.register_error(DMError::new( location, - format!("bad parent type for {}: {}", path, parent_type), + format!("bad parent type for {path}: {parent_type}"), )); NodeIndex::new(0) // on bad parent_type, fall back to the root } @@ -1273,7 +1273,7 @@ impl ObjectTreeBuilder { if let Some(other) = path.next() { return Err(DMError::new( location, - format!("proc name must be a single identifier (spurious {:?})", other), + format!("proc name must be a single identifier (spurious {other:?})"), )); } diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index a4c929ce..e91f8cbe 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -459,14 +459,14 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { fn describe_parse_error(&mut self) -> DMError { let expected = self.expected.join(", "); if self.eof { - let mut error = self.error(format!("got EOF, expected one of: {}", expected)); + let mut error = self.error(format!("got EOF, expected one of: {expected}")); if let Some(loc) = self.skipping_location { error.add_note(loc, "unmatched pair here"); } error } else { let got = self.peek(); - let message = format!("got '{:#}', expected one of: {}", got, expected); + let message = format!("got '{got:#}', expected one of: {expected}"); let mut error = self.error(message); if self.possible_indentation_error { let mut loc = error.location(); @@ -615,7 +615,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } fn exact_ident(&mut self, ident: &'static str) -> Status<()> { - self.expected(format!("'{}'", ident)); + self.expected(format!("'{ident}'")); take_match!(self { Token::Ident(i, _) if i == ident => SUCCESS, } else try_another()) @@ -734,7 +734,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { Token::Punct(p @ Punctuation::Dot) | Token::Punct(p @ Punctuation::CloseColon) | Token::Punct(p @ Punctuation::Colon) => { - self.error(format!("path started by '{}', should be unprefixed", p)) + self.error(format!("path started by '{p}', should be unprefixed")) .set_severity(Severity::Warning) .register(self.context); Ok((false, true)) @@ -750,7 +750,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { Token::Punct(p @ Punctuation::Dot) | Token::Punct(p @ Punctuation::CloseColon) | Token::Punct(p @ Punctuation::Colon) => { - self.error(format!("path separated by '{}', should be '/'", p)) + self.error(format!("path separated by '{p}', should be '/'")) .set_severity(Severity::Warning) .register(self.context); SUCCESS @@ -951,7 +951,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { .register(self.context); } else if let Some(mut var_type) = var_type.take() { if VarTypeFlags::from_name(last_part).is_some() { - self.error(format!("`var/{};` item has no effect", last_part)) + self.error(format!("`var/{last_part};` item has no effect")) .set_severity(Severity::Warning) .register(self.context); } else { @@ -1185,7 +1185,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { "".to_owned() } }; - if path.first().map_or(false, |i| i == "var") { + if path.first().is_some_and(|i| i == "var") { path.remove(0); DMError::new(leading_loc, "'var/' is unnecessary here") .set_severity(Severity::Hint) @@ -1310,7 +1310,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let mut as_what = match InputType::from_str(&ident) { Ok(what) => what, Err(()) => { - self.context.register_error(self.error(format!("bad input type: '{}'", ident))); + self.context.register_error(self.error(format!("bad input type: '{ident}'"))); InputType::empty() } }; @@ -1319,7 +1319,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { match InputType::from_str(&ident) { Ok(what) => as_what |= what, Err(()) => { - self.context.register_error(self.error(format!("bad input type: '{}'", ident))); + self.context.register_error(self.error(format!("bad input type: '{ident}'"))); } } } diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index d8c7cf3b..0917ae13 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -193,7 +193,7 @@ impl DefineMap { /// Returns true if the map contains a value for the specified key. pub fn contains_key(&self, key: &str) -> bool { - self.inner.get(key).map_or(false, |v| !v.is_empty()) + self.inner.get(key).is_some_and(|v| !v.is_empty()) } /// Returns a reference to the value corresponding to the key. @@ -649,7 +649,7 @@ impl<'ctx> Preprocessor<'ctx> { fn prepare_include_file(&mut self, path: PathBuf) -> Result, DMError> { // Attempt to open the file. let read = io::BufReader::new(File::open(&path).map_err(|e| - DMError::new(self.last_input_loc, format!("failed to open file: #include {:?}", path)) + DMError::new(self.last_input_loc, format!("failed to open file: #include {path:?}")) .with_cause(e))?); // Get the path relative to the environment root, for easy lookup later. @@ -660,7 +660,7 @@ impl<'ctx> Preprocessor<'ctx> { let file_id = self.context.register_file(register); if let Some(&loc) = self.include_locations.get(&file_id) { if !self.multiple_locations.contains_key(&file_id) { - Err(DMError::new(self.last_input_loc, format!("duplicate #include {:?}", path)) + Err(DMError::new(self.last_input_loc, format!("duplicate #include {path:?}")) .set_severity(Severity::Warning) .with_note(loc, "previously included here") .with_errortype("duplicate_include")) @@ -684,8 +684,8 @@ impl<'ctx> Preprocessor<'ctx> { fn check_danger_ident(&mut self, name: &str, kind: &str) { if let Some(loc) = self.danger_idents.get(name) { self.context.register_error(DMError::new(*loc, format!( - "macro {:?} used immediately before being {}:\n\ - https://www.byond.com/forum/?post=2072419", name, kind + "macro {name:?} used immediately before being {kind}:\n\ + https://www.byond.com/forum/?post=2072419" )).set_severity(Severity::Warning)); } } @@ -803,7 +803,7 @@ impl<'ctx> Preprocessor<'ctx> { Some(ext) => { self.context.register_error(DMError::new( self.last_input_loc, - format!("unknown extension {:?}", ext), + format!("unknown extension {ext:?}"), )); return Ok(()); } @@ -838,7 +838,7 @@ impl<'ctx> Preprocessor<'ctx> { return Ok(()); } - self.context.register_error(DMError::new(self.last_input_loc, format!("failed to find #include {:?}", path))); + self.context.register_error(DMError::new(self.last_input_loc, format!("failed to find #include {path:?}"))); return Ok(()); } // both constant and function defines @@ -943,9 +943,9 @@ impl<'ctx> Preprocessor<'ctx> { // DM doesn't issue a warning for this, but it's usually a mistake, so let's. // FILE_DIR is handled specially and sometimes makes sense to define multiple times. if define_name != "FILE_DIR" { - DMError::new(define_name_loc, format!("macro redefined: {}", define_name)) + DMError::new(define_name_loc, format!("macro redefined: {define_name}")) .set_severity(Severity::Warning) - .with_note(previous_loc, format!("previous definition of {}", define_name)) + .with_note(previous_loc, format!("previous definition of {define_name}")) .with_errortype("macro_redefined") .register(self.context); } @@ -961,7 +961,7 @@ impl<'ctx> Preprocessor<'ctx> { if let Some(previous) = self.defines.remove(&define_name) { self.move_to_history(define_name, previous); } else { - DMError::new(define_name_loc, format!("macro undefined while not defined: {}", define_name)) + DMError::new(define_name_loc, format!("macro undefined while not defined: {define_name}")) .with_errortype("macro_undefined_no_definition") .set_severity(Severity::Warning) .register(self.context); @@ -1046,8 +1046,7 @@ impl<'ctx> Preprocessor<'ctx> { // if it's a define, perform the substitution let mut expansion = self.defines.get(ident).cloned(); // TODO: don't clone? if expansion.is_some() && self.include_stack.stack.len() > MAX_RECURSION_DEPTH { - self.error(format!("expanding {:?} would exceed max recursion depth of {} levels", - ident, MAX_RECURSION_DEPTH)).register(self.context); + self.error(format!("expanding {ident:?} would exceed max recursion depth of {MAX_RECURSION_DEPTH} levels")).register(self.context); expansion = None; } @@ -1139,13 +1138,13 @@ impl<'ctx> Preprocessor<'ctx> { match arg.next() { Some(Token::Ident(param_ident, ws)) => { expansion.push_back(Token::Ident( - format!("{}{}", first, param_ident), + format!("{first}{param_ident}"), ws, )); } Some(Token::Int(param_int)) => { expansion.push_back(Token::Ident( - format!("{}{}", first, param_int), + format!("{first}{param_int}"), ws, )) } @@ -1157,7 +1156,7 @@ impl<'ctx> Preprocessor<'ctx> { } expansion.extend(arg); } - None => expansion.push_back(Token::Ident(format!("{}{}", first, param_name), ws)), + None => expansion.push_back(Token::Ident(format!("{first}{param_name}"), ws)), } } (non_ident_first, Some(Token::Ident(second, ws))) => { @@ -1185,16 +1184,16 @@ impl<'ctx> Preprocessor<'ctx> { if !string.is_empty() { string.push(' '); } - let _e = write!(string, "{}", each); + let _e = write!(string, "{each}"); #[cfg(debug_assertions)] { _e.unwrap(); } } expansion.push_back(Token::String(string)); } - None => return Err(DMError::new(self.last_input_loc, format!("can't stringify non-argument ident {:?}", argname))), + None => return Err(DMError::new(self.last_input_loc, format!("can't stringify non-argument ident {argname:?}"))), } - Some(tok) => return Err(DMError::new(self.last_input_loc, format!("can't stringify non-ident '{}'", tok))), + Some(tok) => return Err(DMError::new(self.last_input_loc, format!("can't stringify non-ident '{tok}'"))), None => return Err(DMError::new(self.last_input_loc, "can't stringify EOF")), } } diff --git a/crates/dreammaker/tests/annotation_tests.rs b/crates/dreammaker/tests/annotation_tests.rs index 4757f44f..7d0685a7 100644 --- a/crates/dreammaker/tests/annotation_tests.rs +++ b/crates/dreammaker/tests/annotation_tests.rs @@ -33,7 +33,7 @@ fn annotation_basic() { line: 9, column: 14, }) { - println!("{:?}", each); + println!("{each:?}"); for each in annotations.get_range_raw(each.0) { println!(" {:?}", each.1); } diff --git a/crates/dreammaker/tests/ast_tests.rs b/crates/dreammaker/tests/ast_tests.rs index ac582d63..a5e86a63 100644 --- a/crates/dreammaker/tests/ast_tests.rs +++ b/crates/dreammaker/tests/ast_tests.rs @@ -72,7 +72,7 @@ var/global/bill = 1 // Check for errors let mut sum_errors: Vec = vec![]; for error in errors.iter() { - sum_errors.push(format!("{}", error)); + sum_errors.push(format!("{error}")); } if !sum_errors.is_empty() { panic!("\n{}", sum_errors.join("\n").as_str()); diff --git a/crates/dreammaker/tests/lexer_tests.rs b/crates/dreammaker/tests/lexer_tests.rs index 98fbd65c..7566ef7c 100644 --- a/crates/dreammaker/tests/lexer_tests.rs +++ b/crates/dreammaker/tests/lexer_tests.rs @@ -15,7 +15,7 @@ fn lex(f: &str) -> Vec { fn one_token(f: &str) -> Token { let mut v = lex(f); - assert_eq!(v.len(), 2, "not one token: {:?} -> {:?}", f, v); + assert_eq!(v.len(), 2, "not one token: {f:?} -> {v:?}"); assert_eq!(v[1], Punct(Newline)); v.remove(0) } @@ -23,7 +23,7 @@ fn one_token(f: &str) -> Token { fn float(f: &str) -> f32 { match one_token(f) { Token::Float(f) => f, - other => panic!("{:?}: expected float, got {:?}", f, other), + other => panic!("{f:?}: expected float, got {other:?}"), } } diff --git a/crates/dreammaker/tests/location_tests.rs b/crates/dreammaker/tests/location_tests.rs index a1ce2e0a..08110080 100644 --- a/crates/dreammaker/tests/location_tests.rs +++ b/crates/dreammaker/tests/location_tests.rs @@ -31,7 +31,7 @@ fn simple_location_test() { let reconstructed = reconstruct(&located_tokens, false); if reconstructed.trim() != code { - println!("{}", reconstructed); + println!("{reconstructed}"); panic!("Some lines differed"); } @@ -42,7 +42,7 @@ fn simple_location_test() { println!("{}:{}: {:?}", token.location.line, token.location.column, token.token); } let reconstructed = reconstruct(&indented_tokens, true); - println!("{}", reconstructed); + println!("{reconstructed}"); } fn reconstruct(tokens: &[LocatedToken], iffy: bool) -> String { diff --git a/crates/interval-tree/src/iterators.rs b/crates/interval-tree/src/iterators.rs index d79a9732..2e6c74f9 100644 --- a/crates/interval-tree/src/iterators.rs +++ b/crates/interval-tree/src/iterators.rs @@ -154,10 +154,7 @@ impl Iterator for IntoIter { } if self.current.is_none() { - let mut node = match self.stack.pop() { - Some(node) => node, - None => return None, - }; + let mut node = self.stack.pop()?; self.push_node(node.right.take()); self.current = Some((node.key, node.data.into_iter())); } @@ -178,7 +175,7 @@ fn test_iterators() { let iter = RangePairIter::new(&tree, Bound::Included(0), Bound::Included(1000)); for (k, v) in iter { - println!("{:?} {}", k, v); + println!("{k:?} {v}"); } let mut iter = RangePairIter::new(&tree, Bound::Included(0), Bound::Included(1000)); diff --git a/crates/interval-tree/src/node.rs b/crates/interval-tree/src/node.rs index ecba21ef..d3c34577 100644 --- a/crates/interval-tree/src/node.rs +++ b/crates/interval-tree/src/node.rs @@ -282,10 +282,10 @@ pub mod tests { t } fn is_sorted_left(node: &Node) -> bool { - node.left.as_ref().map_or(true, |succ| succ.key < node.key) + node.left.as_ref().is_none_or(|succ| succ.key < node.key) } fn is_sorted_right(node: &Node) -> bool { - node.right.as_ref().map_or(true, |succ| succ.key > node.key) + node.right.as_ref().is_none_or(|succ| succ.key > node.key) } fn is_interval_node(node: &Node) -> bool { let sorted = is_sorted_left(node) && is_sorted_right(node); @@ -299,7 +299,7 @@ pub mod tests { } pub fn is_interval_tree(root: &Option>>) -> bool { - (*root).as_ref().map_or(true, |n| is_interval_node(n)) + (*root).as_ref().is_none_or(|n| is_interval_node(n)) } #[test] @@ -424,7 +424,7 @@ pub mod tests { fn test_min_after() { let t = simple_tree(50); for old_key in 0..55 { - println!("trying value: {}", old_key); + println!("trying value: {old_key}"); match min_after(&RangeInclusive::new(old_key, old_key), &t) { Some((k, _d)) => assert_eq!(k, &(RangeInclusive::new(old_key + 1, old_key + 1))), None => assert!(old_key >= 50), diff --git a/crates/interval-tree/src/tests.rs b/crates/interval-tree/src/tests.rs index 02848c1d..aece4772 100644 --- a/crates/interval-tree/src/tests.rs +++ b/crates/interval-tree/src/tests.rs @@ -88,7 +88,7 @@ fn test_iter() { t.insert(RangeInclusive::new(38, 38), 1340); for (i, pair) in t.iter().enumerate() { let (k, v) = pair; - println!("{:?}, {}", k, v); + println!("{k:?}, {v}"); let key = (i as u64) * 2 + 32; assert_eq!(k, RangeInclusive::new(key, key)); assert_eq!(v, &((i as i32) + 1337)); @@ -104,7 +104,7 @@ fn test_range_iter() { t.insert(RangeInclusive::new(38, 38), 1340); for (i, pair) in t.range(RangeInclusive::new(34, 36)).enumerate() { let (k, v) = pair; - println!("{:?}, {}", k, v); + println!("{k:?}, {v}"); let key = (i as u64) * 2 + 34; assert_eq!(k, RangeInclusive::new(key, key)); assert_eq!(v, &((i as i32) + 1338)); From 8ef9761b8ef2a452da99bcbd0e8e4f9b76a923b6 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 26 Jun 2025 19:04:10 -0700 Subject: [PATCH 167/197] Fix clippy lint about unnecessary boxing --- crates/dreammaker/src/parser.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index e91f8cbe..e024881d 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -1434,7 +1434,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // for(var/a = 1 to require!(self.exact_ident("to")); let rhs = require!(self.expression()); - return spanned(require!(self.for_range(Some(vs.var_type), vs.name, Box::new(value), Box::new(rhs)))); + return spanned(require!(self.for_range(Some(vs.var_type), vs.name, value, rhs))); } }, Statement::Expr(Expression::AssignOp { @@ -1449,7 +1449,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { }; require!(self.exact_ident("to")); let to_rhs = require!(self.expression()); - return spanned(require!(self.for_range(None, name, rhs, Box::new(to_rhs)))); + return spanned(require!(self.for_range(None, name, *rhs, to_rhs))); } Statement::Expr(Expression::BinaryOp { op: BinaryOp::In, @@ -1462,7 +1462,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { }; match *rhs { Expression::BinaryOp { op: BinaryOp::To, lhs, rhs } => { - return spanned(require!(self.for_range(None, name, lhs, rhs))); + return spanned(require!(self.for_range(None, name, *lhs, *rhs))); }, rhs => { // I love code duplication, don't you? @@ -1495,7 +1495,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let value = require!(self.expression()); if let Some(()) = self.exact_ident("to")? { let rhs = require!(self.expression()); - return spanned(require!(self.for_range(var_type, name, Box::new(value), Box::new(rhs)))); + return spanned(require!(self.for_range(var_type, name, value, rhs))); } Some(value) } else { @@ -1761,8 +1761,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { &mut self, var_type: Option, name: Ident, - start: Box, - end: Box, + start: Expression, + end: Expression, ) -> Status { // step 2 let step = if let Some(()) = self.exact_ident("step")? { @@ -1776,8 +1776,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { success(Statement::ForRange(Box::new(ForRangeStatement { var_type, name: name.into(), - start: *start, - end: *end, + start, + end, step, block: require!(self.block(&LoopContext::ForRange)), }))) From 5a96f6bc2212161de04dd6072cde0718ae8ce605 Mon Sep 17 00:00:00 2001 From: Lucy Date: Fri, 27 Jun 2025 00:32:53 -0400 Subject: [PATCH 168/197] Add support for `call_ext(LoadedFunc)` syntax (#433) This adds support for 516's `call_ext(LoadedFunc)` syntax (allowing either one or two args to `call_ext`). The `call_ext_missing_arg` test is removed as a result, as `call_ext` with a single arg is now valid syntax. --- crates/dm-langserver/src/find_references.rs | 8 ++- crates/dreamchecker/src/lib.rs | 8 ++- crates/dreamchecker/tests/call_ext_tests.rs | 13 ---- crates/dreammaker/src/ast.rs | 4 +- crates/dreammaker/src/parser.rs | 29 ++++++--- crates/dreammaker/tests/expression_tests.rs | 70 ++++++++++++++++++++- 6 files changed, 101 insertions(+), 31 deletions(-) diff --git a/crates/dm-langserver/src/find_references.rs b/crates/dm-langserver/src/find_references.rs index 075a554a..46b8ee94 100644 --- a/crates/dm-langserver/src/find_references.rs +++ b/crates/dm-langserver/src/find_references.rs @@ -519,9 +519,11 @@ impl<'o> WalkProc<'o> { self.visit_arguments(location, args_2); StaticType::None }, - Term::ExternalCall { library_name, function_name, args } => { - self.visit_expression(location, library_name, None); - self.visit_expression(location, function_name, None); + Term::ExternalCall { library, function, args } => { + if let Some(library) = library { + self.visit_expression(location, library, None); + } + self.visit_expression(location, function, None); self.visit_arguments(location, args); StaticType::None }, diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 3cb6d8e6..accec807 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -1935,9 +1935,11 @@ impl<'o, 's> AnalyzeProc<'o, 's> { self.visit_arguments(location, rhs_args, local_vars); Analysis::empty() // TODO }, - Term::ExternalCall { library_name, function_name, args } => { - self.visit_expression(location, library_name, None, local_vars); - self.visit_expression(location, function_name, None, local_vars); + Term::ExternalCall { library, function, args } => { + if let Some(library) = library { + self.visit_expression(location, library, None, local_vars); + } + self.visit_expression(location, function, None, local_vars); self.visit_arguments(location, args, local_vars); Analysis::empty() // TODO }, diff --git a/crates/dreamchecker/tests/call_ext_tests.rs b/crates/dreamchecker/tests/call_ext_tests.rs index 2dbf083f..13ed9fc9 100644 --- a/crates/dreamchecker/tests/call_ext_tests.rs +++ b/crates/dreamchecker/tests/call_ext_tests.rs @@ -2,19 +2,6 @@ extern crate dreamchecker as dc; use dc::test_helpers::*; -pub const CALL_EXT_MISSING_ARG_ERRORS: &[(u32, u16, &str)] = &[ - (2, 15, "got ')', expected one of: operator, field access, ','"), -]; - -#[test] -fn call_ext_missing_arg() { - let code = r##" -/proc/f() - call_ext(1)(3, 4, 5) -"##.trim(); - check_errors_match(code, CALL_EXT_MISSING_ARG_ERRORS); -} - pub const CALL_EXT_MISSING_CALL_ERRORS: &[(u32, u16, &str)] = &[ (2, 19, "got ';', expected one of: '('"), ]; diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index f10fd4ea..e9fd46f7 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -1071,8 +1071,8 @@ pub enum Term { DynamicCall(Box<[Expression]>, Box<[Expression]>), /// A use of the `call_ext()()` primitive. ExternalCall { - library_name: Box, - function_name: Box, + library: Option>, + function: Box, args: Box<[Expression]>, }, /// Unscoped `::A` is a shorthand for `global.A` diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index e024881d..9d2128ce 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -2146,18 +2146,31 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { require!(self.arguments(&[], "call*")), ), - // term :: 'call_ext' (library_name, function_name) arglist + // term :: 'call_ext' ([library,] function) arglist Token::Ident(ref i, _) if i == "call_ext" => { require!(self.exact(Token::Punct(Punctuation::LParen))); - let library_name = require!(self.expression()); - require!(self.exact(Token::Punct(Punctuation::Comma))); - let function_name = require!(self.expression()); + let first = require!(self.expression()); + let second = if self.exact(Token::Punct(Punctuation::Comma))?.is_some() { + Some(require!(self.expression())) + } else { + None + }; require!(self.exact(Token::Punct(Punctuation::RParen))); - Term::ExternalCall { - library_name: Box::new(library_name), - function_name: Box::new(function_name), - args: require!(self.arguments(&[], "call_ext*")), + let args = require!(self.arguments(&[], "call_ext*")); + match second { + // call_ext(library, function)(...) + Some(function) => Term::ExternalCall { + library: Some(Box::new(first)), + function: Box::new(function), + args, + }, + // call_ext(loaded_func)(...) + None => Term::ExternalCall { + library: None, + function: Box::new(first), + args, + } } }, diff --git a/crates/dreammaker/tests/expression_tests.rs b/crates/dreammaker/tests/expression_tests.rs index 440dd65d..0fe05ecf 100644 --- a/crates/dreammaker/tests/expression_tests.rs +++ b/crates/dreammaker/tests/expression_tests.rs @@ -7,7 +7,8 @@ use dm::parser::*; fn parse_expr(f: &str) -> Expression { let context = Default::default(); let lexer = Lexer::new(&context, Default::default(), f.as_bytes()); - let result = parse_expression(&context, Default::default(), lexer).expect("failed to parse expression"); + let result = + parse_expression(&context, Default::default(), lexer).expect("failed to parse expression"); context.assert_success(); result } @@ -124,7 +125,72 @@ fn pointer_ops() { follow: vec![ Spanned::new(Default::default(), Follow::Unary(UnaryOp::Reference)), Spanned::new(Default::default(), Follow::Unary(UnaryOp::Dereference)), - ].into_boxed_slice(), + ] + .into_boxed_slice(), + } + ) +} + +#[test] +fn call_ext() { + assert_eq!( + parse_expr("call_ext(\"cat.dll\", \"meow\")(1, 2, 3)"), + Expression::Base { + term: Box::new(Spanned::new( + Default::default(), + Term::ExternalCall { + library: Some(Box::new(Expression::from(Term::String( + "cat.dll".to_owned() + )))), + function: Box::new(Expression::from(Term::String("meow".to_owned()))), + args: Box::new([ + Expression::Base { + term: Box::new(Spanned::new(Default::default(), Term::Int(1))), + follow: Box::new([]) + }, + Expression::Base { + term: Box::new(Spanned::new(Default::default(), Term::Int(2))), + follow: Box::new([]) + }, + Expression::Base { + term: Box::new(Spanned::new(Default::default(), Term::Int(3))), + follow: Box::new([]) + } + ]) + } + )), + follow: Box::new([]), + } + ) +} + +#[test] +fn loaded_call_ext() { + assert_eq!( + parse_expr("call_ext(loaded_cat_meow)(1, 2, 3)"), + Expression::Base { + term: Box::new(Spanned::new( + Default::default(), + Term::ExternalCall { + library: None, + function: Box::new(Expression::from(Term::Ident("loaded_cat_meow".to_owned()))), + args: Box::new([ + Expression::Base { + term: Box::new(Spanned::new(Default::default(), Term::Int(1))), + follow: Box::new([]) + }, + Expression::Base { + term: Box::new(Spanned::new(Default::default(), Term::Int(2))), + follow: Box::new([]) + }, + Expression::Base { + term: Box::new(Spanned::new(Default::default(), Term::Int(3))), + follow: Box::new([]) + } + ]) + } + )), + follow: Box::new([]), } ) } From e2c596a99b71d44644c000ea0da3c2f0f3fd0b99 Mon Sep 17 00:00:00 2001 From: Zonespace <41448081+Zonespace27@users.noreply.github.com> Date: Sat, 12 Jul 2025 20:56:08 +0200 Subject: [PATCH 169/197] Fix filter() not taking `name` as a kwarg (#436) This fixes an issue where the "name" kwarg was erroring (see screenshot) when filter() was called, despite being valid & correct DM. ![](https://github.com/user-attachments/assets/076f7048-d30f-4561-b768-9ac05f2d3b05) Fixes #430. --- crates/dreamchecker/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index accec807..ccbb39ac 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -2462,7 +2462,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { return Analysis::empty() }; for arg in param_name_map.keys() { - if *arg != "type" && !arglist.contains(arg) { + if *arg != "type" && *arg != "name" && !arglist.contains(arg) { error(location, format!("filter(type=\"{typevalue}\") called with invalid keyword parameter '{arg}'")) .with_filter_args(location, typevalue) .register(self.context); From 936a5ee5a0d74d17b1c59353d0c5b439875f4314 Mon Sep 17 00:00:00 2001 From: "Anthony \"Shifty Rail" <31417754+ShiftyRail@users.noreply.github.com> Date: Sat, 19 Jul 2025 04:10:15 +0100 Subject: [PATCH 170/197] Add basic support for `for (var/k, v in X)` syntax (#431) This adds a new arm to the parser for the `for (var/k, v in X)` dict-like syntax that was added in 516. I have hijacked the arm that checks for this type of expressions : `for (init, test, inc)` or `for (init; test; inc)` I have seperated it between `init; test; inc` (left untouched) and `init, test, inc`. If `inc` is not None, I then check if `test` in a `BinaryOp::In` (something like `for(init, [x in y])`. If not I just assume it's a `for (init, test)` which is valid DM syntax. I then check if `init` is a `var/k` type of statement, using copypaste. DM will not compile `for (k, v)` nor will it compile `for (var/k, var/v)`. I check if v is an ident. If we're all good, I create a new type of structure `ForKeyValueStatement` and the lib.rs / findreferences.rs knows what to do with it. Both `for (i = 0, i < 10, i++)`, `for (i = 0, i < 10)` still pass. --- crates/dm-langserver/src/find_references.rs | 18 ++++ crates/dreamchecker/src/lib.rs | 49 +++++++++++ .../dreamchecker/tests/branch_eval_tests.rs | 60 +++++++++++++ crates/dreammaker/src/ast.rs | 11 +++ crates/dreammaker/src/parser.rs | 87 +++++++++++++++++-- 5 files changed, 220 insertions(+), 5 deletions(-) diff --git a/crates/dm-langserver/src/find_references.rs b/crates/dm-langserver/src/find_references.rs index 46b8ee94..31857839 100644 --- a/crates/dm-langserver/src/find_references.rs +++ b/crates/dm-langserver/src/find_references.rs @@ -326,6 +326,24 @@ impl<'o> WalkProc<'o> { Statement::Crash(_) => {}, Statement::Label { name: _, block } => self.visit_block(block), Statement::Del(expr) => { self.visit_expression(location, expr, None); }, + Statement::ForKeyValue(for_key_value) => { + let ForKeyValueStatement { var_type, key, value, in_list, block } = &**for_key_value; + if let Some(in_list) = in_list { + self.visit_expression(location, in_list, None); + } + if let Some(var_type) = var_type { + self.visit_var(location, var_type, key, None); + } + // the "v" in a DM for (var/k, v) statement is essentially typeless. + // There is currently no way to change that. + let var_type_value = VarType { + flags: VarTypeFlags::from_bits_truncate(0), + type_path: Box::new([]), + input_type: InputType::from_bits_truncate(0), + }; + self.visit_var(location, &var_type_value, value, None); + self.visit_block(block); + }, } } diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index ccbb39ac..22cc94ee 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -1575,6 +1575,55 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Statement::Goto(_) => {}, Statement::Label { name: _, block } => { self.visit_block(block, &mut local_vars.clone(), false); }, Statement::Del(expr) => { self.visit_expression(location, expr, None, local_vars); }, + Statement::ForKeyValue(for_key_value) => { + let ForKeyValueStatement { var_type, key, value, in_list, block } = &**for_key_value; + let mut scoped_locals = local_vars.clone(); + if let Some(in_list) = in_list { + let list = self.visit_expression(location, in_list, None, &mut scoped_locals); + match list.static_ty { + StaticType::None => { + // Occurs extremely often due to DM not complaining about this, with + // over 800 detections on /tg/. Maybe a future lint. + } + StaticType::List { .. } => {/* OK */} + StaticType::Type(ty) => { + if ty != self.objtree.expect("/world") && ty != self.objtree.expect("/list") && ty != self.objtree.expect("/alist") { + let atom = self.objtree.expect("/atom"); + if ty.is_subtype_of(&atom) { + // Fine. + } else if atom.is_subtype_of(&ty) { + // Iffy conceptually, but the only detections on /tg/ are false positives in the + // component system, where we loop over `var/datum/parent` that is known to be an + // atom in a way that's hard for Dreamchecker to capture. + error(location, "iterating over a /datum which might not be an /atom") + .set_severity(Severity::Hint) + .register(self.context); + } else { + // The type is a /datum/foo subtype that definitely can't be looped over. + error(location, format!("iterating over a {} which cannot be iterated", ty.path)) + .register(self.context); + } + } + } + } + } + // This quite ugly but DM doesn't let you do for (var/k, var/v) + // only the type of the key is taken into account + if let Some(var_type) = var_type { + self.visit_var(location, var_type, key, None, &mut scoped_locals); + } + // the "v" in a DM for (var/k, v) statement is essentially typeless. + // There is currently no way to change that. + let var_type_value = VarType { + flags: VarTypeFlags::default(), + type_path: Box::new([]), + input_type: InputType::default(), + }; + self.visit_var(location, &var_type_value, value, None, &mut scoped_locals); + let mut state = self.visit_block(block, &mut scoped_locals, false); + state.end_loop(); + return state + } } ControlFlow::allfalse() } diff --git a/crates/dreamchecker/tests/branch_eval_tests.rs b/crates/dreamchecker/tests/branch_eval_tests.rs index b0c50f32..4268dfaf 100644 --- a/crates/dreamchecker/tests/branch_eval_tests.rs +++ b/crates/dreamchecker/tests/branch_eval_tests.rs @@ -94,3 +94,63 @@ fn for_loop_condition() { "##.trim(); check_errors_match(code, FOR_LOOP_CONDITION_ERRORS); } + +#[test] +fn for_kv_check() { + let code = r##" +/proc/test() + var/alist/A = alist() + for (var/k, v in A) + world.log << k + world.log << v + +"##.trim(); + check_errors_match(code, NO_ERRORS); +} + +pub const FOR_KV_VAR_ERROR: &[(u32, u16, &str)] = &[ + (3, 19, "for (var/key, value) requires a 'var' keyword"), +]; + +#[test] +fn for_kv_var_check() { + let code = r##" +/proc/test() + var/alist/A = alist() + for (k, v in A) + world.log << k + world.log << v + +"##.trim(); + check_errors_match(code, FOR_KV_VAR_ERROR); +} + +pub const FOR_KV_VALUE_ERROR: &[(u32, u16, &str)] = &[ + (3, 23, "value must be a variable in a for (var/key, value) statement"), +]; + +#[test] +fn for_kv_value_check() { + let code = r##" +/proc/test() + var/alist/A = alist() + for (var/k, 0 in A) + world.log << k +"##.trim(); + check_errors_match(code, FOR_KV_VALUE_ERROR); +} + +pub const FOR_KV_KEY_ERROR: &[(u32, u16, &str)] = &[ + (3, 27, "cannot assigned a value to var/key in a for(var/key, value) statement"), +]; + +#[test] +fn for_kv_key_check() { + let code = r##" +/proc/test() + var/alist/A = alist() + for (var/k = 5, v in A) + world.log << k +"##.trim(); + check_errors_match(code, FOR_KV_KEY_ERROR); +} diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index e9fd46f7..6c336826 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -1392,6 +1392,7 @@ pub enum Statement { block: Block, }, ForList(Box), + ForKeyValue(Box), ForRange(Box), Var(Box), Vars(Vec), @@ -1449,6 +1450,16 @@ pub struct ForListStatement { pub block: Block, } +#[derive(Debug, Clone, PartialEq, GetSize)] +pub struct ForKeyValueStatement { + pub var_type: Option, + pub key: Ident2, + pub value: Ident2, + /// Defaults to 'world'. + pub in_list: Option, + pub block: Block, +} + #[derive(Debug, Clone, PartialEq, GetSize)] pub struct ForRangeStatement { pub var_type: Option, diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 9d2128ce..190990a7 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -1410,10 +1410,11 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // for (Var = Low to High) require!(self.exact(Token::Punct(Punctuation::LParen))); let init = self.simple_statement(true, vars)?; - if let Some(()) = self.comma_or_semicolon()? { - // three-pronged loop form ("for loop") + // three-pronged loop form ("for loop") + if let Some(()) = self.semicolon()? { + // for(init; test; [inc]) let test = self.expression()?; - let inc = match self.comma_or_semicolon()? { + let inc = match self.semicolon()? { Some(()) => self.simple_statement(false, vars)?, None => None, }; @@ -1424,6 +1425,76 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { inc: inc.map(Box::new), block: require!(self.block(&LoopContext::ForLoop)), }) + // ... copypasted but with commas + } else if let Some(()) = self.comma()? { + // for(init, test [, inc]) + let test = self.expression()?; + let inc = match self.comma()? { + Some(()) => self.simple_statement(false, vars)?, + None => None, + }; + // Increment exists + if inc.is_some() { + require!(self.exact(Token::Punct(Punctuation::RParen))); + spanned(Statement::ForLoop { + init: init.map(Box::new), + test: test.map(Box::new), + inc: inc.map(Box::new), + block: require!(self.block(&LoopContext::ForLoop)), + }) + } else { + // for (..., ... in ...) + match test { + // This should necessarily be caught because the expression is going be + //for(var/k, [v in x]) and [v in x] will be passed as BinaryOp::In + // This is a bit ugly but it workss + Some(Expression::BinaryOp { + op: BinaryOp::In, + lhs, + rhs, + }) => { + // First thing first: for (var/k, v in x) REQUIRES the var/k. + // This unboxes it and rejects other type for(x, [...]), for(0, [...]) + let (var_type, key) = match init { + // this is a really terrible way to do this + Some(Statement::Var(var_statement)) => match var_statement.value { + None => (Some(var_statement.var_type), var_statement.name), + _ => return Err(self.error("cannot assigned a value to var/key in a for(var/key, value) statement")), + }, + _ => return Err(self.error("for (var/key, value) requires a 'var' keyword")), + }; + // Value is the lhs of for(var, k [v in x]) + // It should also pass only if it's an ident + let value = match lhs.into_term() { + Some(Term::Ident(value)) => value, + _ => return Err(self.error( + "value must be a variable in a for (var/key, value) statement", + )), + }; + // TODO : check if `x` is an ident/a "list()" or "alist()" statement ? + require!(self.exact(Token::Punct(Punctuation::RParen))); + // Returns a for(k,v) + spanned(Statement::ForKeyValue(Box::new(ForKeyValueStatement { + var_type: Some(var_type.expect("/")), + key: key.into(), + value: value.into(), + in_list: Some(*rhs), // We'll assume the rhs of [v in x] is a list. Any other case, DM will catch anyway. + block: require!(self.block(&LoopContext::ForLoop)), + }))) + } + // We will just assume everything else for(k, [...]) is a two-pronged for loop + // for (init, test) {...} + _ => { + require!(self.exact(Token::Punct(Punctuation::RParen))); + spanned(Statement::ForLoop { + init: init.map(Box::new), + test: test.map(Box::new), + inc: inc.map(Box::new), + block: require!(self.block(&LoopContext::ForLoop)), + }) + } + } + } } else if let Some(init) = init { // in-list form ("for list") let (var_type, name) = match init { @@ -1783,10 +1854,16 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { }))) } - fn comma_or_semicolon(&mut self) -> Status<()> { + fn comma(&mut self) -> Status<()> { if let Some(()) = self.exact(Token::Punct(Punctuation::Comma))? { SUCCESS - } else if let Some(()) = self.exact(Token::Punct(Punctuation::Semicolon))? { + } else { + Ok(None) + } + } + + fn semicolon(&mut self) -> Status<()> { + if let Some(()) = self.exact(Token::Punct(Punctuation::Semicolon))? { SUCCESS } else { Ok(None) From 442845ff4890d6c617eba8c85f2c3c1a7a05f996 Mon Sep 17 00:00:00 2001 From: Joshua Kidder <49173900+Metekillot@users.noreply.github.com> Date: Wed, 23 Jul 2025 02:11:21 -0400 Subject: [PATCH 171/197] Add a body_range field to ProcValue (#438) I wasn't able to find a concise way to reference the range and/or contents of proc bodies without also needing to reference the Annotation tree. I haven't implemented any use case for the added information outside of some experiments I'm doing with the deeper analysis companion; I think it could be useful for determining return values and types without the need for SpacemanDMM directives, at a later point. It's an Option to account for built-ins not having any actual presence in the syntax tree. --- crates/dreammaker/src/objtree.rs | 16 ++++++++++++++-- crates/dreammaker/src/parser.rs | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index a4633b66..7a9a1f60 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -2,6 +2,8 @@ use std::collections::BTreeMap; use std::fmt; +use std::ops::Range; +use std::mem::size_of; use get_size::GetSize; use get_size_derive::GetSize; @@ -91,12 +93,18 @@ pub struct ProcDeclaration { pub id: SymbolId, } +fn heap_size_of_location_range(_range: &Option>) -> usize { + size_of::>() +} + #[derive(Debug, Clone, GetSize)] pub struct ProcValue { pub location: Location, pub parameters: Box<[Parameter]>, pub docs: DocCollection, pub code: Option, + #[get_size(size_fn = heap_size_of_location_range)] + pub body_range: Option>, } #[derive(Debug, Clone, Default, GetSize)] @@ -1126,6 +1134,7 @@ impl ObjectTreeBuilder { parameters: Vec, return_type: ProcReturnType, code: Option, + body_range: Option>, ) -> Result<(usize, &mut ProcValue), DMError> { let node = &mut self.inner.graph[parent.index()]; let proc = node.procs.entry(name.to_owned()).or_insert_with(|| TypeProc { @@ -1152,7 +1161,8 @@ impl ObjectTreeBuilder { location, parameters: parameters.into(), docs: Default::default(), - code + code, + body_range, }; // DM really does reorder the declaration to appear before the override, @@ -1240,6 +1250,7 @@ impl ObjectTreeBuilder { elems.len() + 1, params.iter().copied().map(|param| Parameter { name: param.into(), .. Default::default() }).collect(), None, + None, ).unwrap().1 } @@ -1252,6 +1263,7 @@ impl ObjectTreeBuilder { len: usize, parameters: Vec, code: Option, + body_range: Option>, ) -> Result<(usize, &mut ProcValue), DMError> { let (parent, mut proc_name) = self.get_from_path(location, &mut path, len)?; let mut declaration = None; @@ -1277,7 +1289,7 @@ impl ObjectTreeBuilder { )); } - self.register_proc(context, location, parent, proc_name, declaration, parameters, ProcReturnType::default(), code) + self.register_proc(context, location, parent, proc_name, declaration, parameters, ProcReturnType::default(), code, body_range) } } diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 190990a7..a07878db 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -1142,7 +1142,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { None }; - match self.tree.register_proc(self.context, location, current, name, proc_builder, parameters, return_type, code) { + match self.tree.register_proc(self.context, location, current, name, proc_builder, parameters, return_type, code, Some(body_start..self.location)) { Ok((idx, proc)) => { proc.docs.extend(docs); // manually performed for borrowck reasons From 5c3ea44a99554feb59e21d41e4dedc8b5f4e8262 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Tue, 22 Jul 2025 23:13:34 -0700 Subject: [PATCH 172/197] Remove macro use-near-undef warning This BYOND bug was fixed in 515.1607 in May 2023. It's no longer necessary for SpacemanDMM to warn about it. Fixes #423. --- crates/dreammaker/src/preprocessor.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index 0917ae13..a670f1f1 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -681,15 +681,6 @@ impl<'ctx> Preprocessor<'ctx> { } } - fn check_danger_ident(&mut self, name: &str, kind: &str) { - if let Some(loc) = self.danger_idents.get(name) { - self.context.register_error(DMError::new(*loc, format!( - "macro {name:?} used immediately before being {kind}:\n\ - https://www.byond.com/forum/?post=2072419" - )).set_severity(Severity::Warning)); - } - } - fn push_output(&mut self, token: Token) { self.output.push_back(LocatedToken::new(self.last_input_loc, token)); } @@ -863,7 +854,6 @@ impl<'ctx> Preprocessor<'ctx> { define_name_loc .. define_name_loc.add_columns(define_name.len() as u16), Annotation::MacroDefinition(define_name.to_owned())); } - self.check_danger_ident(&define_name, "defined"); let mut params = Vec::new(); let mut subst = Vec::new(); let mut variadic = false; @@ -956,7 +946,6 @@ impl<'ctx> Preprocessor<'ctx> { "undef" => { expect_token!((define_name) = Token::Ident(define_name, _)); let define_name_loc = _last_expected_loc; - self.check_danger_ident(&define_name, "undefined"); expect_token!(() = Token::Punct(Punctuation::Newline)); if let Some(previous) = self.defines.remove(&define_name) { self.move_to_history(define_name, previous); From 7a1a99093412e6002dfae31bd99a849bd3435da9 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Wed, 23 Jul 2025 01:26:54 -0700 Subject: [PATCH 173/197] Remove unused category field on minimap::Sprite --- crates/dmm-tools/src/minimap.rs | 44 --------------------------------- 1 file changed, 44 deletions(-) diff --git a/crates/dmm-tools/src/minimap.rs b/crates/dmm-tools/src/minimap.rs index 41dc2c05..e6834ff5 100644 --- a/crates/dmm-tools/src/minimap.rs +++ b/crates/dmm-tools/src/minimap.rs @@ -412,45 +412,6 @@ impl<'a> GetVar<'a> for TypeRef<'a> { // ---------------------------------------------------------------------------- // Renderer-agnostic sprite structure -/// Information about when a sprite should be shown or hidden. -#[derive(Default, Debug, Clone, Copy, Eq, PartialEq, Hash)] -pub struct Category { - raw: u32, -} - -impl Category { - const AREA: Category = Category { raw: 1 }; - const TURF: Category = Category { raw: 2 }; - const OBJ: Category = Category { raw: 3 }; - const MOB: Category = Category { raw: 4 }; - - pub fn from_path(path: &str) -> Category { - if path.starts_with("/area") { - Category::AREA - } else if path.starts_with("/turf") { - Category::TURF - } else if path.starts_with("/obj") { - Category::OBJ - } else if path.starts_with("/mob") { - Category::MOB - } else { - Category { raw: 0 } - } - } - - /// Encode this category for FFI representation. - pub fn matches_basic_layers(self, visible: &[bool]) -> bool { - visible.get(self.raw as usize).copied().unwrap_or(false) - } -} - -#[cfg(feature="gfx_core")] -impl gfx_core::shade::BaseTyped for Category { - fn get_base_type() -> gfx_core::shade::BaseType { - u32::get_base_type() - } -} - /// A guaranteed sortable representation of a `layer` float. #[derive(Default, Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash)] pub struct Layer { @@ -490,9 +451,6 @@ impl gfx_core::shade::BaseTyped for Layer { /// overlays. #[derive(Debug, Clone)] pub struct Sprite<'s> { - // filtering - pub category: Category, - // visual appearance pub icon: &'s str, pub icon_state: &'s str, @@ -518,7 +476,6 @@ impl<'s> Sprite<'s> { let step_y = vars.get_var("step_y", objtree).to_int().unwrap_or(0); Sprite { - category: Category::from_path(vars.get_path()), icon: vars.get_var("icon", objtree).as_path_str().unwrap_or(""), icon_state: vars.get_var("icon_state", objtree).as_str().unwrap_or(""), dir: vars.get_var("dir", objtree).to_int().and_then(Dir::from_int).unwrap_or_default(), @@ -534,7 +491,6 @@ impl<'s> Sprite<'s> { impl<'s> Default for Sprite<'s> { fn default() -> Self { Sprite { - category: Category::default(), icon: "", icon_state: "", dir: Dir::default(), From 3162794032d5b7981297b006551d7b9d3229db11 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Wed, 23 Jul 2025 01:34:28 -0700 Subject: [PATCH 174/197] Rename subpath to ispath and allow no trailing slash --- crates/dmm-tools/src/minimap.rs | 2 +- crates/dmm-tools/src/render_passes/mod.rs | 28 +++++++++++------------ crates/dreammaker/src/objtree.rs | 12 ++++++---- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/crates/dmm-tools/src/minimap.rs b/crates/dmm-tools/src/minimap.rs index e6834ff5..5ff00db2 100644 --- a/crates/dmm-tools/src/minimap.rs +++ b/crates/dmm-tools/src/minimap.rs @@ -263,7 +263,7 @@ impl<'a> Atom<'a> { } pub fn istype(&self, parent: &str) -> bool { - subpath(&self.type_.path, parent) + ispath(&self.type_.path, parent) } } diff --git a/crates/dmm-tools/src/render_passes/mod.rs b/crates/dmm-tools/src/render_passes/mod.rs index 7e4063f1..b49c5630 100644 --- a/crates/dmm-tools/src/render_passes/mod.rs +++ b/crates/dmm-tools/src/render_passes/mod.rs @@ -188,7 +188,7 @@ impl RenderPass for HideSpace { pub struct HideAreas; impl RenderPass for HideAreas { fn path_filter(&self, path: &str) -> bool { - !subpath(path, "/area/") + !ispath(path, "/area/") } } @@ -211,7 +211,7 @@ impl RenderPass for HideInvisible { } fn path_filter(&self, path: &str) -> bool { - !subpath(path, "/obj/effect/spawner/xmastree/") + !ispath(path, "/obj/effect/spawner/xmastree/") } fn early_filter(&self, atom: &Atom, objtree: &ObjectTree) -> bool { @@ -499,32 +499,32 @@ fn unary_aboveground(atom: &Atom, objtree: &ObjectTree) -> Option<&'static str> impl FancyLayers { fn fancy_layer_for_path(&self, p: &str) -> Option { for &(ref key, val) in self.overrides.iter() { - if subpath(p, key) { + if ispath(p, key) { return Some(Layer::from(val)); } } - if subpath(p, "/turf/open/floor/plating/") || subpath(p, "/turf/open/space/") { + if ispath(p, "/turf/open/floor/plating/") || ispath(p, "/turf/open/space/") { Some(Layer::from(-10)) // under everything - } else if subpath(p, "/turf/closed/mineral/") { + } else if ispath(p, "/turf/closed/mineral/") { Some(Layer::from(-3)) // above hidden stuff and plating but below walls - } else if subpath(p, "/turf/open/floor/") || subpath(p, "/turf/closed/") { + } else if ispath(p, "/turf/open/floor/") || ispath(p, "/turf/closed/") { Some(Layer::from(-2)) // above hidden pipes and wires - } else if subpath(p, "/turf/") { + } else if ispath(p, "/turf/") { Some(Layer::from(-10)) // under everything - } else if subpath(p, "/obj/effect/turf_decal/") { + } else if ispath(p, "/obj/effect/turf_decal/") { Some(Layer::from(-1)) // above turfs - } else if subpath(p, "/obj/structure/disposalpipe/") { + } else if ispath(p, "/obj/structure/disposalpipe/") { Some(Layer::from(-6)) - } else if subpath(p, "/obj/machinery/atmospherics/pipe/") && !p.contains("visible") { + } else if ispath(p, "/obj/machinery/atmospherics/pipe/") && !p.contains("visible") { Some(Layer::from(-5)) - } else if subpath(p, "/obj/structure/cable/") { + } else if ispath(p, "/obj/structure/cable/") { Some(Layer::from(-4)) - } else if subpath(p, "/obj/machinery/power/terminal/") { + } else if ispath(p, "/obj/machinery/power/terminal/") { Some(Layer::from(-3.5)) - } else if subpath(p, "/obj/structure/lattice/") { + } else if ispath(p, "/obj/structure/lattice/") { Some(Layer::from(-8)) - } else if subpath(p, "/obj/machinery/navbeacon/") { + } else if ispath(p, "/obj/machinery/navbeacon/") { Some(Layer::from(-3)) } else { None diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index 7a9a1f60..f2625b6f 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -181,7 +181,7 @@ impl Type { /// Checks whether this type's path is a subpath of the given path. #[inline] pub fn is_subpath_of(&self, parent: &str) -> bool { - subpath(&self.path, parent) + ispath(&self.path, parent) } // Used in the constant evaluator which holds an &mut ObjectTree and thus @@ -212,9 +212,13 @@ impl Type { } #[inline] -pub fn subpath(path: &str, parent: &str) -> bool { - debug_assert!(path.starts_with('/') && parent.starts_with('/') && parent.ends_with('/')); - path == &parent[..parent.len() - 1] || path.starts_with(parent) +pub fn ispath(path: &str, parent: &str) -> bool { + debug_assert!(path.starts_with('/') && parent.starts_with('/')); + let parent = parent.trim_end_matches('/'); + match path.strip_prefix(parent) { + Some(rest) => rest.is_empty() || rest.starts_with('/'), + None => false, + } } // ---------------------------------------------------------------------------- From 208c5bfac82fa0ed7ff303e01e5c00c1c8cafc5f Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Wed, 23 Jul 2025 17:29:28 -0700 Subject: [PATCH 175/197] Run RenderPass::sprite_filter prior to sorting sprites --- crates/dmm-tools/src/minimap.rs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/crates/dmm-tools/src/minimap.rs b/crates/dmm-tools/src/minimap.rs index 5ff00db2..ee9cf225 100644 --- a/crates/dmm-tools/src/minimap.rs +++ b/crates/dmm-tools/src/minimap.rs @@ -125,17 +125,22 @@ pub fn generate(ctx: Context, icon_cache: &IconCache) -> Result { drop(underlays); drop(overlays); - // sorts the atom list and renders them onto the output image - sprites.sort_by_key(|(_, s)| (s.plane, s.layer)); - - let mut map_image = Image::new_rgba(len_x as u32 * TILE_SIZE, len_y as u32 * TILE_SIZE); - 'sprite: for (loc, sprite) in sprites { + // Drop sprites rejected by any render pass. + sprites.retain(|(_, sprite)| { for pass in render_passes.iter() { - if !pass.sprite_filter(&sprite) { - continue 'sprite; + if !pass.sprite_filter(sprite) { + return false; } } + true + }); + // Sort the sprite list by depth. + sprites.sort_by_key(|(_, s)| (s.plane, s.layer)); + + // Composite the sorted sprites onto the output image. + let mut map_image = Image::new_rgba(len_x as u32 * TILE_SIZE, len_y as u32 * TILE_SIZE); + for ((x, y), sprite) in sprites { let icon_file = match icon_cache.retrieve_shared(sprite.icon.as_ref()) { Some(icon_file) => icon_file, None => continue, @@ -145,8 +150,8 @@ pub fn generate(ctx: Context, icon_cache: &IconCache) -> Result { let pixel_x = sprite.ofs_x; let pixel_y = sprite.ofs_y + icon_file.metadata.height as i32; let loc = ( - ((loc.0 - ctx.min.0 as u32) * TILE_SIZE) as i32 + pixel_x, - ((loc.1 + 1 - min_y as u32) * TILE_SIZE) as i32 - pixel_y, + ((x - ctx.min.0 as u32) * TILE_SIZE) as i32 + pixel_x, + ((y + 1 - min_y as u32) * TILE_SIZE) as i32 - pixel_y, ); if let Some((loc, rect)) = clip((map_image.width, map_image.height), loc, rect) { From b40d2176cd52d5c1c36459609dd4838bc2ae1fe9 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Wed, 23 Jul 2025 18:17:38 -0700 Subject: [PATCH 176/197] Use math instead of a loop when clipping sprites --- crates/dmm-tools/src/minimap.rs | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/crates/dmm-tools/src/minimap.rs b/crates/dmm-tools/src/minimap.rs index ee9cf225..95a6d65d 100644 --- a/crates/dmm-tools/src/minimap.rs +++ b/crates/dmm-tools/src/minimap.rs @@ -173,31 +173,21 @@ pub fn generate(ctx: Context, icon_cache: &IconCache) -> Result { fn clip(bounds: dmi::Coordinate, mut loc: (i32, i32), mut rect: dmi::Rect) -> Option<(dmi::Coordinate, dmi::Rect)> { if loc.0 < 0 { rect.0 += (-loc.0) as u32; - match rect.2.checked_sub((-loc.0) as u32) { - Some(s) => rect.2 = s, - None => return None, // out of the viewport - } + rect.2 = rect.2.checked_sub((-loc.0) as u32)?; loc.0 = 0; } - while loc.0 + rect.2 as i32 > bounds.0 as i32 { - rect.2 -= 1; - if rect.2 == 0 { - return None; - } + let overhang = loc.0 + rect.2 as i32 - bounds.0 as i32; + if overhang > 0 { + rect.2 = rect.2.checked_sub(overhang as u32)?; } if loc.1 < 0 { rect.1 += (-loc.1) as u32; - match rect.3.checked_sub((-loc.1) as u32) { - Some(s) => rect.3 = s, - None => return None, // out of the viewport - } + rect.3 = rect.3.checked_sub((-loc.1) as u32)?; loc.1 = 0; } - while loc.1 + rect.3 as i32 > bounds.1 as i32 { - rect.3 -= 1; - if rect.3 == 0 { - return None; - } + let overhang = loc.1 + rect.3 as i32 - bounds.1 as i32; + if overhang > 0 { + rect.3 = rect.3.checked_sub(overhang as u32)?; } Some(((loc.0 as u32, loc.1 as u32), rect)) } From 8187b2e06561fc3f020b10244e675f0b50f2bdad Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 31 Jul 2025 19:53:03 -0700 Subject: [PATCH 177/197] Identify as DM 516.1666 --- crates/dreammaker/src/builtins.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/dreammaker/src/builtins.rs b/crates/dreammaker/src/builtins.rs index 3fb95b7d..555ed643 100644 --- a/crates/dreammaker/src/builtins.rs +++ b/crates/dreammaker/src/builtins.rs @@ -8,8 +8,8 @@ use super::objtree::*; use super::preprocessor::{Define, DefineMap}; use super::Location; -const DM_VERSION: i32 = 515; -const DM_BUILD: i32 = 1619; +const DM_VERSION: i32 = 516; +const DM_BUILD: i32 = 1666; /// Register BYOND builtin macros to the given define map. pub fn default_defines(defines: &mut DefineMap) { From 5fa2cbb4db9554aa689f9dae231f9402676fa725 Mon Sep 17 00:00:00 2001 From: ZeWaka Date: Thu, 31 Jul 2025 22:04:18 -0700 Subject: [PATCH 178/197] Fix missing pixloc vars (#441) `undefined field: "x" on /pixloc` `undefined field: "y" on /pixloc` --- crates/dreammaker/src/builtins.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/dreammaker/src/builtins.rs b/crates/dreammaker/src/builtins.rs index 555ed643..5985237e 100644 --- a/crates/dreammaker/src/builtins.rs +++ b/crates/dreammaker/src/builtins.rs @@ -1269,9 +1269,9 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { pixloc/var/atom/loc; pixloc/var/step_x; pixloc/var/step_y; - pixloc/x; - pixloc/y; - pixloc/z; + pixloc/var/x; + pixloc/var/y; + pixloc/var/z; proc/vector(x, y, z); From 72ed2bce62f1ad25f29cf9c89d9eba80a1727adb Mon Sep 17 00:00:00 2001 From: Zonespace <41448081+Zonespace27@users.noreply.github.com> Date: Sat, 2 Aug 2025 22:03:14 +0200 Subject: [PATCH 179/197] Fix alists not being marked as iterable (#442) Trying to loop over values using `for(var/v in alist("a" = 2))` would throw an "iterating over a /alist which cannot be iterated" error despite working in DM. --- crates/dreamchecker/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 22cc94ee..96df7f90 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -1433,7 +1433,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } StaticType::List { .. } => {/* OK */} StaticType::Type(ty) => { - if ty != self.objtree.expect("/world") && ty != self.objtree.expect("/list") { + if ty != self.objtree.expect("/world") && ty != self.objtree.expect("/list") && ty != self.objtree.expect("/alist") { let atom = self.objtree.expect("/atom"); if ty.is_subtype_of(&atom) { // Fine. From 814f96a53854a1aca27458df5ef71bff783a8497 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 18 Aug 2025 18:51:42 -0700 Subject: [PATCH 180/197] Fix missing completions for caller and callee vars --- crates/dm-langserver/src/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index 6ef5cd70..307f22a2 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -783,6 +783,8 @@ impl Engine { // nothing } else if first == "usr" { next = self.objtree.find("/mob"); + } else if first == "caller" || first == "callee" { + next = self.objtree.find("/callee"); } else { next = match self.find_unscoped_var(iter, next, proc_name, first) { UnscopedVar::Parameter { param, .. } => self.objtree.type_by_path(param.var_type.type_path.iter()), From 98e69a4b4a8ed346dd13a14856b39484da02945f Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 18 Aug 2025 18:51:58 -0700 Subject: [PATCH 181/197] Set /callee parent_type to none instead of /datum --- crates/dreammaker/src/objtree.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index f2625b6f..6b313569 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -837,7 +837,15 @@ impl ObjectTreeBuilder { fn assign_parent_types(&mut self, context: &Context) { for (path, &type_idx) in self.inner.types.iter() { let mut location = self.inner[type_idx].location; - let idx = if path == "/datum" || path == "/list" || path == "/alist" || path == "/savefile" || path == "/world" || path == "/vector" || path == "/pixloc" { + let idx = if path == "/datum" + || path == "/list" + || path == "/alist" + || path == "/savefile" + || path == "/world" + || path == "/vector" + || path == "/pixloc" + || path == "/callee" + { // These types have no parent and cannot have one added. In the official compiler: // - setting list or savefile/parent_type is denied with the same error as setting something's parent type to them; // - setting datum/parent_type infinite loops the compiler; From 63b34b6585579378baf8a57d3ed22b0d1270ddaf Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 18 Aug 2025 23:34:18 -0700 Subject: [PATCH 182/197] Typecheck fields on `callee.proc` --- crates/dreamchecker/src/lib.rs | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 96df7f90..2fa566af 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -31,6 +31,7 @@ pub enum StaticType<'o> { list: TypeRef<'o>, keys: Box>, }, + Proc, } impl<'o> StaticType<'o> { @@ -43,6 +44,7 @@ impl<'o> StaticType<'o> { StaticType::None => None, StaticType::Type(t) => Some(t), StaticType::List { list, .. } => Some(list), + StaticType::Proc => None, } } @@ -74,6 +76,7 @@ impl<'o> StaticType<'o> { StaticType::None => false, StaticType::Type(ty) => ty.path == "/list", StaticType::List { .. } => true, + StaticType::Proc => false, } } } @@ -1451,6 +1454,10 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } } + StaticType::Proc => { + error(location, format!("iterating over a procpath which cannot be iterated")) + .register(self.context); + } } } if let Some(var_type) = var_type { @@ -1605,6 +1612,10 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } } + StaticType::Proc => { + error(location, format!("iterating over a procpath which cannot be iterated")) + .register(self.context); + } } } // This quite ugly but DM doesn't let you do for (var/k, var/v) @@ -2098,8 +2109,21 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } }, Follow::Field(kind, name) => { - if let Some(ty) = lhs.static_ty.basic_type() { - if let Some(decl) = ty.get_var_declaration(name) { + if let StaticType::Proc = lhs.static_ty { + match name.as_str() { + "type" | "name" | "desc" | "category" | "invisibility" => {}, + _ => { + error(location, format!("undefined field: {name:?} on procpath")) + .register(self.context); + } + } + Analysis::empty() + } else if let Some(ty) = lhs.static_ty.basic_type() { + if ty.path == "/callee" && name == "proc" { + // Special cased for now because this might be the only place it appears? + // Or maybe we should also handle new procpath() returning a procpath. + Analysis::from(StaticType::Proc) + } else if let Some(decl) = ty.get_var_declaration(name) { if ty != self.ty && decl.var_type.flags.is_private() { error(location, format!("field {name:?} on {ty} is declared as private")) .with_errortype("private_var") @@ -2278,6 +2302,9 @@ impl<'o, 's> AnalyzeProc<'o, 's> { StaticType::List { list, .. } => { typeerror = "list"; }, + StaticType::Proc => { + return Analysis::empty() + } }; error(location, format!("Attempting {operator} on a {typeerror} which does not overload {operator}")) .register(self.context); From 873b75c9d59b7ebdd4af2bb841febc9b497679e5 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 18 Aug 2025 23:35:14 -0700 Subject: [PATCH 183/197] Run cargo update --- Cargo.lock | 775 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 474 insertions(+), 301 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b2a5643a..10e4f9e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "adler32" @@ -40,9 +40,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" dependencies = [ "anstyle", "anstyle-parse", @@ -55,47 +55,48 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ "anstyle", - "windows-sys 0.59.0", + "once_cell_polyfill", + "windows-sys 0.60.2", ] [[package]] name = "async-trait" -version = "0.1.85" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", ] [[package]] @@ -107,7 +108,7 @@ dependencies = [ "attribute-derive-macro", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", ] [[package]] @@ -123,14 +124,14 @@ dependencies = [ "proc-macro2", "quote", "quote-use", - "syn 2.0.96", + "syn 2.0.106", ] [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "base64" @@ -155,9 +156,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.7.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" +checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29" [[package]] name = "block-buffer" @@ -179,47 +180,41 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytemuck" -version = "1.21.0" +version = "1.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" +checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.8.1" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" +checksum = "4f154e572231cb6ba2bd1176980827e3d5dc04cc183a75dea38109fbdd672d29" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", ] -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "bytes" -version = "1.9.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.8" +version = "1.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0cf6e91fde44c773c6ee7ec6bba798504641a8bc2eb7e37a04ffbf4dfaa55a" +checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f" dependencies = [ "jobserver", "libc", @@ -228,29 +223,29 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "chrono" -version = "0.4.39" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets", + "windows-link", ] [[package]] name = "clap" -version = "4.5.26" +version = "4.5.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" +checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318" dependencies = [ "clap_builder", "clap_derive", @@ -258,9 +253,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.26" +version = "4.5.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" +checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8" dependencies = [ "anstream", "anstyle", @@ -270,27 +265,27 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.24" +version = "4.5.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" +checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", ] [[package]] name = "clap_lex" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "collection_literals" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186dce98367766de751c42c4f03970fc60fc012296e706ccbb9d5df9b6c1e271" +checksum = "26b3f65b8fb8e88ba339f7d23a390fe1b0896217da05e2a66c584c9b29a91df8" [[package]] name = "color_quant" @@ -306,9 +301,9 @@ checksum = "52fdfaf2bee6357023bf7f95b15a8ef0b82759d2bce705cc45efcae9ae10f0ff" [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "core-foundation-sys" @@ -318,18 +313,18 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] @@ -392,13 +387,13 @@ dependencies = [ [[package]] name = "derive-where" -version = "1.2.7" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" +checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", ] [[package]] @@ -419,7 +414,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", ] [[package]] @@ -541,15 +536,15 @@ dependencies = [ [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "fdeflate" @@ -562,19 +557,20 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.35" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ "crc32fast", + "libz-rs-sys", "miniz_oxide", ] [[package]] name = "foldhash" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "form_urlencoded" @@ -641,7 +637,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", ] [[package]] @@ -698,27 +694,39 @@ checksum = "13a1bcfb855c1f340d5913ab542e36f25a1c56f57de79022928297632435dec2" dependencies = [ "attribute-derive", "quote", - "syn 2.0.96", + "syn 2.0.106", ] [[package]] name = "getopts" -version = "0.2.21" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1" dependencies = [ "unicode-width", ] [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] @@ -748,7 +756,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2deb07a133b1520dc1a5690e9bd08950108873d7ed5de38dcc74d3b5ebffa110" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.2", "libc", "libgit2-sys", "log", @@ -757,9 +765,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" [[package]] name = "heck" @@ -775,14 +783,15 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -798,21 +807,22 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", "litemap", @@ -821,31 +831,11 @@ dependencies = [ "zerovec", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -853,67 +843,54 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", + "zerotrie", "zerovec", ] -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - [[package]] name = "idna" version = "1.0.3" @@ -927,9 +904,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -937,9 +914,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", "hashbrown", @@ -975,24 +952,25 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ + "getrandom 0.3.3", "libc", ] [[package]] name = "js-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", @@ -1021,15 +999,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.169" +version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] name = "libgit2-sys" -version = "0.18.1+1.9.0" +version = "0.18.2+1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1dcb20f84ffcdd825c7a311ae347cce604a6f084a767dec4a4929829645290e" +checksum = "1c42fe03df2bd3c53a3a9c7317ad91d80c81cd1fb0caec8d7cc4cd2bfa10c222" dependencies = [ "cc", "libc", @@ -1038,10 +1016,19 @@ dependencies = [ ] [[package]] -name = "libz-sys" -version = "1.1.21" +name = "libz-rs-sys" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9b68e50e6e0b26f672573834882eb57759f6db9b3be2ea3c35c91188bb4eaa" +checksum = "172a788537a2221661b480fee8dc5f96c580eb34fa88764d3205dc356c7e4221" +dependencies = [ + "zlib-rs", +] + +[[package]] +name = "libz-sys" +version = "1.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" dependencies = [ "cc", "libc", @@ -1051,15 +1038,15 @@ dependencies = [ [[package]] name = "litemap" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lodepng" -version = "3.10.7" +version = "3.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2dea7cda68e381418c985fd8f32a9c279a21ae8c715f2376adb20c27a0fad3" +checksum = "77a32335d22e44238e2bb0b4d726964d18952ce1f1279ec3305305d2c61539eb" dependencies = [ "crc32fast", "flate2", @@ -1069,9 +1056,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.24" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6ea2a48c204030ee31a7d7fc72c93294c92fe87ecb1789881c9543516e1a0d" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "lsp-types" @@ -1088,9 +1075,9 @@ dependencies = [ [[package]] name = "matrixmultiply" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" dependencies = [ "autocfg", "rawpointer", @@ -1120,15 +1107,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "miniz_oxide" -version = "0.8.2" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", "simd-adler32", @@ -1176,9 +1163,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.2" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] name = "ordered-float" @@ -1225,7 +1218,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", ] [[package]] @@ -1251,9 +1244,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "png" @@ -1269,10 +1262,19 @@ dependencies = [ ] [[package]] -name = "ppv-lite86" -version = "0.2.20" +name = "potential_utf" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] @@ -1314,9 +1316,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -1327,7 +1329,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.2", "getopts", "memchr", "unicase", @@ -1335,9 +1337,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] @@ -1350,7 +1352,7 @@ checksum = "a7b5abe3fe82fdeeb93f44d66a7b444dedf2e4827defb0a8e69c437b2de2ef94" dependencies = [ "quote", "quote-use-macros", - "syn 2.0.96", + "syn 2.0.106", ] [[package]] @@ -1362,9 +1364,15 @@ dependencies = [ "derive-where", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "rand" version = "0.8.5" @@ -1392,7 +1400,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.16", ] [[package]] @@ -1403,9 +1411,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ "either", "rayon-core", @@ -1413,9 +1421,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -1452,22 +1460,22 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rgb" -version = "0.8.50" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" +checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" dependencies = [ "bytemuck", ] [[package]] name = "ring" -version = "0.17.13" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.16", "libc", "untrusted", "windows-sys 0.52.0", @@ -1475,9 +1483,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.21" +version = "0.23.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ "log", "once_cell", @@ -1490,15 +1498,18 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.10.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] [[package]] name = "rustls-webpki" -version = "0.102.8" +version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ "ring", "rustls-pki-types", @@ -1506,10 +1517,16 @@ dependencies = [ ] [[package]] -name = "ryu" -version = "1.0.18" +name = "rustversion" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" @@ -1522,29 +1539,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.217" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", ] [[package]] name = "serde_json" -version = "1.0.135" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ "itoa", "memchr", @@ -1554,20 +1571,20 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", ] [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -1576,9 +1593,9 @@ dependencies = [ [[package]] name = "sha256" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18278f6a914fa3070aa316493f7d2ddfb9ac86ebc06fa3b83bffda487e9065b0" +checksum = "f880fc8562bdeb709793f00eb42a2ad0e672c4f883bbe59122b926eca935c8f6" dependencies = [ "async-trait", "bytes", @@ -1606,18 +1623,15 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "stable_deref_trait" @@ -1650,9 +1664,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.96" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -1661,13 +1675,13 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", ] [[package]] @@ -1681,9 +1695,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", @@ -1700,9 +1714,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unicase" @@ -1712,15 +1726,15 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-width" -version = "0.1.14" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" [[package]] name = "untrusted" @@ -1741,7 +1755,7 @@ dependencies = [ "rustls", "rustls-pki-types", "url", - "webpki-roots", + "webpki-roots 0.26.11", ] [[package]] @@ -1756,12 +1770,6 @@ dependencies = [ "serde", ] -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -1798,40 +1806,50 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] [[package]] name = "wasm-bindgen" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1839,37 +1857,49 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "webpki-roots" -version = "0.26.7" +version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.2", +] + +[[package]] +name = "webpki-roots" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" dependencies = [ "rustls-pki-types", ] [[package]] name = "weezl" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" +checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" [[package]] name = "winapi-util" @@ -1882,11 +1912,61 @@ dependencies = [ [[package]] name = "windows-core" -version = "0.52.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-targets", + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link", ] [[package]] @@ -1895,7 +1975,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1904,7 +1984,16 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", ] [[package]] @@ -1913,14 +2002,31 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -1929,42 +2035,84 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -1972,22 +2120,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "write16" -version = "1.0.0" +name = "windows_x86_64_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.2", +] [[package]] name = "writeable" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "yoke" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -1997,55 +2154,54 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", "synstructure", ] [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ - "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", ] [[package]] name = "zerofrom" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", "synstructure", ] @@ -2056,10 +2212,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] -name = "zerovec" -version = "0.10.4" +name = "zerotrie" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" dependencies = [ "yoke", "zerofrom", @@ -2068,11 +2235,17 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.106", ] + +[[package]] +name = "zlib-rs" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626bd9fa9734751fc50d6060752170984d7053f5a39061f524cda68023d4db8a" From 38f570f04e580ebbb17d527c5269b28320c7ba0c Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Mon, 18 Aug 2025 23:40:39 -0700 Subject: [PATCH 184/197] Resolve 'hiding a lifetime' warnings from Rust 1.89 --- crates/dm-langserver/src/debugger/extools.rs | 2 +- crates/dm-langserver/src/main.rs | 2 +- crates/dmm-tools/src/dmm.rs | 2 +- crates/dreamchecker/src/lib.rs | 6 +++--- crates/dreammaker/src/annotation.rs | 8 ++++---- crates/dreammaker/src/error.rs | 8 ++++---- crates/dreammaker/src/lexer.rs | 2 +- crates/dreammaker/src/lib.rs | 4 ++-- crates/dreammaker/src/objtree.rs | 12 ++++++------ crates/interval-tree/src/tree.rs | 4 ++-- 10 files changed, 25 insertions(+), 25 deletions(-) diff --git a/crates/dm-langserver/src/debugger/extools.rs b/crates/dm-langserver/src/debugger/extools.rs index 172d03c4..3a352f27 100644 --- a/crates/dm-langserver/src/debugger/extools.rs +++ b/crates/dm-langserver/src/debugger/extools.rs @@ -197,7 +197,7 @@ impl Extools { (extools, thread) } - pub fn get_all_threads(&self) -> std::sync::MutexGuard> { + pub fn get_all_threads(&self) -> std::sync::MutexGuard<'_, HashMap> { self.threads.lock().unwrap() } diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index 307f22a2..43f56bfc 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -683,7 +683,7 @@ impl Engine { }) } - fn find_type_context<'b, I, Ign>(&self, iter: &I) -> (Option, Option<(&'b str, usize)>) + fn find_type_context<'b, I, Ign>(&self, iter: &I) -> (Option>, Option<(&'b str, usize)>) where I: Iterator + Clone, { diff --git a/crates/dmm-tools/src/dmm.rs b/crates/dmm-tools/src/dmm.rs index 1ba025d5..bf44fb44 100644 --- a/crates/dmm-tools/src/dmm.rs +++ b/crates/dmm-tools/src/dmm.rs @@ -218,7 +218,7 @@ impl Map { } #[inline] - pub fn z_level(&self, z: usize) -> ZLevel { + pub fn z_level(&self, z: usize) -> ZLevel<'_> { ZLevel { grid: self.grid.index_axis(Axis(0), z) } } diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 2fa566af..6b7f3f96 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -175,7 +175,7 @@ impl<'o> AssumptionSet<'o> { assumption_set![Assumption::Truthy(true), Assumption::IsNull(false), Assumption::IsType(true, ty)] } - fn conflicts_with(&self, new: &Assumption) -> Option<&Assumption> { + fn conflicts_with(&self, new: &Assumption) -> Option<&Assumption<'_>> { self.set.iter().find(|&each| each.oneway_conflict(new) || new.oneway_conflict(each)) } } @@ -1455,7 +1455,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } StaticType::Proc => { - error(location, format!("iterating over a procpath which cannot be iterated")) + error(location, "iterating over a procpath which cannot be iterated".to_string()) .register(self.context); } } @@ -1613,7 +1613,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } StaticType::Proc => { - error(location, format!("iterating over a procpath which cannot be iterated")) + error(location, "iterating over a procpath which cannot be iterated".to_string()) .register(self.context); } } diff --git a/crates/dreammaker/src/annotation.rs b/crates/dreammaker/src/annotation.rs index bfebf1c3..3ee0877a 100644 --- a/crates/dreammaker/src/annotation.rs +++ b/crates/dreammaker/src/annotation.rs @@ -85,19 +85,19 @@ impl AnnotationTree { self.len == 0 } - pub fn iter(&self) -> Iter { + pub fn iter(&self) -> Iter<'_> { self.tree.iter() } - pub fn get_location(&self, loc: Location) -> Iter { + pub fn get_location(&self, loc: Location) -> Iter<'_> { self.tree.range(range(loc.pred(), loc)) } - pub fn get_range(&self, place: std::ops::Range) -> Iter { + pub fn get_range(&self, place: std::ops::Range) -> Iter<'_> { self.tree.range(range(place.start, place.end.pred())) } - pub fn get_range_raw(&self, place: RangeInclusive) -> Iter { + pub fn get_range_raw(&self, place: RangeInclusive) -> Iter<'_> { self.tree.range(place) } } diff --git a/crates/dreammaker/src/error.rs b/crates/dreammaker/src/error.rs index ce6b9001..7cc585ab 100644 --- a/crates/dreammaker/src/error.rs +++ b/crates/dreammaker/src/error.rs @@ -73,7 +73,7 @@ impl FileList { } /// Look up a file path by its index returned from `register_file`. - pub fn get_path(&self, file: FileId) -> Ref { + pub fn get_path(&self, file: FileId) -> Ref<'_, Path> { let files = self.files.borrow(); if file == FILEID_BUILTINS { return Ref::map(files, |_| Path::new("(builtins)")); @@ -108,7 +108,7 @@ impl Context { } /// Look up a file path by its index returned from `register_file`. - pub fn file_path(&self, file: FileId) -> Ref { + pub fn file_path(&self, file: FileId) -> Ref<'_, Path> { self.files.get_path(file) } @@ -191,13 +191,13 @@ impl Context { } /// Access the list of diagnostics generated so far. - pub fn errors(&self) -> Ref<[DMError]> { + pub fn errors(&self) -> Ref<'_, [DMError]> { Ref::map(self.errors.borrow(), |x| &**x) } /// Mutably access the diagnostics list. Dangerous. #[doc(hidden)] - pub fn errors_mut(&self) -> RefMut> { + pub fn errors_mut(&self) -> RefMut<'_, Vec> { self.errors.borrow_mut() } diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index b96df3a3..f0a2fee2 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -473,7 +473,7 @@ pub fn from_utf8_or_latin1(bytes: Vec) -> String { } /// Convert the input bytes to a `String` attempting UTF-8 or falling back to Latin-1. -pub fn from_utf8_or_latin1_borrowed(bytes: &[u8]) -> Cow { +pub fn from_utf8_or_latin1_borrowed(bytes: &[u8]) -> Cow<'_, str> { match std::str::from_utf8(bytes) { Ok(v) => Cow::Borrowed(v), Err(_) => Cow::Owned(from_latin1(bytes)), diff --git a/crates/dreammaker/src/lib.rs b/crates/dreammaker/src/lib.rs index b893d941..43d02abd 100644 --- a/crates/dreammaker/src/lib.rs +++ b/crates/dreammaker/src/lib.rs @@ -123,7 +123,7 @@ pub fn pretty_print(w: &mut W, input: I, show_ws: bool) -> std::fmt::Resul /// On Windows, this is a no-op. #[cfg(windows)] #[inline(always)] -pub fn fix_case(path: &Path) -> Cow { +pub fn fix_case(path: &Path) -> Cow<'_, Path> { Cow::Borrowed(path) } @@ -132,7 +132,7 @@ pub fn fix_case(path: &Path) -> Cow { /// On non-Windows platforms, the parent of the given path is searched for a /// file with the same name but a different case. #[cfg(not(windows))] -pub fn fix_case(path: &Path) -> Cow { +pub fn fix_case(path: &Path) -> Cow<'_, Path> { if path.exists() { return Cow::Borrowed(path); } diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index 6b313569..940b4697 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -673,18 +673,18 @@ impl ObjectTree { self.node_indices().map(move |idx| TypeRef::new(self, idx)) } - pub fn root(&self) -> TypeRef { + pub fn root(&self) -> TypeRef<'_> { TypeRef::new(self, NodeIndex::new(0)) } - pub fn find(&self, path: &str) -> Option { + pub fn find(&self, path: &str) -> Option> { if path.is_empty() { return Some(self.root()); } self.types.get(path).map(|&ix| TypeRef::new(self, ix)) } - pub fn expect(&self, path: &str) -> TypeRef { + pub fn expect(&self, path: &str) -> TypeRef<'_> { match self.types.get(path) { Some(&ix) => TypeRef::new(self, ix), None => panic!("type not found: {path:?}"), @@ -695,7 +695,7 @@ impl ObjectTree { self.graph.get(type_.parent_type.index()) } - pub fn type_by_path(&self, path: I) -> Option + pub fn type_by_path(&self, path: I) -> Option> where I: IntoIterator, I::Item: AsRef, @@ -708,7 +708,7 @@ impl ObjectTree { } } - pub fn type_by_path_approx(&self, path: I) -> (bool, TypeRef) + pub fn type_by_path_approx(&self, path: I) -> (bool, TypeRef<'_>) where I: IntoIterator, I::Item: AsRef, @@ -732,7 +732,7 @@ impl ObjectTree { (true, TypeRef::new(self, current)) } - pub fn type_by_constant(&self, constant: &Constant) -> Option { + pub fn type_by_constant(&self, constant: &Constant) -> Option> { match constant { Constant::String(string_path) => self.find(string_path), Constant::Prefab(pop) => self.type_by_path(pop.path.iter()), diff --git a/crates/interval-tree/src/tree.rs b/crates/interval-tree/src/tree.rs index 9e7e30b8..c3f7d055 100644 --- a/crates/interval-tree/src/tree.rs +++ b/crates/interval-tree/src/tree.rs @@ -214,7 +214,7 @@ impl IntervalTree { /// } /// /// ``` - pub fn range(&self, range: RangeInclusive) -> RangePairIter { + pub fn range(&self, range: RangeInclusive) -> RangePairIter<'_, K, V> { RangePairIter::new( self, Bound::Included(range.start), @@ -231,7 +231,7 @@ impl IntervalTree { /// } /// /// ``` - pub fn iter(&self) -> RangePairIter { + pub fn iter(&self) -> RangePairIter<'_, K, V> { RangePairIter::new(self, Bound::Unbounded, Bound::Unbounded) } } From 1b930c0a808c4711cd453e90a1212ca1643d06f5 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 23 Aug 2025 16:41:04 -0700 Subject: [PATCH 185/197] Update foldhash and maud dependencies Also run cargo update. --- Cargo.lock | 128 ++++++++++++++++---------------- crates/dap-types/Cargo.toml | 2 +- crates/dm-langserver/Cargo.toml | 2 +- crates/dmdoc/Cargo.toml | 4 +- crates/dmm-tools-cli/Cargo.toml | 2 +- crates/dmm-tools/Cargo.toml | 2 +- crates/dreamchecker/Cargo.toml | 2 +- crates/dreammaker/Cargo.toml | 2 +- 8 files changed, 72 insertions(+), 72 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10e4f9e5..fd6d3c5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,9 +156,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.2" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29" +checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" [[package]] name = "block-buffer" @@ -212,9 +212,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.33" +version = "1.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f" +checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" dependencies = [ "jobserver", "libc", @@ -223,9 +223,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "chrono" @@ -243,9 +243,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.45" +version = "4.5.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318" +checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57" dependencies = [ "clap_builder", "clap_derive", @@ -253,9 +253,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.44" +version = "4.5.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8" +checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41" dependencies = [ "anstream", "anstyle", @@ -568,15 +568,15 @@ dependencies = [ [[package]] name = "foldhash" -version = "0.1.5" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -699,9 +699,9 @@ dependencies = [ [[package]] name = "getopts" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1" +checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" dependencies = [ "unicode-width", ] @@ -726,7 +726,7 @@ dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasi 0.14.3+wasi-0.2.4", ] [[package]] @@ -756,7 +756,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2deb07a133b1520dc1a5690e9bd08950108873d7ed5de38dcc74d3b5ebffa110" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "libc", "libgit2-sys", "log", @@ -893,9 +893,9 @@ dependencies = [ [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -914,9 +914,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" dependencies = [ "equivalent", "hashbrown", @@ -958,9 +958,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ "getrandom 0.3.3", "libc", @@ -1085,9 +1085,9 @@ dependencies = [ [[package]] name = "maud" -version = "0.25.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0bab19cef8a7fe1c18a43e881793bfc9d4ea984befec3ae5bd0415abf3ecf00" +checksum = "8156733e27020ea5c684db5beac5d1d611e1272ab17901a49466294b84fc217e" dependencies = [ "itoa", "maud_macros", @@ -1095,14 +1095,14 @@ dependencies = [ [[package]] name = "maud_macros" -version = "0.25.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be95d66c3024ffce639216058e5bae17a83ecaf266ffc6e4d060ad447c9eed2" +checksum = "7261b00f3952f617899bc012e3dbd56e4f0110a038175929fa5d18e5a19913ca" dependencies = [ - "proc-macro-error", "proc-macro2", + "proc-macro2-diagnostics", "quote", - "syn 1.0.109", + "syn 2.0.106", ] [[package]] @@ -1184,9 +1184,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "phf" @@ -1263,9 +1263,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" dependencies = [ "zerovec", ] @@ -1323,13 +1323,25 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "version_check", +] + [[package]] name = "pulldown-cmark" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "getopts", "memchr", "unicase", @@ -1431,9 +1443,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" dependencies = [ "aho-corasick", "memchr", @@ -1443,9 +1455,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" dependencies = [ "aho-corasick", "memchr", @@ -1454,9 +1466,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" [[package]] name = "rgb" @@ -1760,9 +1772,9 @@ dependencies = [ [[package]] name = "url" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", @@ -1812,11 +1824,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.14.2+wasi-0.2.4" +version = "0.14.3+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "6a51ae83037bdd272a9e28ce236db8c07016dd0d50c27038b3f407533c030c95" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] @@ -1903,11 +1915,11 @@ checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -1978,15 +1990,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.60.2" @@ -2126,13 +2129,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.2", -] +checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814" [[package]] name = "writeable" diff --git a/crates/dap-types/Cargo.toml b/crates/dap-types/Cargo.toml index 406a77e0..41ed3fa1 100644 --- a/crates/dap-types/Cargo.toml +++ b/crates/dap-types/Cargo.toml @@ -8,4 +8,4 @@ edition = "2021" serde = "1.0.213" serde_json = "1.0.132" serde_derive = "1.0.213" -foldhash = "0.1.3" +foldhash = "0.2.0" diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index f14a7d02..eae17646 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -19,7 +19,7 @@ interval-tree = { path = "../interval-tree" } libc = "0.2.161" regex = "1.11.1" lazy_static = "1.5" -foldhash = "0.1.3" +foldhash = "0.2.0" [build-dependencies] chrono = "0.4.38" diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index bb82d6b6..48a886f5 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -10,8 +10,8 @@ dreammaker = { path = "../dreammaker" } pulldown-cmark = "0.9.6" walkdir = "2.5.0" git2 = { version = "0.20.2", default-features = false } -maud = "0.25.0" -foldhash = "0.1.3" +maud = "0.27.0" +foldhash = "0.2.0" [dev-dependencies] walkdir = "2.5.0" diff --git a/crates/dmm-tools-cli/Cargo.toml b/crates/dmm-tools-cli/Cargo.toml index c7f62faa..eeb6b47c 100644 --- a/crates/dmm-tools-cli/Cargo.toml +++ b/crates/dmm-tools-cli/Cargo.toml @@ -17,7 +17,7 @@ serde_json = "1.0.132" rayon = "1.10.0" dreammaker = { path = "../dreammaker" } dmm-tools = { path = "../dmm-tools", features = ["png"] } -foldhash = "0.1.3" +foldhash = "0.2.0" [build-dependencies] chrono = "0.4.38" diff --git a/crates/dmm-tools/Cargo.toml b/crates/dmm-tools/Cargo.toml index 9f43cafd..695fb59e 100644 --- a/crates/dmm-tools/Cargo.toml +++ b/crates/dmm-tools/Cargo.toml @@ -11,7 +11,7 @@ rand = "0.8.5" dreammaker = { path = "../dreammaker" } lodepng = "3.10.7" indexmap = "2.6.0" -foldhash = "0.1.3" +foldhash = "0.2.0" either = "1.13.0" [dependencies.bytemuck] diff --git a/crates/dreamchecker/Cargo.toml b/crates/dreamchecker/Cargo.toml index 466fc90f..68e51854 100644 --- a/crates/dreamchecker/Cargo.toml +++ b/crates/dreamchecker/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] dreammaker = { path = "../dreammaker" } serde_json = "1.0" -foldhash = "0.1.3" +foldhash = "0.2.0" [build-dependencies] chrono = "0.4.38" diff --git a/crates/dreammaker/Cargo.toml b/crates/dreammaker/Cargo.toml index bdbdd80e..affcb446 100644 --- a/crates/dreammaker/Cargo.toml +++ b/crates/dreammaker/Cargo.toml @@ -16,7 +16,7 @@ serde_derive = "1.0.213" toml = "0.5.11" phf = { version = "0.11.2", features = ["macros"] } color_space = "0.5.4" -foldhash = "0.1.3" +foldhash = "0.2.0" indexmap = "2.6.0" derivative = "2.2.0" get-size = "0.1.4" From 0290db5c752fa292f9824521515b603a2afd11dc Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Sat, 30 Aug 2025 14:47:12 -0700 Subject: [PATCH 186/197] Bump versions for suite 1.11 --- Cargo.lock | 8 ++++---- crates/dm-langserver/Cargo.toml | 2 +- crates/dmdoc/Cargo.toml | 2 +- crates/dmm-tools-cli/Cargo.toml | 2 +- crates/dreamchecker/Cargo.toml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fd6d3c5e..249ccbac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -419,7 +419,7 @@ dependencies = [ [[package]] name = "dm-langserver" -version = "1.10.0" +version = "1.11.0" dependencies = [ "bincode", "chrono", @@ -444,7 +444,7 @@ dependencies = [ [[package]] name = "dmdoc" -version = "1.10.0" +version = "1.11.0" dependencies = [ "chrono", "dreammaker", @@ -477,7 +477,7 @@ dependencies = [ [[package]] name = "dmm-tools-cli" -version = "1.10.0" +version = "1.11.0" dependencies = [ "chrono", "clap", @@ -502,7 +502,7 @@ dependencies = [ [[package]] name = "dreamchecker" -version = "1.10.0" +version = "1.11.0" dependencies = [ "chrono", "dreammaker", diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index eae17646..158e168d 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dm-langserver" -version = "1.10.0" +version = "1.11.0" authors = ["Tad Hardesty "] edition = "2021" diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index 48a886f5..ab3fda18 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dmdoc" -version = "1.10.0" +version = "1.11.0" authors = ["Tad Hardesty "] homepage = "https://github.com/SpaceManiac/SpacemanDMM/blob/master/crates/dmdoc/README.md" edition = "2021" diff --git a/crates/dmm-tools-cli/Cargo.toml b/crates/dmm-tools-cli/Cargo.toml index eeb6b47c..aa73eeb8 100644 --- a/crates/dmm-tools-cli/Cargo.toml +++ b/crates/dmm-tools-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dmm-tools-cli" -version = "1.10.0" +version = "1.11.0" authors = ["Tad Hardesty "] description = "BYOND map rendering and analysis tools powered by SpacemanDMM" edition = "2021" diff --git a/crates/dreamchecker/Cargo.toml b/crates/dreamchecker/Cargo.toml index 68e51854..5c9ee8fc 100644 --- a/crates/dreamchecker/Cargo.toml +++ b/crates/dreamchecker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dreamchecker" -version = "1.10.0" +version = "1.11.0" authors = ["Tad Hardesty "] edition = "2021" From 567e57b817fd5531df58a442beadff50e9befd9c Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Tue, 28 Oct 2025 18:11:42 -0700 Subject: [PATCH 187/197] Move version, authors, edition into workspace Cargo.toml --- Cargo.toml | 7 ++++++- crates/dm-langserver/Cargo.toml | 6 +++--- crates/dmdoc/Cargo.toml | 6 +++--- crates/dmm-tools-cli/Cargo.toml | 6 +++--- crates/dreamchecker/Cargo.toml | 6 +++--- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index db15750d..c5e3616f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver = "2" members = [ "crates/builtins-proc-macro", "crates/dap-types", @@ -11,7 +12,11 @@ members = [ "crates/interval-tree", #"crates/spaceman-dmm", ] -resolver = "2" + +[workspace.package] +version = "1.11.0" +authors = ["Tad Hardesty "] +edition = "2021" [profile.dev] opt-level = 2 diff --git a/crates/dm-langserver/Cargo.toml b/crates/dm-langserver/Cargo.toml index 158e168d..d2010f7e 100644 --- a/crates/dm-langserver/Cargo.toml +++ b/crates/dm-langserver/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "dm-langserver" -version = "1.11.0" -authors = ["Tad Hardesty "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] url = "2.5.2" diff --git a/crates/dmdoc/Cargo.toml b/crates/dmdoc/Cargo.toml index ab3fda18..bbe6923a 100644 --- a/crates/dmdoc/Cargo.toml +++ b/crates/dmdoc/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "dmdoc" -version = "1.11.0" -authors = ["Tad Hardesty "] homepage = "https://github.com/SpaceManiac/SpacemanDMM/blob/master/crates/dmdoc/README.md" -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] dreammaker = { path = "../dreammaker" } diff --git a/crates/dmm-tools-cli/Cargo.toml b/crates/dmm-tools-cli/Cargo.toml index aa73eeb8..252407c5 100644 --- a/crates/dmm-tools-cli/Cargo.toml +++ b/crates/dmm-tools-cli/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "dmm-tools-cli" -version = "1.11.0" -authors = ["Tad Hardesty "] description = "BYOND map rendering and analysis tools powered by SpacemanDMM" -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [[bin]] name = "dmm-tools" diff --git a/crates/dreamchecker/Cargo.toml b/crates/dreamchecker/Cargo.toml index 5c9ee8fc..3f9b9198 100644 --- a/crates/dreamchecker/Cargo.toml +++ b/crates/dreamchecker/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "dreamchecker" -version = "1.11.0" -authors = ["Tad Hardesty "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] dreammaker = { path = "../dreammaker" } From 848352e671a63fc343eb18345cb9c2079d1e178d Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Wed, 29 Oct 2025 23:34:54 -0700 Subject: [PATCH 188/197] Move LSP handler bodies outside the dispatch macro --- crates/dm-langserver/src/macros.rs | 76 ---------- crates/dm-langserver/src/main.rs | 218 ++++++++++++++++++++--------- 2 files changed, 150 insertions(+), 144 deletions(-) diff --git a/crates/dm-langserver/src/macros.rs b/crates/dm-langserver/src/macros.rs index 66800e2b..0a5afb91 100644 --- a/crates/dm-langserver/src/macros.rs +++ b/crates/dm-langserver/src/macros.rs @@ -1,81 +1,5 @@ //! Utility macros. -pub mod all_methods { - pub use crate::extras::*; - pub use lsp_types::request::*; -} - -pub mod all_notifications { - pub use crate::extras::*; - pub use lsp_types::notification::*; -} - -macro_rules! handle_method_call { - ($($(#[$attr:meta])* on $what:ident(&mut $self:ident, $p:pat) $b:block)*) => { - impl Engine { - fn handle_method_call_table(method: &str) -> Option Result> { - use macros::all_methods::*; - $(if method == <$what>::METHOD { - Some(|this, params_value| { - let params: <$what as Request>::Params = serde_json::from_value(params_value).map_err(invalid_request)?; - let result: <$what as Request>::Result = this.$what(params)?; - Ok(serde_json::to_value(result).expect("encode problem")) - }) - } else)* { - None - } - } - - $( - #[allow(non_snake_case)] - $(#[$attr])* - fn $what(&mut $self, $p: ::Params) - -> Result<::Result, jsonrpc::Error> - { - #[allow(unused_imports)] - use lsp_types::*; - #[allow(unused_imports)] - use lsp_types::request::*; - let _v = $b; - #[allow(unreachable_code)] { Ok(_v) } - } - )* - } - } -} - -macro_rules! handle_notification { - ($(on $what:ident(&mut $self:ident, $p:pat) $b:block)*) => { - impl Engine { - fn handle_notification_table(method: &str) -> Option Result<(), jsonrpc::Error>> { - use macros::all_notifications::*; - $(if method == <$what>::METHOD { - Some(|this, params_value| { - let params: <$what as Notification>::Params = serde_json::from_value(params_value).map_err(invalid_request)?; - this.$what(params) - }) - } else)* { - None - } - } - - $( - #[allow(non_snake_case)] - fn $what(&mut $self, $p: ::Params) - -> Result<(), jsonrpc::Error> - { - #[allow(unused_imports)] - use lsp_types::*; - #[allow(unused_imports)] - use lsp_types::notification::*; - let _v = $b; - #[allow(unreachable_code)] { Ok(_v) } - } - )* - } - } -} - macro_rules! handle_request { ($(on $what:ident(&mut $self:ident, $p:pat) $b:block)*) => { impl Debugger { diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index 43f56bfc..a0a94e2a 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -27,28 +27,26 @@ mod macros; mod background; mod color; mod completion; +mod debugger; mod document; mod extras; mod find_references; mod jrpc_io; mod symbol_search; -mod debugger; - -use std::collections::hash_map::Entry; -use std::collections::VecDeque; -use foldhash::{HashMap, HashMapExt, HashSet, HashSetExt}; -use std::path::PathBuf; -use std::rc::Rc; -use std::sync::{Arc, Mutex}; - -use jsonrpc::{Call, Output, Request, Response}; -use lsp_types::MessageType; -use url::Url; - +use crate::extras::{Reparse, StartDebugger}; use dm::annotation::{Annotation, AnnotationTree}; use dm::objtree::TypeRef; use dm::FileId; +use foldhash::{HashMap, HashMapExt, HashSet, HashSetExt}; +use jsonrpc::{Call, Output, Response}; +use lsp_types::{notification::*, request::*, *}; +use std::collections::hash_map::Entry; +use std::collections::VecDeque; +use std::path::PathBuf; +use std::rc::Rc; +use std::sync::{Arc, Mutex}; +use url::Url; fn main() { std::env::set_var("RUST_BACKTRACE", "1"); @@ -1024,8 +1022,8 @@ impl Engine { fn handle_input(&mut self, message: &str) { let mut outputs: Vec = match serde_json::from_str(message) { - Ok(Request::Single(call)) => self.handle_call(call).into_iter().collect(), - Ok(Request::Batch(calls)) => calls.into_iter().flat_map(|call| self.handle_call(call)).collect(), + Ok(jsonrpc::Request::Single(call)) => self.handle_call(call).into_iter().collect(), + Ok(jsonrpc::Request::Batch(calls)) => calls.into_iter().flat_map(|call| self.handle_call(call)).collect(), Err(decode_error) => vec![Output::Failure(jsonrpc::Failure { jsonrpc: VERSION, error: jsonrpc::Error { @@ -1065,7 +1063,7 @@ impl Engine { fn handle_method_call(&mut self, call: jsonrpc::MethodCall) -> Result { // "If the server receives a request... before the initialize request... // the response should be an error with code: -32002" - if call.method != ::METHOD && self.status != InitStatus::Running { + if call.method != Initialize::METHOD && self.status != InitStatus::Running { return Err(jsonrpc::Error { code: jsonrpc::ErrorCode::from(-32002), message: "method call before initialize or after shutdown".to_owned(), @@ -1112,10 +1110,52 @@ impl Engine { } } -handle_method_call! { +// ---------------------------------------------------------------------------- +// Request handlers + +type P = ::Params; +type R = Result<::Result, jsonrpc::Error>; + +macro_rules! handle_method_call_table { + ($($what:ident;)*) => { + fn handle_method_call_table(method: &str) -> Option Result> { + match method { + $($what::METHOD => { + Some(|this, params_value| { + let params: <$what as Request>::Params = serde_json::from_value(params_value).map_err(invalid_request)?; + let result: <$what as Request>::Result = this.$what(params)?; + Ok(serde_json::to_value(result).expect("encode problem")) + }) + },)* + _ => None + } + } + } +} + +#[allow(non_snake_case)] +impl Engine { + handle_method_call_table! { + Initialize; + Shutdown; + WorkspaceSymbol; + HoverRequest; + GotoDefinition; + GotoTypeDefinition; + References; + GotoImplementation; + Completion; + SignatureHelpRequest; + DocumentSymbolRequest; + DocumentColor; + ColorPresentationRequest; + DocumentLinkRequest; + StartDebugger; + } + // ------------------------------------------------------------------------ // basic setup - on Initialize(&mut self, init) { + fn Initialize(&mut self, init: P) -> R { if self.status != InitStatus::Starting { return Err(invalid_request("")) } @@ -1153,7 +1193,7 @@ handle_method_call! { } eprintln!(); - InitializeResult { + Ok(InitializeResult { capabilities: ServerCapabilities { definition_provider: Some(OneOf::Left(true)), workspace_symbol_provider: Some(OneOf::Left(true)), @@ -1189,17 +1229,18 @@ handle_method_call! { name: "dm-langserver".to_owned(), version: Some(env!("CARGO_PKG_VERSION").to_owned()), }), - } + }) } - on Shutdown(&mut self, ()) { + fn Shutdown(&mut self, (): P) -> R { self.status = InitStatus::ShuttingDown; + Ok(()) } // ------------------------------------------------------------------------ // actual stuff provision #[allow(deprecated)] // DocumentSymbol::deprecated is... deprecated. But we need to provide a `None` anyways. - on WorkspaceSymbol(&mut self, params) { + fn WorkspaceSymbol(&mut self, params: P) -> R { let query = symbol_search::Query::parse(¶ms.query); let query = match query { @@ -1274,10 +1315,10 @@ handle_method_call! { } } } - Some(results) + Ok(Some(results)) } - on HoverRequest(&mut self, params) { + fn HoverRequest(&mut self, params: P) -> R { let tdp = params.text_document_position_params; let (_, file_id, annotations) = self.get_annotations(&tdp.text_document.uri)?; let location = dm::Location { @@ -1413,16 +1454,16 @@ handle_method_call! { } } if results.is_empty() { - None + Ok(None) } else { - Some(Hover { + Ok(Some(Hover { range: None, contents: HoverContents::Array(results.into_iter().map(MarkedString::String).collect()), - }) + })) } } - on GotoDefinition(&mut self, params) { + fn GotoDefinition(&mut self, params: P) -> R { let tdp = params.text_document_position_params; let (real_file_id, file_id, annotations) = self.get_annotations(&tdp.text_document.uri)?; let location = dm::Location { @@ -1546,13 +1587,13 @@ handle_method_call! { } if results.is_empty() { - None + Ok(None) } else { - Some(GotoDefinitionResponse::Array(results)) + Ok(Some(GotoDefinitionResponse::Array(results))) } } - on GotoTypeDefinition(&mut self, params) { + fn GotoTypeDefinition(&mut self, params: P) -> R { // Like GotoDefinition, but only supports vars, then finds their types let tdp = params.text_document_position_params; let (_, file_id, annotations) = self.get_annotations(&tdp.text_document.uri)?; @@ -1598,16 +1639,16 @@ handle_method_call! { } if type_path.is_empty() { - None + Ok(None) } else if let Some(ty) = self.objtree.type_by_path(type_path) { let ty_loc = self.convert_location(ty.location, &ty.docs, &[&ty.path])?; - Some(GotoDefinitionResponse::Scalar(ty_loc)) + Ok(Some(GotoDefinitionResponse::Scalar(ty_loc))) } else { - None + Ok(None) } } - on References(&mut self, params) { + fn References(&mut self, params: P) -> R { // Like GotoDefinition, but looks up references instead let symbol_id = self.symbol_id_at(params.text_document_position)?; @@ -1619,17 +1660,17 @@ handle_method_call! { } } if result.is_empty() { - None + Ok(None) } else { let mut output = Vec::new(); for each in result { output.push(self.convert_location(*each, &Default::default(), &[])?); } - Some(output) + Ok(Some(output)) } } - on GotoImplementation(&mut self, params) { + fn GotoImplementation(&mut self, params: P) -> R { let tdp = params.text_document_position_params; let symbol_id = self.symbol_id_at(tdp)?; @@ -1641,17 +1682,17 @@ handle_method_call! { } } if result.is_empty() { - None + Ok(None) } else { let mut output = Vec::new(); for each in result { output.push(self.convert_location(*each, &Default::default(), &[])?); } - Some(GotoDefinitionResponse::Array(output)) + Ok(Some(GotoDefinitionResponse::Array(output))) } } - on Completion(&mut self, params) { + fn Completion(&mut self, params: P) -> R { let (_, file_id, annotations) = self.get_annotations(¶ms.text_document_position.text_document.uri)?; let location = dm::Location { file: file_id, @@ -1721,13 +1762,13 @@ handle_method_call! { } if results.is_empty() { - None + Ok(None) } else { - Some(CompletionResponse::Array(results)) + Ok(Some(CompletionResponse::Array(results))) } } - on SignatureHelpRequest(&mut self, params) { + fn SignatureHelpRequest(&mut self, params: P) -> R { let tdp = params.text_document_position_params; let (_, file_id, annotations) = self.get_annotations(&tdp.text_document.uri)?; let location = dm::Location { @@ -1798,11 +1839,11 @@ handle_method_call! { } }} - result + Ok(result) } #[allow(deprecated)] // DocumentSymbol::deprecated is... deprecated. But we need to provide a `None` anyways. - on DocumentSymbolRequest(&mut self, params) { + fn DocumentSymbolRequest(&mut self, params: P) -> R { fn name_and_detail(path: &[String], skip_front: usize) -> (String, Option) { let (name, rest) = path.split_last().unwrap(); ( @@ -1925,7 +1966,7 @@ handle_method_call! { // root let (_, file_id, annotations) = self.get_annotations(¶ms.text_document.uri)?; if annotations.is_empty() { - None + Ok(None) } else { let start = dm::Location { file: file_id, line: 0, column: 0 }; let end = dm::Location { file: file_id, line: !0, column: !0 }; @@ -1935,11 +1976,11 @@ handle_method_call! { // sort TreeBlocks first as well. vec.sort_by_key(|x| (x.0.start, std::cmp::Reverse(x.0.end), if matches!(x.1, Annotation::TreeBlock(_)) { 0 } else { 1 })); let mut iter = vec.into_iter().peekable(); - Some(DocumentSymbolResponse::Nested(find_document_symbols(&mut iter, end, 0))) + Ok(Some(DocumentSymbolResponse::Nested(find_document_symbols(&mut iter, end, 0)))) } } - on DocumentColor(&mut self, params) { + fn DocumentColor(&mut self, params: P) -> R { let content = self.docs.get_contents(¶ms.text_document.uri).map_err(invalid_request)?; let mut output = Vec::new(); for (start, end, [r, g, b, a]) in color::extract_colors(&content) { @@ -1956,16 +1997,16 @@ handle_method_call! { }, }); } - output + Ok(output) } - on ColorPresentationRequest(&mut self, params) { + fn ColorPresentationRequest(&mut self, params: P) -> R { let content = self.docs.get_contents(¶ms.text_document.uri).map_err(invalid_request)?; let chunk = document::get_range(&content, params.range)?; let color_format = color::ColorFormat::parse(chunk).unwrap_or_default(); // TODO: return compatible alternate presentations for converting // between "#..." and rgb(). - vec![ + Ok(vec![ ColorPresentation { label: color_format.format([ (params.color.red * 255.).round() as u8, @@ -1975,13 +2016,13 @@ handle_method_call! { ]), .. Default::default() }, - ] + ]) } - on DocumentLinkRequest(&mut self, params) { + fn DocumentLinkRequest(&mut self, params: P) -> R { let (_, file_id, annotations) = self.get_annotations(¶ms.text_document.uri)?; if annotations.is_empty() { - None + Ok(None) } else { let mut results = Vec::new(); for (span, annotation) in annotations.iter() { @@ -2007,13 +2048,13 @@ handle_method_call! { } } - Some(results) + Ok(Some(results)) } } // ------------------------------------------------------------------------ // debugger entry point - on StartDebugger(&mut self, params) { + fn StartDebugger(&mut self, params: P) -> R { let root_dir = match self.root.as_ref() { Some(url) => url_to_path(url)?, None => Default::default(), @@ -2027,14 +2068,47 @@ handle_method_call! { }; let (port, handle) = debugger::start_server(self.context.config().debugger.engine, params.dreamseeker_exe, params.env, db).map_err(invalid_request)?; self.threads.push(handle); - extras::StartDebuggerResult { port } + Ok(extras::StartDebuggerResult { port }) } } -handle_notification! { +// ---------------------------------------------------------------------------- +// Notification handlers + +type N = ::Params; +type NR = Result<(), jsonrpc::Error>; + +macro_rules! handle_notification_table { + ($($what:ident;)*) => { + fn handle_notification_table(method: &str) -> Option Result<(), jsonrpc::Error>> { + match method { + $($what::METHOD => { + Some(|this, params_value| { + let params: <$what as Notification>::Params = serde_json::from_value(params_value).map_err(invalid_request)?; + this.$what(params) + }) + },)* + _ => None + } + } + } +} + +#[allow(non_snake_case)] +impl Engine { + handle_notification_table! { + Initialized; + Reparse; + Cancel; + DidOpenTextDocument; + DidCloseTextDocument; + DidChangeTextDocument; + DidChangeConfiguration; + } + // ------------------------------------------------------------------------ // basic setup - on Initialized(&mut self, _) { + fn Initialized(&mut self, _: N) -> NR { let mut environment = None; if let Some(ref root) = self.root { // TODO: support non-files here @@ -2054,34 +2128,41 @@ handle_notification! { } else { self.show_status("single file mode"); } + Ok(()) } - on Reparse(&mut self, _p) { + fn Reparse(&mut self, _p: N) -> NR { eprintln!(); eprintln!("reparsing by request..."); self.context.errors_mut().clear(); - return self.Initialized(_p); + self.Initialized(_p) } - on Cancel(&mut self, _) { /* Not implemented, but don't log that. */ } + fn Cancel(&mut self, _: N) -> NR { + // Not implemented, but don't log that. + Ok(()) + } // ------------------------------------------------------------------------ // document content management - on DidOpenTextDocument(&mut self, params) { + fn DidOpenTextDocument(&mut self, params: N) -> NR { self.docs.open(params.text_document)?; + Ok(()) } - on DidCloseTextDocument(&mut self, params) { + fn DidCloseTextDocument(&mut self, params: N) -> NR { let url = self.docs.close(params.text_document)?; self.annotations.remove(&url); + Ok(()) } - on DidChangeTextDocument(&mut self, params) { + fn DidChangeTextDocument(&mut self, params: N) -> NR { let url = self.docs.change(params.text_document, params.content_changes)?; self.annotations.remove(&url); + Ok(()) } - on DidChangeConfiguration(&mut self, params) { + fn DidChangeConfiguration(&mut self, params: N) -> NR { if let Some(extools_dll) = params.settings["dreammaker"]["extoolsDLL"] .as_str() .filter(|path| !path.trim().is_empty()) @@ -2094,6 +2175,7 @@ handle_notification! { { self.debug_server_dll = Some(debug_server_dll.to_owned()); } + Ok(()) } } @@ -2195,7 +2277,7 @@ where T::Params: serde::Serialize, { let params = serde_json::to_value(params).expect("notification bad to_value"); - let request = Request::Single(Call::Notification(jsonrpc::Notification { + let request = jsonrpc::Request::Single(Call::Notification(jsonrpc::Notification { jsonrpc: VERSION, method: T::METHOD.to_owned(), params: value_to_params(params), From 6087530e0d728eacba6ad25d957879a9eff2f5ba Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Wed, 29 Oct 2025 23:55:20 -0700 Subject: [PATCH 189/197] Move DAP and extools handler bodies outside the dispatch macro --- crates/dm-langserver/src/debugger/auxtools.rs | 3 + crates/dm-langserver/src/debugger/extools.rs | 74 ++++++-- .../src/debugger/extools_types.rs | 1 + crates/dm-langserver/src/debugger/mod.rs | 172 ++++++++++++------ crates/dm-langserver/src/macros.rs | 55 ------ 5 files changed, 179 insertions(+), 126 deletions(-) diff --git a/crates/dm-langserver/src/debugger/auxtools.rs b/crates/dm-langserver/src/debugger/auxtools.rs index 69685205..e6dd0433 100644 --- a/crates/dm-langserver/src/debugger/auxtools.rs +++ b/crates/dm-langserver/src/debugger/auxtools.rs @@ -23,6 +23,7 @@ enum StreamState { } pub struct Auxtools { + #[allow(dead_code)] seq: Arc, responses: mpsc::Receiver, _thread: JoinHandle<()>, @@ -183,6 +184,7 @@ impl Auxtools { } } + #[allow(dead_code)] pub fn get_current_proc(&mut self, frame_id: u32) -> Result, Box> { self.send_or_disconnect(Request::CurrentInstruction { frame_id })?; @@ -192,6 +194,7 @@ impl Auxtools { } } + #[allow(dead_code)] pub fn get_line_number(&mut self, path: &str, override_id: u32, offset: u32) -> Result, Box> { self.send_or_disconnect(Request::LineNumber { proc: ProcRef { diff --git a/crates/dm-langserver/src/debugger/extools.rs b/crates/dm-langserver/src/debugger/extools.rs index 3a352f27..623c5b14 100644 --- a/crates/dm-langserver/src/debugger/extools.rs +++ b/crates/dm-langserver/src/debugger/extools.rs @@ -32,6 +32,7 @@ enum ExtoolsHolderInner { /// Used to avoid a layer of Option. None, Listening { + #[allow(dead_code)] port: u16, conn_rx: mpsc::Receiver, }, @@ -292,6 +293,7 @@ impl Extools { self.sender.send(Pause); } + #[allow(dead_code)] pub fn get_reference_type(&self, reference: Ref) -> Result> { // TODO: error handling self.sender.send(GetType(reference)); @@ -431,20 +433,57 @@ impl ExtoolsThread { } } -handle_extools! { - on Raw(&mut self, Raw(message)) { +type R = Result<(), Box>; + +macro_rules! handle_response_table { + ($($what:ident;)*) => { + fn handle_response_table(type_: &str) -> Option Result<(), Box>> { + match type_ { + $(<$what as Response>::TYPE => { + Some(|this, content| { + let deserialized: $what = serde_json::from_value(content)?; + this.$what(deserialized) + }) + },)* + _ => None + } + } + } +} + +#[allow(non_snake_case)] +impl ExtoolsThread { + handle_response_table! { + Raw; + BreakpointSet; + BreakpointUnset; + BreakpointHit; + Runtime; + CallStack; + DisassembledProc; + GetTypeResponse; + GetAllFieldsResponse; + ListContents; + GetSource; + BreakOnRuntime; + } + + fn Raw(&mut self, Raw(message): Raw) -> R { output!(in self.seq, "[extools] Message: {}", message); + Ok(()) } - on BreakpointSet(&mut self, BreakpointSet(_bp)) { + fn BreakpointSet(&mut self, BreakpointSet(_bp): BreakpointSet) -> R { debug_output!(in self.seq, "[extools] {}#{}@{} validated", _bp.proc, _bp.override_id, _bp.offset); + Ok(()) } - on BreakpointUnset(&mut self, _) { + fn BreakpointUnset(&mut self, _: BreakpointUnset) -> R { // silent + Ok(()) } - on BreakpointHit(&mut self, hit) { + fn BreakpointHit(&mut self, hit: BreakpointHit) -> R { match hit.reason { BreakpointHitReason::Step => { self.stopped(dap_types::StoppedEvent { @@ -467,9 +506,10 @@ handle_extools! { }); } } + Ok(()) } - on Runtime(&mut self, runtime) { + fn Runtime(&mut self, runtime: Runtime) -> R { output!(in self.seq, "[extools] Runtime in {}: {}", runtime.proc, runtime.message); self.stopped(dap_types::StoppedEvent { reason: dap_types::StoppedEvent::REASON_EXCEPTION.to_owned(), @@ -477,39 +517,47 @@ handle_extools! { .. Default::default() }); self.queue(&self.runtime_tx, runtime); + Ok(()) } - on CallStack(&mut self, stack) { + fn CallStack(&mut self, stack: CallStack) -> R { let mut map = self.threads.lock().unwrap(); map.clear(); map.entry(0).or_default().call_stack = stack.current; for (i, list) in stack.suspended.into_iter().enumerate() { map.entry((i + 1) as i64).or_default().call_stack = list; } + Ok(()) } - on DisassembledProc(&mut self, disasm) { + fn DisassembledProc(&mut self, disasm: DisassembledProc) -> R { self.queue(&self.bytecode_tx, disasm); + Ok(()) } - on GetTypeResponse(&mut self, response) { + fn GetTypeResponse(&mut self, response: GetTypeResponse) -> R { self.queue(&self.get_type_tx, response); + Ok(()) } - on GetAllFieldsResponse(&mut self, response) { + fn GetAllFieldsResponse(&mut self, response: GetAllFieldsResponse) -> R { self.queue(&self.get_field_tx, response); + Ok(()) } - on ListContents(&mut self, response) { + fn ListContents(&mut self, response: ListContents) -> R { self.queue(&self.get_list_contents_tx, response); + Ok(()) } - on GetSource(&mut self, response) { + fn GetSource(&mut self, response: GetSource) -> R { self.queue(&self.get_source_tx, response); + Ok(()) } - on BreakOnRuntime(&mut self, _) { + fn BreakOnRuntime(&mut self, _: BreakOnRuntime) -> R { // Either it worked or it didn't, nothing we can do about it now. + Ok(()) } } diff --git a/crates/dm-langserver/src/debugger/extools_types.rs b/crates/dm-langserver/src/debugger/extools_types.rs index ce9f382e..182b359e 100644 --- a/crates/dm-langserver/src/debugger/extools_types.rs +++ b/crates/dm-langserver/src/debugger/extools_types.rs @@ -4,6 +4,7 @@ //! //! > All communication happens over a TCP socket using a JSON-based protocol. //! > A null byte signifies the end of a message. +#![allow(dead_code)] use serde_json::Value as Json; use foldhash::HashMap; diff --git a/crates/dm-langserver/src/debugger/mod.rs b/crates/dm-langserver/src/debugger/mod.rs index 5a0e0412..30b7bb2a 100644 --- a/crates/dm-langserver/src/debugger/mod.rs +++ b/crates/dm-langserver/src/debugger/mod.rs @@ -1,7 +1,6 @@ //! Debug adapter protocol implementation for DreamSeeker. //! //! * https://microsoft.github.io/debug-adapter-protocol/ -#![allow(dead_code)] // In BYOND references 0xAA_BBBBBB, A is the the type and B is the instance ID. #![allow(clippy::unusual_byte_groupings)] @@ -385,8 +384,53 @@ impl Debugger { const EXCEPTION_FILTER_RUNTIMES: &str = "runtimes"; -handle_request! { - on Initialize(&mut self, params) { +type P = ::Params; +type R = Result<::Result, Box>; + +macro_rules! handle_request_table { + ($($what:ident;)*) => { + fn handle_request_table(command: &str) -> Option Result>> { + match command { + $($what::COMMAND => { + Some(|this, arguments| { + let params: <$what as Request>::Params = serde_json::from_value(arguments)?; + let result: <$what as Request>::Result = this.$what(params)?; + Ok(serde_json::to_value(result).expect("encode problem")) + }) + },)* + _ => None + } + } + } +} + +#[allow(non_snake_case)] +impl Debugger { + handle_request_table! { + Initialize; + LaunchVsc; + AttachVsc; + Disconnect; + ConfigurationDone; + Threads; + SetBreakpoints; + SetFunctionBreakpoints; + StackTrace; + Scopes; + Variables; + Continue; + StepIn; + Next; + StepOut; + Pause; + SetExceptionBreakpoints; + ExceptionInfo; + Evaluate; + Source; + Disassemble; + } + + fn Initialize(&mut self, params: P) -> R { // Initialize client caps from request self.client_caps = ClientCaps::parse(¶ms); @@ -403,7 +447,7 @@ handle_request! { // ... clientID, clientName, adapterID, locale, pathFormat // Tell the client our caps - Some(Capabilities { + Ok(Some(Capabilities { supportTerminateDebuggee: Some(true), supportsExceptionInfoRequest: Some(true), supportsConfigurationDoneRequest: Some(true), @@ -418,10 +462,10 @@ handle_request! { } ]), .. Default::default() - }) + })) } - on LaunchVsc(&mut self, params) { + fn LaunchVsc(&mut self, params: P) -> R { // Determine port number to pass if debugging is enabled. let debug = !params.base.noDebug.unwrap_or(false); @@ -482,9 +526,10 @@ handle_request! { // Launch the subprocess. self.launched = Some(Launched::new(self.seq.clone(), &self.dreamseeker_exe, self.env.as_ref(), ¶ms.dmb, engine_params)?); + Ok(()) } - on AttachVsc(&mut self, params) { + fn AttachVsc(&mut self, params: P) -> R { self.client = match self.engine { DebugEngine::Extools => { DebugClient::Extools(ExtoolsHolder::attach(self.seq.clone(), params.port.unwrap_or(extools::DEFAULT_PORT))?) @@ -494,9 +539,10 @@ handle_request! { DebugClient::Auxtools(Auxtools::connect(self.seq.clone(), params.port)?) } }; + Ok(()) } - on Disconnect(&mut self, params) { + fn Disconnect(&mut self, params: P) -> R { let default_terminate = self.launched.is_some(); let terminate = params.terminateDebuggee.unwrap_or(default_terminate); @@ -517,9 +563,10 @@ handle_request! { launched.detach(); } } + Ok(()) } - on ConfigurationDone(&mut self, ()) { + fn ConfigurationDone(&mut self, (): P) -> R { match &mut self.client { DebugClient::Extools(extools) => { let extools = extools.get()?; @@ -535,9 +582,10 @@ handle_request! { auxtools.configured()?; } } + Ok(()) } - on Threads(&mut self, ()) { + fn Threads(&mut self, (): P) -> R { match &mut self.client { DebugClient::Extools(extools) => { @@ -558,9 +606,9 @@ handle_request! { }); } - ThreadsResponse { + Ok(ThreadsResponse { threads, - } + }) }, DebugClient::Auxtools(auxtools) => { @@ -581,14 +629,14 @@ handle_request! { ); } - ThreadsResponse { + Ok(ThreadsResponse { threads, - } + }) } } } - on SetBreakpoints(&mut self, params) { + fn SetBreakpoints(&mut self, params: P) -> R { let Some(file_path) = params.source.path else { return Err(Box::new(GenericError("missing .source.path"))); }; @@ -668,7 +716,7 @@ handle_request! { } }); - SetBreakpointsResponse { breakpoints } + Ok(SetBreakpointsResponse { breakpoints }) } DebugClient::Auxtools(auxtools) => { @@ -745,12 +793,12 @@ handle_request! { } }); - SetBreakpointsResponse { breakpoints } + Ok(SetBreakpointsResponse { breakpoints }) } } } - on SetFunctionBreakpoints(&mut self, params) { + fn SetFunctionBreakpoints(&mut self, params: P) -> R { let file_id = FileId::default(); let inputs = params.breakpoints; @@ -811,7 +859,7 @@ handle_request! { } }); - SetFunctionBreakpointsResponse { breakpoints } + Ok(SetFunctionBreakpointsResponse { breakpoints }) } @@ -874,12 +922,12 @@ handle_request! { } }); - SetFunctionBreakpointsResponse { breakpoints } + Ok(SetFunctionBreakpointsResponse { breakpoints }) } } } - on StackTrace(&mut self, params) { + fn StackTrace(&mut self, params: P) -> R { match &mut self.client { DebugClient::Extools(extools) => { let extools = extools.get()?; @@ -939,10 +987,10 @@ handle_request! { frames.push(dap_frame); } - StackTraceResponse { + Ok(StackTraceResponse { totalFrames: Some(len as i64), stackFrames: frames, - } + }) } DebugClient::Auxtools(auxtools) => { @@ -1005,15 +1053,15 @@ handle_request! { frames.push(dap_frame); } - StackTraceResponse { + Ok(StackTraceResponse { totalFrames: Some(aux_frames_total as i64), stackFrames: frames, - } + }) } } } - on Scopes(&mut self, ScopesArguments { frameId }) { + fn Scopes(&mut self, ScopesArguments { frameId }: P) -> R { match &mut self.client { DebugClient::Extools(extools) => { let extools = extools.get()?; @@ -1027,7 +1075,7 @@ handle_request! { return Err(Box::new(GenericError2(format!("Stack frame out of range: {frameId} (thread {thread_id}, depth {frame_no})")))); }; - ScopesResponse { + Ok(ScopesResponse { scopes: vec![ Scope { name: "Locals".to_owned(), @@ -1049,7 +1097,7 @@ handle_request! { .. Default::default() }, ] - } + }) } DebugClient::Auxtools(auxtools) => { @@ -1080,14 +1128,14 @@ handle_request! { }); } - ScopesResponse { + Ok(ScopesResponse { scopes - } + }) } } } - on Variables(&mut self, params) { + fn Variables(&mut self, params: P) -> R { match &mut self.client { DebugClient::Extools(extools) => { let extools = extools.get()?; @@ -1187,7 +1235,7 @@ handle_request! { variablesReference: vt.to_variables_reference(), .. Default::default() })); - VariablesResponse { variables } + Ok(VariablesResponse { variables }) } else if mod2 == 0 { // locals let mut variables = Vec::with_capacity(1 + frame.locals.len()); @@ -1216,9 +1264,9 @@ handle_request! { variablesReference: vt.to_variables_reference(), .. Default::default() })); - VariablesResponse { variables } + Ok(VariablesResponse { variables }) } else { - return Err(Box::new(GenericError("Bad variables reference"))); + Err(Box::new(GenericError("Bad variables reference"))) } } @@ -1244,14 +1292,14 @@ handle_request! { }); } - VariablesResponse { + Ok(VariablesResponse { variables - } + }) } } } - on Continue(&mut self, _params) { + fn Continue(&mut self, _params: P) -> R { self.notify_continue(); match &mut self.client { @@ -1265,12 +1313,12 @@ handle_request! { } } - ContinueResponse { + Ok(ContinueResponse { allThreadsContinued: Some(true), - } + }) } - on StepIn(&mut self, params) { + fn StepIn(&mut self, params: P) -> R { self.notify_continue(); match &mut self.client { @@ -1283,9 +1331,10 @@ handle_request! { auxtools.step_into(params.threadId as u32)?; } } + Ok(()) } - on Next(&mut self, params) { + fn Next(&mut self, params: P) -> R { self.notify_continue(); match &mut self.client { @@ -1298,9 +1347,10 @@ handle_request! { auxtools.next(params.threadId as u32)?; } } + Ok(()) } - on StepOut(&mut self, params) { + fn StepOut(&mut self, params: P) -> R { self.notify_continue(); match &mut self.client { @@ -1313,9 +1363,10 @@ handle_request! { auxtools.step_out(params.threadId as u32)?; } } + Ok(()) } - on Pause(&mut self, _params) { + fn Pause(&mut self, _params: P) -> R { match &mut self.client { DebugClient::Extools(extools) => { let extools = extools.get()?; @@ -1326,9 +1377,10 @@ handle_request! { auxtools.pause()?; } } + Ok(()) } - on SetExceptionBreakpoints(&mut self, params) { + fn SetExceptionBreakpoints(&mut self, params: P) -> R { match &mut self.client { DebugClient::Extools(extools) => { let extools = extools.get()?; @@ -1339,38 +1391,39 @@ handle_request! { auxtools.set_catch_runtimes(params.filters.iter().any(|x| x == EXCEPTION_FILTER_RUNTIMES))?; } } + Ok(()) } - on ExceptionInfo(&mut self, _params) { + fn ExceptionInfo(&mut self, _params: P) -> R { match &mut self.client { DebugClient::Extools(extools) => { let extools = extools.get()?; // VSC shows exceptionId, description, stackTrace in that order. let message = extools.last_error_message(); - ExceptionInfoResponse { + Ok(ExceptionInfoResponse { exceptionId: message.unwrap_or_default().to_owned(), description: None, breakMode: ExceptionBreakMode::Always, details: None, - } + }) } DebugClient::Auxtools(auxtools) => { - ExceptionInfoResponse { + Ok(ExceptionInfoResponse { exceptionId: auxtools.get_last_error_message(), description: None, breakMode: ExceptionBreakMode::Always, details: None, - } + }) } } } - on Evaluate(&mut self, params) { - self.evaluate(params)? + fn Evaluate(&mut self, params: P) -> R { + self.evaluate(params) } - on Source(&mut self, params) { + fn Source(&mut self, params: P) -> R { let mut source_reference = params.sourceReference; if let Some(source) = params.source { if let Some(reference) = source.sourceReference { @@ -1383,13 +1436,13 @@ handle_request! { } if let Some(info) = self.stddef_dm_info.as_ref() { - SourceResponse::from(info.text.clone()) + Ok(SourceResponse::from(info.text.clone())) } else { - return Err(Box::new(GenericError("stddef.dm not available"))); + Err(Box::new(GenericError("stddef.dm not available"))) } } - on Disassemble(&mut self, params) { + fn Disassemble(&mut self, params: P) -> R { match &mut self.client { DebugClient::Extools(extools) => { let Some(captures) = MEMORY_REFERENCE_REGEX.captures(¶ms.memoryReference) else { @@ -1410,13 +1463,13 @@ handle_request! { }); } - DisassembleResponse { + Ok(DisassembleResponse { instructions: result - } + }) } DebugClient::Auxtools(_) => { - return Err(Box::new(GenericError("auxtools can't disassemble yet"))); + Err(Box::new(GenericError("auxtools can't disassemble yet"))) } } } @@ -1428,6 +1481,7 @@ lazy_static! { } #[derive(Default, Debug)] +#[allow(dead_code)] struct ClientCaps { lines_start_at_1: bool, columns_start_at_1: bool, @@ -1492,6 +1546,7 @@ impl SequenceNumber { }) } + #[allow(dead_code)] fn eprintln>(&self, output: S) { let mut output = output.into(); output.push('\n'); @@ -1570,6 +1625,7 @@ impl Request for AttachVsc { #[derive(Deserialize)] pub struct AttachRequestArgumentsVsc { #[serde(flatten)] + #[allow(dead_code)] base: AttachRequestArguments, port: Option, } diff --git a/crates/dm-langserver/src/macros.rs b/crates/dm-langserver/src/macros.rs index 0a5afb91..56d74364 100644 --- a/crates/dm-langserver/src/macros.rs +++ b/crates/dm-langserver/src/macros.rs @@ -1,59 +1,4 @@ //! Utility macros. - -macro_rules! handle_request { - ($(on $what:ident(&mut $self:ident, $p:pat) $b:block)*) => { - impl Debugger { - fn handle_request_table(command: &str) -> Option Result>> { - use dap_types::*; - $(if command == <$what>::COMMAND { - Some(|this, arguments| { - let params: <$what as Request>::Params = serde_json::from_value(arguments)?; - let result: <$what as Request>::Result = this.$what(params)?; - Ok(serde_json::to_value(result).expect("encode problem")) - }) - } else)* { - None - } - } - - $( - #[allow(non_snake_case)] - fn $what(&mut $self, $p: <$what as dap_types::Request>::Params) - -> Result<<$what as dap_types::Request>::Result, Box> - { - let _v = $b; - #[allow(unreachable_code)] { Ok(_v) } - } - )* - } - } -} - -macro_rules! handle_extools { - ($(on $what:ident(&mut $self:ident, $p:pat) $b:block)*) => { - impl ExtoolsThread { - fn handle_response_table(type_: &str) -> Option Result<(), Box>> { - $(if type_ == <$what as Response>::TYPE { - Some(|this, content| { - let deserialized: $what = serde_json::from_value(content)?; - this.$what(deserialized) - }) - } else)* { - None - } - } - - $( - #[allow(non_snake_case)] - fn $what(&mut $self, $p: $what) -> Result<(), Box> { - let _v = $b; - #[allow(unreachable_code)] { Ok(_v) } - } - )* - } - } -} - macro_rules! if_annotation { ($p:pat in $a:expr; $b:block) => { for (_, thing) in $a.clone() { From b8bb72a5435165449e128b722eeff67a392b7d05 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 30 Oct 2025 00:08:06 -0700 Subject: [PATCH 190/197] Change default debug engine to Auxtools --- crates/dreammaker/src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/dreammaker/src/config.rs b/crates/dreammaker/src/config.rs index 7c949069..56fa2ffc 100644 --- a/crates/dreammaker/src/config.rs +++ b/crates/dreammaker/src/config.rs @@ -185,7 +185,7 @@ impl PartialEq for WarningLevel { impl Default for DebugEngine { fn default() -> Self { - Self::Extools + Self::Auxtools } } From b6125848e29b9ff8cee479adc233225dc4f09bbf Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 30 Oct 2025 00:18:43 -0700 Subject: [PATCH 191/197] Add a missing integrity check for bundled DLLs --- crates/dm-langserver/build.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/dm-langserver/build.rs b/crates/dm-langserver/build.rs index 54309c45..9616fb61 100644 --- a/crates/dm-langserver/build.rs +++ b/crates/dm-langserver/build.rs @@ -84,6 +84,8 @@ fn download_dll(out_dir: &Path, fname: &str, tag: &str, url: &str, sha256: &str) std::io::copy( &mut ureq::get(url).call().expect("Error downloading DLL to bundle").into_reader(), - &mut std::fs::File::create(full_path).unwrap(), + &mut std::fs::File::create(&full_path).unwrap(), ).unwrap(); + + assert_eq!(sha256, sha256::try_digest(&full_path).unwrap()); } From ab4e94def1afdc7c4e9419c698a7890887ddba99 Mon Sep 17 00:00:00 2001 From: Krashly <104254674+Krashly@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:57:10 +0300 Subject: [PATCH 192/197] Fix displace filter flags (#445) The Displace filter has the ability to add an Overlay flag. It works properly and as expected. Link to the Byond documentation: https://www.byond.com/docs/ref/#/{notes}/filters/displace > The optional FILTER_OVERLAY flag is supported for the flags argument, > which will overlay the displaced image onto the original. --- crates/dreammaker/src/ast.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 6c336826..69786e03 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -1492,7 +1492,7 @@ pub static VALID_FILTER_TYPES: phf::Map<&'static str, &[&str]> = phf_map! { "angular_blur" => &[ "x", "y", "size" ], "bloom" => &[ "threshold", "size", "offset", "alpha" ], "color" => &[ "color", "space" ], - "displace" => &[ "x", "y", "size", "icon", "render_source" ], + "displace" => &[ "x", "y", "size", "icon", "render_source", "flags" ], "drop_shadow" => &[ "x", "y", "size", "offset", "color"], "blur" => &[ "size" ], "layer" => &[ "x", "y", "icon", "render_source", "flags", "color", "transform", "blend_mode" ], @@ -1508,6 +1508,7 @@ pub static VALID_FILTER_TYPES: phf::Map<&'static str, &[&str]> = phf_map! { pub static VALID_FILTER_FLAGS: phf::Map<&'static str, (&str, bool, bool, &[&str])> = phf_map! { "alpha" => ("flags", false, true, &[ "MASK_INVERSE", "MASK_SWAP" ]), "color" => ("space", true, false, &[ "FILTER_COLOR_RGB", "FILTER_COLOR_HSV", "FILTER_COLOR_HSL", "FILTER_COLOR_HCY" ]), + "displace" => ("flags", false, true, &[ "FILTER_OVERLAY" ]), "layer" => ("flags", true, true, &[ "FILTER_OVERLAY", "FILTER_UNDERLAY" ]), "rays" => ("flags", false, true, &[ "FILTER_OVERLAY", "FILTER_UNDERLAY" ]), "outline" => ("flags", false, true, &[ "OUTLINE_SHARP", "OUTLINE_SQUARE" ]), From 660457818ecfce691374d7dffa8d8203a21410d3 Mon Sep 17 00:00:00 2001 From: ZeWaka Date: Thu, 18 Dec 2025 16:04:08 -0800 Subject: [PATCH 193/197] Fix parsing of alist for-k,v key type filtering (#447) fix parsing of ```dm var/alist/foo = list() for (var/index as num, C in foo) world << index ``` currently `got ',', expected one of: '|', 'in', ')'` also fixes two clippy warnings ref: bottom of https://www.byond.com/docs/ref/#/proc/for/list --- crates/dm-langserver/src/find_references.rs | 2 +- crates/dreamchecker/src/lib.rs | 2 +- crates/dreammaker/src/ast.rs | 1 + crates/dreammaker/src/config.rs | 9 ++------ crates/dreammaker/src/objtree.rs | 1 + crates/dreammaker/src/parser.rs | 11 +++++++++- crates/dreammaker/tests/ast_tests.rs | 23 +++++++++++++++++++++ 7 files changed, 39 insertions(+), 10 deletions(-) diff --git a/crates/dm-langserver/src/find_references.rs b/crates/dm-langserver/src/find_references.rs index 31857839..138d7956 100644 --- a/crates/dm-langserver/src/find_references.rs +++ b/crates/dm-langserver/src/find_references.rs @@ -327,7 +327,7 @@ impl<'o> WalkProc<'o> { Statement::Label { name: _, block } => self.visit_block(block), Statement::Del(expr) => { self.visit_expression(location, expr, None); }, Statement::ForKeyValue(for_key_value) => { - let ForKeyValueStatement { var_type, key, value, in_list, block } = &**for_key_value; + let ForKeyValueStatement { var_type, key, key_input_type: _, value, in_list, block } = &**for_key_value; if let Some(in_list) = in_list { self.visit_expression(location, in_list, None); } diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 6b7f3f96..62ea2322 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -1583,7 +1583,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Statement::Label { name: _, block } => { self.visit_block(block, &mut local_vars.clone(), false); }, Statement::Del(expr) => { self.visit_expression(location, expr, None, local_vars); }, Statement::ForKeyValue(for_key_value) => { - let ForKeyValueStatement { var_type, key, value, in_list, block } = &**for_key_value; + let ForKeyValueStatement { var_type, key, key_input_type: _, value, in_list, block } = &**for_key_value; let mut scoped_locals = local_vars.clone(); if let Some(in_list) = in_list { let list = self.visit_expression(location, in_list, None, &mut scoped_locals); diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 69786e03..27864c9b 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -1454,6 +1454,7 @@ pub struct ForListStatement { pub struct ForKeyValueStatement { pub var_type: Option, pub key: Ident2, + pub key_input_type: Option, pub value: Ident2, /// Defaults to 'world'. pub in_list: Option, diff --git a/crates/dreammaker/src/config.rs b/crates/dreammaker/src/config.rs index 56fa2ffc..29f9946d 100644 --- a/crates/dreammaker/src/config.rs +++ b/crates/dreammaker/src/config.rs @@ -85,11 +85,12 @@ pub enum WarningLevel { } /// Available debug engines. -#[derive(Debug, Deserialize, Clone, Copy, PartialEq)] +#[derive(Debug, Default, Deserialize, Clone, Copy, PartialEq)] pub enum DebugEngine { #[serde(alias = "extools")] Extools, #[serde(alias = "auxtools")] + #[default] Auxtools, } @@ -183,12 +184,6 @@ impl PartialEq for WarningLevel { } } -impl Default for DebugEngine { - fn default() -> Self { - Self::Auxtools - } -} - /// Config parse error #[derive(Debug)] pub enum Error { diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index 940b4697..ce6811cf 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -1267,6 +1267,7 @@ impl ObjectTreeBuilder { } // an entry which is definitely a proc because an argument list is specified + #[allow(clippy::too_many_arguments)] fn add_proc<'a, I: Iterator>( &mut self, context: &Context, diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index a07878db..fc0f27f7 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -1410,6 +1410,14 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // for (Var = Low to High) require!(self.exact(Token::Punct(Punctuation::LParen))); let init = self.simple_statement(true, vars)?; + + // We do this here otherwise it's consumed after the comma (for key-value loops with typed keys) + let key_input_type = if let Some(()) = self.exact_ident("as")? { + Some(require!(self.input_type())) + } else { + None + }; + // three-pronged loop form ("for loop") if let Some(()) = self.semicolon()? { // for(init; test; [inc]) @@ -1463,7 +1471,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { }, _ => return Err(self.error("for (var/key, value) requires a 'var' keyword")), }; - // Value is the lhs of for(var, k [v in x]) + // Value is the lhs of for(var/k, [v in x]) // It should also pass only if it's an ident let value = match lhs.into_term() { Some(Term::Ident(value)) => value, @@ -1477,6 +1485,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { spanned(Statement::ForKeyValue(Box::new(ForKeyValueStatement { var_type: Some(var_type.expect("/")), key: key.into(), + key_input_type, value: value.into(), in_list: Some(*rhs), // We'll assume the rhs of [v in x] is a list. Any other case, DM will catch anyway. block: require!(self.block(&LoopContext::ForLoop)), diff --git a/crates/dreammaker/tests/ast_tests.rs b/crates/dreammaker/tests/ast_tests.rs index a5e86a63..bc4482be 100644 --- a/crates/dreammaker/tests/ast_tests.rs +++ b/crates/dreammaker/tests/ast_tests.rs @@ -288,3 +288,26 @@ fn proc_operator_slash() { tree.expect("/datum/operator").get_proc("bar").unwrap(); }); } + +#[test] +fn for_key_value_with_as() { + // https://github.com/SpaceManiac/SpacemanDMM/issues/421 - 'as' keyword in for-key-value loops + with_code(" +/proc/test() + var/alist/foo = list() + for (var/index as num, C in foo) + world << index + ", |context, tree| { + context.assert_success(); + + let proc = tree.root().get_proc("test").unwrap(); + let code = proc.get().code.as_ref().unwrap(); + + if let Statement::ForKeyValue(ref fkv) = code[1].elem { + assert!(fkv.key_input_type.is_some()); + assert_eq!(fkv.key_input_type.unwrap(), InputType::NUM); + } else { + panic!("Expected ForKeyValue statement, got {:?}", code[1].elem); + } + }); +} From 70176ca27d1e499d97ca25df0245fa40f6a89e29 Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Thu, 18 Dec 2025 16:32:08 -0800 Subject: [PATCH 194/197] Implement compile time warning for datum[] (#397) Lummox recently made this a RUNTIME error, but also irrespective of that this tends to mask HELL vars[] security holes. We really should be linting for it. I had to implement operator overloading support for the builtin parser, which was far more annoying then I expected. Bit scuffed, but it works. (I am unsure of how to parse for "" though so I left that unimplemented) This will likely throw errors on most codebases, I'm unsure of how to handle that. --- CONFIGURING.md | 1 + crates/builtins-proc-macro/src/lib.rs | 110 +++++++++++++++++++++++++- crates/dreamchecker/src/lib.rs | 8 ++ crates/dreammaker/src/builtins.rs | 4 + 4 files changed, 122 insertions(+), 1 deletion(-) diff --git a/CONFIGURING.md b/CONFIGURING.md index 34a59dc0..a868fafa 100644 --- a/CONFIGURING.md +++ b/CONFIGURING.md @@ -50,6 +50,7 @@ Raised by DreamChecker: * `control_condition_static` - Raised on a control condition such as `if`/`while` having a static condition such as `1` or `"string"` * `if_condition_determinate` - Raised on if condition being always true or always false * `loop_condition_determinate` - Raised on loop condition such as in `for` being always true or always false +* `improper_index` - Raised on accessing a non list with [] Raised by Lexer: diff --git a/crates/builtins-proc-macro/src/lib.rs b/crates/builtins-proc-macro/src/lib.rs index 9d64abcf..64be58a9 100644 --- a/crates/builtins-proc-macro/src/lib.rs +++ b/crates/builtins-proc-macro/src/lib.rs @@ -11,6 +11,7 @@ use syn::*; struct Header { attrs: Vec, path: Vec, + operator_overload_target: Option, } impl Header { @@ -24,7 +25,110 @@ impl Header { input.parse::()?; self.path.push(Ident::parse_any(input)?); } + if let Some(final_ident) = self.path.last() { + // If we find an operator{some token}() pattern we allow the some token part + if final_ident == "operator" { + self.parse_operator(input)?; + } + } + Ok(()) + } + fn parse_operator(&mut self, input: ParseStream) -> Result<()> { + let text_token: Option<&str> = if input.parse::().is_ok() { + if input.parse::().is_ok() { + Some("%%") + } else if input.parse::().is_ok() { + Some("%%=") + } else { + Some("%") + } + } else if input.parse::().is_ok() { + Some("&") + } else if input.parse::().is_ok() { + Some("&=") + } else if input.parse::().is_ok() { + if input.parse::().is_ok() { + Some("**") + } else { + Some("*") + } + } else if input.parse::().is_ok() { + Some("*=") + } else if input.parse::().is_ok() { + Some("/") + } else if input.parse::().is_ok() { + Some("/=") + } else if input.parse::().is_ok() { + if input.parse::().is_ok() { + Some("++") + } else { + Some("+") + } + } else if input.parse::().is_ok() { + Some("+=") + } else if input.parse::().is_ok() { + if input.parse::().is_ok() { + Some("--") + } else { + Some("-") + } + } else if input.parse::().is_ok() { + Some("-=") + } else if input.parse::().is_ok() { + Some("<") + } else if input.parse::().is_ok() { + Some("<<") + } else if input.parse::().is_ok() { + Some("<<=") + } else if input.parse::().is_ok() { + Some("<=") + } else if input.parse::=]>().is_ok() { + Some(">=") + } else if input.parse::>]>().is_ok() { + Some(">>") + } else if input.parse::>=]>().is_ok() { + Some(">>=") + } else if input.parse::().is_ok() { + Some("^") + } else if input.parse::().is_ok() { + Some("^=") + } else if input.parse::().is_ok() { + Some("|") + } else if input.parse::().is_ok() { + Some("|=") + } else if input.parse::().is_ok() { + if input.parse::().is_ok() { + Some("~=") + } else { + Some("~") + } + } else if input.parse::().is_ok() { + Some("~") + } else if input.peek(Token![:]) && input.peek2(Token![=]) { + input.parse::()?; + input.parse::()?; + Some(":=") + } else if self.brackets_next(input).is_ok() { + if input.parse::().is_ok() { + Some("[]=") + } else { + Some("[]") + } + } else { + // Todo: Implement operator""() support. Unsure how to expect an empty string + None + }; + if let Some(text) = text_token { + self.operator_overload_target = Some(text.to_string()); + } + Ok(()) + } + + fn brackets_next(&mut self, input: ParseStream) -> Result<()> { + // Sorry + let _bracket_dummy; + bracketed!(_bracket_dummy in input); Ok(()) } } @@ -143,7 +247,11 @@ pub fn builtins_table(input: TokenStream) -> TokenStream { let mut output = Vec::new(); for entry in builtins { let span = entry.header.path.first().unwrap().span(); - let lit_strs: Vec<_> = entry.header.path.into_iter().map(|x| LitStr::new(&x.to_string(), x.span())).collect(); + let mut lit_strs: Vec<_> = entry.header.path.into_iter().map(|x| LitStr::new(&x.to_string(), x.span())).collect(); + if let Some(operator) = entry.header.operator_overload_target { + let last_entry = lit_strs.pop().unwrap(); + lit_strs.push(LitStr::new((last_entry.value() + operator.as_str()).as_str(), last_entry.span())); + } let path = quote! { &[ #(#lit_strs),* ] }; diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 62ea2322..5988f070 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -2105,6 +2105,14 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } res }, + StaticType::Type(typeref) => { + if typeref.get_proc("operator[]").is_none() { + error(location, format!("invalid list access on {}", typeref.path)) + .with_errortype("improper_index") + .register(self.context); + } + lhs.clone() + }, _ => lhs.clone() // carry through fix_hint } }, diff --git a/crates/dreammaker/src/builtins.rs b/crates/dreammaker/src/builtins.rs index 5985237e..1506d2d5 100644 --- a/crates/dreammaker/src/builtins.rs +++ b/crates/dreammaker/src/builtins.rs @@ -626,6 +626,7 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { list/var/const/parent_type; list/var/tag; list/var/const/list/vars; + list/proc/operator[](); list/proc/Add(Item1, Item2/*,...*/); list/proc/Copy(Start=1, End=0); list/proc/Cut(Start=1, End=0); @@ -642,6 +643,7 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { alist/var/const/type; alist/var/const/parent_type; alist/var/tag; + alist/proc/operator[](); alist/proc/Add(Item1, Item2/*,...*/); alist/proc/Copy(Start=1, End=0); alist/proc/Cut(Start=1, End=0); @@ -1110,6 +1112,7 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { savefile/var/list/dir; savefile/var/eof; savefile/var/name; + savefile/proc/operator[](); savefile/proc/ExportText(/* path=cd, file */); savefile/proc/Flush(); savefile/proc/ImportText(/* path=cd, file */); @@ -1282,6 +1285,7 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) { vector/var/y; vector/var/z; + vector/proc/operator[](); vector/proc/Cross(B); vector/proc/Dot(B); vector/proc/Interpolate(B, t); From 1259ccd3a039236d61502e5f8d430b700cb08618 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 18 Dec 2025 21:13:19 -0800 Subject: [PATCH 195/197] Apply most rustfmt suggestions --- crates/builtins-proc-macro/src/lib.rs | 38 +- crates/dap-types/src/lib.rs | 23 +- crates/dm-langserver/build.rs | 31 +- crates/dm-langserver/src/background.rs | 4 +- crates/dm-langserver/src/color.rs | 70 +- crates/dm-langserver/src/completion.rs | 61 +- crates/dm-langserver/src/debugger/auxtools.rs | 146 +- crates/dm-langserver/src/debugger/evaluate.rs | 15 +- crates/dm-langserver/src/debugger/extools.rs | 121 +- .../src/debugger/extools_types.rs | 25 +- crates/dm-langserver/src/debugger/launched.rs | 35 +- crates/dm-langserver/src/debugger/mod.rs | 471 +++-- crates/dm-langserver/src/document.rs | 52 +- crates/dm-langserver/src/find_references.rs | 345 +++- crates/dm-langserver/src/main.rs | 631 ++++-- crates/dm-langserver/src/symbol_search.rs | 25 +- crates/dmdoc/src/main.rs | 840 ++++---- crates/dmdoc/src/markdown.rs | 50 +- crates/dmdoc/src/template.rs | 26 +- crates/dmm-tools-cli/src/main.rs | 225 ++- .../examples/duplicate_icon_states.rs | 4 +- crates/dmm-tools/src/dmi.rs | 9 +- crates/dmm-tools/src/dmi/render.rs | 89 +- crates/dmm-tools/src/dmm.rs | 111 +- crates/dmm-tools/src/dmm/read.rs | 44 +- crates/dmm-tools/src/dmm/save_tgm.rs | 3 +- crates/dmm-tools/src/icon_cache.rs | 29 +- crates/dmm-tools/src/lib.rs | 2 +- crates/dmm-tools/src/minimap.rs | 69 +- .../src/render_passes/icon_smoothing.rs | 90 +- .../src/render_passes/icon_smoothing_2020.rs | 137 +- crates/dmm-tools/src/render_passes/mod.rs | 294 ++- crates/dmm-tools/src/render_passes/random.rs | 61 +- .../src/render_passes/smart_cables.rs | 14 +- .../dmm-tools/src/render_passes/structures.rs | 21 +- .../src/render_passes/transit_tube.rs | 13 +- crates/dmm-tools/tests/parse_codebase.rs | 2 +- crates/dreamchecker/src/lib.rs | 1724 ++++++++++++----- crates/dreamchecker/src/main.rs | 24 +- crates/dreamchecker/src/switch_rand_range.rs | 9 +- crates/dreamchecker/src/test_helpers.rs | 6 +- crates/dreamchecker/src/type_expr.rs | 26 +- .../dreamchecker/tests/branch_eval_tests.rs | 69 +- crates/dreamchecker/tests/call_ext_tests.rs | 8 +- crates/dreamchecker/tests/directive_tests.rs | 43 +- crates/dreamchecker/tests/kwargs_tests.rs | 50 +- crates/dreamchecker/tests/local_vars_tests.rs | 3 +- crates/dreamchecker/tests/new_tests.rs | 22 +- crates/dreamchecker/tests/operator_tests.rs | 28 +- crates/dreamchecker/tests/private_tests.rs | 36 +- crates/dreamchecker/tests/proc_tests.rs | 19 +- crates/dreamchecker/tests/sleep_pure_tests.rs | 34 +- .../dreamchecker/tests/static_type_tests.rs | 13 +- .../tests/switch_rand_range_tests.rs | 53 +- .../dreamchecker/tests/var_declare_tests.rs | 26 +- crates/dreammaker/examples/count-vars.rs | 10 +- crates/dreammaker/examples/flags.rs | 46 +- crates/dreammaker/examples/lint.rs | 3 +- crates/dreammaker/src/annotation.rs | 15 +- crates/dreammaker/src/ast.rs | 122 +- crates/dreammaker/src/builtins.rs | 92 +- crates/dreammaker/src/config.rs | 12 +- crates/dreammaker/src/constants.rs | 433 +++-- crates/dreammaker/src/dmi.rs | 95 +- crates/dreammaker/src/docs.rs | 40 +- crates/dreammaker/src/error.rs | 76 +- crates/dreammaker/src/indents.rs | 77 +- crates/dreammaker/src/lexer.rs | 276 +-- crates/dreammaker/src/lib.rs | 44 +- crates/dreammaker/src/objtree.rs | 275 ++- crates/dreammaker/src/parser.rs | 538 +++-- crates/dreammaker/src/preprocessor.rs | 513 +++-- crates/dreammaker/tests/annotation_tests.rs | 3 +- crates/dreammaker/tests/ast_tests.rs | 484 +++-- crates/dreammaker/tests/constants_tests.rs | 6 +- crates/dreammaker/tests/format_tests.rs | 30 +- crates/dreammaker/tests/lexer_tests.rs | 21 +- crates/dreammaker/tests/location_tests.rs | 19 +- crates/dreammaker/tests/macro_tests.rs | 76 +- crates/dreammaker/tests/pipeline_tests.rs | 10 +- crates/interval-tree/src/iterators.rs | 4 +- crates/interval-tree/src/node.rs | 6 +- rustfmt.toml | 1 + 83 files changed, 6448 insertions(+), 3298 deletions(-) create mode 100644 rustfmt.toml diff --git a/crates/builtins-proc-macro/src/lib.rs b/crates/builtins-proc-macro/src/lib.rs index 64be58a9..2130d4fb 100644 --- a/crates/builtins-proc-macro/src/lib.rs +++ b/crates/builtins-proc-macro/src/lib.rs @@ -152,9 +152,7 @@ impl Parse for ProcArgument { input.parse::()?; input.parse::()?; } - Ok(ProcArgument { - name, - }) + Ok(ProcArgument { name }) } } @@ -172,7 +170,9 @@ impl EntryBody { } else if input.peek(syn::token::Paren) { let content; parenthesized!(content in input); - Ok(EntryBody::Proc(content.parse_terminated(ProcArgument::parse)?)) + Ok(EntryBody::Proc( + content.parse_terminated(ProcArgument::parse)?, + )) } else if path.iter().any(|i| i == "var") { Ok(EntryBody::Variable(None)) } else { @@ -192,17 +192,18 @@ impl Parse for BuiltinEntry { let body = EntryBody::parse_with_path(&header.path, input)?; input.parse::()?; - Ok(BuiltinEntry { - header, - body, - }) + Ok(BuiltinEntry { header, body }) } } struct BuiltinsTable(Vec); impl BuiltinsTable { - fn parse_with_header_into(vec: &mut Vec, header: &Header, input: ParseStream) -> Result<()> { + fn parse_with_header_into( + vec: &mut Vec, + header: &Header, + input: ParseStream, + ) -> Result<()> { while !input.is_empty() { let mut new_header = header.clone(); new_header.parse_mut(input)?; @@ -247,10 +248,18 @@ pub fn builtins_table(input: TokenStream) -> TokenStream { let mut output = Vec::new(); for entry in builtins { let span = entry.header.path.first().unwrap().span(); - let mut lit_strs: Vec<_> = entry.header.path.into_iter().map(|x| LitStr::new(&x.to_string(), x.span())).collect(); + let mut lit_strs: Vec<_> = entry + .header + .path + .into_iter() + .map(|x| LitStr::new(&x.to_string(), x.span())) + .collect(); if let Some(operator) = entry.header.operator_overload_target { let last_entry = lit_strs.pop().unwrap(); - lit_strs.push(LitStr::new((last_entry.value() + operator.as_str()).as_str(), last_entry.span())); + lit_strs.push(LitStr::new( + (last_entry.value() + operator.as_str()).as_str(), + last_entry.span(), + )); } let path = quote! { &[ #(#lit_strs),* ] @@ -296,11 +305,14 @@ pub fn builtins_table(input: TokenStream) -> TokenStream { } }, EntryBody::Proc(args) => { - let args: Vec<_> = args.into_iter().map(|x| LitStr::new(&x.name.to_string(), x.name.span())).collect(); + let args: Vec<_> = args + .into_iter() + .map(|x| LitStr::new(&x.name.to_string(), x.name.span())) + .collect(); quote_spanned! { span => tree.add_builtin_proc(#path, &[ #(#args),* ]) #attr_calls; } - } + }, }; output.push(line); } diff --git a/crates/dap-types/src/lib.rs b/crates/dap-types/src/lib.rs index 14b4b33e..303b05e4 100644 --- a/crates/dap-types/src/lib.rs +++ b/crates/dap-types/src/lib.rs @@ -4,9 +4,9 @@ #![deny(unsafe_code)] #![allow(non_snake_case)] +use foldhash::HashMap; use serde_derive::{Deserialize, Serialize}; use serde_json::Value; -use foldhash::HashMap; pub trait Request { type Params; @@ -175,8 +175,8 @@ pub struct ThreadEvent { pub reason: String, /** - * The identifier of the thread. - */ + * The identifier of the thread. + */ pub threadId: i64, } @@ -610,13 +610,19 @@ pub struct EvaluateResponse { impl From for EvaluateResponse { fn from(result: String) -> EvaluateResponse { - EvaluateResponse { result, .. Default::default() } + EvaluateResponse { + result, + ..Default::default() + } } } impl From<&str> for EvaluateResponse { fn from(result: &str) -> EvaluateResponse { - EvaluateResponse { result: result.to_owned(), .. Default::default() } + EvaluateResponse { + result: result.to_owned(), + ..Default::default() + } } } @@ -928,7 +934,10 @@ pub struct SourceResponse { impl From for SourceResponse { fn from(content: String) -> SourceResponse { - SourceResponse { content, mimeType: None } + SourceResponse { + content, + mimeType: None, + } } } @@ -1660,7 +1669,6 @@ pub struct Source { * Optional data that a debug adapter might want to loop through the client. The client should leave the data intact and persist it across sessions. The client should not interpret the data. */ pub adapterData: Option, - /*/** * The checksums associated with this file. */ @@ -1753,7 +1761,6 @@ pub struct StackFrame { * The module associated with this frame, if any. */ moduleId?: number | string;*/ - /** * An optional hint for how to present this frame in the UI. A value of 'label' can be used to indicate that the frame is an artificial frame that is used as a visual label or separator. A value of 'subtle' can be used to change the appearance of a frame in a 'subtle' way. */ diff --git a/crates/dm-langserver/build.rs b/crates/dm-langserver/build.rs index 9616fb61..456a4c20 100644 --- a/crates/dm-langserver/build.rs +++ b/crates/dm-langserver/build.rs @@ -13,7 +13,7 @@ fn main() { match read_commit() { Ok(commit) => writeln!(f, "commit: {commit}").unwrap(), - Err(err) => println!("cargo:warning=Failed to fetch commit info: {err}") + Err(err) => println!("cargo:warning=Failed to fetch commit info: {err}"), } writeln!(f, "build date: {}", chrono::Utc::now().date_naive()).unwrap(); @@ -43,7 +43,10 @@ fn read_commit() -> Result { let head = repo.head()?.peel_to_commit()?.id(); let mut all_tags = Vec::new(); - repo.tag_foreach(|oid, _| { all_tags.push(oid); true })?; + repo.tag_foreach(|oid, _| { + all_tags.push(oid); + true + })?; let mut best = None; for tag_id in all_tags { @@ -54,7 +57,7 @@ fn read_commit() -> Result { match best { None => best = Some(ahead), Some(prev) if ahead < prev => best = Some(ahead), - _ => {} + _ => {}, } } if ahead == 0 { @@ -64,8 +67,12 @@ fn read_commit() -> Result { } match best { - None | Some(0) => {} - Some(ahead) => println!("cargo:rustc-env=CARGO_PKG_VERSION={}+{}", std::env::var("CARGO_PKG_VERSION").unwrap(), ahead), + None | Some(0) => {}, + Some(ahead) => println!( + "cargo:rustc-env=CARGO_PKG_VERSION={}+{}", + std::env::var("CARGO_PKG_VERSION").unwrap(), + ahead + ), } Ok(head.to_string()) @@ -73,7 +80,11 @@ fn read_commit() -> Result { fn download_dll(out_dir: &Path, fname: &str, tag: &str, url: &str, sha256: &str) { let full_path = out_dir.join(fname); - println!("cargo:rustc-env=BUNDLE_PATH_{}={}", fname, full_path.display()); + println!( + "cargo:rustc-env=BUNDLE_PATH_{}={}", + fname, + full_path.display() + ); println!("cargo:rustc-env=BUNDLE_VERSION_{fname}={tag}"); if let Ok(digest) = sha256::try_digest(&full_path) { @@ -83,9 +94,13 @@ fn download_dll(out_dir: &Path, fname: &str, tag: &str, url: &str, sha256: &str) } std::io::copy( - &mut ureq::get(url).call().expect("Error downloading DLL to bundle").into_reader(), + &mut ureq::get(url) + .call() + .expect("Error downloading DLL to bundle") + .into_reader(), &mut std::fs::File::create(&full_path).unwrap(), - ).unwrap(); + ) + .unwrap(); assert_eq!(sha256, sha256::try_digest(&full_path).unwrap()); } diff --git a/crates/dm-langserver/src/background.rs b/crates/dm-langserver/src/background.rs index db04e008..18085aef 100644 --- a/crates/dm-langserver/src/background.rs +++ b/crates/dm-langserver/src/background.rs @@ -34,9 +34,9 @@ impl Background { match rx.try_recv() { Ok(v) => { self.value = Some(v); - } + }, Err(TryRecvError::Empty) => self.rx = Some(rx), - Err(TryRecvError::Disconnected) => {} + Err(TryRecvError::Disconnected) => {}, } } self diff --git a/crates/dm-langserver/src/color.rs b/crates/dm-langserver/src/color.rs index 8426202e..bad2f899 100644 --- a/crates/dm-langserver/src/color.rs +++ b/crates/dm-langserver/src/color.rs @@ -7,7 +7,7 @@ use regex::Regex; /// Extract ranges and colors from an input string. -pub fn extract_colors(input: &str) -> impl Iterator + '_ { +pub fn extract_colors(input: &str) -> impl Iterator + '_ { COLOR_REGEX.captures_iter(input).flat_map(|capture| { parse_capture(&capture).map(|rgba| { let totality = capture.get(0).unwrap(); @@ -26,7 +26,7 @@ pub enum ColorFormat { }, Rgb { alpha: bool, - } + }, } impl ColorFormat { @@ -53,15 +53,30 @@ impl ColorFormat { pub fn format(self, [r, g, b, a]: [u8; 4]) -> String { match self { - ColorFormat::Hex { single_quoted, short, alpha } => { + ColorFormat::Hex { + single_quoted, + short, + alpha, + } => { let q = if single_quoted { '\'' } else { '"' }; - let short = short && r % 0x11 == 0 && g % 0x11 == 0 && b % 0x11 == 0 && a % 0x11 == 0; + let short = + short && r % 0x11 == 0 && g % 0x11 == 0 && b % 0x11 == 0 && a % 0x11 == 0; let alpha = alpha || a != 255; match (short, alpha) { (false, false) => format!("{q}#{r:02x}{g:02x}{b:02x}{q}"), (false, true) => format!("{q}#{r:02x}{g:02x}{b:02x}{a:02x}{q}"), - (true, false) => format!("{}#{:x}{:x}{:x}{}", q, r / 0x11, g / 0x11, b / 0x11, q), - (true, true) => format!("{}#{:x}{:x}{:x}{:x}{}", q, r / 0x11, g / 0x11, b / 0x11, a / 0x11, q), + (true, false) => { + format!("{}#{:x}{:x}{:x}{}", q, r / 0x11, g / 0x11, b / 0x11, q) + }, + (true, true) => format!( + "{}#{:x}{:x}{:x}{:x}{}", + q, + r / 0x11, + g / 0x11, + b / 0x11, + a / 0x11, + q + ), } }, ColorFormat::Rgb { alpha } if alpha || a != 255 => format!("rgb({r}, {g}, {b}, {a})"), @@ -72,7 +87,11 @@ impl ColorFormat { impl Default for ColorFormat { fn default() -> ColorFormat { - ColorFormat::Hex { single_quoted: false, short: false, alpha: false } + ColorFormat::Hex { + single_quoted: false, + short: false, + alpha: false, + } } } @@ -83,11 +102,19 @@ lazy_static! { fn parse_capture(capture: ®ex::Captures) -> Option<[u8; 4]> { // Tied closely to the regex above. - match (capture.get(1), capture.get(2), capture.get(3), capture.get(4), capture.get(5), capture.get(6)) { - (Some(cap), _, _, _, _, _) | - (_, Some(cap), _, _, _, _) => parse_hex(cap.as_str()), - (_, _, Some(r), Some(g), Some(b), a) => parse_rgba(r.as_str(), g.as_str(), b.as_str(), a.map(|a| a.as_str())), - _ => None + match ( + capture.get(1), + capture.get(2), + capture.get(3), + capture.get(4), + capture.get(5), + capture.get(6), + ) { + (Some(cap), _, _, _, _, _) | (_, Some(cap), _, _, _, _) => parse_hex(cap.as_str()), + (_, _, Some(r), Some(g), Some(b), a) => { + parse_rgba(r.as_str(), g.as_str(), b.as_str(), a.map(|a| a.as_str())) + }, + _ => None, } } @@ -97,28 +124,27 @@ fn parse_hex(hex: &str) -> Option<[u8; 4]> { sum = 16 * sum + ch.to_digit(16).unwrap_or(0); } - if hex.len() == 8 { // #rrggbbaa + if hex.len() == 8 { + // #rrggbbaa Some([ (sum >> 24) as u8, (sum >> 16) as u8, (sum >> 8) as u8, sum as u8, ]) - } else if hex.len() == 6 { // #rrggbb - Some([ - (sum >> 16) as u8, - (sum >> 8) as u8, - sum as u8, - 255, - ]) - } else if hex.len() == 4 { // #rgba + } else if hex.len() == 6 { + // #rrggbb + Some([(sum >> 16) as u8, (sum >> 8) as u8, sum as u8, 255]) + } else if hex.len() == 4 { + // #rgba Some([ (0x11 * ((sum >> 12) & 0xf)) as u8, (0x11 * ((sum >> 8) & 0xf)) as u8, (0x11 * ((sum >> 4) & 0xf)) as u8, (0x11 * (sum & 0xf)) as u8, ]) - } else if hex.len() == 3 { // #rgb + } else if hex.len() == 3 { + // #rgb Some([ (0x11 * ((sum >> 8) & 0xf)) as u8, (0x11 * ((sum >> 4) & 0xf)) as u8, diff --git a/crates/dm-langserver/src/completion.rs b/crates/dm-langserver/src/completion.rs index 2311c283..15e3713c 100644 --- a/crates/dm-langserver/src/completion.rs +++ b/crates/dm-langserver/src/completion.rs @@ -70,7 +70,7 @@ fn item_var(ty: TypeRef, name: &str, var: &TypeVar) -> CompletionItem { kind: Some(CompletionItemKind::FIELD), detail: Some(detail), documentation: item_documentation(&var.value.docs), - .. Default::default() + ..Default::default() } } @@ -125,14 +125,19 @@ fn items_ty<'a>( if contains(name, query) { results.push(CompletionItem { insert_text: Some(name.to_owned()), - .. item_proc(ty, name, proc) + ..item_proc(ty, name, proc) }); } } } -pub fn combine_tree_path<'a, I>(iter: &I, mut absolute: bool, mut parts: &'a [String]) -> impl Iterator - where I: Iterator + Clone +pub fn combine_tree_path<'a, I>( + iter: &I, + mut absolute: bool, + mut parts: &'a [String], +) -> impl Iterator +where + I: Iterator + Clone, { // cut off the part of the path we haven't selected if_annotation! { Annotation::InSequence(idx) in iter; { @@ -167,7 +172,11 @@ pub fn combine_tree_path<'a, I>(iter: &I, mut absolute: bool, mut parts: &'a [St } impl Engine { - pub fn follow_type_path<'b, I>(&'b self, iter: &I, mut parts: &'b [(PathOp, String)]) -> Option> + pub fn follow_type_path<'b, I>( + &'b self, + iter: &I, + mut parts: &'b [(PathOp, String)], + ) -> Option> where I: Iterator + Clone, { @@ -178,7 +187,7 @@ impl Engine { // if we're on the right side of a 'list/', start the lookup there match parts.split_first() { Some(((PathOp::Slash, kwd), rest)) if kwd == "list" && !rest.is_empty() => parts = rest, - _ => {} + _ => {}, } // use the first path op to select the starting type of the lookup @@ -190,7 +199,7 @@ impl Engine { }); } let mut ty = match parts[0].0 { - PathOp::Colon => return None, // never finds anything, apparently? + PathOp::Colon => return None, // never finds anything, apparently? PathOp::Slash => self.objtree.root(), PathOp::Dot => match self.find_type_context(iter) { (Some(base), _) => base, @@ -229,14 +238,20 @@ impl Engine { Some(TypePathResult { ty, decl, proc }) } - pub fn tree_completions(&self, results: &mut Vec, exact: bool, ty: TypeRef, query: &str) { + pub fn tree_completions( + &self, + results: &mut Vec, + exact: bool, + ty: TypeRef, + query: &str, + ) { // path keywords for &name in ["proc", "var", "verb"].iter() { if contains(name, query) { results.push(CompletionItem { label: name.to_owned(), kind: Some(CompletionItemKind::KEYWORD), - .. Default::default() + ..Default::default() }) } } @@ -249,7 +264,7 @@ impl Engine { label: child.name().to_owned(), kind: Some(CompletionItemKind::CLASS), documentation: item_documentation(&child.docs), - .. Default::default() + ..Default::default() }); } } @@ -266,7 +281,7 @@ impl Engine { if contains(name, query) { results.push(CompletionItem { insert_text: Some(format!("{name} = ")), - .. item_var(ty, name, var) + ..item_var(ty, name, var) }); } } @@ -293,7 +308,7 @@ impl Engine { results.push(CompletionItem { insert_text: Some(completion), - .. item_proc(ty, name, proc) + ..item_proc(ty, name, proc) }); } } @@ -325,7 +340,7 @@ impl Engine { results.push(CompletionItem { label: name.to_owned(), kind: Some(CompletionItemKind::KEYWORD), - .. Default::default() + ..Default::default() }) } } @@ -337,7 +352,7 @@ impl Engine { label: child.name().to_owned(), kind: Some(CompletionItemKind::CLASS), documentation: item_documentation(&child.docs), - .. Default::default() + ..Default::default() }); } } @@ -372,12 +387,16 @@ impl Engine { next = ty.parent_type_without_root(); } }, - _ => {} + _ => {}, } } - pub fn unscoped_completions<'b, I>(&'b self, results: &mut Vec, iter: &I, query: &str) - where + pub fn unscoped_completions<'b, I>( + &'b self, + results: &mut Vec, + iter: &I, + query: &str, + ) where I: Iterator + Clone, { let (ty, proc_name) = self.find_type_context(iter); @@ -389,7 +408,7 @@ impl Engine { results.push(CompletionItem { label: name.to_owned(), kind: Some(CompletionItemKind::KEYWORD), - .. Default::default() + ..Default::default() }); } } @@ -403,7 +422,7 @@ impl Engine { label: name.clone(), kind: Some(CompletionItemKind::VARIABLE), detail: Some("(local)".to_owned()), - .. Default::default() + ..Default::default() }); } } @@ -420,7 +439,7 @@ impl Engine { label: param.name.clone(), kind: Some(CompletionItemKind::VARIABLE), detail: Some("(parameter)".to_owned()), - .. Default::default() + ..Default::default() }); } } @@ -438,7 +457,7 @@ impl Engine { kind: Some(CompletionItemKind::CONSTANT), detail: Some(define.display_with_name(name).to_string()), documentation: item_documentation(define.docs()), - .. Default::default() + ..Default::default() }); } } diff --git a/crates/dm-langserver/src/debugger/auxtools.rs b/crates/dm-langserver/src/debugger/auxtools.rs index e6dd0433..4babce9a 100644 --- a/crates/dm-langserver/src/debugger/auxtools.rs +++ b/crates/dm-langserver/src/debugger/auxtools.rs @@ -59,7 +59,8 @@ impl Auxtools { seq, responses: responses_sender, last_error, - }.run(stream); + } + .run(stream); }) }; @@ -87,25 +88,34 @@ impl Auxtools { seq, responses: responses_sender, last_error, - }.spawn_listener(listener, connection_sender) + } + .spawn_listener(listener, connection_sender) }; - Ok((port, Auxtools { - seq, - responses: responses_receiver, - _thread: thread, - stream: StreamState::Waiting(connection_receiver), - last_error, - })) + Ok(( + port, + Auxtools { + seq, + responses: responses_receiver, + _thread: thread, + stream: StreamState::Waiting(connection_receiver), + last_error, + }, + )) } fn read_response_or_disconnect(&mut self) -> Result> { - match self.responses.recv_timeout(std::time::Duration::from_secs(5)) { + match self + .responses + .recv_timeout(std::time::Duration::from_secs(5)) + { Ok(response) => Ok(response), Err(_) => { self.disconnect(); - Err(Box::new(super::GenericError("timed out waiting for response"))) - } + Err(Box::new(super::GenericError( + "timed out waiting for response", + ))) + }, } } @@ -123,12 +133,12 @@ impl Auxtools { stream.write_all(&data[..])?; stream.flush()?; Ok(()) - } + }, _ => { // Success if not connected (kinda dumb) Ok(()) - } + }, } } @@ -171,8 +181,13 @@ impl Auxtools { } } - pub fn eval(&mut self, frame_id: Option, command: &str, context: Option) -> Result> { - self.send_or_disconnect(Request::Eval{ + pub fn eval( + &mut self, + frame_id: Option, + command: &str, + context: Option, + ) -> Result> { + self.send_or_disconnect(Request::Eval { frame_id, command: command.to_owned(), context, @@ -185,17 +200,28 @@ impl Auxtools { } #[allow(dead_code)] - pub fn get_current_proc(&mut self, frame_id: u32) -> Result, Box> { + pub fn get_current_proc( + &mut self, + frame_id: u32, + ) -> Result, Box> { self.send_or_disconnect(Request::CurrentInstruction { frame_id })?; match self.read_response_or_disconnect()? { Response::CurrentInstruction(ins) => Ok(ins.map(|x| (x.proc.path, x.proc.override_id))), - response => Err(Box::new(UnexpectedResponse::new("CurrentInstruction", response))), + response => Err(Box::new(UnexpectedResponse::new( + "CurrentInstruction", + response, + ))), } } #[allow(dead_code)] - pub fn get_line_number(&mut self, path: &str, override_id: u32, offset: u32) -> Result, Box> { + pub fn get_line_number( + &mut self, + path: &str, + override_id: u32, + offset: u32, + ) -> Result, Box> { self.send_or_disconnect(Request::LineNumber { proc: ProcRef { path: path.to_owned(), @@ -210,7 +236,12 @@ impl Auxtools { } } - pub fn get_offset(&mut self, path: &str, override_id: u32, line: u32) -> Result, Box> { + pub fn get_offset( + &mut self, + path: &str, + override_id: u32, + line: u32, + ) -> Result, Box> { self.send_or_disconnect(Request::Offset { proc: ProcRef { path: path.to_owned(), @@ -225,10 +256,14 @@ impl Auxtools { } } - pub fn set_breakpoint(&mut self, instruction: InstructionRef, condition: Option) -> Result> { + pub fn set_breakpoint( + &mut self, + instruction: InstructionRef, + condition: Option, + ) -> Result> { self.send_or_disconnect(Request::BreakpointSet { instruction, - condition + condition, })?; match self.read_response_or_disconnect()? { @@ -237,14 +272,20 @@ impl Auxtools { } } - pub fn unset_breakpoint(&mut self, instruction: &InstructionRef) -> Result<(), Box> { + pub fn unset_breakpoint( + &mut self, + instruction: &InstructionRef, + ) -> Result<(), Box> { self.send_or_disconnect(Request::BreakpointUnset { instruction: instruction.clone(), })?; match self.read_response_or_disconnect()? { Response::BreakpointUnset { .. } => Ok(()), - response => Err(Box::new(UnexpectedResponse::new("BreakpointUnset", response))), + response => Err(Box::new(UnexpectedResponse::new( + "BreakpointUnset", + response, + ))), } } @@ -332,25 +373,31 @@ impl Auxtools { } // TODO: return all the scopes - pub fn get_scopes(&mut self, frame_id: u32) -> Result> { - self.send_or_disconnect(Request::Scopes { - frame_id - })?; + pub fn get_scopes( + &mut self, + frame_id: u32, + ) -> Result> { + self.send_or_disconnect(Request::Scopes { frame_id })?; match self.read_response_or_disconnect()? { Response::Scopes { arguments, locals, globals, - } => Ok(AuxtoolsScopes { arguments, locals, globals }), + } => Ok(AuxtoolsScopes { + arguments, + locals, + globals, + }), response => Err(Box::new(UnexpectedResponse::new("Scopes", response))), } } - pub fn get_variables(&mut self, vars: VariablesRef) -> Result, Box> { - self.send_or_disconnect(Request::Variables { - vars - })?; + pub fn get_variables( + &mut self, + vars: VariablesRef, + ) -> Result, Box> { + self.send_or_disconnect(Request::Variables { vars })?; match self.read_response_or_disconnect()? { Response::Variables { vars } => Ok(vars), @@ -362,7 +409,10 @@ impl Auxtools { self.last_error.read().unwrap().clone() } - pub fn set_catch_runtimes(&mut self, should_catch: bool) -> Result<(), Box> { + pub fn set_catch_runtimes( + &mut self, + should_catch: bool, + ) -> Result<(), Box> { self.send_or_disconnect(Request::CatchRuntimes { should_catch }) } } @@ -376,19 +426,19 @@ impl AuxtoolsThread { thread::spawn(move || match listener.accept() { Ok((stream, _)) => { match connection_sender.send(stream.try_clone().unwrap()) { - Ok(_) => {} + Ok(_) => {}, Err(e) => { eprintln!("Debug client thread failed to pass cloned TcpStream: {e}"); return; - } + }, } self.run(stream); - } + }, Err(e) => { eprintln!("Debug client failed to accept connection: {e}"); - } + }, }) } @@ -401,7 +451,7 @@ impl AuxtoolsThread { Response::Notification { message: _message } => { debug_output!(in self.seq, "[auxtools] {}", _message); - } + }, Response::BreakpointHit { reason } => { let mut description = None; @@ -414,7 +464,7 @@ impl AuxtoolsThread { self.last_error.write().unwrap().clone_from(&error); description = Some(error); dap_types::StoppedEvent::REASON_EXCEPTION - } + }, }; self.seq.issue_event(dap_types::StoppedEvent { @@ -424,11 +474,11 @@ impl AuxtoolsThread { allThreadsStopped: Some(true), ..Default::default() }); - } + }, x => { self.responses.send(x)?; - } + }, } Ok(false) @@ -449,7 +499,7 @@ impl AuxtoolsThread { Err(e) => { eprintln!("Debug server thread read error: {e}"); break; - } + }, }; buf.resize(len as usize, 0); @@ -459,7 +509,7 @@ impl AuxtoolsThread { Err(e) => { eprintln!("Debug server thread read error: {e}"); break; - } + }, }; match self.handle_response(&buf[..]) { @@ -468,12 +518,12 @@ impl AuxtoolsThread { eprintln!("Debug server disconnected"); break; } - } + }, Err(e) => { eprintln!("Debug server thread failed to handle request: {e}"); break; - } + }, } } @@ -486,7 +536,9 @@ pub struct UnexpectedResponse(String); impl UnexpectedResponse { fn new(expected: &'static str, received: Response) -> Self { - Self(format!("received unexpected response: expected {expected}, got {received:?}")) + Self(format!( + "received unexpected response: expected {expected}, got {received:?}" + )) } } diff --git a/crates/dm-langserver/src/debugger/evaluate.rs b/crates/dm-langserver/src/debugger/evaluate.rs index 4b8a9ca7..508a076c 100644 --- a/crates/dm-langserver/src/debugger/evaluate.rs +++ b/crates/dm-langserver/src/debugger/evaluate.rs @@ -20,7 +20,9 @@ impl Debugger { } let Some(frame_id) = params.frameId else { - return Err(Box::new(GenericError("Must select a stack frame to evaluate in"))); + return Err(Box::new(GenericError( + "Must select a stack frame to evaluate in", + ))); }; let (thread, frame_no) = extools.get_thread_by_frame_id(frame_id)?; @@ -37,21 +39,18 @@ impl Debugger { return Err(Box::new(GenericError("Unknown #command"))); } } - } + }, DebugClient::Auxtools(auxtools) => { - let response = auxtools.eval( - params.frameId.map(|x| x as u32), - input, - params.context, - )?; + let response = + auxtools.eval(params.frameId.map(|x| x as u32), input, params.context)?; return Ok(EvaluateResponse { result: response.value, variablesReference: response.variables.map(|x| x.0 as i64).unwrap_or(0), ..Default::default() }); - } + }, } Err(Box::new(GenericError("Not yet implemented"))) diff --git a/crates/dm-langserver/src/debugger/extools.rs b/crates/dm-langserver/src/debugger/extools.rs index 623c5b14..6c2fda72 100644 --- a/crates/dm-langserver/src/debugger/extools.rs +++ b/crates/dm-langserver/src/debugger/extools.rs @@ -71,10 +71,10 @@ impl ExtoolsHolder { } })?; - Ok((port, ExtoolsHolder(ExtoolsHolderInner::Listening { + Ok(( port, - conn_rx, - }))) + ExtoolsHolder(ExtoolsHolderInner::Listening { port, conn_rx }), + )) } pub fn attach(seq: Arc, port: u16) -> std::io::Result { @@ -88,7 +88,9 @@ impl ExtoolsHolder { .name(format!("extools attaching on port {port}")) .spawn(move || { while let Err(mpsc::TryRecvError::Empty) = cancel_rx.try_recv() { - if let Ok(stream) = TcpStream::connect_timeout(&addr, std::time::Duration::from_secs(5)) { + if let Ok(stream) = + TcpStream::connect_timeout(&addr, std::time::Duration::from_secs(5)) + { let (conn, mut thread) = Extools::from_stream(seq, stream); if conn_tx.send(conn).is_ok() { thread.read_loop(); @@ -105,22 +107,23 @@ impl ExtoolsHolder { } pub fn get(&mut self) -> Result<&mut Extools, Box> { - self.as_ref().ok_or_else(|| Box::new(super::GenericError("No extools connection")) as Box) + self.as_ref() + .ok_or_else(|| Box::new(super::GenericError("No extools connection")) as Box) } pub fn as_ref(&mut self) -> Option<&mut Extools> { match &mut self.0 { - ExtoolsHolderInner::Listening { conn_rx, .. } | - ExtoolsHolderInner::Attaching { conn_rx, .. } => { + ExtoolsHolderInner::Listening { conn_rx, .. } + | ExtoolsHolderInner::Attaching { conn_rx, .. } => { if let Ok(conn) = conn_rx.try_recv() { self.0 = ExtoolsHolderInner::Active(Box::new(conn)); } - } - _ => {} + }, + _ => {}, } match &mut self.0 { ExtoolsHolderInner::Active(conn) => Some(conn), - _ => None + _ => None, } } @@ -128,9 +131,11 @@ impl ExtoolsHolder { // This part of code is not complete, we don't want to use matches! #[allow(clippy::single_match)] match std::mem::replace(&mut self.0, ExtoolsHolderInner::None) { - ExtoolsHolderInner::Attaching { cancel_tx, .. } => { let _ = cancel_tx.send(()); }, + ExtoolsHolderInner::Attaching { cancel_tx, .. } => { + let _ = cancel_tx.send(()); + }, // TODO: ExtoolsHolderInner::Listening - _ => {} + _ => {}, } } } @@ -203,22 +208,38 @@ impl Extools { } pub fn get_thread(&self, thread_id: i64) -> Result> { - self.threads.lock().unwrap().get(&thread_id).cloned() - .ok_or_else(|| Box::new(super::GenericError("Getting call stack failed")) as Box) + self.threads + .lock() + .unwrap() + .get(&thread_id) + .cloned() + .ok_or_else(|| { + Box::new(super::GenericError("Getting call stack failed")) as Box + }) } - pub fn get_thread_by_frame_id(&self, frame_id: i64) -> Result<(ThreadInfo, usize), Box> { + pub fn get_thread_by_frame_id( + &self, + frame_id: i64, + ) -> Result<(ThreadInfo, usize), Box> { let frame_id = frame_id as usize; let threads = self.threads.lock().unwrap(); let thread_id = (frame_id % threads.len()) as i64; let frame_no = frame_id / threads.len(); - let thread = threads.get(&thread_id).cloned() - .ok_or_else(|| Box::new(super::GenericError("Getting call stack failed")) as Box)?; + let thread = threads.get(&thread_id).cloned().ok_or_else(|| { + Box::new(super::GenericError("Getting call stack failed")) as Box + })?; Ok((thread, frame_no)) } pub fn bytecode(&mut self, proc_ref: &str, override_id: usize) -> &[DisassembledInstruction] { - let Extools { bytecode, sender, seq: _seq, bytecode_rx, .. } = self; + let Extools { + bytecode, + sender, + seq: _seq, + bytecode_rx, + .. + } = self; bytecode.entry((proc_ref.to_owned(), override_id)).or_insert_with(|| { debug_output!(in _seq, "[extools] Fetching bytecode for {}#{}", proc_ref, override_id); sender.send(ProcDisassemblyRequest(ProcId { @@ -229,7 +250,12 @@ impl Extools { }) } - pub fn offset_to_line(&mut self, proc_ref: &str, override_id: usize, offset: i64) -> Option { + pub fn offset_to_line( + &mut self, + proc_ref: &str, + override_id: usize, + offset: i64, + ) -> Option { let bc = self.bytecode(proc_ref, override_id); let mut comment = ""; for instr in bc.iter() { @@ -262,11 +288,19 @@ impl Extools { } pub fn set_breakpoint(&self, proc: &str, override_id: usize, offset: i64) { - self.sender.send(BreakpointSet(ProcOffset { proc: proc.to_owned(), override_id, offset })); + self.sender.send(BreakpointSet(ProcOffset { + proc: proc.to_owned(), + override_id, + offset, + })); } pub fn unset_breakpoint(&self, proc: &str, override_id: usize, offset: i64) { - self.sender.send(BreakpointUnset(ProcOffset { proc: proc.to_owned(), override_id, offset })); + self.sender.send(BreakpointUnset(ProcOffset { + proc: proc.to_owned(), + override_id, + offset, + })); } pub fn continue_execution(&self) { @@ -300,7 +334,10 @@ impl Extools { Ok(self.get_type_rx.recv_timeout(RECV_TIMEOUT)?.0) } - pub fn get_all_fields(&self, reference: Ref) -> Result, Box> { + pub fn get_all_fields( + &self, + reference: Ref, + ) -> Result, Box> { self.sender.send(GetAllFields(reference)); Ok(self.get_field_rx.recv_timeout(RECV_TIMEOUT)?.0) } @@ -373,7 +410,7 @@ impl ExtoolsThread { terminator = Some(buffer.len() + pos); } buffer.extend_from_slice(slice); - } + }, Err(e) => panic!("extools read error: {e:?}"), } @@ -422,13 +459,13 @@ impl ExtoolsThread { reason: "sleep".to_owned(), threadId: Some(k), preserveFocusHint: Some(true), - .. Default::default() + ..Default::default() }); } } self.seq.issue_event(dap_types::StoppedEvent { threadId: Some(0), - .. base + ..base }); } } @@ -488,23 +525,21 @@ impl ExtoolsThread { BreakpointHitReason::Step => { self.stopped(dap_types::StoppedEvent { reason: dap_types::StoppedEvent::REASON_STEP.to_owned(), - .. Default::default() + ..Default::default() }); - } - BreakpointHitReason::Pause => { - self.stopped(dap_types::StoppedEvent { - reason: dap_types::StoppedEvent::REASON_PAUSE.to_owned(), - description: Some("Paused by request".to_owned()), - .. Default::default() - }) - } + }, + BreakpointHitReason::Pause => self.stopped(dap_types::StoppedEvent { + reason: dap_types::StoppedEvent::REASON_PAUSE.to_owned(), + description: Some("Paused by request".to_owned()), + ..Default::default() + }), _ => { debug_output!(in self.seq, "[extools] {}#{}@{} hit", hit.proc, hit.override_id, hit.offset); self.stopped(dap_types::StoppedEvent { reason: dap_types::StoppedEvent::REASON_BREAKPOINT.to_owned(), - .. Default::default() + ..Default::default() }); - } + }, } Ok(()) } @@ -514,7 +549,7 @@ impl ExtoolsThread { self.stopped(dap_types::StoppedEvent { reason: dap_types::StoppedEvent::REASON_EXCEPTION.to_owned(), text: Some(runtime.message.clone()), - .. Default::default() + ..Default::default() }); self.queue(&self.runtime_tx, runtime); Ok(()) @@ -570,7 +605,10 @@ impl Clone for ExtoolsSender { fn clone(&self) -> ExtoolsSender { ExtoolsSender { seq: self.seq.clone(), - stream: self.stream.try_clone().expect("TcpStream::try_clone failed in ExtoolsSender::clone") + stream: self + .stream + .try_clone() + .expect("TcpStream::try_clone failed in ExtoolsSender::clone"), } } } @@ -581,9 +619,12 @@ impl ExtoolsSender { let mut buffer = serde_json::to_vec(&ProtocolMessage { type_: M::TYPE.to_owned(), content: Some(content), - }).expect("extools encode error"); + }) + .expect("extools encode error"); buffer.push(0); // TODO: needs more synchronization - (&self.stream).write_all(&buffer[..]).expect("extools write error"); + (&self.stream) + .write_all(&buffer[..]) + .expect("extools write error"); } } diff --git a/crates/dm-langserver/src/debugger/extools_types.rs b/crates/dm-langserver/src/debugger/extools_types.rs index 182b359e..783f2811 100644 --- a/crates/dm-langserver/src/debugger/extools_types.rs +++ b/crates/dm-langserver/src/debugger/extools_types.rs @@ -5,8 +5,8 @@ //! > All communication happens over a TCP socket using a JSON-based protocol. //! > A null byte signifies the end of a message. #![allow(dead_code)] -use serde_json::Value as Json; use foldhash::HashMap; +use serde_json::Value as Json; // ---------------------------------------------------------------------------- // Extools data structures @@ -132,11 +132,14 @@ impl ValueText { let ref_ = Ref(raw); let is_list = raw >> 24 == 0x0F; - (ValueText { - literal: Literal::Ref(ref_), - has_vars: !is_list, - is_list, - }, ref_) + ( + ValueText { + literal: Literal::Ref(ref_), + has_vars: !is_list, + is_list, + }, + ref_, + ) } pub fn to_variables_reference(&self) -> i64 { @@ -165,12 +168,10 @@ impl std::fmt::Display for Literal { Literal::String(s) => write!(fmt, "{s:?}"), Literal::Typepath(t) => write!(fmt, "{t}"), Literal::Resource(f) => write!(fmt, "'{f}'"), - Literal::Proc(p) => { - match p.rfind('/') { - Some(idx) => write!(fmt, "{}/proc/{}", &p[..idx], &p[idx + 1..]), - None => write!(fmt, "{p}"), - } - } + Literal::Proc(p) => match p.rfind('/') { + Some(idx) => write!(fmt, "{}/proc/{}", &p[..idx], &p[idx + 1..]), + None => write!(fmt, "{p}"), + }, } } } diff --git a/crates/dm-langserver/src/debugger/launched.rs b/crates/dm-langserver/src/debugger/launched.rs index 5e486e25..299aedfe 100644 --- a/crates/dm-langserver/src/debugger/launched.rs +++ b/crates/dm-langserver/src/debugger/launched.rs @@ -31,12 +31,12 @@ pub struct Launched { pub enum EngineParams { Extools { port: u16, - dll: Option + dll: Option, }, Auxtools { port: u16, - dll: Option - } + dll: Option, + }, } impl Launched { @@ -49,7 +49,8 @@ impl Launched { ) -> std::io::Result { let mut command = Command::new(dreamseeker_exe); - #[cfg(unix)] { + #[cfg(unix)] + { if let Some(parent) = std::path::Path::new(dreamseeker_exe).parent() { command.env("LD_LIBRARY_PATH", parent); } @@ -73,7 +74,7 @@ impl Launched { if let Some(dll) = dll { command.env("EXTOOLS_DLL", dll); } - } + }, Some(EngineParams::Auxtools { port, dll }) => { command.env("AUXTOOLS_DEBUG_MODE", "LAUNCHED"); @@ -81,7 +82,7 @@ impl Launched { if let Some(dll) = dll { command.env("AUXTOOLS_DEBUG_DLL", dll); } - } + }, None => (), } @@ -140,12 +141,12 @@ impl Launched { true => Ok(()), false => Err(std::io::Error::last_os_error()), } - } + }, State::Exited => Ok(()), _other => { debug_output!(in self.seq, "[launched] kill no-op in state {:?}", _other); Ok(()) - } + }, } } @@ -155,16 +156,22 @@ impl Launched { State::Active => { output!(in self.seq, "[launched] Detaching from child process..."); *state = State::Detached; - } + }, _other => { debug_output!(in self.seq, "[launched] detach no-op in state {:?}", _other); - } + }, } } } -fn pipe_output(seq: Arc, keyword: &'static str, stream: Option) -> std::io::Result<()> { - let Some(stream2) = stream else { return Ok(()); }; +fn pipe_output( + seq: Arc, + keyword: &'static str, + stream: Option, +) -> std::io::Result<()> { + let Some(stream2) = stream else { + return Ok(()); + }; std::thread::Builder::new() .name(format!("launched debuggee {keyword} relay")) .spawn(move || { @@ -182,7 +189,7 @@ fn pipe_output(seq: Arc, keyw category: Some(keyword.to_owned()), ..Default::default() }); - } + }, Err(e) => { seq.issue_event(dap_types::OutputEvent { output: format!("[launched {keyword}] {e}"), @@ -190,7 +197,7 @@ fn pipe_output(seq: Arc, keyw ..Default::default() }); break; - } + }, } } })?; diff --git a/crates/dm-langserver/src/debugger/mod.rs b/crates/dm-langserver/src/debugger/mod.rs index 30b7bb2a..5dd5d434 100644 --- a/crates/dm-langserver/src/debugger/mod.rs +++ b/crates/dm-langserver/src/debugger/mod.rs @@ -121,7 +121,13 @@ pub fn debugger_main>(mut args: I) { extools_dll: None, debug_server_dll: None, }; - let mut debugger = Debugger::new(ctx.config().debugger.engine, dreamseeker_exe, None, db, Box::new(std::io::stdout())); + let mut debugger = Debugger::new( + ctx.config().debugger.engine, + dreamseeker_exe, + None, + db, + Box::new(std::io::stdout()), + ); jrpc_io::run_until_stdin_eof(|message| debugger.handle_input(message)); } @@ -142,8 +148,7 @@ impl DebugDatabaseBuilder { extools_dll: _, debug_server_dll: _, } = self; - let mut line_numbers: HashMap> = - HashMap::new(); + let mut line_numbers: HashMap> = HashMap::new(); objtree.root().recurse(&mut |ty| { for (name, proc) in ty.procs.iter() { @@ -196,8 +201,8 @@ fn get_proc<'o>( match bits.last() { Some(&"proc") | Some(&"verb") => { bits.pop(); - } - _ => {} + }, + _ => {}, } let typename = bits.join("/"); @@ -260,7 +265,13 @@ struct Debugger { } impl Debugger { - fn new(engine: DebugEngine, dreamseeker_exe: String, env: Option>, mut db: DebugDatabaseBuilder, stream: OutStream) -> Self { + fn new( + engine: DebugEngine, + dreamseeker_exe: String, + env: Option>, + mut db: DebugDatabaseBuilder, + stream: OutStream, + ) -> Self { Debugger { engine, dreamseeker_exe, @@ -296,7 +307,7 @@ impl Debugger { let handled = match Self::handle_request_table(&request.command) { Some(handler) => { handler(self, request.arguments.unwrap_or(serde_json::Value::Null)) - } + }, None => Err(format!("Request NYI: {}", request.command).into()), }; @@ -316,13 +327,13 @@ impl Debugger { } debug_output!(in self.seq, " - {}", message); None - } + }, }, command, }; self.seq .send_raw(&serde_json::to_string(&response).expect("response encode error")) - } + }, other => return Err(format!("unknown `type` field {other:?}").into()), } Ok(()) @@ -367,9 +378,10 @@ impl Debugger { threadId: k, }); } - } + }, - DebugClient::Auxtools(auxtools) => for stack in auxtools.get_stacks().unwrap_or_default() { + DebugClient::Auxtools(auxtools) => { + for stack in auxtools.get_stacks().unwrap_or_default() { if stack.id == 0 { continue; } @@ -377,7 +389,8 @@ impl Debugger { reason: dap_types::ThreadEvent::REASON_EXITED.to_owned(), threadId: stack.id as i64, }); - }, + } + }, } } } @@ -454,14 +467,12 @@ impl Debugger { supportsFunctionBreakpoints: Some(true), supportsConditionalBreakpoints: Some(true), supportsDisassembleRequest: Some(true), - exceptionBreakpointFilters: Some(vec![ - ExceptionBreakpointsFilter { - filter: EXCEPTION_FILTER_RUNTIMES.to_owned(), - label: "Runtime errors".to_owned(), - default: Some(true), - } - ]), - .. Default::default() + exceptionBreakpointFilters: Some(vec![ExceptionBreakpointsFilter { + filter: EXCEPTION_FILTER_RUNTIMES.to_owned(), + label: "Runtime errors".to_owned(), + default: Some(true), + }]), + ..Default::default() })) } @@ -484,7 +495,8 @@ impl Debugger { extools_dll = Some(dll.into()); } - #[cfg(extools_bundle)] { + #[cfg(extools_bundle)] + { if extools_dll.is_none() { extools_dll = Some(self::extools_bundle::extract()?); } @@ -494,7 +506,7 @@ impl Debugger { port, dll: extools_dll, } - } + }, DebugEngine::Auxtools => { let (port, auxtools) = Auxtools::listen(self.seq.clone())?; @@ -508,7 +520,8 @@ impl Debugger { debug_server_dll = Some(dll.into()); } - #[cfg(auxtools_bundle)] { + #[cfg(auxtools_bundle)] + { if debug_server_dll.is_none() { debug_server_dll = Some(self::auxtools_bundle::extract()?); } @@ -518,26 +531,33 @@ impl Debugger { port, dll: debug_server_dll, } - } + }, }) } else { None }; // Launch the subprocess. - self.launched = Some(Launched::new(self.seq.clone(), &self.dreamseeker_exe, self.env.as_ref(), ¶ms.dmb, engine_params)?); + self.launched = Some(Launched::new( + self.seq.clone(), + &self.dreamseeker_exe, + self.env.as_ref(), + ¶ms.dmb, + engine_params, + )?); Ok(()) } fn AttachVsc(&mut self, params: P) -> R { self.client = match self.engine { - DebugEngine::Extools => { - DebugClient::Extools(ExtoolsHolder::attach(self.seq.clone(), params.port.unwrap_or(extools::DEFAULT_PORT))?) - } + DebugEngine::Extools => DebugClient::Extools(ExtoolsHolder::attach( + self.seq.clone(), + params.port.unwrap_or(extools::DEFAULT_PORT), + )?), DebugEngine::Auxtools => { DebugClient::Auxtools(Auxtools::connect(self.seq.clone(), params.port)?) - } + }, }; Ok(()) } @@ -549,11 +569,11 @@ impl Debugger { match &mut self.client { DebugClient::Extools(extools) => { extools.disconnect(); - } + }, DebugClient::Auxtools(auxtools) => { auxtools.disconnect(); - } + }, } if let Some(launched) = self.launched.take() { @@ -575,12 +595,12 @@ impl Debugger { self.stddef_dm_info = Some(StddefDmInfo::new(text)); extools.configuration_done(); - } + }, DebugClient::Auxtools(auxtools) => { self.stddef_dm_info = auxtools.get_stddef()?.map(StddefDmInfo::new); auxtools.configured()?; - } + }, } Ok(()) } @@ -588,7 +608,6 @@ impl Debugger { fn Threads(&mut self, (): P) -> R { match &mut self.client { DebugClient::Extools(extools) => { - let mut threads = Vec::new(); let extools = extools.get()?; @@ -606,33 +625,29 @@ impl Debugger { }); } - Ok(ThreadsResponse { - threads, - }) + Ok(ThreadsResponse { threads }) }, DebugClient::Auxtools(auxtools) => { - let mut threads : Vec = auxtools.get_stacks()?.into_iter().map(|x| { - Thread { + let mut threads: Vec = auxtools + .get_stacks()? + .into_iter() + .map(|x| Thread { id: x.id as i64, name: x.name, - } - }).collect(); + }) + .collect(); // If we tell DAP that there are no threads, Pause requests never get passed through! if threads.is_empty() { - threads.push( - Thread { - id: 0, - name: "Main".to_owned(), - } - ); + threads.push(Thread { + id: 0, + name: "Main".to_owned(), + }); } - Ok(ThreadsResponse { - threads, - }) - } + Ok(ThreadsResponse { threads }) + }, } } @@ -645,7 +660,9 @@ impl Debugger { }; if params.sourceModified.unwrap_or(false) { - return Err(Box::new(GenericError("cannot update breakpoints in modified source"))); + return Err(Box::new(GenericError( + "cannot update breakpoints in modified source", + ))); } let inputs = params.breakpoints.unwrap_or_default(); @@ -662,14 +679,16 @@ impl Debugger { message: Some("Debugging hooks not available".to_owned()), line: Some(sbp.line), verified: false, - .. Default::default() + ..Default::default() }); } return Ok(SetBreakpointsResponse { breakpoints }); }; for sbp in inputs { - if let Some((typepath, name, override_id)) = self.db.location_to_proc_ref(file_id, sbp.line) { + if let Some((typepath, name, override_id)) = + self.db.location_to_proc_ref(file_id, sbp.line) + { // TODO: better discipline around format!("{}/{}") and so on let proc = format!("{typepath}/{name}"); if let Some(offset) = extools.line_to_offset(&proc, override_id, sbp.line) { @@ -682,7 +701,7 @@ impl Debugger { line: Some(sbp.line), verified: true, column: Some(0), - .. Default::default() + ..Default::default() }); } else { debug_output!(in self.seq, @@ -694,7 +713,7 @@ impl Debugger { message: Some("Unable to determine offset in proc".to_owned()), line: Some(sbp.line), verified: false, - .. Default::default() + ..Default::default() }); } } else { @@ -702,7 +721,7 @@ impl Debugger { message: Some("Unable to determine proc ref".to_owned()), line: Some(sbp.line), verified: false, - .. Default::default() + ..Default::default() }); } } @@ -717,43 +736,50 @@ impl Debugger { }); Ok(SetBreakpointsResponse { breakpoints }) - } + }, DebugClient::Auxtools(auxtools) => { let mut breakpoints = vec![]; for sbp in inputs { - if let Some((typepath, name, override_id)) = self.db.location_to_proc_ref(file_id, sbp.line) { + if let Some((typepath, name, override_id)) = + self.db.location_to_proc_ref(file_id, sbp.line) + { // TODO: better discipline around format!("{}/{}") and so on let proc = format!("{typepath}/{name}"); - if let Some(offset) = auxtools.get_offset(proc.as_str(), override_id as u32, sbp.line as u32)? { + if let Some(offset) = auxtools.get_offset( + proc.as_str(), + override_id as u32, + sbp.line as u32, + )? { saved.insert((proc.clone(), override_id, offset as i64)); keep.insert((proc.clone(), override_id, offset as i64)); - let result = auxtools.set_breakpoint(auxtools_types::InstructionRef { - proc: auxtools_types::ProcRef { - path: proc, - override_id: override_id as u32 + let result = auxtools.set_breakpoint( + auxtools_types::InstructionRef { + proc: auxtools_types::ProcRef { + path: proc, + override_id: override_id as u32, + }, + offset, }, - offset - }, sbp.condition)?; + sbp.condition, + )?; breakpoints.push(match result { auxtools_types::BreakpointSetResult::Success { line } => { Breakpoint { verified: true, line: line.map(|x| x as i64), - .. Default::default() + ..Default::default() } }, - auxtools_types::BreakpointSetResult::Failed => { - Breakpoint { - verified: false, - .. Default::default() - } - } + auxtools_types::BreakpointSetResult::Failed => Breakpoint { + verified: false, + ..Default::default() + }, }); } else { // debug_output!(in self.seq, @@ -765,7 +791,7 @@ impl Debugger { message: Some("Unable to determine offset in proc".to_owned()), line: Some(sbp.line), verified: false, - .. Default::default() + ..Default::default() }); } } else { @@ -773,7 +799,7 @@ impl Debugger { message: Some("Unable to determine proc ref".to_owned()), line: Some(sbp.line), verified: false, - .. Default::default() + ..Default::default() }); } } @@ -783,7 +809,7 @@ impl Debugger { let _ = auxtools.unset_breakpoint(&auxtools_types::InstructionRef { proc: auxtools_types::ProcRef { path: k.0.clone(), - override_id: k.1 as u32 + override_id: k.1 as u32, }, offset: k.2 as u32, }); @@ -794,11 +820,14 @@ impl Debugger { }); Ok(SetBreakpointsResponse { breakpoints }) - } + }, } } - fn SetFunctionBreakpoints(&mut self, params: P) -> R { + fn SetFunctionBreakpoints( + &mut self, + params: P, + ) -> R { let file_id = FileId::default(); let inputs = params.breakpoints; @@ -813,7 +842,7 @@ impl Debugger { breakpoints.push(Breakpoint { message: Some("Debugging hooks not available".to_owned()), verified: false, - .. Default::default() + ..Default::default() }); } return Ok(SetFunctionBreakpointsResponse { breakpoints }); @@ -825,7 +854,7 @@ impl Debugger { let mut override_id = 0; if let Some(idx) = sbp.name.find('#') { proc = &sbp.name[..idx]; - override_id = sbp.name[idx+1..].parse()?; + override_id = sbp.name[idx + 1..].parse()?; } if let Some(proc_ref) = self.db.get_proc(proc, override_id) { @@ -839,13 +868,13 @@ impl Debugger { line: Some(proc_ref.location.line as i64), verified: true, column: Some(0), - .. Default::default() + ..Default::default() }); } else { breakpoints.push(Breakpoint { message: Some(format!("Unknown proc {proc}#{override_id}")), verified: false, - .. Default::default() + ..Default::default() }); } } @@ -860,8 +889,7 @@ impl Debugger { }); Ok(SetFunctionBreakpointsResponse { breakpoints }) - } - + }, DebugClient::Auxtools(auxtools) => { let mut breakpoints = vec![]; @@ -872,7 +900,7 @@ impl Debugger { let mut override_id = 0; if let Some(idx) = sbp.name.find('#') { proc = &sbp.name[..idx]; - override_id = sbp.name[idx+1..].parse()?; + override_id = sbp.name[idx + 1..].parse()?; } let offset = 0; @@ -881,29 +909,28 @@ impl Debugger { saved.insert(tup.clone()); keep.insert(tup.clone()); - let result = auxtools.set_breakpoint(auxtools_types::InstructionRef { - proc: auxtools_types::ProcRef { - path: tup.0, - override_id: override_id as u32 + let result = auxtools.set_breakpoint( + auxtools_types::InstructionRef { + proc: auxtools_types::ProcRef { + path: tup.0, + override_id: override_id as u32, + }, + offset: offset as u32, }, - offset: offset as u32, - }, sbp.condition)?; + sbp.condition, + )?; breakpoints.push(match result { - auxtools_types::BreakpointSetResult::Success { line } => { - Breakpoint { - verified: true, - line: line.map(|x| x as i64), - .. Default::default() - } + auxtools_types::BreakpointSetResult::Success { line } => Breakpoint { + verified: true, + line: line.map(|x| x as i64), + ..Default::default() }, - auxtools_types::BreakpointSetResult::Failed => { - Breakpoint { - verified: false, - .. Default::default() - } - } + auxtools_types::BreakpointSetResult::Failed => Breakpoint { + verified: false, + ..Default::default() + }, }); } @@ -912,7 +939,7 @@ impl Debugger { let _ = auxtools.unset_breakpoint(&auxtools_types::InstructionRef { proc: auxtools_types::ProcRef { path: k.0.clone(), - override_id: k.1 as u32 + override_id: k.1 as u32, }, offset: k.2 as u32, }); @@ -923,7 +950,7 @@ impl Debugger { }); Ok(SetFunctionBreakpointsResponse { breakpoints }) - } + }, } } @@ -939,8 +966,11 @@ impl Debugger { let mut dap_frame = StackFrame { name: ex_frame.proc.clone(), id: (i * extools.get_all_threads().len()) as i64 + params.threadId, - instructionPointerReference: Some(format!("{}@{}#{}", ex_frame.proc, ex_frame.override_id, ex_frame.offset)), - .. Default::default() + instructionPointerReference: Some(format!( + "{}@{}#{}", + ex_frame.proc, ex_frame.override_id, ex_frame.offset + )), + ..Default::default() }; if i == 0 { @@ -953,11 +983,15 @@ impl Debugger { if proc.location.is_builtins() { // `stddef.dm` proc. if let Some(stddef_dm_info) = self.stddef_dm_info.as_ref() { - if let Some(proc) = get_proc(&stddef_dm_info.objtree, &ex_frame.proc, ex_frame.override_id) { + if let Some(proc) = get_proc( + &stddef_dm_info.objtree, + &ex_frame.proc, + ex_frame.override_id, + ) { dap_frame.source = Some(Source { name: Some("stddef.dm".to_owned()), sourceReference: Some(STDDEF_SOURCE_REFERENCE), - .. Default::default() + ..Default::default() }); dap_frame.line = i64::from(proc.location.line); //dap_frame.column = i64::from(proc.location.column); @@ -968,19 +1002,27 @@ impl Debugger { let path = self.db.files.get_path(proc.location.file); dap_frame.source = Some(Source { - name: Some(path.file_name() - .unwrap_or_default() - .to_string_lossy() - .into_owned()), - path: Some(self.db.root_dir.join(&*path).to_string_lossy().into_owned()), - .. Default::default() + name: Some( + path.file_name() + .unwrap_or_default() + .to_string_lossy() + .into_owned(), + ), + path: Some( + self.db.root_dir.join(&*path).to_string_lossy().into_owned(), + ), + ..Default::default() }); dap_frame.line = i64::from(proc.location.line); //dap_frame.column = i64::from(proc.location.column); } } - if let Some(line) = extools.offset_to_line(&ex_frame.proc, ex_frame.override_id, ex_frame.offset) { + if let Some(line) = extools.offset_to_line( + &ex_frame.proc, + ex_frame.override_id, + ex_frame.offset, + ) { dap_frame.line = line; } @@ -991,13 +1033,14 @@ impl Debugger { totalFrames: Some(len as i64), stackFrames: frames, }) - } + }, DebugClient::Auxtools(auxtools) => { let (aux_frames, aux_frames_total) = auxtools.get_stack_frames( params.threadId as u32, params.startFrame.map(|x| x as u32), - params.levels.map(|x| x as u32))?; + params.levels.map(|x| x as u32), + )?; let mut frames = Vec::with_capacity(aux_frames.len()); for (i, aux_frame) in aux_frames.iter().enumerate() { @@ -1005,8 +1048,11 @@ impl Debugger { let mut dap_frame = StackFrame { name: aux_proc.path.to_owned(), id: aux_frame.id as i64, - instructionPointerReference: Some(format!("{}@{}#{}", aux_proc.path, aux_proc.override_id, aux_frame.instruction.offset)), - .. Default::default() + instructionPointerReference: Some(format!( + "{}@{}#{}", + aux_proc.path, aux_proc.override_id, aux_frame.instruction.offset + )), + ..Default::default() }; if i == 0 { @@ -1015,15 +1061,22 @@ impl Debugger { dap_frame.column = 1; } - if let Some(proc) = self.db.get_proc(&aux_proc.path, aux_proc.override_id as usize) { + if let Some(proc) = self + .db + .get_proc(&aux_proc.path, aux_proc.override_id as usize) + { if proc.location.is_builtins() { // `stddef.dm` proc. if let Some(stddef_dm_info) = self.stddef_dm_info.as_ref() { - if let Some(proc) = get_proc(&stddef_dm_info.objtree, &aux_proc.path, aux_proc.override_id as usize) { + if let Some(proc) = get_proc( + &stddef_dm_info.objtree, + &aux_proc.path, + aux_proc.override_id as usize, + ) { dap_frame.source = Some(Source { name: Some("stddef.dm".to_owned()), sourceReference: Some(STDDEF_SOURCE_REFERENCE), - .. Default::default() + ..Default::default() }); dap_frame.line = i64::from(proc.location.line); //dap_frame.column = i64::from(proc.location.column); @@ -1034,12 +1087,16 @@ impl Debugger { let path = self.db.files.get_path(proc.location.file); dap_frame.source = Some(Source { - name: Some(path.file_name() - .unwrap_or_default() - .to_string_lossy() - .into_owned()), - path: Some(self.db.root_dir.join(&*path).to_string_lossy().into_owned()), - .. Default::default() + name: Some( + path.file_name() + .unwrap_or_default() + .to_string_lossy() + .into_owned(), + ), + path: Some( + self.db.root_dir.join(&*path).to_string_lossy().into_owned(), + ), + ..Default::default() }); dap_frame.line = i64::from(proc.location.line); //dap_frame.column = i64::from(proc.location.column); @@ -1057,7 +1114,7 @@ impl Debugger { totalFrames: Some(aux_frames_total as i64), stackFrames: frames, }) - } + }, } } @@ -1082,33 +1139,41 @@ impl Debugger { presentationHint: Some("locals".to_owned()), variablesReference: frameId * 2 + 2, indexedVariables: Some(frame.locals.len() as i64), - .. Default::default() + ..Default::default() }, Scope { name: "Arguments".to_owned(), presentationHint: Some("arguments".to_owned()), variablesReference: frameId * 2 + 1, namedVariables: Some(2 + frame.args.len() as i64), - .. Default::default() + ..Default::default() }, Scope { name: "Globals".to_owned(), variablesReference: 0x0e_000001, - .. Default::default() + ..Default::default() }, - ] + ], }) - } + }, DebugClient::Auxtools(auxtools) => { - let AuxtoolsScopes { arguments, locals, globals } = auxtools.get_scopes(frameId as u32)?; - let mut scopes = Vec::with_capacity(locals.is_some() as usize + arguments.is_some() as usize + globals.is_some() as usize); + let AuxtoolsScopes { + arguments, + locals, + globals, + } = auxtools.get_scopes(frameId as u32)?; + let mut scopes = Vec::with_capacity( + locals.is_some() as usize + + arguments.is_some() as usize + + globals.is_some() as usize, + ); if let Some(locals) = locals { scopes.push(Scope { name: "Locals".to_owned(), variablesReference: locals.0 as i64, - .. Default::default() + ..Default::default() }); } @@ -1116,7 +1181,7 @@ impl Debugger { scopes.push(Scope { name: "Arguments".to_owned(), variablesReference: arguments.0 as i64, - .. Default::default() + ..Default::default() }); } @@ -1124,14 +1189,12 @@ impl Debugger { scopes.push(Scope { name: "Globals".to_owned(), variablesReference: globals.0 as i64, - .. Default::default() + ..Default::default() }); } - Ok(ScopesResponse { - scopes - }) - } + Ok(ScopesResponse { scopes }) + }, } } @@ -1141,7 +1204,9 @@ impl Debugger { let extools = extools.get()?; if params.variablesReference >= 0x01_000000 { - let (var, ref_) = extools_types::ValueText::from_variables_reference(params.variablesReference); + let (var, ref_) = extools_types::ValueText::from_variables_reference( + params.variablesReference, + ); let mut variables = Vec::new(); if var.is_list { @@ -1153,26 +1218,26 @@ impl Debugger { name: format!("[{}]", 1 + i), value: entry.to_string(), variablesReference: entry.to_variables_reference(), - .. Default::default() + ..Default::default() }); } - } + }, extools_types::ListContents::Associative(entries) => { for (i, (key, val)) in entries.iter().enumerate() { variables.push(Variable { name: format!("keys[{}]", 1 + i), value: key.to_string(), variablesReference: key.to_variables_reference(), - .. Default::default() + ..Default::default() }); variables.push(Variable { name: format!("vals[{}]", 1 + i), value: val.to_string(), variablesReference: val.to_variables_reference(), - .. Default::default() + ..Default::default() }); } - } + }, } } else if var.has_vars { // Datum reference @@ -1184,7 +1249,7 @@ impl Debugger { name: name.to_owned(), value: vt.to_string(), variablesReference: vt.to_variables_reference(), - .. Default::default() + ..Default::default() }) } } @@ -1211,14 +1276,14 @@ impl Debugger { name: "src".to_owned(), value: frame.src.to_string(), variablesReference: frame.src.to_variables_reference(), - .. Default::default() + ..Default::default() }); seen.insert("usr", 0); variables.push(Variable { name: "usr".to_owned(), value: frame.usr.to_string(), variablesReference: frame.usr.to_variables_reference(), - .. Default::default() + ..Default::default() }); variables.extend(frame.args.iter().enumerate().map(|(i, vt)| Variable { @@ -1228,12 +1293,12 @@ impl Debugger { 0 => param.clone(), n => format!("{param} #{n}"), } - } + }, None => format!("args[{}]", i + 1), }, value: vt.to_string(), variablesReference: vt.to_variables_reference(), - .. Default::default() + ..Default::default() })); Ok(VariablesResponse { variables }) } else if mod2 == 0 { @@ -1244,7 +1309,7 @@ impl Debugger { name: ".".to_owned(), value: frame.dot.to_string(), variablesReference: frame.dot.to_variables_reference(), - .. Default::default() + ..Default::default() }); // If VSC receives two Variables with the same name, it only @@ -1257,21 +1322,23 @@ impl Debugger { 0 => local.clone(), n => format!("{local} #{n}"), } - } + }, None => i.to_string(), }, value: vt.to_string(), variablesReference: vt.to_variables_reference(), - .. Default::default() + ..Default::default() })); Ok(VariablesResponse { variables }) } else { Err(Box::new(GenericError("Bad variables reference"))) } - } + }, DebugClient::Auxtools(auxtools) => { - let aux_variables = auxtools.get_variables(auxtools_types::VariablesRef(params.variablesReference as i32))?; + let aux_variables = auxtools.get_variables(auxtools_types::VariablesRef( + params.variablesReference as i32, + ))?; let mut variables = vec![]; // If VSC receives two Variables with the same name, it only @@ -1279,7 +1346,11 @@ impl Debugger { let mut seen = HashMap::new(); for aux_var in aux_variables { - let name = match seen.entry(aux_var.name.clone()).and_modify(|e| *e += 1).or_default() { + let name = match seen + .entry(aux_var.name.clone()) + .and_modify(|e| *e += 1) + .or_default() + { 0 => aux_var.name, n => format!("{} #{}", aux_var.name, n), }; @@ -1288,14 +1359,12 @@ impl Debugger { name, value: aux_var.value, variablesReference: aux_var.variables.map(|x| x.0 as i64).unwrap_or(0), - .. Default::default() + ..Default::default() }); } - Ok(VariablesResponse { - variables - }) - } + Ok(VariablesResponse { variables }) + }, } } @@ -1306,11 +1375,11 @@ impl Debugger { DebugClient::Extools(extools) => { let extools = extools.get()?; extools.continue_execution(); - } + }, DebugClient::Auxtools(auxtools) => { auxtools.continue_execution()?; - } + }, } Ok(ContinueResponse { @@ -1325,11 +1394,11 @@ impl Debugger { DebugClient::Extools(extools) => { let extools = extools.get()?; extools.step_in(params.threadId); - } + }, DebugClient::Auxtools(auxtools) => { auxtools.step_into(params.threadId as u32)?; - } + }, } Ok(()) } @@ -1341,11 +1410,11 @@ impl Debugger { DebugClient::Extools(extools) => { let extools = extools.get()?; extools.step_over(params.threadId); - } + }, DebugClient::Auxtools(auxtools) => { auxtools.next(params.threadId as u32)?; - } + }, } Ok(()) } @@ -1357,11 +1426,11 @@ impl Debugger { DebugClient::Extools(extools) => { let extools = extools.get()?; extools.step_out(params.threadId); - } + }, DebugClient::Auxtools(auxtools) => { auxtools.step_out(params.threadId as u32)?; - } + }, } Ok(()) } @@ -1371,25 +1440,38 @@ impl Debugger { DebugClient::Extools(extools) => { let extools = extools.get()?; extools.pause(); - } + }, DebugClient::Auxtools(auxtools) => { auxtools.pause()?; - } + }, } Ok(()) } - fn SetExceptionBreakpoints(&mut self, params: P) -> R { + fn SetExceptionBreakpoints( + &mut self, + params: P, + ) -> R { match &mut self.client { DebugClient::Extools(extools) => { let extools = extools.get()?; - extools.set_break_on_runtime(params.filters.iter().any(|x| x == EXCEPTION_FILTER_RUNTIMES)); - } + extools.set_break_on_runtime( + params + .filters + .iter() + .any(|x| x == EXCEPTION_FILTER_RUNTIMES), + ); + }, DebugClient::Auxtools(auxtools) => { - auxtools.set_catch_runtimes(params.filters.iter().any(|x| x == EXCEPTION_FILTER_RUNTIMES))?; - } + auxtools.set_catch_runtimes( + params + .filters + .iter() + .any(|x| x == EXCEPTION_FILTER_RUNTIMES), + )?; + }, } Ok(()) } @@ -1406,16 +1488,14 @@ impl Debugger { breakMode: ExceptionBreakMode::Always, details: None, }) - } + }, - DebugClient::Auxtools(auxtools) => { - Ok(ExceptionInfoResponse { - exceptionId: auxtools.get_last_error_message(), - description: None, - breakMode: ExceptionBreakMode::Always, - details: None, - }) - } + DebugClient::Auxtools(auxtools) => Ok(ExceptionInfoResponse { + exceptionId: auxtools.get_last_error_message(), + description: None, + breakMode: ExceptionBreakMode::Always, + details: None, + }), } } @@ -1445,7 +1525,8 @@ impl Debugger { fn Disassemble(&mut self, params: P) -> R { match &mut self.client { DebugClient::Extools(extools) => { - let Some(captures) = MEMORY_REFERENCE_REGEX.captures(¶ms.memoryReference) else { + let Some(captures) = MEMORY_REFERENCE_REGEX.captures(¶ms.memoryReference) + else { return Err(Box::new(GenericError("Invalid memory reference"))); }; let proc = &captures[1]; @@ -1459,18 +1540,18 @@ impl Debugger { address: format!("{}#{}@{}", proc, override_id, instr.offset), instructionBytes: Some(instr.bytes.clone()), instruction: format!("{} {}", instr.mnemonic, instr.comment), - .. Default::default() + ..Default::default() }); } Ok(DisassembleResponse { - instructions: result + instructions: result, }) - } + }, DebugClient::Auxtools(_) => { Err(Box::new(GenericError("auxtools can't disassemble yet"))) - } + }, } } } diff --git a/crates/dm-langserver/src/document.rs b/crates/dm-langserver/src/document.rs index 83069c3c..005c224f 100644 --- a/crates/dm-langserver/src/document.rs +++ b/crates/dm-langserver/src/document.rs @@ -2,8 +2,8 @@ //! language server protocol. #![allow(dead_code)] -use std::borrow::Cow; use foldhash::HashMap; +use std::borrow::Cow; use std::io::{self, BufRead, Read}; use std::rc::Rc; use url::Url; @@ -24,7 +24,10 @@ pub struct DocumentStore { impl DocumentStore { pub fn open(&mut self, doc: TextDocumentItem) -> Result<(), jsonrpc::Error> { - match self.map.insert(doc.uri.clone(), Document::new(doc.version, doc.text)) { + match self + .map + .insert(doc.uri.clone(), Document::new(doc.version, doc.text)) + { None => Ok(()), Some(_) => Err(invalid_request(format!("opened twice: {}", doc.uri))), } @@ -33,7 +36,10 @@ impl DocumentStore { pub fn close(&mut self, id: TextDocumentIdentifier) -> Result { match self.map.remove(&id.uri) { Some(_) => Ok(id.uri), - None => Err(invalid_request(format!("cannot close non-opened: {}", id.uri))), + None => Err(invalid_request(format!( + "cannot close non-opened: {}", + id.uri + ))), } } @@ -46,12 +52,22 @@ impl DocumentStore { let document = match self.map.get_mut(&doc_id.uri) { Some(doc) => doc, - None => return Err(invalid_request(format!("cannot change non-opened: {}", doc_id.uri))), + None => { + return Err(invalid_request(format!( + "cannot change non-opened: {}", + doc_id.uri + ))) + }, }; if new_version < document.version { - eprintln!("new_version: {} < document_version: {}", new_version, document.version); - return Err(invalid_request("document version numbers shouldn't go backwards")); + eprintln!( + "new_version: {} < document_version: {}", + new_version, document.version + ); + return Err(invalid_request( + "document version numbers shouldn't go backwards", + )); } document.version = new_version; @@ -77,8 +93,10 @@ impl DocumentStore { return Ok(Cow::Owned(text)); } - Err(io::Error::new(io::ErrorKind::NotFound, - format!("URL not opened and schema is not 'file': {url}"))) + Err(io::Error::new( + io::ErrorKind::NotFound, + format!("URL not opened and schema is not 'file': {url}"), + )) } pub fn read(&self, url: &Url) -> io::Result> { @@ -91,8 +109,10 @@ impl DocumentStore { return Ok(Box::new(file) as Box); } - Err(io::Error::new(io::ErrorKind::NotFound, - format!("URL not opened and schema is not 'file': {url}"))) + Err(io::Error::new( + io::ErrorKind::NotFound, + format!("URL not opened and schema is not 'file': {url}"), + )) } } @@ -119,7 +139,7 @@ impl Document { // considered to be the full content of the document." self.text = Rc::new(change.text); return Ok(()); - } + }, }; let start_pos = total_offset(&self.text, range.start.line, range.start.character)?; @@ -152,7 +172,7 @@ fn total_offset(text: &str, line: u32, mut character: u32) -> Result lsp_types::Position { } pub fn get_range(text: &str, range: lsp_types::Range) -> Result<&str, jsonrpc::Error> { - Ok(&text[ - total_offset(text, range.start.line, range.start.character)? - ..total_offset(text, range.end.line, range.end.character)? - ]) + Ok( + &text[total_offset(text, range.start.line, range.start.character)? + ..total_offset(text, range.end.line, range.end.character)?], + ) } pub fn find_word(text: &str, offset: usize) -> &str { diff --git a/crates/dm-langserver/src/find_references.rs b/crates/dm-langserver/src/find_references.rs index 138d7956..8f3c4001 100644 --- a/crates/dm-langserver/src/find_references.rs +++ b/crates/dm-langserver/src/find_references.rs @@ -26,10 +26,13 @@ impl ReferencesTable { // Insert the "definition" locations for the types and such objtree.root().recurse(&mut |ty| { - tab.uses.insert(ty.id, References { - references: vec![], - implementations: vec![ty.location], - }); + tab.uses.insert( + ty.id, + References { + references: vec![], + implementations: vec![ty.location], + }, + ); for (name, var) in ty.vars.iter() { if let Some(decl) = ty.get_var_declaration(name) { tab.impl_symbol(decl.id, var.value.location); @@ -47,7 +50,9 @@ impl ReferencesTable { if let Some(ref expr) = var.value.expression { let mut walk = WalkProc::from_ty(&mut tab, objtree, ty); let type_hint = match ty.get_var_declaration(name) { - Some(decl) => walk.static_type(decl.location, &decl.var_type.type_path).basic_type(), + Some(decl) => walk + .static_type(decl.location, &decl.var_type.type_path) + .basic_type(), None => None, }; walk.visit_expression(var.value.location, expr, type_hint); @@ -86,19 +91,30 @@ impl ReferencesTable { fn new_symbol(&mut self, location: Location) -> SymbolId { let id = self.symbols.allocate(); - self.uses.insert(id, References { - references: vec![location], - implementations: vec![], - }); + self.uses.insert( + id, + References { + references: vec![location], + implementations: vec![], + }, + ); id } fn use_symbol(&mut self, symbol: SymbolId, location: Location) { - self.uses.entry(symbol).or_default().references.push(location); + self.uses + .entry(symbol) + .or_default() + .references + .push(location); } fn impl_symbol(&mut self, symbol: SymbolId, location: Location) { - self.uses.entry(symbol).or_default().implementations.push(location); + self.uses + .entry(symbol) + .or_default() + .implementations + .push(location); } } @@ -138,29 +154,44 @@ struct WalkProc<'o> { impl<'o> WalkProc<'o> { fn from_proc(tab: &'o mut ReferencesTable, objtree: &'o ObjectTree, proc: ProcRef<'o>) -> Self { let mut local_vars = HashMap::new(); - local_vars.insert("global".to_owned(), Local { - ty: StaticType::Type(objtree.root()), - symbol: objtree.root().id, - }); - local_vars.insert(".".to_owned(), Local { - ty: StaticType::None, - symbol: tab.new_symbol(proc.location), - }); - local_vars.insert("args".to_owned(), Local { - ty: StaticType::Type(objtree.expect("/list")), - symbol: tab.new_symbol(proc.location), - }); - local_vars.insert("usr".to_owned(), Local { - ty: StaticType::Type(objtree.expect("/mob")), - symbol: tab.new_symbol(proc.location), - }); + local_vars.insert( + "global".to_owned(), + Local { + ty: StaticType::Type(objtree.root()), + symbol: objtree.root().id, + }, + ); + local_vars.insert( + ".".to_owned(), + Local { + ty: StaticType::None, + symbol: tab.new_symbol(proc.location), + }, + ); + local_vars.insert( + "args".to_owned(), + Local { + ty: StaticType::Type(objtree.expect("/list")), + symbol: tab.new_symbol(proc.location), + }, + ); + local_vars.insert( + "usr".to_owned(), + Local { + ty: StaticType::Type(objtree.expect("/mob")), + symbol: tab.new_symbol(proc.location), + }, + ); let ty = proc.ty(); if !ty.is_root() { - local_vars.insert("src".to_owned(), Local { - ty: StaticType::Type(ty), - symbol: tab.new_symbol(proc.location), - }); + local_vars.insert( + "src".to_owned(), + Local { + ty: StaticType::Type(ty), + symbol: tab.new_symbol(proc.location), + }, + ); } WalkProc { @@ -168,23 +199,26 @@ impl<'o> WalkProc<'o> { objtree, ty: proc.ty(), proc: Some(proc), - local_vars + local_vars, } } fn from_ty(tab: &'o mut ReferencesTable, objtree: &'o ObjectTree, ty: TypeRef<'o>) -> Self { let mut local_vars = HashMap::new(); - local_vars.insert("global".to_owned(), Local { - ty: StaticType::Type(objtree.root()), - symbol: objtree.root().id, - }); + local_vars.insert( + "global".to_owned(), + Local { + ty: StaticType::Type(objtree.root()), + symbol: objtree.root().id, + }, + ); WalkProc { tab, objtree, ty, proc: None, - local_vars + local_vars, } } @@ -195,10 +229,13 @@ impl<'o> WalkProc<'o> { if let Some(expr) = ¶m.default { self.visit_expression(param.location, expr, None); } - self.local_vars.insert(param.name.to_owned(), Local { - ty, - symbol: self.tab.new_symbol(param.location) - }); + self.local_vars.insert( + param.name.to_owned(), + Local { + ty, + symbol: self.tab.new_symbol(param.location), + }, + ); } self.visit_block(block); } @@ -211,7 +248,9 @@ impl<'o> WalkProc<'o> { fn visit_statement(&mut self, location: Location, statement: &'o Statement) { match statement { - Statement::Expr(expr) => { self.visit_expression(location, expr, None); }, + Statement::Expr(expr) => { + self.visit_expression(location, expr, None); + }, Statement::Return(expr) => { let dot = self.local_vars.get(".").unwrap().symbol; self.tab.use_symbol(dot, location); @@ -219,7 +258,9 @@ impl<'o> WalkProc<'o> { self.visit_expression(location, expr, None); } }, - Statement::Throw(expr) => { self.visit_expression(location, expr, None); }, + Statement::Throw(expr) => { + self.visit_expression(location, expr, None); + }, Statement::While { condition, block } => { self.visit_expression(location, condition, None); self.visit_block(block); @@ -239,8 +280,13 @@ impl<'o> WalkProc<'o> { }, Statement::ForInfinite { block } => { self.visit_block(block); - } - Statement::ForLoop { init, test, inc, block } => { + }, + Statement::ForLoop { + init, + test, + inc, + block, + } => { if let Some(init) = init { self.visit_statement(location, init); } @@ -253,7 +299,13 @@ impl<'o> WalkProc<'o> { self.visit_block(block); }, Statement::ForList(for_list) => { - let ForListStatement { var_type, name, in_list, block, .. } = &**for_list; + let ForListStatement { + var_type, + name, + in_list, + block, + .. + } = &**for_list; if let Some(in_list) = in_list { self.visit_expression(location, in_list, None); } @@ -263,7 +315,14 @@ impl<'o> WalkProc<'o> { self.visit_block(block); }, Statement::ForRange(for_range) => { - let ForRangeStatement { var_type, name, start, end, step, block } = &**for_range; + let ForRangeStatement { + var_type, + name, + start, + end, + step, + block, + } = &**for_range; self.visit_expression(location, end, None); if let Some(step) = step { self.visit_expression(location, step, None); @@ -286,16 +345,22 @@ impl<'o> WalkProc<'o> { } self.visit_block(block); }, - Statement::Switch { input, cases, default } => { + Statement::Switch { + input, + cases, + default, + } => { self.visit_expression(location, input, None); for (case, ref block) in cases.iter() { for case_part in case.elem.iter() { match case_part { - dm::ast::Case::Exact(expr) => { self.visit_expression(case.location, expr, None); }, + dm::ast::Case::Exact(expr) => { + self.visit_expression(case.location, expr, None); + }, dm::ast::Case::Range(start, end) => { self.visit_expression(case.location, start, None); self.visit_expression(case.location, end, None); - } + }, } } self.visit_block(block); @@ -304,16 +369,20 @@ impl<'o> WalkProc<'o> { self.visit_block(default); } }, - Statement::TryCatch { try_block, catch_params, catch_block } => { + Statement::TryCatch { + try_block, + catch_params, + catch_block, + } => { self.visit_block(try_block); for caught in catch_params.iter() { let (var_name, mut type_path) = match caught.split_last() { Some(x) => x, - None => continue + None => continue, }; match type_path.split_first() { Some((first, rest)) if first == "var" => type_path = rest, - _ => {} + _ => {}, } let var_type: VarType = type_path.iter().map(ToOwned::to_owned).collect(); self.visit_var(location, &var_type, var_name, None); @@ -325,9 +394,18 @@ impl<'o> WalkProc<'o> { Statement::Goto(_) => {}, Statement::Crash(_) => {}, Statement::Label { name: _, block } => self.visit_block(block), - Statement::Del(expr) => { self.visit_expression(location, expr, None); }, + Statement::Del(expr) => { + self.visit_expression(location, expr, None); + }, Statement::ForKeyValue(for_key_value) => { - let ForKeyValueStatement { var_type, key, key_input_type: _, value, in_list, block } = &**for_key_value; + let ForKeyValueStatement { + var_type, + key, + key_input_type: _, + value, + in_list, + block, + } = &**for_key_value; if let Some(in_list) = in_list { self.visit_expression(location, in_list, None); } @@ -351,16 +429,25 @@ impl<'o> WalkProc<'o> { self.visit_var(location, &var.var_type, &var.name, var.value.as_ref()) } - fn visit_var(&mut self, location: Location, var_type: &VarType, name: &str, value: Option<&'o Expression>) { + fn visit_var( + &mut self, + location: Location, + var_type: &VarType, + name: &str, + value: Option<&'o Expression>, + ) { let ty = self.static_type(location, &var_type.type_path); self.use_type(location, &ty); if let Some(expr) = value { self.visit_expression(location, expr, ty.basic_type()); } - self.local_vars.insert(name.to_owned(), Local { - ty, - symbol: self.tab.new_symbol(location), - }); + self.local_vars.insert( + name.to_owned(), + Local { + ty, + symbol: self.tab.new_symbol(location), + }, + ); } fn use_type(&mut self, location: Location, ty: &StaticType<'o>) { @@ -370,26 +457,31 @@ impl<'o> WalkProc<'o> { StaticType::List { list, keys } => { self.tab.use_symbol(list.id, location); self.use_type(location, keys); - } + }, } } #[allow(clippy::only_used_in_recursion)] - fn visit_expression(&mut self, location: Location, expression: &'o Expression, type_hint: Option>) -> StaticType<'o> { + fn visit_expression( + &mut self, + location: Location, + expression: &'o Expression, + type_hint: Option>, + ) -> StaticType<'o> { match expression { Expression::Base { term, follow } => { - let base_type_hint = if follow.is_empty() { - type_hint - } else { - None - }; + let base_type_hint = if follow.is_empty() { type_hint } else { None }; let mut ty = self.visit_term(term.location, &term.elem, base_type_hint); for each in follow.iter() { ty = self.visit_follow(each.location, ty, &each.elem); } ty }, - Expression::BinaryOp { op: BinaryOp::Or, lhs, rhs } => { + Expression::BinaryOp { + op: BinaryOp::Or, + lhs, + rhs, + } => { // It appears that DM does this in more cases than this, but // this is the only case I've seen it used in the wild. // ex: var/datum/cache_entry/E = cache[key] || new @@ -412,7 +504,7 @@ impl<'o> WalkProc<'o> { let ty = self.visit_expression(location, if_, type_hint); self.visit_expression(location, else_, type_hint); ty - } + }, } } @@ -429,7 +521,12 @@ impl<'o> WalkProc<'o> { } } - fn visit_term(&mut self, location: Location, term: &'o Term, type_hint: Option>) -> StaticType<'o> { + fn visit_term( + &mut self, + location: Location, + term: &'o Term, + type_hint: Option>, + ) -> StaticType<'o> { match term { Term::Null => StaticType::None, Term::Int(_) => StaticType::None, @@ -481,9 +578,7 @@ impl<'o> WalkProc<'o> { } }, - Term::NewImplicit { args } => { - self.visit_new(location, type_hint, args) - }, + Term::NewImplicit { args } => self.visit_new(location, type_hint, args), Term::NewPrefab { prefab, args } => { let typepath = self.visit_prefab(location, prefab); self.visit_new(location, typepath, args) @@ -513,7 +608,11 @@ impl<'o> WalkProc<'o> { } StaticType::None }, - Term::Input { args, input_type: _, in_list } => { + Term::Input { + args, + input_type: _, + in_list, + } => { // TODO: use /proc/input self.visit_arguments(location, args); if let Some(ref expr) = in_list { @@ -537,7 +636,11 @@ impl<'o> WalkProc<'o> { self.visit_arguments(location, args_2); StaticType::None }, - Term::ExternalCall { library, function, args } => { + Term::ExternalCall { + library, + function, + args, + } => { if let Some(library) = library { self.visit_expression(location, library, None); } @@ -568,16 +671,16 @@ impl<'o> WalkProc<'o> { }, Term::__PROC__ => { let Some(proc) = self.proc else { - return StaticType::None + return StaticType::None; }; if let Some(decl) = self.ty.get_proc_declaration(proc.name()) { self.tab.use_symbol(decl.id, location); } StaticType::None - } + }, Term::__IMPLIED_TYPE__ => { let Some(implied_type) = type_hint else { - return StaticType::None + return StaticType::None; }; self.tab.use_symbol(implied_type.id, location); StaticType::Type(implied_type) @@ -585,7 +688,12 @@ impl<'o> WalkProc<'o> { } } - fn visit_new(&mut self, location: Location, typepath: Option>, args: &'o Option>) -> StaticType<'o> { + fn visit_new( + &mut self, + location: Location, + typepath: Option>, + args: &'o Option>, + ) -> StaticType<'o> { if let Some(typepath) = typepath { if let Some(new_proc) = typepath.get_proc("New") { self.visit_call( @@ -595,7 +703,8 @@ impl<'o> WalkProc<'o> { args.as_ref().map_or(&[], |v| &v[..]), // New calls are exact: `new /datum()` will always call // `/datum/New()` and never an override. - true); + true, + ); } // If we had a diagnostic context here, we'd error for // types other than `/list`, which has no `New()`. @@ -620,7 +729,9 @@ impl<'o> WalkProc<'o> { let mut type_hint = None; if let Some(decl) = nav.ty().get_var_declaration(key) { self.tab.use_symbol(decl.id, location); - type_hint = self.static_type(location, &decl.var_type.type_path).basic_type(); + type_hint = self + .static_type(location, &decl.var_type.type_path) + .basic_type(); } self.visit_expression(location, expr, type_hint); } @@ -631,7 +742,12 @@ impl<'o> WalkProc<'o> { } } - fn visit_field(&mut self, location: Location, lhs: StaticType<'o>, name: &'o str) -> StaticType<'o> { + fn visit_field( + &mut self, + location: Location, + lhs: StaticType<'o>, + name: &'o str, + ) -> StaticType<'o> { if let Some(ty) = lhs.basic_type() { if let Some(decl) = ty.get_var_declaration(name) { self.tab.use_symbol(decl.id, location); @@ -644,7 +760,12 @@ impl<'o> WalkProc<'o> { } } - fn visit_follow(&mut self, location: Location, lhs: StaticType<'o>, rhs: &'o Follow) -> StaticType<'o> { + fn visit_follow( + &mut self, + location: Location, + lhs: StaticType<'o>, + rhs: &'o Follow, + ) -> StaticType<'o> { match rhs { Follow::Unary(op) => self.visit_unary(lhs, *op), Follow::Index(_, expr) => { @@ -687,12 +808,24 @@ impl<'o> WalkProc<'o> { StaticType::None } - fn visit_binary(&mut self, _lhs: StaticType<'o>, _rhs: StaticType<'o>, _op: BinaryOp) -> StaticType<'o> { + fn visit_binary( + &mut self, + _lhs: StaticType<'o>, + _rhs: StaticType<'o>, + _op: BinaryOp, + ) -> StaticType<'o> { // TODO: mark usage of operatorX procs StaticType::None } - fn visit_call(&mut self, location: Location, src: TypeRef<'o>, proc: ProcRef, args: &'o [Expression], is_exact: bool) -> StaticType<'o> { + fn visit_call( + &mut self, + location: Location, + src: TypeRef<'o>, + proc: ProcRef, + args: &'o [Expression], + is_exact: bool, + ) -> StaticType<'o> { // register use of symbol if !is_exact { // Only include uses of the symbol by name, not `.()` or `..()` @@ -705,17 +838,21 @@ impl<'o> WalkProc<'o> { // identify and register kwargs used for arg in args { let mut argument_value = arg; - if let Expression::AssignOp { op: AssignOp::Assign, lhs, rhs } = arg { + if let Expression::AssignOp { + op: AssignOp::Assign, + lhs, + rhs, + } = arg + { match lhs.as_term() { - Some(Term::Ident(_name)) | - Some(Term::String(_name)) => { + Some(Term::Ident(_name)) | Some(Term::String(_name)) => { // Don't visit_expression the kwarg key. argument_value = rhs; // TODO: register a usage of the kwarg symbol here. // Recurse to children too? - } - _ => {} + }, + _ => {}, } } @@ -728,14 +865,18 @@ impl<'o> WalkProc<'o> { fn visit_arguments(&mut self, location: Location, args: &'o [Expression]) { for arg in args { let mut argument_value = arg; - if let Expression::AssignOp { op: AssignOp::Assign, lhs, rhs } = arg { + if let Expression::AssignOp { + op: AssignOp::Assign, + lhs, + rhs, + } = arg + { match lhs.as_term() { - Some(Term::Ident(_name)) | - Some(Term::String(_name)) => { + Some(Term::Ident(_name)) | Some(Term::String(_name)) => { // Don't visit_expression the kwarg key. argument_value = rhs; - } - _ => {} + }, + _ => {}, } } @@ -745,7 +886,19 @@ impl<'o> WalkProc<'o> { #[allow(clippy::only_used_in_recursion)] fn static_type(&mut self, location: Location, mut of: &[String]) -> StaticType<'o> { - while !of.is_empty() && ["static", "global", "const", "tmp", "final", "SpacemanDMM_final", "SpacemanDMM_private", "SpacemanDMM_protected"].contains(&&*of[0]) { + while !of.is_empty() + && [ + "static", + "global", + "const", + "tmp", + "final", + "SpacemanDMM_final", + "SpacemanDMM_private", + "SpacemanDMM_protected", + ] + .contains(&&*of[0]) + { of = &of[1..]; } diff --git a/crates/dm-langserver/src/main.rs b/crates/dm-langserver/src/main.rs index a0a94e2a..023c454a 100644 --- a/crates/dm-langserver/src/main.rs +++ b/crates/dm-langserver/src/main.rs @@ -63,12 +63,20 @@ fn main() { Ok(path) => eprintln!("executable: {}", path.display()), Err(e) => eprintln!("exe check failure: {e}"), } - eprint!("{}", include_str!(concat!(env!("OUT_DIR"), "/build-info.txt"))); - #[cfg(extools_bundle)] { + eprint!( + "{}", + include_str!(concat!(env!("OUT_DIR"), "/build-info.txt")) + ); + #[cfg(extools_bundle)] + { eprintln!("extools commit: {}", env!("BUNDLE_VERSION_extools.dll")); } - #[cfg(auxtools_bundle)] { - eprintln!("auxtools commit: {}", env!("BUNDLE_VERSION_debug_server.dll")); + #[cfg(auxtools_bundle)] + { + eprintln!( + "auxtools commit: {}", + env!("BUNDLE_VERSION_debug_server.dll") + ); } match std::env::current_dir() { Ok(path) => eprintln!("directory: {}", path.display()), @@ -76,7 +84,7 @@ fn main() { } let mut args = std::env::args(); - let _ = args.next(); // skip executable name + let _ = args.next(); // skip executable name if let Some(arg) = args.next() { if arg == "--debugger" { return debugger::debugger_main(args); @@ -116,8 +124,12 @@ impl ClientCaps { if let Some(ref text_document) = caps.text_document { if let Some(ref signature_help) = text_document.signature_help { if let Some(ref signature_information) = signature_help.signature_information { - if let Some(ref parameter_information) = signature_information.parameter_information { - if let Some(label_offset_support) = parameter_information.label_offset_support { + if let Some(ref parameter_information) = + signature_information.parameter_information + { + if let Some(label_offset_support) = + parameter_information.label_offset_support + { this.label_offset_support = label_offset_support; } } @@ -158,7 +170,12 @@ impl DiagnosticsTracker { } } - fn build(root: Option<&Url>, file_list: &dm::FileList, errors: &[dm::DMError], related_info: bool) -> HashMap> { + fn build( + root: Option<&Url>, + file_list: &dm::FileList, + errors: &[dm::DMError], + related_info: bool, + ) -> HashMap> { let mut map: HashMap<_, Vec<_>> = HashMap::new(); for error in errors.iter() { let loc = error.location(); @@ -167,7 +184,11 @@ impl DiagnosticsTracker { } else { let mut notes = Vec::with_capacity(error.notes().len()); for note in error.notes().iter() { - let Some(uri) = DiagnosticsTracker::file_url(root, file_list, note.location().file) else { continue }; + let Some(uri) = + DiagnosticsTracker::file_url(root, file_list, note.location().file) + else { + continue; + }; notes.push(lsp_types::DiagnosticRelatedInformation { location: lsp_types::Location { uri, @@ -185,12 +206,12 @@ impl DiagnosticsTracker { source: component_to_source(error.component()), code: convert_errorcode(error.errortype()), related_information, - .. Default::default() + ..Default::default() }; - let Some(uri) = DiagnosticsTracker::file_url(root, file_list, loc.file) else { continue }; - map.entry(uri) - .or_insert_with(Default::default) - .push(diag); + let Some(uri) = DiagnosticsTracker::file_url(root, file_list, loc.file) else { + continue; + }; + map.entry(uri).or_insert_with(Default::default).push(diag); if !related_info { // Fallback in case the client does not support related info @@ -200,12 +221,14 @@ impl DiagnosticsTracker { severity: Some(lsp_types::DiagnosticSeverity::INFORMATION), range: location_to_range(note.location()), source: component_to_source(error.component()), - .. Default::default() + ..Default::default() }; - let Some(uri) = DiagnosticsTracker::file_url(root, file_list, note.location().file) else { continue }; - map.entry(uri) - .or_insert_with(Default::default) - .push(diag); + let Some(uri) = + DiagnosticsTracker::file_url(root, file_list, note.location().file) + else { + continue; + }; + map.entry(uri).or_insert_with(Default::default).push(diag); } } } @@ -215,7 +238,7 @@ impl DiagnosticsTracker { fn send(&mut self, map: HashMap>) { let mut new_sent = HashSet::with_capacity(map.len()); for (url, diagnostics) in map { - self.sent.remove(&url); // don't erase below + self.sent.remove(&url); // don't erase below new_sent.insert(url.clone()); issue_notification::( lsp_types::PublishDiagnosticsParams { @@ -295,18 +318,20 @@ impl Engine { issue_notification::(params) } - fn show_message(&mut self, typ: MessageType, message: S) where - S: Into + fn show_message(&mut self, typ: MessageType, message: S) + where + S: Into, { let message = message.into(); eprintln!("{typ:?}: {message}"); self.issue_notification::( - lsp_types::ShowMessageParams { typ, message } + lsp_types::ShowMessageParams { typ, message }, ) } - fn show_status(&self, message: S) where - S: Into + fn show_status(&self, message: S) + where + S: Into, { self.issue_notification::(extras::WindowStatusParams { environment: None, @@ -334,7 +359,12 @@ impl Engine { } } - fn convert_location(&self, loc: dm::Location, docs: &dm::docs::DocCollection, if_builtin: &[&str]) -> Result { + fn convert_location( + &self, + loc: dm::Location, + docs: &dm::docs::DocCollection, + if_builtin: &[&str], + ) -> Result { Ok(lsp_types::Location { uri: if loc.is_builtins() { let temp; @@ -346,7 +376,8 @@ impl Engine { temp = if_builtin.join(""); &temp } - )).map_err(invalid_request)? + )) + .map_err(invalid_request)? } else { self.file_url(loc.file)? }, @@ -363,9 +394,7 @@ impl Engine { // offload serialization costs to another thread std::thread::spawn(move || { let start = std::time::Instant::now(); - issue_notification::(extras::ObjectTreeParams { - root, - }); + issue_notification::(extras::ObjectTreeParams { root }); let elapsed = start.elapsed(); eprintln!( "serialized objtree in {}.{:03}s", @@ -380,7 +409,9 @@ impl Engine { let mut entry = extras::ObjectTreeType { name: ty.name().to_owned(), kind: lsp_types::SymbolKind::CLASS, - location: self.convert_location(ty.location, &ty.docs, &[&ty.path]).ok(), + location: self + .convert_location(ty.location, &ty.docs, &[&ty.path]) + .ok(), vars: Vec::new(), procs: Vec::new(), children: Vec::new(), @@ -392,7 +423,13 @@ impl Engine { entry.vars.push(extras::ObjectTreeVar { name: name.to_owned(), kind: lsp_types::SymbolKind::FIELD, - location: self.convert_location(var.value.location, &var.value.docs, &[&ty.path, "/var/", name]).ok(), + location: self + .convert_location( + var.value.location, + &var.value.docs, + &[&ty.path, "/var/", name], + ) + .ok(), is_declaration, }); } @@ -405,7 +442,9 @@ impl Engine { entry.procs.push(extras::ObjectTreeProc { name: name.to_owned(), kind: lsp_types::SymbolKind::METHOD, - location: self.convert_location(value.location, &value.docs, &[&ty.path, "/proc/", name]).ok(), + location: self + .convert_location(value.location, &value.docs, &[&ty.path, "/proc/", name]) + .ok(), is_verb, }); is_verb = None; @@ -441,7 +480,11 @@ impl Engine { let print_thread_total = move || { let elapsed = original_start.elapsed(); - eprintln!(" - total {}.{:03}s", elapsed.as_secs(), elapsed.subsec_millis()); + eprintln!( + " - total {}.{:03}s", + elapsed.as_secs(), + elapsed.subsec_millis() + ); }; // Set up the preprocessor. @@ -455,35 +498,50 @@ impl Engine { uri: path_to_url(environment)?, diagnostics: vec![lsp_types::Diagnostic { message: err.to_string(), - .. Default::default() + ..Default::default() }], version: None, }, ); eprintln!("{err:?}"); return Ok(()); - } + }, }; - let elapsed = start.elapsed(); start += elapsed; + let elapsed = start.elapsed(); + start += elapsed; if elapsed.as_millis() > 0 { - eprint!("setup {}.{:03}s - ", elapsed.as_secs(), elapsed.subsec_millis()); + eprint!( + "setup {}.{:03}s - ", + elapsed.as_secs(), + elapsed.subsec_millis() + ); } // Parse the environment. let fatal_errored; { - let mut parser = dm::parser::Parser::new(&self.context, dm::indents::IndentProcessor::new(&self.context, &mut pp)); + let mut parser = dm::parser::Parser::new( + &self.context, + dm::indents::IndentProcessor::new(&self.context, &mut pp), + ); parser.enable_procs(); let (fatal_errored_2, objtree) = parser.parse_object_tree_2(); fatal_errored = fatal_errored_2; self.objtree = Arc::new(objtree); } - let elapsed = start.elapsed(); start += elapsed; + let elapsed = start.elapsed(); + start += elapsed; { let disk = self.context.get_io_time(); let parse = elapsed.saturating_sub(disk); - eprint!("disk {}.{:03}s - parse {}.{:03}s", disk.as_secs(), disk.subsec_millis(), parse.as_secs(), parse.subsec_millis()); + eprint!( + "disk {}.{:03}s - parse {}.{:03}s", + disk.as_secs(), + disk.subsec_millis(), + parse.as_secs(), + parse.subsec_millis() + ); } // Background thread: prepare the Find All References database. @@ -491,7 +549,11 @@ impl Engine { self.references_table.spawn(move || { let table = find_references::ReferencesTable::new(&references_objtree); let elapsed = start.elapsed(); - eprint!("references {}.{:03}s", elapsed.as_secs(), elapsed.subsec_millis()); + eprint!( + "references {}.{:03}s", + elapsed.as_secs(), + elapsed.subsec_millis() + ); print_thread_total(); table }); @@ -509,8 +571,13 @@ impl Engine { let diagnostics_tracker = self.diagnostics_tracker.clone(); std::thread::spawn(move || { dreamchecker::run(&context, &objtree); - let elapsed = start.elapsed(); start += elapsed; - eprint!("dreamchecker {}.{:03}s", elapsed.as_secs(), elapsed.subsec_millis()); + let elapsed = start.elapsed(); + start += elapsed; + eprint!( + "dreamchecker {}.{:03}s", + elapsed.as_secs(), + elapsed.subsec_millis() + ); print_thread_total(); let map = DiagnosticsTracker::build( @@ -539,14 +606,24 @@ impl Engine { self.defines = Some(pp.finalize()); - let elapsed = start.elapsed(); start += elapsed; - eprint!(" - diagnostics {}.{:03}s", elapsed.as_secs(), elapsed.subsec_millis()); + let elapsed = start.elapsed(); + start += elapsed; + eprint!( + " - diagnostics {}.{:03}s", + elapsed.as_secs(), + elapsed.subsec_millis() + ); // If enabled, send the JSON for the object tree panel. if self.client_caps.object_tree { self.update_objtree(); - let elapsed = start.elapsed(); start += elapsed; - eprint!(" - object tree {}.{:03}s", elapsed.as_secs(), elapsed.subsec_millis()); + let elapsed = start.elapsed(); + start += elapsed; + eprint!( + " - object tree {}.{:03}s", + elapsed.as_secs(), + elapsed.subsec_millis() + ); } /*if let Some(objtree) = Arc::get_mut(&mut self.objtree) { @@ -559,7 +636,10 @@ impl Engine { Ok(()) } - fn get_annotations(&mut self, url: &Url) -> Result<(FileId, FileId, Rc), jsonrpc::Error> { + fn get_annotations( + &mut self, + url: &Url, + ) -> Result<(FileId, FileId, Rc), jsonrpc::Error> { Ok(match self.annotations.entry(url.to_owned()) { Entry::Occupied(o) => o.get().clone(), Entry::Vacant(v) => match self.root { @@ -582,26 +662,43 @@ impl Engine { None => (FileId::default(), defines.branch_at_end(&self.context)), }; let contents = self.docs.read(url).map_err(invalid_request)?; - let file_id = preprocessor.push_file(stripped.to_owned(), contents).map_err(invalid_request)?; + let file_id = preprocessor + .push_file(stripped.to_owned(), contents) + .map_err(invalid_request)?; preprocessor.enable_annotations(); let mut annotations = AnnotationTree::default(); { - let indent = dm::indents::IndentProcessor::new(&self.context, &mut preprocessor); + let indent = + dm::indents::IndentProcessor::new(&self.context, &mut preprocessor); let parser = dm::parser::Parser::new(&self.context, indent); parser.parse_annotations_only(&mut annotations); } annotations.merge(preprocessor.take_annotations().unwrap()); - v.insert((real_file_id, file_id, Rc::new(annotations))).clone() + v.insert((real_file_id, file_id, Rc::new(annotations))) + .clone() }, None => { // single-file mode let filename = url.to_string(); - let contents = self.docs.get_contents(url).map_err(invalid_request)?.into_owned(); - let mut pp = dm::preprocessor::Preprocessor::from_buffer(&self.context, filename.clone().into(), contents); - let file_id = self.context.get_file(filename.as_ref()).expect("file didn't exist?"); + let contents = self + .docs + .get_contents(url) + .map_err(invalid_request)? + .into_owned(); + let mut pp = dm::preprocessor::Preprocessor::from_buffer( + &self.context, + filename.clone().into(), + contents, + ); + let file_id = self + .context + .get_file(filename.as_ref()) + .expect("file didn't exist?"); // Clear old errors for this file. Hacky, but it will work for now. - self.context.errors_mut().retain(|error| error.location().file != file_id); + self.context + .errors_mut() + .retain(|error| error.location().file != file_id); pp.enable_annotations(); let mut annotations = AnnotationTree::default(); @@ -626,21 +723,22 @@ impl Engine { continue; } - let related_information = if !self.client_caps.related_info || error.notes().is_empty() { - None - } else { - let mut notes = Vec::with_capacity(error.notes().len()); - for note in error.notes().iter() { - notes.push(lsp_types::DiagnosticRelatedInformation { - location: lsp_types::Location { - uri: url.to_owned(), - range: location_to_range(note.location()), - }, - message: note.description().to_owned(), - }); - } - Some(notes) - }; + let related_information = + if !self.client_caps.related_info || error.notes().is_empty() { + None + } else { + let mut notes = Vec::with_capacity(error.notes().len()); + for note in error.notes().iter() { + notes.push(lsp_types::DiagnosticRelatedInformation { + location: lsp_types::Location { + uri: url.to_owned(), + range: location_to_range(note.location()), + }, + message: note.description().to_owned(), + }); + } + Some(notes) + }; let diag = lsp_types::Diagnostic { message: error.description().to_owned(), severity: Some(convert_severity(error.severity())), @@ -648,7 +746,7 @@ impl Engine { source: component_to_source(error.component()), code: convert_errorcode(error.errortype()), related_information, - .. Default::default() + ..Default::default() }; diagnostics.push(diag); @@ -660,7 +758,7 @@ impl Engine { severity: Some(lsp_types::DiagnosticSeverity::INFORMATION), range: location_to_range(note.location()), source: component_to_source(error.component()), - .. Default::default() + ..Default::default() }; diagnostics.push(diag); } @@ -676,12 +774,15 @@ impl Engine { ); (file_id, file_id, Rc::new(annotations)) - } - } + }, + }, }) } - fn find_type_context<'b, I, Ign>(&self, iter: &I) -> (Option>, Option<(&'b str, usize)>) + fn find_type_context<'b, I, Ign>( + &self, + iter: &I, + ) -> (Option>, Option<(&'b str, usize)>) where I: Iterator + Clone, { @@ -745,7 +846,11 @@ impl Engine { if let Some(value) = proc.value.get(idx) { for param in value.parameters.iter() { if param.name == var_name { - return UnscopedVar::Parameter { ty, proc: proc_name, param }; + return UnscopedVar::Parameter { + ty, + proc: proc_name, + param, + }; } } } @@ -764,14 +869,15 @@ impl Engine { } fn find_scoped_type<'b, I>(&'b self, iter: &I, priors: &[String]) -> Option> - where I: Iterator + Clone + where + I: Iterator + Clone, { let (mut next, proc_name) = self.find_type_context(iter); // find the first; check the global scope, parameters, and "src" let mut priors = priors.iter(); let first = match priors.next() { Some(i) => i, - None => return next, // empty priors acts like unscoped + None => return next, // empty priors acts like unscoped }; if first == "args" { next = self.objtree.find("/list"); @@ -785,12 +891,16 @@ impl Engine { next = self.objtree.find("/callee"); } else { next = match self.find_unscoped_var(iter, next, proc_name, first) { - UnscopedVar::Parameter { param, .. } => self.objtree.type_by_path(param.var_type.type_path.iter()), + UnscopedVar::Parameter { param, .. } => { + self.objtree.type_by_path(param.var_type.type_path.iter()) + }, UnscopedVar::Variable { ty, .. } => match ty.get_var_declaration(first) { Some(decl) => self.objtree.type_by_path(decl.var_type.type_path.iter()), None => None, }, - UnscopedVar::Local { var_type, .. } => self.objtree.type_by_path(var_type.type_path.iter()), + UnscopedVar::Local { var_type, .. } => { + self.objtree.type_by_path(var_type.type_path.iter()) + }, UnscopedVar::None => None, }; } @@ -808,8 +918,12 @@ impl Engine { next } - fn symbol_id_at(&mut self, text_document_position: lsp_types::TextDocumentPositionParams) -> Result, jsonrpc::Error> { - let (_, file_id, annotations) = self.get_annotations(&text_document_position.text_document.uri)?; + fn symbol_id_at( + &mut self, + text_document_position: lsp_types::TextDocumentPositionParams, + ) -> Result, jsonrpc::Error> { + let (_, file_id, annotations) = + self.get_annotations(&text_document_position.text_document.uri)?; let location = dm::Location { file: file_id, line: text_document_position.position.line + 1, @@ -932,9 +1046,14 @@ impl Engine { Ok(symbol_id) } - fn construct_proc_hover(&self, proc_name: &str, mut provided_tok: Option, scoped: bool) -> Result, jsonrpc::Error> { + fn construct_proc_hover( + &self, + proc_name: &str, + mut provided_tok: Option, + scoped: bool, + ) -> Result, jsonrpc::Error> { let mut results = Vec::new(); - let mut proclink = String::new(); + let mut proclink = String::new(); let mut defstring = String::new(); let mut docstring: Option = None; while let Some(ty) = provided_tok { @@ -944,7 +1063,11 @@ impl Engine { // Because we need to find our declaration to get the declaration type, we partially // form the markdown text to be used once the proc's declaration is reached if defstring.is_empty() { - proclink = format!("[{}]({})", ty.pretty_path(), self.location_link(proc_value.location)?); + proclink = format!( + "[{}]({})", + ty.pretty_path(), + self.location_link(proc_value.location)? + ); let mut message = format!("{proc_name}("); let mut first = true; for each in proc_value.parameters.iter() { @@ -961,7 +1084,12 @@ impl Engine { } if let Some(ref decl) = proc.declaration { - results.push(format!("{}\n```dm\n{}/{}\n```", proclink, decl.kind.name(), defstring)); + results.push(format!( + "{}\n```dm\n{}/{}\n```", + proclink, + decl.kind.name(), + defstring + )); } if !proc_value.docs.is_empty() { @@ -983,7 +1111,12 @@ impl Engine { Ok(results) } - fn construct_var_hover(&self, var_name: &str, mut provided_tok: Option, scoped: bool) -> Result, jsonrpc::Error> { + fn construct_var_hover( + &self, + var_name: &str, + mut provided_tok: Option, + scoped: bool, + ) -> Result, jsonrpc::Error> { let mut results = Vec::new(); let mut infos = String::new(); let mut docstring: Option = None; @@ -991,10 +1124,19 @@ impl Engine { if let Some(var) = ty.vars.get(var_name) { if let Some(ref decl) = var.declaration { // First get the path of the type containing the declaration - infos.push_str(format!("[{}]({})\n", ty.pretty_path(), self.location_link(var.value.location)?).as_str()); + infos.push_str( + format!( + "[{}]({})\n", + ty.pretty_path(), + self.location_link(var.value.location)? + ) + .as_str(), + ); // Next toss on the declaration itself - infos.push_str(format!("```dm\nvar/{}{}\n```", decl.var_type, var_name).as_str()); + infos.push_str( + format!("```dm\nvar/{}{}\n```", decl.var_type, var_name).as_str(), + ); } if !var.value.docs.is_empty() { docstring = Some(var.value.docs.text()); @@ -1023,7 +1165,10 @@ impl Engine { fn handle_input(&mut self, message: &str) { let mut outputs: Vec = match serde_json::from_str(message) { Ok(jsonrpc::Request::Single(call)) => self.handle_call(call).into_iter().collect(), - Ok(jsonrpc::Request::Batch(calls)) => calls.into_iter().flat_map(|call| self.handle_call(call)).collect(), + Ok(jsonrpc::Request::Batch(calls)) => calls + .into_iter() + .flat_map(|call| self.handle_call(call)) + .collect(), Err(decode_error) => vec![Output::Failure(jsonrpc::Failure { jsonrpc: VERSION, error: jsonrpc::Error { @@ -1036,7 +1181,7 @@ impl Engine { }; let response = match outputs.len() { - 0 => return, // wait for another input + 0 => return, // wait for another input 1 => Response::Single(outputs.remove(0)), _ => Response::Batch(outputs), }; @@ -1049,7 +1194,11 @@ impl Engine { Call::Invalid { id } => Some(Output::invalid_request(id, VERSION)), Call::MethodCall(method_call) => { let id = method_call.id.clone(); - Some(Output::from(self.handle_method_call(method_call), id, VERSION)) + Some(Output::from( + self.handle_method_call(method_call), + id, + VERSION, + )) }, Call::Notification(notification) => { if let Err(e) = self.handle_notification(notification) { @@ -1060,7 +1209,10 @@ impl Engine { } } - fn handle_method_call(&mut self, call: jsonrpc::MethodCall) -> Result { + fn handle_method_call( + &mut self, + call: jsonrpc::MethodCall, + ) -> Result { // "If the server receives a request... before the initialize request... // the response should be an error with code: -32002" if call.method != Initialize::METHOD && self.status != InitStatus::Running { @@ -1068,7 +1220,7 @@ impl Engine { code: jsonrpc::ErrorCode::from(-32002), message: "method call before initialize or after shutdown".to_owned(), data: None, - }) + }); } let params_value = params_to_value(call.params); @@ -1084,13 +1236,22 @@ impl Engine { } } - fn handle_notification(&mut self, notification: jsonrpc::Notification) -> Result<(), jsonrpc::Error> { + fn handle_notification( + &mut self, + notification: jsonrpc::Notification, + ) -> Result<(), jsonrpc::Error> { // "Notifications should be dropped, except for the exit notification" - if notification.method == ::METHOD { - self.exit(if self.status == InitStatus::ShuttingDown { 0 } else { 1 }); + if notification.method + == ::METHOD + { + self.exit(if self.status == InitStatus::ShuttingDown { + 0 + } else { + 1 + }); } if self.status != InitStatus::Running { - return Ok(()) + return Ok(()); } let params_value = params_to_value(notification.params); @@ -1157,7 +1318,7 @@ impl Engine { // basic setup fn Initialize(&mut self, init: P) -> R { if self.status != InitStatus::Starting { - return Err(invalid_request("")) + return Err(invalid_request("")); } self.status = InitStatus::Running; @@ -1202,11 +1363,13 @@ impl Engine { references_provider: Some(OneOf::Left(true)), implementation_provider: Some(ImplementationProviderCapability::Simple(true)), type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)), - text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { - open_close: Some(true), - change: Some(TextDocumentSyncKind::INCREMENTAL), - .. Default::default() - })), + text_document_sync: Some(TextDocumentSyncCapability::Options( + TextDocumentSyncOptions { + open_close: Some(true), + change: Some(TextDocumentSyncKind::INCREMENTAL), + ..Default::default() + }, + )), completion_provider: Some(CompletionOptions { trigger_characters: Some(vec![".".to_owned(), ":".to_owned(), "/".to_owned()]), all_commit_characters: None, @@ -1223,7 +1386,7 @@ impl Engine { work_done_progress_options: Default::default(), }), color_provider: Some(ColorProviderCapability::Simple(true)), - .. Default::default() + ..Default::default() }, server_info: Some(ServerInfo { name: "dm-langserver".to_owned(), @@ -1239,7 +1402,7 @@ impl Engine { // ------------------------------------------------------------------------ // actual stuff provision - #[allow(deprecated)] // DocumentSymbol::deprecated is... deprecated. But we need to provide a `None` anyways. + #[allow(deprecated)] // DocumentSymbol::deprecated is... deprecated. But we need to provide a `None` anyways. fn WorkspaceSymbol(&mut self, params: P) -> R { let query = symbol_search::Query::parse(¶ms.query); @@ -1255,7 +1418,11 @@ impl Engine { results.push(SymbolInformation { name: name.to_owned(), kind: SymbolKind::CONSTANT, - location: self.convert_location(range.start, define.docs(), &["/DM/preprocessor/", name])?, + location: self.convert_location( + range.start, + define.docs(), + &["/DM/preprocessor/", name], + )?, container_name: None, tags: None, deprecated: None, @@ -1285,7 +1452,11 @@ impl Engine { results.push(SymbolInformation { name: var_name.clone(), kind: SymbolKind::FIELD, - location: self.convert_location(decl.location, &tv.value.docs, &[&ty.path, "/var/", var_name])?, + location: self.convert_location( + decl.location, + &tv.value.docs, + &[&ty.path, "/var/", var_name], + )?, container_name: Some(ty.path.clone()), tags: None, deprecated: None, @@ -1306,7 +1477,11 @@ impl Engine { } else { SymbolKind::METHOD }, - location: self.convert_location(decl.location, &pv.main_value().docs, &[&ty.path, "/proc/", proc_name])?, + location: self.convert_location( + decl.location, + &pv.main_value().docs, + &[&ty.path, "/proc/", proc_name], + )?, container_name: Some(ty.path.clone()), tags: None, deprecated: None, @@ -1331,7 +1506,8 @@ impl Engine { let iter = annotations.get_location(location); for (_range, annotation) in iter.clone() { - #[cfg(debug_assertions)] { + #[cfg(debug_assertions)] + { results.push(format!("{annotation:?}")); } match annotation { @@ -1340,7 +1516,9 @@ impl Engine { let mut current = objtree.root(); let (last, most) = path.split_last().unwrap(); for part in most { - if part == "var" { break } + if part == "var" { + break; + } if let Some(child) = current.child(part) { current = child; } else { @@ -1358,9 +1536,17 @@ impl Engine { } else { String::new() }; - infos.push_front(format!("[{}]({}){}", current.pretty_path(), self.location_link(var.value.location)?, constant)); + infos.push_front(format!( + "[{}]({}){}", + current.pretty_path(), + self.location_link(var.value.location)?, + constant + )); if let Some(ref decl) = var.declaration { - infos.push_front(format!("```dm\nvar/{}{}\n```", decl.var_type, last)); + infos.push_front(format!( + "```dm\nvar/{}{}\n```", + decl.var_type, last + )); } if !var.value.docs.is_empty() { docstring = Some(var.value.docs.text()); @@ -1374,13 +1560,15 @@ impl Engine { if let Some(ds) = docstring { results.push(ds); } - } + }, Annotation::ProcHeader(path, _idx) if !path.is_empty() => { let objtree = &self.objtree; let mut current = objtree.root(); let (last, most) = path.split_last().unwrap(); for part in most { - if part == "proc" || part == "verb" { break } + if part == "proc" || part == "verb" { + break; + } if let Some(child) = current.child(part) { current = child; } else { @@ -1396,7 +1584,12 @@ impl Engine { while let Some(current) = next { if let Some(proc) = current.procs.get(last) { let proc_value = proc.main_value(); - let mut message = format!("[{}]({}) \n```dm\n{}(", current.pretty_path(), self.location_link(proc_value.location)?, last); + let mut message = format!( + "[{}]({}) \n```dm\n{}(", + current.pretty_path(), + self.location_link(proc_value.location)?, + last + ); let mut first = true; for each in proc_value.parameters.iter() { use std::fmt::Write; @@ -1410,7 +1603,11 @@ impl Engine { message.push_str(")\n```"); infos.push_front(message); if let Some(ref decl) = proc.declaration { - infos.push_front(format!("```dm\n{}/{}\n```", decl.kind.name(), last)); + infos.push_front(format!( + "```dm\n{}/{}\n```", + decl.kind.name(), + last + )); } if !proc_value.docs.is_empty() { @@ -1425,32 +1622,38 @@ impl Engine { if let Some(ds) = docstring { results.push(ds); } - } + }, Annotation::UnscopedVar(var_name) if symbol_id.is_some() => { let (ty, proc_name) = self.find_type_context(&iter); - if let UnscopedVar::Variable { ty, .. } = self.find_unscoped_var(&iter, ty, proc_name, var_name) { + if let UnscopedVar::Variable { ty, .. } = + self.find_unscoped_var(&iter, ty, proc_name, var_name) + { if let Some(_decl) = ty.get_var_declaration(var_name) { - results.append(&mut self.construct_var_hover(var_name, Some(ty), false)?); + results.append(&mut self.construct_var_hover( + var_name, + Some(ty), + false, + )?); } } - } + }, Annotation::UnscopedCall(proc_name) if symbol_id.is_some() => { let (ty, _) = self.find_type_context(&iter); let next = ty.or_else(|| Some(self.objtree.root())); results.append(&mut self.construct_proc_hover(proc_name, next, false)?); - } + }, Annotation::ScopedCall(priors, proc_name) if symbol_id.is_some() => { let next = self.find_scoped_type(&iter, priors); results.append(&mut self.construct_proc_hover(proc_name, next, true)?); - } + }, Annotation::ScopedVar(priors, var_name) if symbol_id.is_some() => { let next = self.find_scoped_type(&iter, priors); results.append(&mut self.construct_var_hover(var_name, next, true)?); - } + }, Annotation::MacroUse { docs: Some(dc), .. } if !dc.is_empty() => { results.push(dc.text()); - } - _ => {} + }, + _ => {}, } } if results.is_empty() { @@ -1458,7 +1661,9 @@ impl Engine { } else { Ok(Some(Hover { range: None, - contents: HoverContents::Array(results.into_iter().map(MarkedString::String).collect()), + contents: HoverContents::Array( + results.into_iter().map(MarkedString::String).collect(), + ), })) } } @@ -1693,7 +1898,8 @@ impl Engine { } fn Completion(&mut self, params: P) -> R { - let (_, file_id, annotations) = self.get_annotations(¶ms.text_document_position.text_document.uri)?; + let (_, file_id, annotations) = + self.get_annotations(¶ms.text_document_position.text_document.uri)?; let location = dm::Location { file: file_id, line: params.text_document_position.position.line + 1, @@ -1757,7 +1963,12 @@ impl Engine { // TODO: unscoped_completions calls find_type_context again self.unscoped_completions(&mut results, &iter, ""); } else { - self.tree_completions(&mut results, true, ty.unwrap_or_else(|| self.objtree.root()), ""); + self.tree_completions( + &mut results, + true, + ty.unwrap_or_else(|| self.objtree.root()), + "", + ); } } @@ -1842,20 +2053,26 @@ impl Engine { Ok(result) } - #[allow(deprecated)] // DocumentSymbol::deprecated is... deprecated. But we need to provide a `None` anyways. - fn DocumentSymbolRequest(&mut self, params: P) -> R { + #[allow(deprecated)] // DocumentSymbol::deprecated is... deprecated. But we need to provide a `None` anyways. + fn DocumentSymbolRequest( + &mut self, + params: P, + ) -> R { fn name_and_detail(path: &[String], skip_front: usize) -> (String, Option) { let (name, rest) = path.split_last().unwrap(); ( name.to_owned(), - rest.get(skip_front..).and_then(|i| - i.iter().rev().find(|x| - dm::ast::ProcDeclKind::from_name(x).is_none() && - dm::ast::ProcFlags::from_name(x).is_none() && - dm::ast::VarTypeFlags::from_name(x).is_none() && - *x != "var" - ).map(ToOwned::to_owned) - ) + rest.get(skip_front..).and_then(|i| { + i.iter() + .rev() + .find(|x| { + dm::ast::ProcDeclKind::from_name(x).is_none() + && dm::ast::ProcFlags::from_name(x).is_none() + && dm::ast::VarTypeFlags::from_name(x).is_none() + && *x != "var" + }) + .map(ToOwned::to_owned) + }), ) } @@ -1865,7 +2082,8 @@ impl Engine { section_end: dm::Location, skip_front: usize, ) -> Vec - where I: Iterator, &'a Annotation)> + where + I: Iterator, &'a Annotation)>, { let mut result = Vec::new(); @@ -1885,7 +2103,9 @@ impl Engine { let selection_range = location_to_range(start); match annotation { Annotation::TreeBlock(ref path) => { - if path.is_empty() { continue } + if path.is_empty() { + continue; + } let (name, detail) = name_and_detail(path, skip_front); result.push(DocumentSymbol { name, @@ -1912,7 +2132,9 @@ impl Engine { }); }, Annotation::ProcBody(ref path, _) => { - if path.is_empty() { continue } + if path.is_empty() { + continue; + } let (name, detail) = name_and_detail(path, skip_front); let kind = if path.len() == 1 || (path.len() == 2 && path[0] == "proc") { SymbolKind::FUNCTION @@ -1944,19 +2166,17 @@ impl Engine { children: None, }); }, - Annotation::MacroDefinition(ref name) => { - result.push(DocumentSymbol { - name: name.to_owned(), - detail: None, - kind: SymbolKind::CONSTANT, - tags: None, - deprecated: None, - range, - selection_range, - children: None, - }) - }, - _ => {} + Annotation::MacroDefinition(ref name) => result.push(DocumentSymbol { + name: name.to_owned(), + detail: None, + kind: SymbolKind::CONSTANT, + tags: None, + deprecated: None, + range, + selection_range, + children: None, + }), + _ => {}, } } @@ -1968,20 +2188,43 @@ impl Engine { if annotations.is_empty() { Ok(None) } else { - let start = dm::Location { file: file_id, line: 0, column: 0 }; - let end = dm::Location { file: file_id, line: !0, column: !0 }; + let start = dm::Location { + file: file_id, + line: 0, + column: 0, + }; + let end = dm::Location { + file: file_id, + line: !0, + column: !0, + }; let mut vec: Vec<_> = annotations.get_range(start..end).collect(); // Our traversal is outside-in. TreeBlock and Variable can have the // same extent if the variable is the only thing in the block, so // sort TreeBlocks first as well. - vec.sort_by_key(|x| (x.0.start, std::cmp::Reverse(x.0.end), if matches!(x.1, Annotation::TreeBlock(_)) { 0 } else { 1 })); + vec.sort_by_key(|x| { + ( + x.0.start, + std::cmp::Reverse(x.0.end), + if matches!(x.1, Annotation::TreeBlock(_)) { + 0 + } else { + 1 + }, + ) + }); let mut iter = vec.into_iter().peekable(); - Ok(Some(DocumentSymbolResponse::Nested(find_document_symbols(&mut iter, end, 0)))) + Ok(Some(DocumentSymbolResponse::Nested(find_document_symbols( + &mut iter, end, 0, + )))) } } fn DocumentColor(&mut self, params: P) -> R { - let content = self.docs.get_contents(¶ms.text_document.uri).map_err(invalid_request)?; + let content = self + .docs + .get_contents(¶ms.text_document.uri) + .map_err(invalid_request)?; let mut output = Vec::new(); for (start, end, [r, g, b, a]) in color::extract_colors(&content) { output.push(ColorInformation { @@ -2000,23 +2243,27 @@ impl Engine { Ok(output) } - fn ColorPresentationRequest(&mut self, params: P) -> R { - let content = self.docs.get_contents(¶ms.text_document.uri).map_err(invalid_request)?; + fn ColorPresentationRequest( + &mut self, + params: P, + ) -> R { + let content = self + .docs + .get_contents(¶ms.text_document.uri) + .map_err(invalid_request)?; let chunk = document::get_range(&content, params.range)?; let color_format = color::ColorFormat::parse(chunk).unwrap_or_default(); // TODO: return compatible alternate presentations for converting // between "#..." and rgb(). - Ok(vec![ - ColorPresentation { - label: color_format.format([ - (params.color.red * 255.).round() as u8, - (params.color.green * 255.).round() as u8, - (params.color.blue * 255.).round() as u8, - (params.color.alpha * 255.).round() as u8, - ]), - .. Default::default() - }, - ]) + Ok(vec![ColorPresentation { + label: color_format.format([ + (params.color.red * 255.).round() as u8, + (params.color.green * 255.).round() as u8, + (params.color.blue * 255.).round() as u8, + (params.color.alpha * 255.).round() as u8, + ]), + ..Default::default() + }]) } fn DocumentLinkRequest(&mut self, params: P) -> R { @@ -2030,8 +2277,7 @@ impl Engine { continue; } match annotation { - Annotation::Include(path) | - Annotation::Resource(path) => { + Annotation::Include(path) | Annotation::Resource(path) => { let pathbuf = if path.is_relative() { std::env::current_dir().map_err(invalid_request)?.join(path) } else { @@ -2043,8 +2289,8 @@ impl Engine { tooltip: None, data: None, }); - } - _ => {} + }, + _ => {}, } } @@ -2066,7 +2312,13 @@ impl Engine { extools_dll: self.extools_dll.clone(), debug_server_dll: self.debug_server_dll.clone(), }; - let (port, handle) = debugger::start_server(self.context.config().debugger.engine, params.dreamseeker_exe, params.env, db).map_err(invalid_request)?; + let (port, handle) = debugger::start_server( + self.context.config().debugger.engine, + params.dreamseeker_exe, + params.env, + db, + ) + .map_err(invalid_request)?; self.threads.push(handle); Ok(extras::StartDebuggerResult { port }) } @@ -2116,7 +2368,8 @@ impl Engine { if let Some(dme) = self.context.config().environment.as_ref() { environment = Some(root_path.join(dme)); } else { - environment = dm::detect_environment(&root_path, dm::DEFAULT_ENV).map_err(invalid_request)?; + environment = dm::detect_environment(&root_path, dm::DEFAULT_ENV) + .map_err(invalid_request)?; } } } @@ -2157,7 +2410,9 @@ impl Engine { } fn DidChangeTextDocument(&mut self, params: N) -> NR { - let url = self.docs.change(params.text_document, params.content_changes)?; + let url = self + .docs + .change(params.text_document, params.content_changes)?; self.annotations.remove(&url); Ok(()) } @@ -2211,14 +2466,13 @@ fn url_to_path(url: &Url) -> Result { if url.scheme() != "file" { return Err(invalid_request("URI must have 'file' scheme")); } - url.to_file_path().map_err(|_| invalid_request("URI must be a valid path")) + url.to_file_path() + .map_err(|_| invalid_request("URI must be a valid path")) } fn path_to_url(path: PathBuf) -> Result { let formatted = path.display().to_string(); - Url::from_file_path(path).map_err(|_| invalid_request(format!( - "bad file path: {formatted}", - ))) + Url::from_file_path(path).map_err(|_| invalid_request(format!("bad file path: {formatted}",))) } fn convert_severity(severity: dm::Severity) -> lsp_types::DiagnosticSeverity { @@ -2255,7 +2509,7 @@ fn is_constructor_name(name: &str) -> bool { name == "New" || name == "init" || name == "Initialize" } -fn location_to_position(loc: dm::Location) -> lsp_types::Position { +fn location_to_position(loc: dm::Location) -> lsp_types::Position { lsp_types::Position { line: loc.line.saturating_sub(1), character: loc.column.saturating_sub(1) as u32, @@ -2268,7 +2522,10 @@ fn location_to_range(loc: dm::Location) -> lsp_types::Range { } fn span_to_range(range: std::ops::Range) -> lsp_types::Range { - lsp_types::Range::new(location_to_position(range.start), location_to_position(range.end)) + lsp_types::Range::new( + location_to_position(range.start), + location_to_position(range.end), + ) } fn issue_notification(params: T::Params) diff --git a/crates/dm-langserver/src/symbol_search.rs b/crates/dm-langserver/src/symbol_search.rs index 624b4701..21c65529 100644 --- a/crates/dm-langserver/src/symbol_search.rs +++ b/crates/dm-langserver/src/symbol_search.rs @@ -53,36 +53,37 @@ impl Query { } pub fn matches_on_type(&self, _path: &str) -> bool { - matches!(*self, Query::Anything(_) | - Query::Proc(_) | - Query::Var(_)) + matches!(*self, Query::Anything(_) | Query::Proc(_) | Query::Var(_)) } pub fn matches_var(&self, name: &str) -> bool { match *self { - Query::Anything(ref q) | - Query::Var(ref q) => starts_with(name, q), + Query::Anything(ref q) | Query::Var(ref q) => starts_with(name, q), _ => false, } } pub fn matches_proc(&self, name: &str, _kind: dm::ast::ProcDeclKind) -> bool { match *self { - Query::Anything(ref q) | - Query::Proc(ref q) => starts_with(name, q), + Query::Anything(ref q) | Query::Proc(ref q) => starts_with(name, q), _ => false, } } } -fn simplify(s: &str) -> impl Iterator + Clone + '_ { - s.chars().flat_map(|c| c.to_lowercase()).filter(|c| c.is_alphanumeric()) +fn simplify(s: &str) -> impl Iterator + Clone + '_ { + s.chars() + .flat_map(|c| c.to_lowercase()) + .filter(|c| c.is_alphanumeric()) } // ignore case and underscores pub fn starts_with<'a>(fulltext: &'a str, query: &'a str) -> bool { let mut query_chars = simplify(query); - simplify(fulltext).zip(&mut query_chars).all(|(a, b)| a == b) && query_chars.next().is_none() + simplify(fulltext) + .zip(&mut query_chars) + .all(|(a, b)| a == b) + && query_chars.next().is_none() } pub fn contains<'a>(fulltext: &'a str, query: &'a str) -> bool { @@ -99,5 +100,7 @@ pub fn contains<'a>(fulltext: &'a str, query: &'a str) -> bool { } fn any_alphanumeric(text: &str) -> bool { - text.chars().flat_map(|c| c.to_lowercase()).any(|c| c.is_alphanumeric()) + text.chars() + .flat_map(|c| c.to_lowercase()) + .any(|c| c.is_alphanumeric()) } diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 8298a4a9..64470035 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -10,10 +10,10 @@ mod template; use dm::ast::{InputType, ProcReturnType}; use dm::objtree::ObjectTree; +use foldhash::HashSet; use maud::{Markup, PreEscaped}; use pulldown_cmark::{BrokenLink, CowStr}; use std::collections::{BTreeMap, BTreeSet}; -use foldhash::HashSet; use std::fs::{self, File}; use std::io::{self, Write}; use std::path::{Path, PathBuf}; @@ -51,7 +51,7 @@ fn main2() -> Result<(), Box> { let mut dry_run = false; let mut args = std::env::args(); - let _ = args.next(); // skip executable name + let _ = args.next(); // skip executable name while let Some(arg) = args.next() { if arg == "-V" || arg == "--version" { println!("{BUILD_INFO}"); @@ -78,8 +78,8 @@ fn main2() -> Result<(), Box> { Some(env) => env, None => { return Err("Unable to find a .dme file in this directory".into()); - } - } + }, + }, }; println!("parsing {}", environment.display()); @@ -90,7 +90,7 @@ fn main2() -> Result<(), Box> { let (objtree, module_docs) = { let indents = dm::indents::IndentProcessor::new(&context, &mut pp); let mut parser = dm::parser::Parser::new(&context, indents); - parser.enable_procs(); // for `set SpacemanDMM_return_type` + parser.enable_procs(); // for `set SpacemanDMM_return_type` parser.parse_with_module_docs() }; let define_history = pp.finalize(); @@ -114,7 +114,13 @@ fn main2() -> Result<(), Box> { }); } else { // Use what the config specifies without any additional logic. - code_directories = context.config().dmdoc.module_directories.iter().map(std::ffi::OsString::from).collect(); + code_directories = context + .config() + .dmdoc + .module_directories + .iter() + .map(std::ffi::OsString::from) + .collect(); } // get a read on which types *have* docs @@ -123,7 +129,9 @@ fn main2() -> Result<(), Box> { // TODO: it would be nice if this was not a duplicate of below let mut own_docs = false; if !ty.docs.is_empty() { - own_docs = DocBlock::parse_with_title(&ty.docs.text(), None).1.has_description; + own_docs = DocBlock::parse_with_title(&ty.docs.text(), None) + .1 + .has_description; } let mut var_docs = BTreeSet::new(); @@ -142,10 +150,13 @@ fn main2() -> Result<(), Box> { } if own_docs || !var_docs.is_empty() || !proc_docs.is_empty() { - types_with_docs.insert(ty.get().path.as_str(), TypeHasDocs { - var_docs, - proc_docs, - }); + types_with_docs.insert( + ty.get().path.as_str(), + TypeHasDocs { + var_docs, + proc_docs, + }, + ); } }); @@ -188,7 +199,7 @@ fn main2() -> Result<(), Box> { has_params = false; params = &[][..]; is_variadic = false; - } + }, dm::preprocessor::Define::Function { docs: dc, params: macro_params, @@ -199,7 +210,7 @@ fn main2() -> Result<(), Box> { has_params = true; params = macro_params; is_variadic = *variadic; - } + }, } macros_all += 1; if docs.is_empty() { @@ -207,7 +218,16 @@ fn main2() -> Result<(), Box> { } error_entity_put(format!("#define {name}")); let broken_link_callback = &mut |link: BrokenLink| -> Option<(CowStr, CowStr)> { - broken_link_fixer(link, ¯o_to_module_map, ¯o_exists, &diagnostic_count, &error_entity, &modules_which_exist, &objtree, &types_with_docs) + broken_link_fixer( + link, + ¯o_to_module_map, + ¯o_exists, + &diagnostic_count, + &error_entity, + &modules_which_exist, + &objtree, + &types_with_docs, + ) }; let docs = DocBlock::parse(&docs.text(), Some(broken_link_callback)); let module = module_entry(&mut modules1, &context.file_path(range.start.file)); @@ -233,18 +253,24 @@ fn main2() -> Result<(), Box> { // search the code tree for Markdown files for modules_path in code_directories { - for entry in walkdir::WalkDir::new(modules_path).into_iter().filter_entry(is_visible) { + for entry in walkdir::WalkDir::new(modules_path) + .into_iter() + .filter_entry(is_visible) + { let entry = entry?; let path = entry.path(); if let Some(buf) = read_as_markdown(path)? { if Some(path) != index_path.as_ref().map(Path::new) { let module = module_entry(&mut modules1, path); - module.items_wip.push((0, ModuleItem::DocComment(DocComment { - kind: CommentKind::Block, - target: DocTarget::EnclosingItem, - text: buf, - }))); + module.items_wip.push(( + 0, + ModuleItem::DocComment(DocComment { + kind: CommentKind::Block, + target: DocTarget::EnclosingItem, + text: buf, + }), + )); } } } @@ -253,10 +279,20 @@ fn main2() -> Result<(), Box> { // Incorporate the index file if requested. let mut index_docs = None; if let Some(index_path) = index_path { - let buf = read_as_markdown(index_path.as_ref())?.expect("file for --index must be .md or .txt"); + let buf = + read_as_markdown(index_path.as_ref())?.expect("file for --index must be .md or .txt"); error_entity_put(index_path); let broken_link_callback = &mut |link: BrokenLink| -> Option<(CowStr, CowStr)> { - broken_link_fixer(link, ¯o_to_module_map, ¯o_exists, &diagnostic_count, &error_entity, &modules_which_exist, &objtree, &types_with_docs) + broken_link_fixer( + link, + ¯o_to_module_map, + ¯o_exists, + &diagnostic_count, + &error_entity, + &modules_which_exist, + &objtree, + &types_with_docs, + ) }; index_docs = Some(DocBlock::parse_with_title(&buf, Some(broken_link_callback))); } @@ -270,10 +306,7 @@ fn main2() -> Result<(), Box> { let mut parsed_type = ParsedType::default(); if context.config().dmdoc.use_typepath_names { - parsed_type.name = ty - .get() - .name() - .into(); + parsed_type.name = ty.get().name().into(); } else { parsed_type.name = ty .get() @@ -291,9 +324,19 @@ fn main2() -> Result<(), Box> { if !ty.docs.is_empty() { error_entity_put(ty.path.to_owned()); let broken_link_callback = &mut |link: BrokenLink| -> Option<(CowStr, CowStr)> { - broken_link_fixer(link, ¯o_to_module_map, ¯o_exists, &diagnostic_count, &error_entity, &modules_which_exist, &objtree, &types_with_docs) + broken_link_fixer( + link, + ¯o_to_module_map, + ¯o_exists, + &diagnostic_count, + &error_entity, + &modules_which_exist, + &objtree, + &types_with_docs, + ) }; - let (title, block) = DocBlock::parse_with_title(&ty.docs.text(), Some(broken_link_callback)); + let (title, block) = + DocBlock::parse_with_title(&ty.docs.text(), Some(broken_link_callback)); if let Some(title) = title { parsed_type.name = title.into(); } @@ -326,19 +369,29 @@ fn main2() -> Result<(), Box> { error_entity_put(format!("{}/var/{}", ty.path, name)); let broken_link_callback = &mut |link: BrokenLink| -> Option<(CowStr, CowStr)> { - broken_link_fixer(link, ¯o_to_module_map, ¯o_exists, &diagnostic_count, &error_entity, &modules_which_exist, &objtree, &types_with_docs) + broken_link_fixer( + link, + ¯o_to_module_map, + ¯o_exists, + &diagnostic_count, + &error_entity, + &modules_which_exist, + &objtree, + &types_with_docs, + ) }; let block = DocBlock::parse(&var.value.docs.text(), Some(broken_link_callback)); // if the var is global, add it to the module tree if ty.is_root() { - let module = module_entry(&mut modules1, &context.file_path(var.value.location.file)); + let module = + module_entry(&mut modules1, &context.file_path(var.value.location.file)); module.items_wip.push(( var.value.location.line, ModuleItem::GlobalVar { name, teaser: PreEscaped(block.teaser().0.to_owned()), - } + }, )); } @@ -353,15 +406,18 @@ fn main2() -> Result<(), Box> { path: &decl.var_type.type_path, input_type: decl.var_type.input_type, }); - parsed_type.vars.insert(name, Var { - docs: block, - type_, - // but `decl` is only used if it's on this type - decl: if var.declaration.is_some() { "var" } else { "" }, - file: context.file_path(var.value.location.file).to_owned(), - line: var.value.location.line, - parent, - }); + parsed_type.vars.insert( + name, + Var { + docs: block, + type_, + // but `decl` is only used if it's on this type + decl: if var.declaration.is_some() { "var" } else { "" }, + file: context.file_path(var.value.location.file).to_owned(), + line: var.value.location.line, + parent, + }, + ); anything = true; substance = true; } @@ -386,47 +442,70 @@ fn main2() -> Result<(), Box> { error_entity_put(format!("{}/proc/{}", ty.path, name)); let broken_link_callback = &mut |link: BrokenLink| -> Option<(CowStr, CowStr)> { - broken_link_fixer(link, ¯o_to_module_map, ¯o_exists, &diagnostic_count, &error_entity, &modules_which_exist, &objtree, &types_with_docs) + broken_link_fixer( + link, + ¯o_to_module_map, + ¯o_exists, + &diagnostic_count, + &error_entity, + &modules_which_exist, + &objtree, + &types_with_docs, + ) }; let block = DocBlock::parse(&proc_value.docs.text(), Some(broken_link_callback)); // if the proc is global, add it to the module tree if ty.is_root() { - let module = module_entry(&mut modules1, &context.file_path(proc_value.location.file)); + let module = + module_entry(&mut modules1, &context.file_path(proc_value.location.file)); module.items_wip.push(( proc_value.location.line, ModuleItem::GlobalProc { name, teaser: PreEscaped(block.teaser().0.to_owned()), - } + }, )); } - let return_type = proc.declaration.as_ref() + let return_type = proc + .declaration + .as_ref() .map(|decl| &decl.return_type) .filter(|ret| !ret.is_empty()) .cloned() // could use Cow maybe .or_else(|| { - proc_value.code.as_ref().and_then(find_return_type).map(ProcReturnType::TypePath) + proc_value + .code + .as_ref() + .and_then(find_return_type) + .map(ProcReturnType::TypePath) }); // add the proc to the type containing it - parsed_type.procs.insert(name, Proc { - docs: block, - params: proc_value.parameters.iter().map(|p| Param { - name: p.name.clone(), - type_path: format_type_path(&p.var_type.type_path), - input_type: p.input_type, - }).collect(), - decl: match proc.declaration { - Some(ref decl) => decl.kind.name(), - None => "", + parsed_type.procs.insert( + name, + Proc { + docs: block, + params: proc_value + .parameters + .iter() + .map(|p| Param { + name: p.name.clone(), + type_path: format_type_path(&p.var_type.type_path), + input_type: p.input_type, + }) + .collect(), + decl: match proc.declaration { + Some(ref decl) => decl.kind.name(), + None => "", + }, + file: context.file_path(proc_value.location.file).to_owned(), + line: proc_value.location.line, + return_type, + parent, }, - file: context.file_path(proc_value.location.file).to_owned(), - line: proc_value.location.line, - return_type, - parent, - }); + ); anything = true; substance = true; } @@ -464,71 +543,94 @@ fn main2() -> Result<(), Box> { }); // collate all hrefable entities to use in autolinking - let all_type_names: Arc> = Arc::new(type_docs.iter() - .filter(|(_, v)| v.substance) - .map(|(&t, _)| t.to_owned()) - .collect()); + let all_type_names: Arc> = Arc::new( + type_docs + .iter() + .filter(|(_, v)| v.substance) + .map(|(&t, _)| t.to_owned()) + .collect(), + ); // finalize modules - let modules: BTreeMap<_, _> = modules1.into_iter().map(|(key, module1)| { - let Module1 { - htmlname, - orig_filename, - name, - teaser, - mut items_wip, - defines, - } = module1; - let mut module = Module { - htmlname, - orig_filename, - name, - teaser, - items: Vec::new(), - defines, - }; + let modules: BTreeMap<_, _> = modules1 + .into_iter() + .map(|(key, module1)| { + let Module1 { + htmlname, + orig_filename, + name, + teaser, + mut items_wip, + defines, + } = module1; + let mut module = Module { + htmlname, + orig_filename, + name, + teaser, + items: Vec::new(), + defines, + }; - let mut docs = DocCollection::default(); - let mut _first = true; - macro_rules! push_docs { () => { // oof - if !docs.is_empty() { - let doc = std::mem::take(&mut docs); - let broken_link_callback = &mut |link: BrokenLink| -> Option<(CowStr, CowStr)> { - broken_link_fixer(link, ¯o_to_module_map, ¯o_exists, &diagnostic_count, &error_entity, &modules_which_exist, &objtree, &types_with_docs) - }; - if _first { - _first = false; - let (title, block) = DocBlock::parse_with_title(&doc.text(), Some(broken_link_callback)); - module.name = title; - module.teaser = PreEscaped(block.teaser().0.to_owned()); - module.items.push(ModuleItem::Docs(block.html)); - } else { - module.items.push(ModuleItem::Docs(markdown::render(&doc.text(), Some(broken_link_callback)))); - } - } - }} - - error_entity_put(module.orig_filename.to_owned()); - let mut last_line = 0; - items_wip.sort_by_key(|&(line, _)| line); - for (line, item) in items_wip.drain(..) { - match item { - ModuleItem::DocComment(doc) => { - if line > last_line + 1 { - docs.push(DocComment::new(CommentKind::Line, DocTarget::EnclosingItem)); + let mut docs = DocCollection::default(); + let mut _first = true; + macro_rules! push_docs { + () => { + // oof + if !docs.is_empty() { + let doc = std::mem::take(&mut docs); + let broken_link_callback = + &mut |link: BrokenLink| -> Option<(CowStr, CowStr)> { + broken_link_fixer( + link, + ¯o_to_module_map, + ¯o_exists, + &diagnostic_count, + &error_entity, + &modules_which_exist, + &objtree, + &types_with_docs, + ) + }; + if _first { + _first = false; + let (title, block) = + DocBlock::parse_with_title(&doc.text(), Some(broken_link_callback)); + module.name = title; + module.teaser = PreEscaped(block.teaser().0.to_owned()); + module.items.push(ModuleItem::Docs(block.html)); + } else { + module.items.push(ModuleItem::Docs(markdown::render( + &doc.text(), + Some(broken_link_callback), + ))); + } } - docs.push(doc); - last_line = line; - }, - other => { - push_docs!(); - module.items.push(other); + }; + } + + error_entity_put(module.orig_filename.to_owned()); + let mut last_line = 0; + items_wip.sort_by_key(|&(line, _)| line); + for (line, item) in items_wip.drain(..) { + match item { + ModuleItem::DocComment(doc) => { + if line > last_line + 1 { + docs.push(DocComment::new(CommentKind::Line, DocTarget::EnclosingItem)); + } + docs.push(doc); + last_line = line; + }, + other => { + push_docs!(); + module.items.push(other); + }, } } - } - push_docs!(); - (key, module) - }).collect(); + push_docs!(); + (key, module) + }) + .collect(); print!("documenting {} modules, ", modules.len()); if macros_all == 0 { @@ -647,33 +749,39 @@ fn main2() -> Result<(), Box> { println!("rendering html"); { let mut index = create(&output_path.join("index.html"))?; - index.write_all(template::dm_index(&Index { - env, - html: index_docs.as_ref().map(|(_, docs)| PreEscaped(docs.html.0.as_str())), - modules: build_index_tree(modules.values().map(|module| IndexTree { - htmlname: &module.htmlname, - full_name: &module.htmlname, - self_name: match module.name { - None => last_element(&module.htmlname), - Some(ref t) => t.as_str(), - }, - teaser: PreEscaped(&module.teaser.0), - no_substance: false, - children: Vec::new(), - })), - types: build_index_tree(type_docs.iter().map(|(path, ty)| IndexTree { - htmlname: ty.htmlname, - full_name: path, - self_name: if ty.name.is_empty() { - last_element(path) - } else { - &ty.name - }, - teaser: ty.docs.as_ref().map_or(PreEscaped(""), |d| d.teaser()), - no_substance: !ty.substance, - children: Vec::new(), - })), - }).0.as_bytes())?; + index.write_all( + template::dm_index(&Index { + env, + html: index_docs + .as_ref() + .map(|(_, docs)| PreEscaped(docs.html.0.as_str())), + modules: build_index_tree(modules.values().map(|module| IndexTree { + htmlname: &module.htmlname, + full_name: &module.htmlname, + self_name: match module.name { + None => last_element(&module.htmlname), + Some(ref t) => t.as_str(), + }, + teaser: PreEscaped(&module.teaser.0), + no_substance: false, + children: Vec::new(), + })), + types: build_index_tree(type_docs.iter().map(|(path, ty)| IndexTree { + htmlname: ty.htmlname, + full_name: path, + self_name: if ty.name.is_empty() { + last_element(path) + } else { + &ty.name + }, + teaser: ty.docs.as_ref().map_or(PreEscaped(""), |d| d.teaser()), + no_substance: !ty.substance, + children: Vec::new(), + })), + }) + .0 + .as_bytes(), + )?; } for (_path, details) in modules.iter() { @@ -685,12 +793,16 @@ fn main2() -> Result<(), Box> { } let mut f = create(&output_path.join(&fname))?; - f.write_all(template::dm_module(&ModuleArgs { - env, - base_href: &base, - //path, - details, - }).0.as_bytes())?; + f.write_all( + template::dm_module(&ModuleArgs { + env, + base_href: &base, + //path, + details, + }) + .0 + .as_bytes(), + )?; } for (path, details) in type_docs.iter() { @@ -706,13 +818,17 @@ fn main2() -> Result<(), Box> { } let mut f = create(&output_path.join(&fname))?; - f.write_all(template::dm_type(&Type { - env, - base_href: &base, - path, - details, - //types: &type_docs, - }).0.as_bytes())?; + f.write_all( + template::dm_type(&Type { + env, + base_href: &base, + path, + details, + //types: &type_docs, + }) + .0 + .as_bytes(), + )?; } Ok(()) @@ -720,7 +836,12 @@ fn main2() -> Result<(), Box> { fn find_return_type(code: &dm::ast::Block) -> Option> { for stmt in code.iter() { - if let dm::ast::Statement::Setting { name, mode: dm::ast::SettingMode::Assign, value } = &stmt.elem { + if let dm::ast::Statement::Setting { + name, + mode: dm::ast::SettingMode::Assign, + value, + } = &stmt.elem + { if name.as_str() == "SpacemanDMM_return_type" { if let Some(dm::ast::Term::Prefab(fab)) = value.as_term() { let bits: Vec<_> = fab.path.iter().map(|(_, name)| name.to_owned()).collect(); @@ -746,132 +867,173 @@ fn broken_link_fixer<'str>( modules_which_exist: &BTreeSet, objtree: &ObjectTree, types_with_docs: &BTreeMap<&str, TypeHasDocs>, -) -> Option<(CowStr<'str>, CowStr<'str>)> +) -> Option<(CowStr<'str>, CowStr<'str>)> { + let referie = link.reference.into_string(); + let reference = referie.as_str(); + let error_entity_print = || { + diagnostic_count.set(diagnostic_count.get() + 1); + if let Some(name) = error_entity.take() { + eprintln!("{name}:"); + } + }; + // macros + if let Some(module) = macro_to_module_map.get(reference) { + return Some(( + format!("{module}.html#define/{reference}").into(), + reference.to_owned().into(), + )); + } else if macro_exists.contains(reference) { + error_entity_print(); + eprintln!(" [{reference}]: macro not documented"); + return None; + } else if reference.ends_with(".dm") + || reference.ends_with(".txt") + || reference.ends_with(".md") { - let referie = link.reference.into_string(); - let reference = referie.as_str(); - let error_entity_print = || { - diagnostic_count.set(diagnostic_count.get() + 1); - if let Some(name) = error_entity.take() { - eprintln!("{name}:"); - } - }; - // macros - if let Some(module) = macro_to_module_map.get(reference) { - return Some((format!("{module}.html#define/{reference}").into(), reference.to_owned().into())); - } else if macro_exists.contains(reference) { - error_entity_print(); - eprintln!(" [{reference}]: macro not documented"); - return None; - } else if reference.ends_with(".dm") || reference.ends_with(".txt") || reference.ends_with(".md") { - let mod_path = module_path(reference.as_ref()); - if modules_which_exist.contains(&mod_path) { - return Some((format!("{mod_path}.html").into(), reference.to_owned().into())); - } - error_entity_print(); - eprintln!(" [{}]: module {}", reference, if Path::new(reference).exists() { "not documented" } else { "does not exist" }); - return None; + let mod_path = module_path(reference.as_ref()); + if modules_which_exist.contains(&mod_path) { + return Some(( + format!("{mod_path}.html").into(), + reference.to_owned().into(), + )); } + error_entity_print(); + eprintln!( + " [{}]: module {}", + reference, + if Path::new(reference).exists() { + "not documented" + } else { + "does not exist" + } + ); + return None; + } - // parse "proc" or "var" reference out - let mut ty_path = reference; - let mut proc_name = None; - let mut var_name = None; - let mut entity_exists = false; - if let Some(idx) = reference.find("/proc/") { - // `[/ty/proc/procname]` - let name = &reference[idx + "/proc/".len()..]; - proc_name = Some(name); - ty_path = &reference[..idx]; - if let Some(ty) = objtree.find(ty_path) { - entity_exists = ty.procs.contains_key(name); - } - } else if let Some(idx) = reference.find("/verb/") { - // `[/ty/verb/procname]` - let name = &reference[idx + "/verb/".len()..]; - proc_name = Some(name); - ty_path = &reference[..idx]; - if let Some(ty) = objtree.find(ty_path) { - // there are no builtin verbs - entity_exists = ty.procs.contains_key(name); - } - } else if let Some(idx) = reference.find("/var/") { - // `[/ty/var/varname]` - let name = &reference[idx + "/var/".len()..]; - var_name = Some(name); - ty_path = &reference[..idx]; - if let Some(ty) = objtree.find(ty_path) { - entity_exists = ty.vars.contains_key(name); - } - } else if objtree.find(reference).is_some() { - entity_exists = true; - } else if let Some(idx) = reference.rfind('/') { - let (parent, rest) = (&reference[..idx], &reference[idx + 1..]); - if let Some(ty) = objtree.find(parent) { - if ty.procs.contains_key(rest) && !ty.vars.contains_key(rest) { - // correct `[/ty/procname]` to `[/ty/proc/procname]` - proc_name = Some(rest); - ty_path = parent; - error_entity_print(); - eprintln!(" [{reference}]: correcting to [{parent}/proc/{rest}]"); - entity_exists = true; - } else if ty.vars.contains_key(rest) { - // correct `[/ty/varname]` to `[/ty/var/varname]` - var_name = Some(rest); - ty_path = parent; - error_entity_print(); - eprintln!(" [{reference}]: correcting to [{parent}/var/{rest}]"); - entity_exists = true; - } - } - } else if objtree.root().vars.contains_key(reference) { - ty_path = ""; - var_name = Some(reference); - error_entity_print(); - eprintln!(" [{reference}]: correcting to [/var/{reference}]"); - entity_exists = true; + // parse "proc" or "var" reference out + let mut ty_path = reference; + let mut proc_name = None; + let mut var_name = None; + let mut entity_exists = false; + if let Some(idx) = reference.find("/proc/") { + // `[/ty/proc/procname]` + let name = &reference[idx + "/proc/".len()..]; + proc_name = Some(name); + ty_path = &reference[..idx]; + if let Some(ty) = objtree.find(ty_path) { + entity_exists = ty.procs.contains_key(name); } - // else `[/ty]` + } else if let Some(idx) = reference.find("/verb/") { + // `[/ty/verb/procname]` + let name = &reference[idx + "/verb/".len()..]; + proc_name = Some(name); + ty_path = &reference[..idx]; + if let Some(ty) = objtree.find(ty_path) { + // there are no builtin verbs + entity_exists = ty.procs.contains_key(name); + } + } else if let Some(idx) = reference.find("/var/") { + // `[/ty/var/varname]` + let name = &reference[idx + "/var/".len()..]; + var_name = Some(name); + ty_path = &reference[..idx]; + if let Some(ty) = objtree.find(ty_path) { + entity_exists = ty.vars.contains_key(name); + } + } else if objtree.find(reference).is_some() { + entity_exists = true; + } else if let Some(idx) = reference.rfind('/') { + let (parent, rest) = (&reference[..idx], &reference[idx + 1..]); + if let Some(ty) = objtree.find(parent) { + if ty.procs.contains_key(rest) && !ty.vars.contains_key(rest) { + // correct `[/ty/procname]` to `[/ty/proc/procname]` + proc_name = Some(rest); + ty_path = parent; + error_entity_print(); + eprintln!(" [{reference}]: correcting to [{parent}/proc/{rest}]"); + entity_exists = true; + } else if ty.vars.contains_key(rest) { + // correct `[/ty/varname]` to `[/ty/var/varname]` + var_name = Some(rest); + ty_path = parent; + error_entity_print(); + eprintln!(" [{reference}]: correcting to [{parent}/var/{rest}]"); + entity_exists = true; + } + } + } else if objtree.root().vars.contains_key(reference) { + ty_path = ""; + var_name = Some(reference); + error_entity_print(); + eprintln!(" [{reference}]: correcting to [/var/{reference}]"); + entity_exists = true; + } + // else `[/ty]` - // Determine external doc URL - let mut external_url = None; - if entity_exists { - // TODO: .location.is_builtins() is not the best way to find this out, - // for example if it's overridden in the DM code but not re-documented. - if let Some(ty) = objtree.find(ty_path) { - if let Some(var_name) = var_name { - if let Some(var) = ty.get_value(var_name) { - if var.location.is_builtins() { - external_url = Some(match var.docs.builtin_docs { - BuiltinDocs::None => format!("{}{}/var/{}", DM_REFERENCE_BASE, ty.path, var_name), - BuiltinDocs::ReferenceHash(hash) => format!("{DM_REFERENCE_BASE}{hash}"), - }) - } + // Determine external doc URL + let mut external_url = None; + if entity_exists { + // TODO: .location.is_builtins() is not the best way to find this out, + // for example if it's overridden in the DM code but not re-documented. + if let Some(ty) = objtree.find(ty_path) { + if let Some(var_name) = var_name { + if let Some(var) = ty.get_value(var_name) { + if var.location.is_builtins() { + external_url = Some(match var.docs.builtin_docs { + BuiltinDocs::None => { + format!("{}{}/var/{}", DM_REFERENCE_BASE, ty.path, var_name) + }, + BuiltinDocs::ReferenceHash(hash) => { + format!("{DM_REFERENCE_BASE}{hash}") + }, + }) } - } else if let Some(proc_name) = proc_name { - if let Some(proc) = ty.get_proc(proc_name) { - if proc.location.is_builtins() { - external_url = Some(match proc.docs.builtin_docs { - BuiltinDocs::None => format!("{}{}/proc/{}", DM_REFERENCE_BASE, ty.path, proc_name), - BuiltinDocs::ReferenceHash(hash) => format!("{DM_REFERENCE_BASE}{hash}"), - }) - } - } - } else if ty.location.is_builtins() { - external_url = Some(match ty.docs.builtin_docs { - BuiltinDocs::None => format!("{}{}", DM_REFERENCE_BASE, ty.path), - BuiltinDocs::ReferenceHash(hash) => format!("{DM_REFERENCE_BASE}{hash}"), - }) } + } else if let Some(proc_name) = proc_name { + if let Some(proc) = ty.get_proc(proc_name) { + if proc.location.is_builtins() { + external_url = Some(match proc.docs.builtin_docs { + BuiltinDocs::None => { + format!("{}{}/proc/{}", DM_REFERENCE_BASE, ty.path, proc_name) + }, + BuiltinDocs::ReferenceHash(hash) => { + format!("{DM_REFERENCE_BASE}{hash}") + }, + }) + } + } + } else if ty.location.is_builtins() { + external_url = Some(match ty.docs.builtin_docs { + BuiltinDocs::None => format!("{}{}", DM_REFERENCE_BASE, ty.path), + BuiltinDocs::ReferenceHash(hash) => format!("{DM_REFERENCE_BASE}{hash}"), + }) } } + } - let mut progress = String::new(); - let mut best = 0; + let mut progress = String::new(); + let mut best = 0; - if ty_path.is_empty() { - progress.push_str("/global"); - if let Some(info) = types_with_docs.get("") { + if ty_path.is_empty() { + progress.push_str("/global"); + if let Some(info) = types_with_docs.get("") { + if let Some(proc_name) = proc_name { + if info.proc_docs.contains(proc_name) { + best = progress.len(); + } + } else if let Some(var_name) = var_name { + if info.var_docs.contains(var_name) { + best = progress.len(); + } + } else { + best = progress.len(); + } + } + } else { + for bit in ty_path.trim_start_matches('/').split('/') { + progress.push('/'); + progress.push_str(bit); + if let Some(info) = types_with_docs.get(progress.as_str()) { if let Some(proc_name) = proc_name { if info.proc_docs.contains(proc_name) { best = progress.len(); @@ -884,63 +1046,54 @@ fn broken_link_fixer<'str>( best = progress.len(); } } - } else { - for bit in ty_path.trim_start_matches('/').split('/') { - progress.push('/'); - progress.push_str(bit); - if let Some(info) = types_with_docs.get(progress.as_str()) { - if let Some(proc_name) = proc_name { - if info.proc_docs.contains(proc_name) { - best = progress.len(); - } - } else if let Some(var_name) = var_name { - if info.var_docs.contains(var_name) { - best = progress.len(); - } - } else { - best = progress.len(); - } - } - } } + } - if best > 0 { - use std::fmt::Write; + if best > 0 { + use std::fmt::Write; - if best < progress.len() { - error_entity_print(); - if entity_exists { - eprint!(" [{}]: not documented, guessing [{}", reference, &progress[..best]); - } else { - eprint!(" [{}]: unknown crosslink, guessing [{}", reference, &progress[..best]); - } - if let Some(proc_name) = proc_name { - eprint!("/proc/{proc_name}"); - } else if let Some(var_name) = var_name { - eprint!("/var/{var_name}"); - } - eprintln!("]"); - progress.truncate(best); - } - - let mut href = format!("{}.html", &progress[1..]); - if let Some(proc_name) = proc_name { - let _ = write!(href, "#proc/{proc_name}"); - } else if let Some(var_name) = var_name { - let _ = write!(href, "#var/{var_name}"); - } - Some((href.into(), progress.into())) - } else if let Some(external) = external_url { - Some((external.into(), reference.to_owned().into())) - } else { + if best < progress.len() { error_entity_print(); if entity_exists { - eprintln!(" [{reference}]: not documented"); + eprint!( + " [{}]: not documented, guessing [{}", + reference, + &progress[..best] + ); } else { - eprintln!(" [{reference}]: unknown crosslink"); + eprint!( + " [{}]: unknown crosslink, guessing [{}", + reference, + &progress[..best] + ); } - None + if let Some(proc_name) = proc_name { + eprint!("/proc/{proc_name}"); + } else if let Some(var_name) = var_name { + eprint!("/var/{var_name}"); + } + eprintln!("]"); + progress.truncate(best); } + + let mut href = format!("{}.html", &progress[1..]); + if let Some(proc_name) = proc_name { + let _ = write!(href, "#proc/{proc_name}"); + } else if let Some(var_name) = var_name { + let _ = write!(href, "#var/{var_name}"); + } + Some((href.into(), progress.into())) + } else if let Some(external) = external_url { + Some((external.into(), reference.to_owned().into())) + } else { + error_entity_print(); + if entity_exists { + eprintln!(" [{reference}]: not documented"); + } else { + eprintln!(" [{reference}]: unknown crosslink"); + } + None + } } // ---------------------------------------------------------------------------- @@ -948,22 +1101,29 @@ fn broken_link_fixer<'str>( fn module_path(path: &Path) -> String { let mut path = path.with_extension(""); - if path.file_name().is_some_and(|x| x.to_string_lossy().eq_ignore_ascii_case("README")) { + if path + .file_name() + .is_some_and(|x| x.to_string_lossy().eq_ignore_ascii_case("README")) + { path.pop(); } path.display().to_string().replace('\\', "/") } -fn module_entry<'a, 'b>(modules: &'a mut BTreeMap>, path: &Path) -> &'a mut Module1<'b> { +fn module_entry<'a, 'b>( + modules: &'a mut BTreeMap>, + path: &Path, +) -> &'a mut Module1<'b> { modules.entry(module_path(path)).or_insert_with(|| Module1 { htmlname: module_path(path), orig_filename: path.display().to_string().replace('\\', "/"), - .. Default::default() + ..Default::default() }) } fn is_visible(entry: &walkdir::DirEntry) -> bool { - entry.file_name() + entry + .file_name() .to_str() .map(|s| !s.starts_with('.')) .unwrap_or(true) @@ -977,7 +1137,10 @@ fn format_type_path(vec: &[String]) -> String { } } -fn linkify_type<'a, I: Iterator>(all_type_names: &BTreeSet, iter: I) -> String { +fn linkify_type<'a, I: Iterator>( + all_type_names: &BTreeSet, + iter: I, +) -> String { let mut output = String::new(); let mut all_progress = String::new(); let mut progress = String::new(); @@ -1022,7 +1185,7 @@ fn git_info(git: &mut Git) -> Result<(), git2::Error> { None => { println!("incomplete git info: malformed or non-utf8 name"); return Ok(()); - } + }, } }; } @@ -1107,8 +1270,7 @@ fn read_as_markdown(path: &Path) -> std::io::Result> { } fn strip_propriety(name: &str) -> &str { - name - .trim_start_matches("\\proper") + name.trim_start_matches("\\proper") .trim_start_matches("\\improper") .trim_start() } @@ -1117,7 +1279,7 @@ fn strip_propriety(name: &str) -> &str { // Tree stuff struct IndexTree<'a> { - htmlname: &'a str, // href="{{htmlname}}.html" + htmlname: &'a str, // href="{{htmlname}}.html" full_name: &'a str, self_name: &'a str, teaser: PreEscaped<&'a str>, @@ -1127,7 +1289,7 @@ struct IndexTree<'a> { fn build_index_tree<'a, I>(iter: I) -> Vec> where - I: IntoIterator>, + I: IntoIterator>, { let mut stack = vec![IndexTree { htmlname: "", @@ -1257,11 +1419,17 @@ struct Environment<'a> { impl<'a> Environment<'a> { fn linkify_type_str(&self, s: &str) -> Markup { - PreEscaped(linkify_type(self.all_type_names, s.split('/').skip_while(|b| b.is_empty()))) + PreEscaped(linkify_type( + self.all_type_names, + s.split('/').skip_while(|b| b.is_empty()), + )) } fn linkify_type_array(&self, a: &[String]) -> Markup { - PreEscaped(linkify_type(self.all_type_names, a.iter().map(|x| x.as_str()))) + PreEscaped(linkify_type( + self.all_type_names, + a.iter().map(|x| x.as_str()), + )) } } diff --git a/crates/dmdoc/src/markdown.rs b/crates/dmdoc/src/markdown.rs index c6501d06..a0a44201 100644 --- a/crates/dmdoc/src/markdown.rs +++ b/crates/dmdoc/src/markdown.rs @@ -6,7 +6,10 @@ use std::ops::Range; use maud::PreEscaped; use pulldown_cmark::{self, BrokenLinkCallback, Event, HeadingLevel, Parser, Tag}; -pub fn render<'string>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, '_>) -> PreEscaped { +pub fn render<'string>( + markdown: &'string str, + broken_link_callback: BrokenLinkCallback<'string, '_>, +) -> PreEscaped { let mut buf = String::new(); push_html(&mut buf, parser(markdown, broken_link_callback)); PreEscaped(buf) @@ -20,11 +23,17 @@ pub struct DocBlock { } impl DocBlock { - pub fn parse<'string>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, '_>) -> Self { + pub fn parse<'string>( + markdown: &'string str, + broken_link_callback: BrokenLinkCallback<'string, '_>, + ) -> Self { parse_main(parser(markdown, broken_link_callback).peekable()) } - pub fn parse_with_title<'string>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, '_>) -> (Option, Self) { + pub fn parse_with_title<'string>( + markdown: &'string str, + broken_link_callback: BrokenLinkCallback<'string, '_>, + ) -> (Option, Self) { let mut parser = parser(markdown, broken_link_callback).peekable(); ( if let Some(&Event::Start(Tag::Heading(HeadingLevel::H1, _, _))) = parser.peek() { @@ -52,11 +61,14 @@ impl DocBlock { } } -fn parser<'string, 'func>(markdown: &'string str, broken_link_callback: BrokenLinkCallback<'string, 'func>) -> Parser<'string, 'func> { +fn parser<'string, 'func>( + markdown: &'string str, + broken_link_callback: BrokenLinkCallback<'string, 'func>, +) -> Parser<'string, 'func> { Parser::new_with_broken_link_callback( markdown, pulldown_cmark::Options::ENABLE_TABLES | pulldown_cmark::Options::ENABLE_STRIKETHROUGH, - broken_link_callback + broken_link_callback, ) } @@ -83,14 +95,21 @@ fn parse_main(mut parser: std::iter::Peekable) -> DocBlock { let has_description = parser.peek().is_some(); push_html(&mut html, parser); trim_right(&mut html); - DocBlock { html: PreEscaped(html), teaser, has_description } + DocBlock { + html: PreEscaped(html), + teaser, + has_description, + } } -fn push_html<'a, I: IntoIterator>>(buf: &mut String, iter: I) { - pulldown_cmark::html::push_html(buf, HeadingLinker { - inner: iter.into_iter(), - output: Default::default(), - }); +fn push_html<'a, I: IntoIterator>>(buf: &mut String, iter: I) { + pulldown_cmark::html::push_html( + buf, + HeadingLinker { + inner: iter.into_iter(), + output: Default::default(), + }, + ); } fn trim_right(buf: &mut String) { @@ -105,7 +124,7 @@ struct HeadingLinker<'a, I> { output: VecDeque>, } -impl<'a, I: Iterator>> Iterator for HeadingLinker<'a, I> { +impl<'a, I: Iterator>> Iterator for HeadingLinker<'a, I> { type Item = Event<'a>; fn next(&mut self) -> Option> { @@ -129,8 +148,11 @@ impl<'a, I: Iterator>> Iterator for HeadingLinker<'a, I> { self.output.push_back(event); } - self.output.push_back(Event::Html(format!("").into())); - return Some(Event::Html(format!("<{} id=\"{}\">", heading, slugify(&text_buf)).into())); + self.output + .push_back(Event::Html(format!("").into())); + return Some(Event::Html( + format!("<{} id=\"{}\">", heading, slugify(&text_buf)).into(), + )); } original } diff --git a/crates/dmdoc/src/template.rs b/crates/dmdoc/src/template.rs index 6b1bcd5b..30c50c26 100644 --- a/crates/dmdoc/src/template.rs +++ b/crates/dmdoc/src/template.rs @@ -169,7 +169,12 @@ fn percentage(amt: usize, total: usize) -> Markup { } pub(crate) fn dm_index(index: &Index) -> Markup { - let Index { env, html, modules, types } = index; + let Index { + env, + html, + modules, + types, + } = index; base( env, "", @@ -213,12 +218,16 @@ pub(crate) fn dm_index(index: &Index) -> Markup { } (index_tree(types, "")) } - } + }, ) } pub(crate) fn dm_module(module: &ModuleArgs) -> Markup { - let ModuleArgs { env, base_href, details } = *module; + let ModuleArgs { + env, + base_href, + details, + } = *module; base( env, base_href, @@ -338,12 +347,17 @@ pub(crate) fn dm_module(module: &ModuleArgs) -> Markup { (define.docs.html) } } - } + }, ) } pub(crate) fn dm_type(ty: &Type) -> Markup { - let Type { env, base_href, path, details } = *ty; + let Type { + env, + base_href, + path, + details, + } = *ty; base( env, base_href, @@ -492,7 +506,7 @@ pub(crate) fn dm_type(ty: &Type) -> Markup { (proc.docs.html) } } - } + }, ) } diff --git a/crates/dmm-tools-cli/src/main.rs b/crates/dmm-tools-cli/src/main.rs index 1bed6380..cc4bdace 100644 --- a/crates/dmm-tools-cli/src/main.rs +++ b/crates/dmm-tools-cli/src/main.rs @@ -1,6 +1,6 @@ //! CLI tools, including a map renderer, using the same backend as the editor. #![forbid(unsafe_code)] -#![doc(hidden)] // Don't interfere with lib docs. +#![doc(hidden)] // Don't interfere with lib docs. extern crate clap; extern crate rayon; @@ -32,7 +32,9 @@ use dmm_tools::*; fn main() { let opt = Opt::parse(); let mut context = Context::default(); - context.dm_context.set_print_severity(Some(dm::Severity::Error)); + context + .dm_context + .set_print_severity(Some(dm::Severity::Error)); rayon::ThreadPoolBuilder::new() .num_threads(opt.jobs) .build_global() @@ -74,7 +76,7 @@ impl Context { Err(e) => { eprintln!("i/o error opening environment:\n{e}"); std::process::exit(1); - } + }, }; let indents = dm::indents::IndentProcessor::new(&self.dm_context, pp); let parser = dm::parser::Parser::new(&self.dm_context, indents); @@ -160,10 +162,7 @@ enum Command { }, /// List the differing coordinates between two maps. #[command(name = "diff-maps")] - DiffMaps { - left: String, - right: String, - }, + DiffMaps { left: String, right: String }, /// Show metadata information about the map. #[command(name = "map-info")] MapInfo { @@ -192,9 +191,17 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { let mut report = Vec::new(); for &render_passes::RenderPassInfo { - name, desc, default, new: _, - } in render_passes::RENDER_PASSES { - report.push(Pass { name, desc, default }); + name, + desc, + default, + new: _, + } in render_passes::RENDER_PASSES + { + report.push(Pass { + name, + desc, + default, + }); } output_json(&report); } else { @@ -217,8 +224,14 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { }, // -------------------------------------------------------------------- Command::Minimap { - ref output, min, max, ref enable, ref disable, ref files, - pngcrush, optipng, + ref output, + min, + max, + ref enable, + ref disable, + ref files, + pngcrush, + optipng, } => { context.objtree(opt); if context @@ -237,7 +250,11 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { .. } = *context; - let render_passes = &dmm_tools::render_passes::configure(&context.dm_context.config().map_renderer, enable, disable); + let render_passes = &dmm_tools::render_passes::configure( + &context.dm_context.config().map_renderer, + enable, + disable, + ); let paths: Vec<&Path> = files.iter().map(|p| p.as_ref()).collect(); let errors: RwLock> = Default::default(); @@ -259,7 +276,7 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { eprintln!("Failed to load {}:\n{}", path.display(), e); exit_status.fetch_add(1, Ordering::Relaxed); return; - } + }, }; let (dim_x, dim_y, dim_z) = map.dim_xyz(); @@ -307,23 +324,29 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { if pngcrush { println!(" pngcrush {outfile}"); let temp = format!("{outfile}.temp"); - assert!(std::process::Command::new("pngcrush") - .arg("-ow") - .arg(&outfile) - .arg(&temp) - .stderr(std::process::Stdio::null()) - .status() - .unwrap() - .success(), "pngcrush failed"); + assert!( + std::process::Command::new("pngcrush") + .arg("-ow") + .arg(&outfile) + .arg(&temp) + .stderr(std::process::Stdio::null()) + .status() + .unwrap() + .success(), + "pngcrush failed" + ); } if optipng { println!("{prefix}optipng {outfile}"); - assert!(std::process::Command::new("optipng") - .arg(&outfile) - .stderr(std::process::Stdio::null()) - .status() - .unwrap() - .success(), "optipng failed"); + assert!( + std::process::Command::new("optipng") + .arg(&outfile) + .stderr(std::process::Stdio::null()) + .status() + .unwrap() + .success(), + "optipng failed" + ); } }; @@ -344,7 +367,8 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { }, // -------------------------------------------------------------------- Command::DiffMaps { - ref left, ref right, + ref left, + ref right, } => { use std::cmp::min; @@ -364,8 +388,10 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { for z in 0..min(left_dims.2, right_dims.2) { for y in 0..min(left_dims.1, right_dims.1) { for x in 0..min(left_dims.0, right_dims.0) { - let left_tile = &left_map.dictionary[&left_map.grid[(z, left_dims.1 - y - 1, x)]]; - let right_tile = &right_map.dictionary[&right_map.grid[(z, right_dims.1 - y - 1, x)]]; + let left_tile = + &left_map.dictionary[&left_map.grid[(z, left_dims.1 - y - 1, x)]]; + let right_tile = + &right_map.dictionary[&right_map.grid[(z, right_dims.1 - y - 1, x)]]; if left_tile != right_tile { println!(" different tile: ({}, {}, {})", x + 1, y + 1, z + 1); } @@ -374,9 +400,7 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { } }, // -------------------------------------------------------------------- - Command::MapInfo { - json, ref files, - } => { + Command::MapInfo { json, ref files } => { if !json { eprintln!("non-JSON output is not yet supported"); } @@ -392,11 +416,14 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { for path in files.iter() { let path = std::path::Path::new(path); let map = dmm::Map::from_file(path).unwrap(); - report.insert(path, Map { - size: map.dim_xyz(), - key_length: map.key_length(), - num_keys: map.dictionary.len(), - }); + report.insert( + path, + Map { + size: map.dim_xyz(), + key_length: map.key_length(), + num_keys: map.dictionary.len(), + }, + ); } output_json(&report); }, @@ -557,72 +584,92 @@ fn render_many(context: &Context, command: RenderManyCommand) -> RenderManyComma ref exit_status, .. } = *context; - let render_passes = &dmm_tools::render_passes::configure_list(&context.dm_context.config().map_renderer, &command.enable, &command.disable); + let render_passes = &dmm_tools::render_passes::configure_list( + &context.dm_context.config().map_renderer, + &command.enable, + &command.disable, + ); let errors: RwLock> = Default::default(); // Prepare output directory. let output_directory = command.output_directory; if let Err(e) = std::fs::create_dir_all(&output_directory) { - eprintln!("failed to create output directory {}:\n{}", output_directory.display(), e); + eprintln!( + "failed to create output directory {}:\n{}", + output_directory.display(), + e + ); exit_status.fetch_add(1, Ordering::Relaxed); panic!(); } - // Iterate over the maps - let result_files: Vec<_> = command.files.into_par_iter().enumerate().map(|(file_idx, file)| { - eprintln!("{}: load {}", file_idx, file.path.display()); - let stem = file.path.file_stem().unwrap().to_string_lossy(); - let map = dmm::Map::from_file(&file.path).unwrap(); // TODO: error handling - let (dim_x, dim_y, dim_z) = map.dim_xyz(); + let result_files: Vec<_> = command + .files + .into_par_iter() + .enumerate() + .map(|(file_idx, file)| { + eprintln!("{}: load {}", file_idx, file.path.display()); + let stem = file.path.file_stem().unwrap().to_string_lossy(); + let map = dmm::Map::from_file(&file.path).unwrap(); // TODO: error handling + let (dim_x, dim_y, dim_z) = map.dim_xyz(); - // If `chunks` was not specified, render one chunk per z-level. - let chunks = file.chunks.unwrap_or_else(|| (1..=dim_z).map(|z| RenderManyChunk { - z, - min_x: None, - min_y: None, - max_x: None, - max_y: None, - }).collect()); + // If `chunks` was not specified, render one chunk per z-level. + let chunks = file.chunks.unwrap_or_else(|| { + (1..=dim_z) + .map(|z| RenderManyChunk { + z, + min_x: None, + min_y: None, + max_x: None, + max_y: None, + }) + .collect() + }); - let result_chunks: Vec<_> = chunks.into_par_iter().enumerate().map(|(chunk_idx, chunk)| { - eprintln!("{file_idx}/{chunk_idx}: render {chunk:?}"); + let result_chunks: Vec<_> = chunks + .into_par_iter() + .enumerate() + .map(|(chunk_idx, chunk)| { + eprintln!("{file_idx}/{chunk_idx}: render {chunk:?}"); - // Render the image. - let bump = Default::default(); - let minimap_context = minimap::Context { - objtree, - map: &map, - level: map.z_level(chunk.z - 1), - // Default and clamp to [1, max]. - min: (chunk.min_x.unwrap_or(1).max(1) - 1, chunk.min_y.unwrap_or(1).max(1) - 1), - max: (chunk.max_x.unwrap_or(dim_x).min(dim_x) - 1, chunk.max_y.unwrap_or(dim_y).min(dim_y) - 1), - render_passes, - errors: &errors, - bump: &bump, - }; - let image = minimap::generate(minimap_context, icon_cache).unwrap(); // TODO: error handling + // Render the image. + let bump = Default::default(); + let minimap_context = minimap::Context { + objtree, + map: &map, + level: map.z_level(chunk.z - 1), + // Default and clamp to [1, max]. + min: ( + chunk.min_x.unwrap_or(1).max(1) - 1, + chunk.min_y.unwrap_or(1).max(1) - 1, + ), + max: ( + chunk.max_x.unwrap_or(dim_x).min(dim_x) - 1, + chunk.max_y.unwrap_or(dim_y).min(dim_y) - 1, + ), + render_passes, + errors: &errors, + bump: &bump, + }; + let image = minimap::generate(minimap_context, icon_cache).unwrap(); // TODO: error handling - // Write it to file. - let filename = PathBuf::from(format!( - "{}_z{}_chunk{}.png", - stem, - chunk.z, - chunk_idx, - )); - eprintln!("{}/{}: save {}", file_idx, chunk_idx, filename.display()); - let outfile = output_directory.join(&filename); - image.to_file(&outfile).unwrap(); // TODO: error handling + // Write it to file. + let filename = + PathBuf::from(format!("{}_z{}_chunk{}.png", stem, chunk.z, chunk_idx,)); + eprintln!("{}/{}: save {}", file_idx, chunk_idx, filename.display()); + let outfile = output_directory.join(&filename); + image.to_file(&outfile).unwrap(); // TODO: error handling - RenderManyChunkResult { - filename, + RenderManyChunkResult { filename } + }) + .collect(); + + RenderManyFileResult { + chunks: result_chunks, } - }).collect(); - - RenderManyFileResult { - chunks: result_chunks, - } - }).collect(); + }) + .collect(); RenderManyCommandResult { files: result_files, diff --git a/crates/dmm-tools/examples/duplicate_icon_states.rs b/crates/dmm-tools/examples/duplicate_icon_states.rs index 859a70d5..546a5b47 100644 --- a/crates/dmm-tools/examples/duplicate_icon_states.rs +++ b/crates/dmm-tools/examples/duplicate_icon_states.rs @@ -4,8 +4,8 @@ extern crate ndarray; extern crate walkdir; use dmm_tools::dmi::*; -use ndarray::s; use foldhash::{HashMap, HashMapExt}; +use ndarray::s; use std::path::Path; use walkdir::{DirEntry, WalkDir}; @@ -25,7 +25,7 @@ fn files_with_extension(ext: &str, mut f: F) { None => { println!("Set TEST_DME to check .{ext} files"); return; - } + }, }; for entry in WalkDir::new(dir).into_iter().filter_entry(is_visible) { let entry = entry.unwrap(); diff --git a/crates/dmm-tools/src/dmi.rs b/crates/dmm-tools/src/dmi.rs index 1a309099..8db801ff 100644 --- a/crates/dmm-tools/src/dmi.rs +++ b/crates/dmm-tools/src/dmi.rs @@ -124,9 +124,7 @@ impl Image { Image { width, height, - data: { - Array2::default((width as usize, height as usize)) - }, + data: { Array2::default((width as usize, height as usize)) }, } } @@ -210,10 +208,7 @@ impl Image { let src = other_dat[(sy * other.width + sx) as usize]; macro_rules! tint { ($i:expr) => { - mul255( - src[$i], - color[$i], - ) + mul255(src[$i], color[$i]) }; } let dst = &mut self_dat[(y * self.width + x) as usize]; diff --git a/crates/dmm-tools/src/dmi/render.rs b/crates/dmm-tools/src/dmi/render.rs index 55e61c04..19596b44 100644 --- a/crates/dmm-tools/src/dmi/render.rs +++ b/crates/dmm-tools/src/dmi/render.rs @@ -11,12 +11,12 @@ pub struct IconRenderer<'a> { source: &'a IconFile, } -/// [`IconRenderer::render`] will return this to indicate if it wrote to the stream using +/// [`IconRenderer::render`] will return this to indicate if it wrote to the stream using /// [`gif::Encoder`] or `[`png::Encoder`]. #[derive(Debug, Clone, Copy)] pub enum RenderType { Png, - Gif + Gif, } #[derive(Debug)] @@ -29,12 +29,8 @@ pub struct RenderStateGuard<'a> { impl<'a> RenderStateGuard<'a> { pub fn render(self, target: W) -> io::Result<()> { match self.render_type { - RenderType::Png => { - self.renderer.render_to_png(self.state, target) - }, - RenderType::Gif => { - self.renderer.render_gif(self.state, target) - }, + RenderType::Png => self.renderer.render_to_png(self.state, target), + RenderType::Gif => self.renderer.render_gif(self.state, target), } } } @@ -42,9 +38,7 @@ impl<'a> RenderStateGuard<'a> { /// Public API impl<'a> IconRenderer<'a> { pub fn new(source: &'a IconFile) -> Self { - Self { - source, - } + Self { source } } /// Renders with either [`gif::Encoder`] or [`png::Encoder`] depending on whether the icon state is animated @@ -54,8 +48,8 @@ impl<'a> IconRenderer<'a> { self.prepare_render_state(self.source.get_icon_state(icon_state)?) } - /// This is here so that duplicate icon states can be handled by not relying on the btreemap - /// of state names in [`Metadata`]. + /// This is here so that duplicate icon states can be handled by not relying on the btreemap + /// of state names in [`Metadata`]. pub fn prepare_render_state(&'a self, icon_state: &'a State) -> io::Result { match icon_state.is_animated() { false => Ok(RenderStateGuard { @@ -71,7 +65,7 @@ impl<'a> IconRenderer<'a> { } } - /// Instead of writing to a file, this gives a Vec of each frame/dir as it would be composited + /// Instead of writing to a file, this gives a Vec of each frame/dir as it would be composited /// for a file. pub fn render_to_images(&self, icon_state: &StateIndex) -> io::Result> { let state = self.source.get_icon_state(icon_state)?; @@ -90,7 +84,7 @@ impl<'a> IconRenderer<'a> { }; let mut canvas = self.get_canvas(icon_state.dirs); let mut vec = Vec::new(); - let range = if icon_state.rewind { + let range = if icon_state.rewind { Either::Left((0..frames).chain((0..frames).rev())) } else { Either::Right(0..frames) @@ -107,8 +101,12 @@ impl<'a> IconRenderer<'a> { fn get_canvas(&self, dirs: Dirs) -> Image { match dirs { Dirs::One => Image::new_rgba(self.source.metadata.width, self.source.metadata.height), - Dirs::Four => Image::new_rgba(self.source.metadata.width * 4, self.source.metadata.height), - Dirs::Eight => Image::new_rgba(self.source.metadata.width * 8, self.source.metadata.height), + Dirs::Four => { + Image::new_rgba(self.source.metadata.width * 4, self.source.metadata.height) + }, + Dirs::Eight => { + Image::new_rgba(self.source.metadata.width * 8, self.source.metadata.height) + }, } } @@ -116,31 +114,23 @@ impl<'a> IconRenderer<'a> { /// in the same order BYOND uses. fn ordered_dirs(dirs: Dirs) -> Vec { match dirs { - Dirs::One => { [Dir::South].to_vec() }, - Dirs::Four => { - [ - Dir::South, - Dir::North, - Dir::East, - Dir::West, - ].to_vec() - }, - Dirs::Eight => { - [ - Dir::South, - Dir::North, - Dir::East, - Dir::West, - Dir::Southeast, - Dir::Southwest, - Dir::Northeast, - Dir::Northwest, - ].to_vec() - }, + Dirs::One => [Dir::South].to_vec(), + Dirs::Four => [Dir::South, Dir::North, Dir::East, Dir::West].to_vec(), + Dirs::Eight => [ + Dir::South, + Dir::North, + Dir::East, + Dir::West, + Dir::Southeast, + Dir::Southwest, + Dir::Northeast, + Dir::Northwest, + ] + .to_vec(), } } - /// Renders each direction to the same canvas, offsetting them to the right + /// Renders each direction to the same canvas, offsetting them to the right fn render_dirs(&self, icon_state: &State, canvas: &mut Image, frame: u32) { for (dir_no, dir) in Self::ordered_dirs(icon_state.dirs).iter().enumerate() { let frame_idx = icon_state.index_of_frame(*dir, frame as u32); @@ -155,14 +145,12 @@ impl<'a> IconRenderer<'a> { } /// Renders the whole file to a gif, animated states becoming frames - fn render_gif( - &self, - icon_state: &State, - target: W, - ) -> io::Result<()> { - + fn render_gif(&self, icon_state: &State, target: W) -> io::Result<()> { if !icon_state.is_animated() { - return Err(io::Error::new(io::ErrorKind::InvalidData, "Tried to render gif with one frame")); + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "Tried to render gif with one frame", + )); } let (frames, delays) = match &icon_state.frames { @@ -173,15 +161,14 @@ impl<'a> IconRenderer<'a> { let mut canvas = self.get_canvas(icon_state.dirs); - let mut encoder = - gif::Encoder::new(target, canvas.width as u16, canvas.height as u16, &[]) - .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("{e}")))?; + let mut encoder = gif::Encoder::new(target, canvas.width as u16, canvas.height as u16, &[]) + .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("{e}")))?; encoder .set_repeat(gif::Repeat::Infinite) .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("{e}")))?; - let range = if icon_state.rewind { + let range = if icon_state.rewind { Either::Left((0..frames).chain((0..frames).rev())) } else { Either::Right(0..frames) @@ -220,4 +207,4 @@ impl<'a> IconRenderer<'a> { canvas.clear(); Ok(()) } -} \ No newline at end of file +} diff --git a/crates/dmm-tools/src/dmm.rs b/crates/dmm-tools/src/dmm.rs index bf44fb44..39a42c4a 100644 --- a/crates/dmm-tools/src/dmm.rs +++ b/crates/dmm-tools/src/dmm.rs @@ -42,17 +42,34 @@ impl Coord2 { #[inline] pub fn z(self, z: i32) -> Coord3 { - Coord3 { x: self.x, y: self.y, z } + Coord3 { + x: self.x, + y: self.y, + z, + } } fn to_raw(self, (dim_y, dim_x): (usize, usize)) -> (usize, usize) { - assert!(self.x >= 1 && self.x <= dim_x as i32, "x={} not in [1, {}]", self.x, dim_x); - assert!(self.y >= 1 && self.y <= dim_y as i32, "y={} not in [1, {}]", self.y, dim_y); + assert!( + self.x >= 1 && self.x <= dim_x as i32, + "x={} not in [1, {}]", + self.x, + dim_x + ); + assert!( + self.y >= 1 && self.y <= dim_y as i32, + "y={} not in [1, {}]", + self.y, + dim_y + ); (dim_y - self.y as usize, self.x as usize - 1) } fn from_raw((y, x): (usize, usize), (dim_y, _dim_x): (usize, usize)) -> Coord2 { - Coord2 { x: x as i32 + 1, y: (dim_y - y) as i32 } + Coord2 { + x: x as i32 + 1, + y: (dim_y - y) as i32, + } } } @@ -61,7 +78,10 @@ impl std::ops::Add for Coord2 { fn add(self, rhs: Dir) -> Coord2 { let (x, y) = rhs.offset(); - Coord2 { x: self.x + x, y: self.y + y } + Coord2 { + x: self.x + x, + y: self.y + y, + } } } @@ -86,19 +106,48 @@ impl Coord3 { #[inline] pub fn xy(self) -> Coord2 { - Coord2 { x: self.x, y: self.y } + Coord2 { + x: self.x, + y: self.y, + } } fn to_raw(self, (dim_z, dim_y, dim_x): (usize, usize, usize)) -> (usize, usize, usize) { - assert!(self.x >= 1 && self.x <= dim_x as i32, "x={} not in [1, {}]", self.x, dim_x); - assert!(self.y >= 1 && self.y <= dim_y as i32, "y={} not in [1, {}]", self.y, dim_y); - assert!(self.z >= 1 && self.z <= dim_z as i32, "y={} not in [1, {}]", self.z, dim_z); - (self.z as usize - 1, dim_y - self.y as usize, self.x as usize - 1) + assert!( + self.x >= 1 && self.x <= dim_x as i32, + "x={} not in [1, {}]", + self.x, + dim_x + ); + assert!( + self.y >= 1 && self.y <= dim_y as i32, + "y={} not in [1, {}]", + self.y, + dim_y + ); + assert!( + self.z >= 1 && self.z <= dim_z as i32, + "y={} not in [1, {}]", + self.z, + dim_z + ); + ( + self.z as usize - 1, + dim_y - self.y as usize, + self.x as usize - 1, + ) } #[allow(dead_code)] - fn from_raw((z, y, x): (usize, usize, usize), (_dim_z, dim_y, _dim_x): (usize, usize, usize)) -> Coord3 { - Coord3 { x: x as i32 + 1, y: (dim_y - y) as i32, z: z as i32 + 1 } + fn from_raw( + (z, y, x): (usize, usize, usize), + (_dim_z, dim_y, _dim_x): (usize, usize, usize), + ) -> Coord3 { + Coord3 { + x: x as i32 + 1, + y: (dim_y - y) as i32, + z: z as i32 + 1, + } } } @@ -149,12 +198,12 @@ impl Map { assert!(x > 0 && y > 0 && z > 0, "({x}, {y}, {z})"); let mut dictionary = BTreeMap::new(); - dictionary.insert(Key(0), vec![ - Prefab::from_path(turf), - Prefab::from_path(area), - ]); + dictionary.insert( + Key(0), + vec![Prefab::from_path(turf), Prefab::from_path(area)], + ); - let grid = Array3::default((z, y, x)); // default = 0 + let grid = Array3::default((z, y, x)); // default = 0 Map { key_length: 1, @@ -219,11 +268,16 @@ impl Map { #[inline] pub fn z_level(&self, z: usize) -> ZLevel<'_> { - ZLevel { grid: self.grid.index_axis(Axis(0), z) } + ZLevel { + grid: self.grid.index_axis(Axis(0), z), + } } - pub fn iter_levels(&self) -> impl Iterator)> + '_ { - self.grid.axis_iter(Axis(0)).enumerate().map(|(i, grid)| (i as i32 + 1, ZLevel { grid })) + pub fn iter_levels(&self) -> impl Iterator)> + '_ { + self.grid + .axis_iter(Axis(0)) + .enumerate() + .map(|(i, grid)| (i as i32 + 1, ZLevel { grid })) } #[inline] @@ -243,9 +297,11 @@ impl std::ops::Index for Map { impl<'a> ZLevel<'a> { /// Iterate over the z-level in row-major order starting at the top-left. - pub fn iter_top_down(&self) -> impl Iterator + '_ { + pub fn iter_top_down(&self) -> impl Iterator + '_ { let dim = self.grid.dim(); - self.grid.indexed_iter().map(move |(c, k)| (Coord2::from_raw(c, dim), *k)) + self.grid + .indexed_iter() + .map(move |(c, k)| (Coord2::from_raw(c, dim), *k)) } } @@ -349,8 +405,11 @@ fn base_52_reverse(ch: u8) -> Result { } fn advance_key(current: KeyType, next_digit: KeyType) -> Result { - current.checked_mul(52).and_then(|b| b.checked_add(next_digit)).ok_or({ - // https://www.byond.com/forum/?post=2340796#comment23770802 - "Key overflow, max is 'ymo'" - }) + current + .checked_mul(52) + .and_then(|b| b.checked_add(next_digit)) + .ok_or({ + // https://www.byond.com/forum/?post=2340796#comment23770802 + "Key overflow, max is 'ymo'" + }) } diff --git a/crates/dmm-tools/src/dmm/read.rs b/crates/dmm-tools/src/dmm/read.rs index eb7f5916..1885a701 100644 --- a/crates/dmm-tools/src/dmm/read.rs +++ b/crates/dmm-tools/src/dmm/read.rs @@ -41,7 +41,7 @@ pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { if curr_datum.is_empty() { curr_datum_start_location = chars.location(); } - } + }; } macro_rules! insert_current_var { @@ -49,9 +49,17 @@ pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { curr_prefab.vars.insert( from_utf8_or_latin1(take(&mut curr_var)), dm::constants::evaluate_str(curr_datum_start_location, &take(&mut curr_datum)) - .map_err(|e| e.with_note(curr_key_start_location, format!("within key: \"{}\"", super::FormatKey(curr_key_length, super::Key(curr_key)))))? + .map_err(|e| { + e.with_note( + curr_key_start_location, + format!( + "within key: \"{}\"", + super::FormatKey(curr_key_length, super::Key(curr_key)) + ), + ) + })?, ); - } + }; } while let Some(ch) = chars.next() { @@ -97,7 +105,8 @@ pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { set_curr_datum_start_location!(); curr_datum.push(ch); } - } else { // in_quote_block + } else { + // in_quote_block if skip_whitespace && ch == b' ' { skip_whitespace = false; continue; @@ -211,7 +220,10 @@ pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { max_y = max(max_y, curr_y); reading_coord = Coord::Z; } else { - return Err(DMError::new(chars.location(), "Incorrect number of coordinates")); + return Err(DMError::new( + chars.location(), + "Incorrect number of coordinates", + )); } } else if ch == b')' { assert_eq!(reading_coord, Coord::Z); @@ -222,7 +234,12 @@ pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { } else { match (ch as char).to_digit(10) { Some(x) => curr_num = 10 * curr_num + x as usize, - None => return Err(DMError::new(chars.location(), format!("bad digit {ch:?} in map coordinate"))), + None => { + return Err(DMError::new( + chars.location(), + format!("bad digit {ch:?} in map coordinate"), + )) + }, } } } else if in_map_string { @@ -246,8 +263,10 @@ pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { let key = take(&mut curr_key); curr_key_length = 0; if grid.insert((curr_x, curr_y, curr_z), Key(key)).is_some() { - return Err(DMError::new(chars.location(), format!( - "multiple entries for ({curr_x}, {curr_y}, {curr_z})"))) + return Err(DMError::new( + chars.location(), + format!("multiple entries for ({curr_x}, {curr_y}, {curr_z})"), + )); } max_x = max(max_x, curr_x); curr_x += 1; @@ -266,9 +285,10 @@ pub fn parse_map(map: &mut Map, path: &std::path::Path) -> Result<(), DMError> { if let Some(&tile) = grid.get(&(x + 1, y + 1, z + 1)) { tile } else { - result = Err(DMError::new(chars.location(), format!( - "no value for tile ({}, {}, {})", - x + 1, y + 1, z + 1))); + result = Err(DMError::new( + chars.location(), + format!("no value for tile ({}, {}, {})", x + 1, y + 1, z + 1), + )); Key(0) } }); @@ -282,6 +302,6 @@ fn advance_key(loc: Location, curr_key: KeyType, ch: u8) -> Result match super::advance_key(curr_key, single) { Err(err) => Err(DMError::new(loc, err)), Ok(key) => Ok(key), - } + }, } } diff --git a/crates/dmm-tools/src/dmm/save_tgm.rs b/crates/dmm-tools/src/dmm/save_tgm.rs index b3f2996c..a43b5fce 100644 --- a/crates/dmm-tools/src/dmm/save_tgm.rs +++ b/crates/dmm-tools/src/dmm/save_tgm.rs @@ -5,7 +5,8 @@ use ndarray::Axis; use super::Map; -const TGM_HEADER: &str = "//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE"; +const TGM_HEADER: &str = + "//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE"; // Note: writeln! currently (2022-04-30) writes the \n character alone on all platforms // If that changes, this will break. diff --git a/crates/dmm-tools/src/icon_cache.rs b/crates/dmm-tools/src/icon_cache.rs index 63b63d16..38f6e667 100644 --- a/crates/dmm-tools/src/icon_cache.rs +++ b/crates/dmm-tools/src/icon_cache.rs @@ -1,5 +1,5 @@ -use std::collections::{hash_map, HashMap}; use foldhash::fast::RandomState; +use std::collections::{hash_map, HashMap}; use std::path::{Path, PathBuf}; use std::sync::{Arc, RwLock}; @@ -16,12 +16,17 @@ impl IconCache { let map = self.lock.get_mut().unwrap(); (match map.entry(path.to_owned()) { hash_map::Entry::Occupied(entry) => entry.into_mut().as_mut(), - hash_map::Entry::Vacant(entry) => entry.insert( - match &self.icons_root { - Some(root) => load(&root.join(path)), - _ => load(path), - }.map(Arc::new)).as_mut(), - }).map(|x| &**x) + hash_map::Entry::Vacant(entry) => entry + .insert( + match &self.icons_root { + Some(root) => load(&root.join(path)), + _ => load(path), + } + .map(Arc::new), + ) + .as_mut(), + }) + .map(|x| &**x) } pub fn retrieve_shared(&self, path: &Path) -> Option> { @@ -33,8 +38,12 @@ impl IconCache { let arc = match &self.icons_root { Some(root) => load(&root.join(path)), None => load(path), - }.map(Arc::new); - self.lock.write().unwrap().insert(path.to_owned(), arc.clone()); + } + .map(Arc::new); + self.lock + .write() + .unwrap() + .insert(path.to_owned(), arc.clone()); arc }, } @@ -51,6 +60,6 @@ fn load(path: &Path) -> Option { Err(err) => { eprintln!("error loading icon: {}\n {}", path.display(), err); None - } + }, } } diff --git a/crates/dmm-tools/src/lib.rs b/crates/dmm-tools/src/lib.rs index f4c45ab7..319630f9 100644 --- a/crates/dmm-tools/src/lib.rs +++ b/crates/dmm-tools/src/lib.rs @@ -1,5 +1,5 @@ //! SS13 minimap generation tool -#![deny(unsafe_code)] // NB deny rather than forbid, ndarray macros use unsafe +#![deny(unsafe_code)] // NB deny rather than forbid, ndarray macros use unsafe extern crate dreammaker as dm; diff --git a/crates/dmm-tools/src/minimap.rs b/crates/dmm-tools/src/minimap.rs index 95a6d65d..881ef7f6 100644 --- a/crates/dmm-tools/src/minimap.rs +++ b/crates/dmm-tools/src/minimap.rs @@ -50,7 +50,10 @@ pub fn generate(ctx: Context, icon_cache: &IconCache) -> Result { // create atom arrays from the map dictionary let mut atoms = BTreeMap::new(); for (key, prefabs) in map.dictionary.iter() { - atoms.insert(key, get_atom_list(objtree, prefabs, render_passes, ctx.errors)); + atoms.insert( + key, + get_atom_list(objtree, prefabs, render_passes, ctx.errors), + ); } // loads atoms from the prefabs on the map and adds overlays and smoothing @@ -84,7 +87,7 @@ pub fn generate(ctx: Context, icon_cache: &IconCache) -> Result { println!("no icon: {}", atom.type_.path); continue; } - let atom = Atom { sprite, .. *atom }; + let atom = Atom { sprite, ..*atom }; for pass in render_passes { pass.overlays(&atom, objtree, &mut underlays, &mut overlays, bump); @@ -109,7 +112,13 @@ pub fn generate(ctx: Context, icon_cache: &IconCache) -> Result { let mut normal_appearance = true; for pass in render_passes { - if !pass.neighborhood_appearance(&atom, objtree, &neighborhood, &mut underlays, bump) { + if !pass.neighborhood_appearance( + &atom, + objtree, + &neighborhood, + &mut underlays, + bump, + ) { normal_appearance = false; } } @@ -158,7 +167,10 @@ pub fn generate(ctx: Context, icon_cache: &IconCache) -> Result { map_image.composite(&icon_file.image, loc, rect, sprite.color); } } else { - let key = format!("bad icon: {:?}, state: {:?}", sprite.icon, sprite.icon_state); + let key = format!( + "bad icon: {:?}, state: {:?}", + sprite.icon, sprite.icon_state + ); if !ctx.errors.read().unwrap().contains(&key) { eprintln!("{key}"); ctx.errors.write().unwrap().insert(key); @@ -170,7 +182,11 @@ pub fn generate(ctx: Context, icon_cache: &IconCache) -> Result { } // OOB handling -fn clip(bounds: dmi::Coordinate, mut loc: (i32, i32), mut rect: dmi::Rect) -> Option<(dmi::Coordinate, dmi::Rect)> { +fn clip( + bounds: dmi::Coordinate, + mut loc: (i32, i32), + mut rect: dmi::Rect, +) -> Option<(dmi::Coordinate, dmi::Rect)> { if loc.0 < 0 { rect.0 += (-loc.0) as u32; rect.2 = rect.2.checked_sub((-loc.0) as u32)?; @@ -217,7 +233,7 @@ fn get_atom_list<'a>( errors.write().unwrap().insert(key); } continue; - } + }, }; for pass in render_passes { @@ -315,7 +331,8 @@ pub trait GetVar<'a> { fn get_path(&self) -> &str; fn get_var(&self, key: &str, objtree: &'a ObjectTree) -> &'a Constant { - self.get_var_inner(key, objtree).unwrap_or_else(Constant::null) + self.get_var_inner(key, objtree) + .unwrap_or_else(Constant::null) } fn get_var_notnull(&self, key: &str, objtree: &'a ObjectTree) -> Option<&'a Constant> { @@ -423,13 +440,19 @@ impl From for Layer { impl From for Layer { fn from(whole: i32) -> Layer { use std::convert::TryFrom; - Layer { whole: i16::try_from(whole).expect("layer out of range"), frac: 0 } + Layer { + whole: i16::try_from(whole).expect("layer out of range"), + frac: 0, + } } } impl From for Layer { fn from(f: f32) -> Layer { - Layer { whole: f.floor() as i16, frac: ((f.fract() + 1.).fract() * 65536.) as u16 } + Layer { + whole: f.floor() as i16, + frac: ((f.fract() + 1.).fract() * 65536.) as u16, + } } } @@ -450,11 +473,11 @@ pub struct Sprite<'s> { pub icon: &'s str, pub icon_state: &'s str, pub dir: Dir, - pub color: [u8; 4], // [r, g, b, a] + pub color: [u8; 4], // [r, g, b, a] // position - pub ofs_x: i32, // pixel_x + pixel_w + step_x - pub ofs_y: i32, // pixel_y + pixel_z + step_y + pub ofs_x: i32, // pixel_x + pixel_w + step_x + pub ofs_y: i32, // pixel_y + pixel_z + step_y // sorting pub plane: i32, @@ -473,7 +496,11 @@ impl<'s> Sprite<'s> { Sprite { icon: vars.get_var("icon", objtree).as_path_str().unwrap_or(""), icon_state: vars.get_var("icon_state", objtree).as_str().unwrap_or(""), - dir: vars.get_var("dir", objtree).to_int().and_then(Dir::from_int).unwrap_or_default(), + dir: vars + .get_var("dir", objtree) + .to_int() + .and_then(Dir::from_int) + .unwrap_or_default(), color: color_of(objtree, vars), ofs_x: pixel_x + pixel_w + step_x, ofs_y: pixel_y + pixel_z + step_y, @@ -504,7 +531,7 @@ fn plane_of<'s, T: GetVar<'s> + ?Sized>(objtree: &'s ObjectTree, atom: &T) -> i3 other => { eprintln!("not a plane: {:?} on {:?}", other, atom.get_path()); 0 - } + }, } } @@ -514,7 +541,7 @@ pub(crate) fn layer_of<'s, T: GetVar<'s> + ?Sized>(objtree: &'s ObjectTree, atom other => { eprintln!("not a layer: {:?} on {:?}", other, atom.get_path()); Layer::from(2) - } + }, } } @@ -530,9 +557,11 @@ pub fn color_of<'s, T: GetVar<'s> + ?Sized>(objtree: &'s ObjectTree, atom: &T) - for ch in color[1..color.len()].chars() { sum = 16 * sum + ch.to_digit(16).unwrap_or(0); } - if color.len() == 7 { // #rrggbb + if color.len() == 7 { + // #rrggbb [(sum >> 16) as u8, (sum >> 8) as u8, sum as u8, alpha] - } else if color.len() == 4 { // #rgb + } else if color.len() == 4 { + // #rgb [ (0x11 * ((sum >> 8) & 0xf)) as u8, (0x11 * ((sum >> 4) & 0xf)) as u8, @@ -540,13 +569,13 @@ pub fn color_of<'s, T: GetVar<'s> + ?Sized>(objtree: &'s ObjectTree, atom: &T) - alpha, ] } else { - [255, 255, 255, alpha] // invalid + [255, 255, 255, alpha] // invalid } - } + }, Constant::String(ref color) => match html_color(color) { Some([r, g, b]) => [r, g, b, alpha], None => [255, 255, 255, alpha], - } + }, // TODO: color matrix support? _ => [255, 255, 255, alpha], } diff --git a/crates/dmm-tools/src/render_passes/icon_smoothing.rs b/crates/dmm-tools/src/render_passes/icon_smoothing.rs index 5302708a..3c92ae23 100644 --- a/crates/dmm-tools/src/render_passes/icon_smoothing.rs +++ b/crates/dmm-tools/src/render_passes/icon_smoothing.rs @@ -17,10 +17,10 @@ const N_NORTHWEST: i32 = 512; const N_SOUTHEAST: i32 = 64; const N_SOUTHWEST: i32 = 1024; -const SMOOTH_TRUE: i32 = 1; // smooth with exact specified types or just itself -const SMOOTH_MORE: i32 = 2; // smooth with all subtypes thereof -const SMOOTH_DIAGONAL: i32 = 4; // smooth diagonally -const SMOOTH_BORDER: i32 = 8; // smooth with the borders of the map +const SMOOTH_TRUE: i32 = 1; // smooth with exact specified types or just itself +const SMOOTH_MORE: i32 = 2; // smooth with all subtypes thereof +const SMOOTH_DIAGONAL: i32 = 4; // smooth diagonally +const SMOOTH_BORDER: i32 = 8; // smooth with the borders of the map pub struct IconSmoothing { pub mask: i32, @@ -33,7 +33,8 @@ impl Default for IconSmoothing { } impl RenderPass for IconSmoothing { - fn adjust_sprite<'a>(&self, + fn adjust_sprite<'a>( + &self, atom: &Atom<'a>, sprite: &mut Sprite<'a>, _objtree: &'a ObjectTree, @@ -45,7 +46,8 @@ impl RenderPass for IconSmoothing { } } - fn neighborhood_appearance<'a>(&self, + fn neighborhood_appearance<'a>( + &self, atom: &Atom<'a>, objtree: &'a ObjectTree, neighborhood: &Neighborhood<'a, '_>, @@ -67,7 +69,12 @@ impl RenderPass for IconSmoothing { } } -fn calculate_adjacencies(objtree: &ObjectTree, neighborhood: &Neighborhood, atom: &Atom, smooth_flags: i32) -> i32 { +fn calculate_adjacencies( + objtree: &ObjectTree, + neighborhood: &Neighborhood, + atom: &Atom, + smooth_flags: i32, +) -> i32 { // TODO: anchored check let mut adjacencies = 0; @@ -103,29 +110,37 @@ fn calculate_adjacencies(objtree: &ObjectTree, neighborhood: &Neighborhood, atom adjacencies } -fn find_type_in_direction(objtree: &ObjectTree, adjacency: &Neighborhood, source: &Atom, direction: Dir, smooth_flags: i32) -> bool { +fn find_type_in_direction( + objtree: &ObjectTree, + adjacency: &Neighborhood, + source: &Atom, + direction: Dir, + smooth_flags: i32, +) -> bool { let atom_list = adjacency.offset(direction); if atom_list.is_empty() { return smooth_flags & SMOOTH_BORDER != 0; } match source.get_var("canSmoothWith", objtree) { - Constant::List(elements) => if smooth_flags & SMOOTH_MORE != 0 { - // smooth with canSmoothWith + subtypes - for atom in atom_list { - let mut path = atom.get_path(); - while !path.is_empty() { - if smoothlist_contains(elements, path) { + Constant::List(elements) => { + if smooth_flags & SMOOTH_MORE != 0 { + // smooth with canSmoothWith + subtypes + for atom in atom_list { + let mut path = atom.get_path(); + while !path.is_empty() { + if smoothlist_contains(elements, path) { + return true; + } + path = &path[..path.rfind('/').unwrap()]; + } + } + } else { + // smooth only with exact types in canSmoothWith + for atom in atom_list { + if smoothlist_contains(elements, atom.get_path()) { return true; } - path = &path[..path.rfind('/').unwrap()]; - } - } - } else { - // smooth only with exact types in canSmoothWith - for atom in atom_list { - if smoothlist_contains(elements, atom.get_path()) { - return true; } } }, @@ -150,7 +165,13 @@ fn smoothlist_contains(list: &[(Constant, Option)], desired: &str) -> false } -fn cardinal_smooth<'a>(output: &mut Vec>, objtree: &'a ObjectTree, bump: &'a bumpalo::Bump, source: &Atom<'a>, adjacencies: i32) { +fn cardinal_smooth<'a>( + output: &mut Vec>, + objtree: &'a ObjectTree, + bump: &'a bumpalo::Bump, + source: &Atom<'a>, + adjacencies: i32, +) { for &(what, f1, n1, f2, n2, f3) in &[ ("1", N_NORTH, "n", N_WEST, "w", N_NORTHWEST), ("2", N_NORTH, "n", N_EAST, "e", N_NORTHEAST), @@ -173,7 +194,7 @@ fn cardinal_smooth<'a>(output: &mut Vec>, objtree: &'a ObjectTree, bu let mut sprite = Sprite { icon_state: name.into_bump_str(), - .. source.sprite + ..source.sprite }; if let Some(icon) = source.get_var("smooth_icon", objtree).as_path_str() { sprite.icon = icon; @@ -182,7 +203,14 @@ fn cardinal_smooth<'a>(output: &mut Vec>, objtree: &'a ObjectTree, bu } } -fn diagonal_smooth<'a>(output: &mut Vec>, objtree: &'a ObjectTree, bump: &'a bumpalo::Bump, neighborhood: &Neighborhood<'a, '_>, source: &Atom<'a>, adjacencies: i32) { +fn diagonal_smooth<'a>( + output: &mut Vec>, + objtree: &'a ObjectTree, + bump: &'a bumpalo::Bump, + neighborhood: &Neighborhood<'a, '_>, + source: &Atom<'a>, + adjacencies: i32, +) { let presets = if adjacencies == N_NORTH | N_WEST { ["d-se", "d-se-0"] } else if adjacencies == N_NORTH | N_EAST { @@ -211,7 +239,10 @@ fn diagonal_smooth<'a>(output: &mut Vec>, objtree: &'a ObjectTree, bu .index(&Constant::string("space")) .is_some() { - output.push(Sprite::from_vars(objtree, &objtree.expect("/turf/open/space/basic"))); + output.push(Sprite::from_vars( + objtree, + &objtree.expect("/turf/open/space/basic"), + )); } else { let dir = reverse_ndir(adjacencies).flip(); let mut needs_plating = true; @@ -227,7 +258,10 @@ fn diagonal_smooth<'a>(output: &mut Vec>, objtree: &'a ObjectTree, bu } } if needs_plating { - output.push(Sprite::from_vars(objtree, &objtree.expect("/turf/open/floor/plating"))); + output.push(Sprite::from_vars( + objtree, + &objtree.expect("/turf/open/floor/plating"), + )); } } } @@ -236,7 +270,7 @@ fn diagonal_smooth<'a>(output: &mut Vec>, objtree: &'a ObjectTree, bu for &each in presets.iter() { let mut copy = Sprite { icon_state: each, - .. source.sprite + ..source.sprite }; if let Some(icon) = source.get_var("smooth_icon", objtree).as_path_str() { copy.icon = icon; diff --git a/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs b/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs index 3373d45e..aff702f3 100644 --- a/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs +++ b/crates/dmm-tools/src/render_passes/icon_smoothing_2020.rs @@ -41,7 +41,8 @@ impl Default for IconSmoothing { } impl RenderPass for IconSmoothing { - fn adjust_sprite<'a>(&self, + fn adjust_sprite<'a>( + &self, atom: &Atom<'a>, sprite: &mut Sprite<'a>, _objtree: &'a ObjectTree, @@ -53,14 +54,19 @@ impl RenderPass for IconSmoothing { } } - fn neighborhood_appearance<'a>(&self, + fn neighborhood_appearance<'a>( + &self, atom: &Atom<'a>, objtree: &'a ObjectTree, neighborhood: &Neighborhood<'a, '_>, output: &mut Vec>, bump: &'a bumpalo::Bump, ) -> bool { - let smooth_flags = self.mask & atom.get_var("smoothing_flags", objtree).to_int().unwrap_or(0); + let smooth_flags = self.mask + & atom + .get_var("smoothing_flags", objtree) + .to_int() + .unwrap_or(0); if smooth_flags & SMOOTH_CORNERS != 0 { let adjacencies = calculate_adjacencies(objtree, neighborhood, atom, smooth_flags); if smooth_flags & SMOOTH_DIAGONAL_CORNERS != 0 { @@ -71,7 +77,15 @@ impl RenderPass for IconSmoothing { false } else if smooth_flags & SMOOTH_BITMASK != 0 { let adjacencies = calculate_adjacencies(objtree, neighborhood, atom, smooth_flags); - bitmask_smooth(output, objtree, bump, neighborhood, atom, adjacencies, smooth_flags) + bitmask_smooth( + output, + objtree, + bump, + neighborhood, + atom, + adjacencies, + smooth_flags, + ) } else { true } @@ -81,11 +95,18 @@ impl RenderPass for IconSmoothing { // ---------------------------------------------------------------------------- // Older cardinal smoothing system -fn calculate_adjacencies(objtree: &ObjectTree, neighborhood: &Neighborhood, atom: &Atom, smooth_flags: i32) -> i32 { +fn calculate_adjacencies( + objtree: &ObjectTree, + neighborhood: &Neighborhood, + atom: &Atom, + smooth_flags: i32, +) -> i32 { // Easier to read as a nested conditional #[allow(clippy::collapsible_if)] if atom.istype("/atom/movable/") { - if atom.get_var("can_be_unanchored", objtree).to_bool() && !atom.get_var("anchored", objtree).to_bool() { + if atom.get_var("can_be_unanchored", objtree).to_bool() + && !atom.get_var("anchored", objtree).to_bool() + { return 0; } } @@ -124,7 +145,13 @@ fn calculate_adjacencies(objtree: &ObjectTree, neighborhood: &Neighborhood, atom adjacencies } -fn find_type_in_direction(objtree: &ObjectTree, adjacency: &Neighborhood, source: &Atom, direction: Dir, smooth_flags: i32) -> bool { +fn find_type_in_direction( + objtree: &ObjectTree, + adjacency: &Neighborhood, + source: &Atom, + direction: Dir, + smooth_flags: i32, +) -> bool { let atom_list = adjacency.offset(direction); if atom_list.is_empty() { return smooth_flags & SMOOTH_BORDER != 0; @@ -155,12 +182,46 @@ fn find_type_in_direction(objtree: &ObjectTree, adjacency: &Neighborhood, source false } -fn cardinal_smooth<'a>(output: &mut Vec>, objtree: &'a ObjectTree, bump: &'a bumpalo::Bump, source: &Atom<'a>, adjacencies: i32) { +fn cardinal_smooth<'a>( + output: &mut Vec>, + objtree: &'a ObjectTree, + bump: &'a bumpalo::Bump, + source: &Atom<'a>, + adjacencies: i32, +) { for &(what, f1, n1, f2, n2, f3) in &[ - ("1", NORTH_JUNCTION, "n", WEST_JUNCTION, "w", NORTHWEST_JUNCTION), - ("2", NORTH_JUNCTION, "n", EAST_JUNCTION, "e", NORTHEAST_JUNCTION), - ("3", SOUTH_JUNCTION, "s", WEST_JUNCTION, "w", SOUTHWEST_JUNCTION), - ("4", SOUTH_JUNCTION, "s", EAST_JUNCTION, "e", SOUTHEAST_JUNCTION), + ( + "1", + NORTH_JUNCTION, + "n", + WEST_JUNCTION, + "w", + NORTHWEST_JUNCTION, + ), + ( + "2", + NORTH_JUNCTION, + "n", + EAST_JUNCTION, + "e", + NORTHEAST_JUNCTION, + ), + ( + "3", + SOUTH_JUNCTION, + "s", + WEST_JUNCTION, + "w", + SOUTHWEST_JUNCTION, + ), + ( + "4", + SOUTH_JUNCTION, + "s", + EAST_JUNCTION, + "e", + SOUTHEAST_JUNCTION, + ), ] { let name = if (adjacencies & f1 != 0) && (adjacencies & f2 != 0) { if (adjacencies & f3) != 0 { @@ -178,7 +239,7 @@ fn cardinal_smooth<'a>(output: &mut Vec>, objtree: &'a ObjectTree, bu let mut sprite = Sprite { icon_state: name.into_bump_str(), - .. source.sprite + ..source.sprite }; if let Some(icon) = source.get_var("smooth_icon", objtree).as_path_str() { sprite.icon = icon; @@ -187,7 +248,14 @@ fn cardinal_smooth<'a>(output: &mut Vec>, objtree: &'a ObjectTree, bu } } -fn diagonal_smooth<'a>(output: &mut Vec>, objtree: &'a ObjectTree, bump: &'a bumpalo::Bump, neighborhood: &Neighborhood<'a, '_>, source: &Atom<'a>, adjacencies: i32) { +fn diagonal_smooth<'a>( + output: &mut Vec>, + objtree: &'a ObjectTree, + bump: &'a bumpalo::Bump, + neighborhood: &Neighborhood<'a, '_>, + source: &Atom<'a>, + adjacencies: i32, +) { let presets = if adjacencies == NORTH_JUNCTION | WEST_JUNCTION { ["d-se", "d-se-0"] } else if adjacencies == NORTH_JUNCTION | EAST_JUNCTION { @@ -217,7 +285,7 @@ fn diagonal_smooth<'a>(output: &mut Vec>, objtree: &'a ObjectTree, bu for &each in presets.iter() { let mut copy = Sprite { icon_state: each, - .. source.sprite + ..source.sprite }; if let Some(icon) = source.get_var("smooth_icon", objtree).as_path_str() { copy.icon = icon; @@ -226,14 +294,23 @@ fn diagonal_smooth<'a>(output: &mut Vec>, objtree: &'a ObjectTree, bu } } -fn diagonal_underlay<'a>(output: &mut Vec>, objtree: &'a ObjectTree, neighborhood: &Neighborhood<'a, '_>, source: &Atom<'a>, adjacencies: i32) { +fn diagonal_underlay<'a>( + output: &mut Vec>, + objtree: &'a ObjectTree, + neighborhood: &Neighborhood<'a, '_>, + source: &Atom<'a>, + adjacencies: i32, +) { // BYOND memes if source .get_var("fixed_underlay", objtree) .index(&Constant::string("space")) .is_some() { - output.push(Sprite::from_vars(objtree, &objtree.expect("/turf/open/space/basic"))); + output.push(Sprite::from_vars( + objtree, + &objtree.expect("/turf/open/space/basic"), + )); } else if let Some(dir) = reverse_ndir(adjacencies) { let dir = dir.flip(); let mut needs_plating = true; @@ -249,7 +326,10 @@ fn diagonal_underlay<'a>(output: &mut Vec>, objtree: &'a ObjectTree, } } if needs_plating { - output.push(Sprite::from_vars(objtree, &objtree.expect("/turf/open/floor/plating"))); + output.push(Sprite::from_vars( + objtree, + &objtree.expect("/turf/open/floor/plating"), + )); } } } @@ -291,18 +371,27 @@ fn bitmask_smooth<'a>( ) -> bool { let mut diagonal = ""; if source.istype("/turf/open/floor/") { - if source.get_var("broken", objtree).to_bool() || source.get_var("burnt", objtree).to_bool() { - return true; // use original appearance + if source.get_var("broken", objtree).to_bool() || source.get_var("burnt", objtree).to_bool() + { + return true; // use original appearance } - } else if source.istype("/turf/closed/") && (smooth_flags & SMOOTH_DIAGONAL_CORNERS != 0) && reverse_ndir(smoothing_junction).is_some() { + } else if source.istype("/turf/closed/") + && (smooth_flags & SMOOTH_DIAGONAL_CORNERS != 0) + && reverse_ndir(smoothing_junction).is_some() + { diagonal_underlay(output, objtree, neighborhood, source, smoothing_junction); diagonal = "-d"; } - let base_icon_state = source.get_var("base_icon_state", objtree).as_str().unwrap_or(""); + let base_icon_state = source + .get_var("base_icon_state", objtree) + .as_str() + .unwrap_or(""); let mut sprite = Sprite { - icon_state: bumpalo::format!(in bump, "{}-{}{}", base_icon_state, smoothing_junction, diagonal).into_bump_str(), - .. source.sprite + icon_state: + bumpalo::format!(in bump, "{}-{}{}", base_icon_state, smoothing_junction, diagonal) + .into_bump_str(), + ..source.sprite }; if let Some(icon) = source.get_var("smooth_icon", objtree).as_path_str() { sprite.icon = icon; diff --git a/crates/dmm-tools/src/render_passes/mod.rs b/crates/dmm-tools/src/render_passes/mod.rs index b49c5630..a4119e8d 100644 --- a/crates/dmm-tools/src/render_passes/mod.rs +++ b/crates/dmm-tools/src/render_passes/mod.rs @@ -26,61 +26,69 @@ pub trait RenderPass: Sync { fn configure(&mut self, renderer_config: &dm::config::MapRenderer) {} /// Filter atoms based solely on their typepath. - fn path_filter(&self, - path: &str, - ) -> bool { true } + fn path_filter(&self, path: &str) -> bool { + true + } /// Filter atoms at the beginning of the process. /// /// Return `false` to discard the atom. - fn early_filter(&self, - atom: &Atom, - objtree: &ObjectTree, - ) -> bool { true } + fn early_filter(&self, atom: &Atom, objtree: &ObjectTree) -> bool { + true + } /// Expand atoms, such as spawners into the atoms they spawn. /// /// Return `false` to discard the original atom. - fn expand<'a>(&self, + fn expand<'a>( + &self, atom: &Atom<'a>, objtree: &'a ObjectTree, output: &mut Vec>, - ) -> bool { true } + ) -> bool { + true + } - fn adjust_sprite<'a>(&self, + fn adjust_sprite<'a>( + &self, atom: &Atom<'a>, sprite: &mut Sprite<'a>, objtree: &'a ObjectTree, - bump: &'a bumpalo::Bump, // TODO: kind of a hacky way to pass this - ) {} + bump: &'a bumpalo::Bump, // TODO: kind of a hacky way to pass this + ) { + } /// Apply overlays and underlays to an atom, in the form of pseudo-atoms. - fn overlays<'a>(&self, + fn overlays<'a>( + &self, atom: &Atom<'a>, objtree: &'a ObjectTree, underlays: &mut Vec>, overlays: &mut Vec>, - bump: &'a bumpalo::Bump, // TODO: kind of a hacky way to pass this - ) {} + bump: &'a bumpalo::Bump, // TODO: kind of a hacky way to pass this + ) { + } - fn neighborhood_appearance<'a>(&self, + fn neighborhood_appearance<'a>( + &self, atom: &Atom<'a>, objtree: &'a ObjectTree, neighborhood: &Neighborhood<'a, '_>, output: &mut Vec>, - bump: &'a bumpalo::Bump, // TODO: kind of a hacky way to pass this - ) -> bool { true } + bump: &'a bumpalo::Bump, // TODO: kind of a hacky way to pass this + ) -> bool { + true + } /// Filter atoms at the end of the process, after they have been taken into /// account by their neighbors. - fn late_filter(&self, - atom: &Atom, - objtree: &ObjectTree, - ) -> bool { true } + fn late_filter(&self, atom: &Atom, objtree: &ObjectTree) -> bool { + true + } - fn sprite_filter(&self, - sprite: &Sprite, - ) -> bool { true } + fn sprite_filter(&self, sprite: &Sprite) -> bool { + true + } } pub struct RenderPassInfo { @@ -91,40 +99,120 @@ pub struct RenderPassInfo { } macro_rules! pass { - ($typ:ty, $name:expr, $desc:expr, $def:expr) => (RenderPassInfo { - name: $name, - desc: $desc, - default: $def, - new: || Box::<$typ>::default() - }) + ($typ:ty, $name:expr, $desc:expr, $def:expr) => { + RenderPassInfo { + name: $name, + desc: $desc, + default: $def, + new: || Box::<$typ>::default(), + } + }; } pub const RENDER_PASSES: &[RenderPassInfo] = &[ - pass!(HideSpace, "hide-space", "Do not render space tiles, instead leaving transparency.", true), + pass!( + HideSpace, + "hide-space", + "Do not render space tiles, instead leaving transparency.", + true + ), pass!(HideAreas, "hide-areas", "Do not render area icons.", true), - pass!(HideInvisible, "hide-invisible", "Do not render invisible or ephemeral objects such as mapping helpers.", true), - pass!(Random, "random", "Replace random spawners with one of their possibilities.", true), - pass!(Pretty, "pretty", "Add the minor cosmetic overlays for various objects.", true), - pass!(Spawners, "spawners", "Replace object spawners with their spawned objects.", true), - pass!(Overlays, "overlays", "Add overlays and underlays to atoms which usually have them.", true), - pass!(TransitTube, "transit-tube", "Add overlays to connect transit tubes together.", true), - pass!(GravityGen, "gravity-gen", "Expand the gravity generator to the full structure.", true), + pass!( + HideInvisible, + "hide-invisible", + "Do not render invisible or ephemeral objects such as mapping helpers.", + true + ), + pass!( + Random, + "random", + "Replace random spawners with one of their possibilities.", + true + ), + pass!( + Pretty, + "pretty", + "Add the minor cosmetic overlays for various objects.", + true + ), + pass!( + Spawners, + "spawners", + "Replace object spawners with their spawned objects.", + true + ), + pass!( + Overlays, + "overlays", + "Add overlays and underlays to atoms which usually have them.", + true + ), + pass!( + TransitTube, + "transit-tube", + "Add overlays to connect transit tubes together.", + true + ), + pass!( + GravityGen, + "gravity-gen", + "Expand the gravity generator to the full structure.", + true + ), pass!(Wires, "only-powernet", "Render only power cables.", false), - pass!(Pipes, "only-pipenet", "Render only atmospheric pipes.", false), - pass!(FancyLayers, "fancy-layers", "Layer atoms according to in-game rules.", true), - pass!(IconSmoothing2016, "icon-smoothing-2016", "Emulate the icon smoothing subsystem (xxalpha, 2016).", false), - pass!(IconSmoothing, "icon-smoothing", "Emulate the icon smoothing subsystem (Rohesie, 2020).", true), - pass!(SmartCables, "smart-cables", "Handle smart cable layout.", true), - pass!(WiresAndPipes, "only-wires-and-pipes", "Renders only power cables and atmospheric pipes.", false), + pass!( + Pipes, + "only-pipenet", + "Render only atmospheric pipes.", + false + ), + pass!( + FancyLayers, + "fancy-layers", + "Layer atoms according to in-game rules.", + true + ), + pass!( + IconSmoothing2016, + "icon-smoothing-2016", + "Emulate the icon smoothing subsystem (xxalpha, 2016).", + false + ), + pass!( + IconSmoothing, + "icon-smoothing", + "Emulate the icon smoothing subsystem (Rohesie, 2020).", + true + ), + pass!( + SmartCables, + "smart-cables", + "Handle smart cable layout.", + true + ), + pass!( + WiresAndPipes, + "only-wires-and-pipes", + "Renders only power cables and atmospheric pipes.", + false + ), ]; -pub fn configure(renderer_config: &dm::config::MapRenderer, include: &str, exclude: &str) -> Vec> { +pub fn configure( + renderer_config: &dm::config::MapRenderer, + include: &str, + exclude: &str, +) -> Vec> { let include: Vec<&str> = include.split(',').collect(); let exclude: Vec<&str> = exclude.split(',').collect(); configure_list(renderer_config, &include, &exclude) } -pub fn configure_list>(renderer_config: &dm::config::MapRenderer, include: &[T], exclude: &[T]) -> Vec> { +pub fn configure_list>( + renderer_config: &dm::config::MapRenderer, + include: &[T], + exclude: &[T], +) -> Vec> { let include_all = include.iter().any(|name| name.as_ref() == "all"); let exclude_all = exclude.iter().any(|name| name.as_ref() == "all"); @@ -155,14 +243,15 @@ pub fn configure_list>(renderer_config: &dm::config::MapRenderer, fn add_to<'a>(target: &mut Vec>, atom: &Atom<'a>, icon_state: &'a str) { target.push(Sprite { icon_state, - .. atom.sprite + ..atom.sprite }); } #[derive(Default)] pub struct HideSpace; impl RenderPass for HideSpace { - fn expand<'a>(&self, + fn expand<'a>( + &self, atom: &Atom<'a>, objtree: &'a ObjectTree, output: &mut Vec>, @@ -201,7 +290,8 @@ impl RenderPass for HideInvisible { fn configure(&mut self, renderer_config: &dm::config::MapRenderer) { self.overrides.clone_from(&renderer_config.hide_invisible); // Put longer typepaths earlier in the list so that `/foo/bar` can override `/foo`. - self.overrides.sort_unstable_by_key(|k| usize::MAX - k.len()); + self.overrides + .sort_unstable_by_key(|k| usize::MAX - k.len()); // Append `/` to each typepath for faster starts_with later. for key in self.overrides.iter_mut() { if !key.ends_with('/') { @@ -224,14 +314,18 @@ impl RenderPass for HideInvisible { } } // invisible objects and syndicate balloons are not to show - if atom.get_var("invisibility", objtree).to_float().unwrap_or(0.) > 60. || - atom.istype("/obj/effect/mapping_helpers/") + if atom + .get_var("invisibility", objtree) + .to_float() + .unwrap_or(0.) + > 60. + || atom.istype("/obj/effect/mapping_helpers/") { return false; } - if atom.get_var("icon", objtree) == "icons/obj/items_and_weapons.dmi" && - atom.get_var("icon_state", objtree) == "syndballoon" && - !atom.istype("/obj/item/toy/syndicateballoon/") + if atom.get_var("icon", objtree) == "icons/obj/items_and_weapons.dmi" + && atom.get_var("icon_state", objtree) == "syndballoon" + && !atom.istype("/obj/item/toy/syndicateballoon/") { return false; } @@ -242,7 +336,8 @@ impl RenderPass for HideInvisible { #[derive(Default)] pub struct Overlays; impl RenderPass for Overlays { - fn adjust_sprite<'a>(&self, + fn adjust_sprite<'a>( + &self, atom: &Atom<'a>, sprite: &mut Sprite<'a>, objtree: &'a ObjectTree, @@ -252,12 +347,16 @@ impl RenderPass for Overlays { if atom.istype("/obj/machinery/power/apc/") { // auto-set pixel location - match atom.get_var("dir", objtree).to_int().and_then(Dir::from_int) { + match atom + .get_var("dir", objtree) + .to_int() + .and_then(Dir::from_int) + { Some(Dir::North) => sprite.ofs_y = 23, Some(Dir::South) => sprite.ofs_y = -23, Some(Dir::East) => sprite.ofs_x = 24, Some(Dir::West) => sprite.ofs_x = -25, - _ => {} + _ => {}, } } } @@ -275,12 +374,12 @@ impl RenderPass for Overlays { underlays.push(Sprite { icon: "icons/turf/floors.dmi", icon_state: "plating", - .. atom.sprite + ..atom.sprite }); underlays.push(Sprite { icon: "icons/obj/structures.dmi", icon_state: "grille", - .. atom.sprite + ..atom.sprite }); } else if atom.istype("/obj/structure/closet/") { // closet doors @@ -291,19 +390,29 @@ impl RenderPass for Overlays { "icon_state" }; if let Constant::String(door) = atom.get_var(var, objtree) { - add_to(overlays, atom, bumpalo::format!(in bump, "{}_open", door).into_bump_str()); + add_to( + overlays, + atom, + bumpalo::format!(in bump, "{}_open", door).into_bump_str(), + ); } } else { if let Constant::String(door) = atom .get_var_notnull("icon_door", objtree) .unwrap_or_else(|| atom.get_var("icon_state", objtree)) { - add_to(overlays, atom, bumpalo::format!(in bump, "{}_door", door).into_bump_str()); + add_to( + overlays, + atom, + bumpalo::format!(in bump, "{}_door", door).into_bump_str(), + ); } if atom.get_var("welded", objtree).to_bool() { add_to(overlays, atom, "welded"); } - if atom.get_var("secure", objtree).to_bool() && !atom.get_var("broken", objtree).to_bool() { + if atom.get_var("secure", objtree).to_bool() + && !atom.get_var("broken", objtree).to_bool() + { if atom.get_var("locked", objtree).to_bool() { add_to(overlays, atom, "locked"); } else { @@ -311,7 +420,9 @@ impl RenderPass for Overlays { } } } - } else if atom.istype("/obj/machinery/computer/") || atom.istype("/obj/machinery/power/solar_control/") { + } else if atom.istype("/obj/machinery/computer/") + || atom.istype("/obj/machinery/power/solar_control/") + { // computer screens and keyboards if let Some(screen) = atom.get_var("icon_screen", objtree).as_str() { add_to(overlays, atom, screen); @@ -325,7 +436,7 @@ impl RenderPass for Overlays { overlays.push(Sprite { icon: overlays_file, icon_state: "glass_closed", - .. atom.sprite + ..atom.sprite }) } } else { @@ -338,10 +449,12 @@ impl RenderPass for Overlays { } // APC terminals - let mut terminal = Sprite::from_vars(objtree, &objtree.expect("/obj/machinery/power/terminal")); + let mut terminal = + Sprite::from_vars(objtree, &objtree.expect("/obj/machinery/power/terminal")); terminal.dir = atom.sprite.dir; // TODO: un-hack this - FancyLayers::default().apply_fancy_layer("/obj/machinery/power/terminal", &mut terminal); + FancyLayers::default() + .apply_fancy_layer("/obj/machinery/power/terminal", &mut terminal); underlays.push(terminal); } } @@ -350,7 +463,8 @@ impl RenderPass for Overlays { #[derive(Default)] pub struct Pretty; impl RenderPass for Pretty { - fn adjust_sprite<'a>(&self, + fn adjust_sprite<'a>( + &self, atom: &Atom<'a>, sprite: &mut Sprite<'a>, _: &'a ObjectTree, @@ -361,18 +475,20 @@ impl RenderPass for Pretty { } } - fn overlays<'a>(&self, + fn overlays<'a>( + &self, atom: &Atom<'a>, objtree: &'a ObjectTree, _: &mut Vec>, overlays: &mut Vec>, _: &bumpalo::Bump, ) { - if atom.istype("/obj/item/storage/box/") && !atom.istype("/obj/item/storage/box/papersack/") { + if atom.istype("/obj/item/storage/box/") && !atom.istype("/obj/item/storage/box/papersack/") + { if let Some(icon_state) = atom.get_var("illustration", objtree).as_str() { overlays.push(Sprite { icon_state, - .. atom.sprite + ..atom.sprite }); } } else if atom.istype("/obj/machinery/firealarm/") { @@ -386,7 +502,7 @@ impl RenderPass for Pretty { 3 => add_to(overlays, atom, "oxygen-3"), 2 => add_to(overlays, atom, "oxygen-2"), 1 => add_to(overlays, atom, "oxygen-1"), - _ => {} + _ => {}, } } if let &Constant::Float(plasma) = atom.get_var("plasmatanks", objtree) { @@ -396,7 +512,7 @@ impl RenderPass for Pretty { 3 => add_to(overlays, atom, "plasma-3"), 2 => add_to(overlays, atom, "plasma-2"), 1 => add_to(overlays, atom, "plasma-1"), - _ => {} + _ => {}, } } } @@ -434,9 +550,14 @@ pub struct FancyLayers { impl RenderPass for FancyLayers { fn configure(&mut self, renderer_config: &dm::config::MapRenderer) { - self.overrides = renderer_config.fancy_layers.clone().into_iter().collect::>(); + self.overrides = renderer_config + .fancy_layers + .clone() + .into_iter() + .collect::>(); // Put longer typepaths earlier in the list so that `/foo/bar` can override `/foo`. - self.overrides.sort_unstable_by_key(|(k, _)| usize::MAX - k.len()); + self.overrides + .sort_unstable_by_key(|(k, _)| usize::MAX - k.len()); // Append `/` to each typepath for faster starts_with later. for (key, _) in self.overrides.iter_mut() { if !key.ends_with('/') { @@ -445,7 +566,8 @@ impl RenderPass for FancyLayers { } } - fn adjust_sprite<'a>(&self, + fn adjust_sprite<'a>( + &self, atom: &Atom<'a>, sprite: &mut Sprite<'a>, objtree: &'a ObjectTree, @@ -461,7 +583,8 @@ impl RenderPass for FancyLayers { } } - fn overlays<'a>(&self, + fn overlays<'a>( + &self, atom: &Atom<'a>, objtree: &'a ObjectTree, _underlays: &mut Vec>, @@ -475,7 +598,7 @@ impl RenderPass for FancyLayers { icon_state: aboveground, // use original layer, not modified layer above layer: crate::minimap::layer_of(objtree, atom), - .. atom.sprite + ..atom.sprite }); } } @@ -487,7 +610,10 @@ fn unary_aboveground(atom: &Atom, objtree: &ObjectTree) -> Option<&'static str> Constant::String(text) => match &**text { "vent_map-1" | "vent_map-2" | "vent_map-3" | "vent_map-4" => "vent_off", "vent_map_on-1" | "vent_map_on-2" | "vent_map_on-3" | "vent_map_on-4" => "vent_out", - "vent_map_siphon_on-1" | "vent_map_siphon_on-2" | "vent_map_siphon_on-3" | "vent_map_siphon_on-4" => "vent_in", + "vent_map_siphon_on-1" + | "vent_map_siphon_on-2" + | "vent_map_siphon_on-3" + | "vent_map_siphon_on-4" => "vent_in", "scrub_map-1" | "scrub_map-2" | "scrub_map-3" | "scrub_map-4" => "scrub_off", "scrub_map_on-1" | "scrub_map_on-2" | "scrub_map_on-3" | "scrub_map_on-4" => "scrub_on", _ => return None, @@ -505,15 +631,15 @@ impl FancyLayers { } if ispath(p, "/turf/open/floor/plating/") || ispath(p, "/turf/open/space/") { - Some(Layer::from(-10)) // under everything + Some(Layer::from(-10)) // under everything } else if ispath(p, "/turf/closed/mineral/") { - Some(Layer::from(-3)) // above hidden stuff and plating but below walls + Some(Layer::from(-3)) // above hidden stuff and plating but below walls } else if ispath(p, "/turf/open/floor/") || ispath(p, "/turf/closed/") { - Some(Layer::from(-2)) // above hidden pipes and wires + Some(Layer::from(-2)) // above hidden pipes and wires } else if ispath(p, "/turf/") { - Some(Layer::from(-10)) // under everything + Some(Layer::from(-10)) // under everything } else if ispath(p, "/obj/effect/turf_decal/") { - Some(Layer::from(-1)) // above turfs + Some(Layer::from(-1)) // above turfs } else if ispath(p, "/obj/structure/disposalpipe/") { Some(Layer::from(-6)) } else if ispath(p, "/obj/machinery/atmospherics/pipe/") && !p.contains("visible") { diff --git a/crates/dmm-tools/src/render_passes/random.rs b/crates/dmm-tools/src/render_passes/random.rs index 3ca1bbec..30f81b7c 100644 --- a/crates/dmm-tools/src/render_passes/random.rs +++ b/crates/dmm-tools/src/render_passes/random.rs @@ -6,7 +6,8 @@ use rand::Rng; #[derive(Default)] pub struct Random; impl RenderPass for Random { - fn expand<'a>(&self, + fn expand<'a>( + &self, atom: &Atom<'a>, objtree: &'a ObjectTree, output: &mut Vec>, @@ -23,7 +24,7 @@ impl RenderPass for Random { } if let Some(&replacement) = machines.choose(&mut rng) { output.push(Atom::from(replacement)); - return false; // consumed + return false; // consumed } } } else if atom.istype("/obj/machinery/vending/cola/random/") { @@ -36,12 +37,12 @@ impl RenderPass for Random { } if let Some(&replacement) = machines.choose(&mut rng) { output.push(Atom::from(replacement)); - return false; // consumed + return false; // consumed } } } else if atom.istype("/obj/item/bedsheet/random/") { if let Some(root) = objtree.find("/obj/item/bedsheet") { - let mut sheets = vec![root.get()]; // basic bedsheet is included + let mut sheets = vec![root.get()]; // basic bedsheet is included for child in root.children() { if child.name() != "random" { sheets.push(child.get()); @@ -49,7 +50,7 @@ impl RenderPass for Random { } if let Some(&replacement) = sheets.choose(&mut rng) { output.push(Atom::from(replacement)); - return false; // consumed + return false; // consumed } } } else if atom.istype("/obj/effect/spawner/lootdrop/") { @@ -83,12 +84,13 @@ impl RenderPass for Random { loot_spawned += 1; } } - return false; // consumed + return false; // consumed } true } - fn adjust_sprite<'a>(&self, + fn adjust_sprite<'a>( + &self, atom: &Atom<'a>, sprite: &mut Sprite<'a>, objtree: &'a ObjectTree, @@ -100,23 +102,32 @@ impl RenderPass for Random { const LEGIT_POSTERS: u32 = 35; if atom.istype("/obj/structure/sign/poster/contraband/random/") { - sprite.icon_state = bumpalo::format!(in bump, "poster{}", rng.gen_range(1..=CONTRABAND_POSTERS)).into_bump_str(); + sprite.icon_state = + bumpalo::format!(in bump, "poster{}", rng.gen_range(1..=CONTRABAND_POSTERS)) + .into_bump_str(); } else if atom.istype("/obj/structure/sign/poster/official/random/") { - sprite.icon_state = bumpalo::format!(in bump, "poster{}_legit", rng.gen_range(1..=LEGIT_POSTERS)).into_bump_str(); + sprite.icon_state = + bumpalo::format!(in bump, "poster{}_legit", rng.gen_range(1..=LEGIT_POSTERS)) + .into_bump_str(); } else if atom.istype("/obj/structure/sign/poster/random/") { let i = 1 + rng.gen_range(0..CONTRABAND_POSTERS + LEGIT_POSTERS); if i <= CONTRABAND_POSTERS { sprite.icon_state = bumpalo::format!(in bump, "poster{}", i).into_bump_str(); } else { - sprite.icon_state = bumpalo::format!(in bump, "poster{}_legit", i - CONTRABAND_POSTERS).into_bump_str(); + sprite.icon_state = + bumpalo::format!(in bump, "poster{}_legit", i - CONTRABAND_POSTERS) + .into_bump_str(); } - } else if atom.istype("/obj/item/kirbyplants/random/") || atom.istype("/obj/item/twohanded/required/kirbyplants/random/") { + } else if atom.istype("/obj/item/kirbyplants/random/") + || atom.istype("/obj/item/twohanded/required/kirbyplants/random/") + { sprite.icon = "icons/obj/flora/plants.dmi"; let random = rng.gen_range(0..26); if random == 0 { sprite.icon_state = "applebush"; } else { - sprite.icon_state = bumpalo::format!(in bump, "plant-{:02}", random).into_bump_str(); + sprite.icon_state = + bumpalo::format!(in bump, "plant-{:02}", random).into_bump_str(); } } else if atom.istype("/obj/structure/sign/barsign/") { if let Some(root) = objtree.find("/datum/barsign") { @@ -140,7 +151,7 @@ impl RenderPass for Random { } } } else if atom.istype("/obj/item/relic/") { - sprite.icon_state = [ + sprite.icon_state = [ "shock_kit", "armor-igniter-analyzer", "infra-igniter0", @@ -150,7 +161,9 @@ impl RenderPass for Random { "radio-radio", "timer-multitool0", "radio-igniter-tank", - ].choose(&mut rng).unwrap(); + ] + .choose(&mut rng) + .unwrap(); } if atom.istype("/obj/item/lipstick/random/") { @@ -163,16 +176,30 @@ impl RenderPass for Random { "tape_red", "tape_yellow", "tape_purple", - ].choose(&mut rng).unwrap(); + ] + .choose(&mut rng) + .unwrap(); } } } fn pickweight<'a>(list: &[&'a (Constant, Option)]) -> &'a Constant { - let mut total: i32 = list.iter().map(|(_, v)| v.as_ref().unwrap_or_else(Constant::null).to_int().unwrap_or(1)).sum(); + let mut total: i32 = list + .iter() + .map(|(_, v)| { + v.as_ref() + .unwrap_or_else(Constant::null) + .to_int() + .unwrap_or(1) + }) + .sum(); total = rand::thread_rng().gen_range(1..=total); for (k, v) in list.iter() { - total -= v.as_ref().unwrap_or_else(Constant::null).to_int().unwrap_or(1); + total -= v + .as_ref() + .unwrap_or_else(Constant::null) + .to_int() + .unwrap_or(1); if total <= 0 { return k; } diff --git a/crates/dmm-tools/src/render_passes/smart_cables.rs b/crates/dmm-tools/src/render_passes/smart_cables.rs index 8cae1a0c..bc6c717a 100644 --- a/crates/dmm-tools/src/render_passes/smart_cables.rs +++ b/crates/dmm-tools/src/render_passes/smart_cables.rs @@ -1,12 +1,13 @@ -use std::fmt::Write; -use crate::dmi::Dir; use super::*; +use crate::dmi::Dir; +use std::fmt::Write; #[derive(Default)] pub struct SmartCables; impl RenderPass for SmartCables { - fn neighborhood_appearance<'a>(&self, + fn neighborhood_appearance<'a>( + &self, atom: &Atom<'a>, objtree: &'a ObjectTree, neighborhood: &Neighborhood<'a, '_>, @@ -17,7 +18,10 @@ impl RenderPass for SmartCables { return true; } - let cable_layer = atom.get_var("cable_layer", objtree).as_str().unwrap_or("l2"); + let cable_layer = atom + .get_var("cable_layer", objtree) + .as_str() + .unwrap_or("l2"); let mut under_smes = false; let mut under_terminal = false; @@ -83,7 +87,7 @@ impl RenderPass for SmartCables { output.push(Sprite { icon_state: icon_state.into_bump_str(), - .. atom.sprite + ..atom.sprite }); false } diff --git a/crates/dmm-tools/src/render_passes/structures.rs b/crates/dmm-tools/src/render_passes/structures.rs index 9b9e33bf..92648a5e 100644 --- a/crates/dmm-tools/src/render_passes/structures.rs +++ b/crates/dmm-tools/src/render_passes/structures.rs @@ -3,7 +3,8 @@ use super::*; #[derive(Default)] pub struct Spawners; impl RenderPass for Spawners { - fn expand<'a>(&self, + fn expand<'a>( + &self, atom: &Atom<'a>, objtree: &'a ObjectTree, output: &mut Vec>, @@ -26,9 +27,9 @@ impl RenderPass for Spawners { }; output.push(Atom::from(objtree.expect(reference))); } - false // don't include the original atom - } - _ => { true } // TODO: complain? + false // don't include the original atom + }, + _ => true, // TODO: complain? } } } @@ -36,7 +37,8 @@ impl RenderPass for Spawners { #[derive(Default)] pub struct GravityGen; impl RenderPass for GravityGen { - fn overlays<'a>(&self, + fn overlays<'a>( + &self, atom: &Atom<'a>, objtree: &'a ObjectTree, _underlays: &mut Vec>, @@ -57,13 +59,16 @@ impl RenderPass for GravityGen { (7, "on_7", 1, 0), (9, "on_9", -1, 0), ] { - let mut sprite = Sprite::from_vars(objtree, &objtree.expect("/obj/machinery/gravity_generator/part")); + let mut sprite = Sprite::from_vars( + objtree, + &objtree.expect("/obj/machinery/gravity_generator/part"), + ); sprite.ofs_x += 32 * x; sprite.ofs_y += 32 * y; sprite.icon_state = icon_state; - sprite.plane = 0; // TODO: figure out plane handling for real + sprite.plane = 0; // TODO: figure out plane handling for real if count <= 3 { - sprite.layer = Layer::from(4.25); // WALL_OBJ_LAYER + sprite.layer = Layer::from(4.25); // WALL_OBJ_LAYER } if count == 5 { // energy overlay goes above the middle part diff --git a/crates/dmm-tools/src/render_passes/transit_tube.rs b/crates/dmm-tools/src/render_passes/transit_tube.rs index c79009c1..b06f4a87 100644 --- a/crates/dmm-tools/src/render_passes/transit_tube.rs +++ b/crates/dmm-tools/src/render_passes/transit_tube.rs @@ -4,7 +4,8 @@ use crate::dmi::Dir; #[derive(Default)] pub struct TransitTube; impl RenderPass for TransitTube { - fn overlays<'a>(&self, + fn overlays<'a>( + &self, atom: &Atom<'a>, objtree: &'a ObjectTree, _: &mut Vec>, @@ -34,7 +35,11 @@ impl RenderPass for TransitTube { } }; - let dir = atom.get_var("dir", objtree).to_int().and_then(Dir::from_int).unwrap_or_default(); + let dir = atom + .get_var("dir", objtree) + .to_int() + .and_then(Dir::from_int) + .unwrap_or_default(); if atom.istype("/obj/structure/transit_tube/station/reverse/") { fulfill(&match dir { North => [East], @@ -109,7 +114,7 @@ fn create_tube_overlay<'a>( icon: source.sprite.icon, layer: source.sprite.layer, icon_state: "decorative", - .. Default::default() + ..Default::default() }; if let Some(shift) = shift { sprite.icon_state = "decorative_diag"; @@ -118,7 +123,7 @@ fn create_tube_overlay<'a>( Dir::South => sprite.ofs_y -= 32, Dir::East => sprite.ofs_x += 32, Dir::West => sprite.ofs_x -= 32, - _ => {} + _ => {}, } } output.push(sprite); diff --git a/crates/dmm-tools/tests/parse_codebase.rs b/crates/dmm-tools/tests/parse_codebase.rs index e2e3d7ba..3afb1bdc 100644 --- a/crates/dmm-tools/tests/parse_codebase.rs +++ b/crates/dmm-tools/tests/parse_codebase.rs @@ -21,7 +21,7 @@ fn files_with_extension(ext: &str, mut f: F) { None => { println!("Set TEST_DME to check .{ext} files"); return; - } + }, }; for entry in WalkDir::new(dir).into_iter().filter_entry(is_visible) { let entry = entry.unwrap(); diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 5988f070..77a1754d 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -8,15 +8,15 @@ use dm::constants::{ConstFn, Constant}; use dm::objtree::{ObjectTree, ProcRef, TypeRef}; use dm::{Context, DMError, Location, Severity}; -use std::collections::{BTreeMap, VecDeque}; use foldhash::{HashMap, HashMapExt, HashSet, HashSetExt}; +use std::collections::{BTreeMap, VecDeque}; mod type_expr; use type_expr::TypeExpr; mod switch_rand_range; use switch_rand_range::check_switch_rand_range; -#[doc(hidden)] // Intended for the tests only. +#[doc(hidden)] // Intended for the tests only. pub mod test_helpers; // ---------------------------------------------------------------------------- @@ -64,11 +64,17 @@ impl<'o> StaticType<'o> { } fn plain_list(tree: &'o ObjectTree) -> StaticType<'o> { - StaticType::List { list: tree.expect("/list"), keys: Box::new(StaticType::None) } + StaticType::List { + list: tree.expect("/list"), + keys: Box::new(StaticType::None), + } } fn list_of_type(tree: &'o ObjectTree, of: &str) -> StaticType<'o> { - StaticType::List { list: tree.expect("/list"), keys: Box::new(StaticType::Type(tree.expect(of))) } + StaticType::List { + list: tree.expect("/list"), + keys: Box::new(StaticType::Type(tree.expect(of))), + } } fn is_list(&self) -> bool { @@ -97,10 +103,10 @@ impl<'o> Assumption<'o> { use Assumption::*; match (self, other) { // trivial conflicts - (Truthy(a), Truthy(b)) | - (IsNull(a), IsNull(b)) | - (IsText(a), IsText(b)) | - (IsNum(a), IsNum(b)) => a != b, + (Truthy(a), Truthy(b)) + | (IsNull(a), IsNull(b)) + | (IsText(a), IsText(b)) + | (IsNum(a), IsNum(b)) => a != b, // null is always false (Truthy(true), IsNull(true)) => true, // can only be one of null, text, num @@ -108,12 +114,12 @@ impl<'o> Assumption<'o> { (IsNum(true), IsNull(true)) => true, (IsText(true), IsNull(true)) => true, // types and paths are truthy - (IsType(true, _), Truthy(false)) | - (IsType(true, _), IsNull(true)) | - (IsPath(true, _), Truthy(false)) | - (IsPath(true, _), Truthy(true)) => true, + (IsType(true, _), Truthy(false)) + | (IsType(true, _), IsNull(true)) + | (IsPath(true, _), Truthy(false)) + | (IsPath(true, _), Truthy(true)) => true, // no conflict after all - _ => false + _ => false, } } } @@ -132,19 +138,32 @@ macro_rules! assumption_set { } impl<'o> AssumptionSet<'o> { - fn from_constant(objtree: &'o ObjectTree, constant: &Constant, type_hint: Option>) -> AssumptionSet<'o> { + fn from_constant( + objtree: &'o ObjectTree, + constant: &Constant, + type_hint: Option>, + ) -> AssumptionSet<'o> { match constant { - Constant::Null(_) => assumption_set![Assumption::IsNull(true), Assumption::Truthy(false)], - Constant::String(val) => assumption_set![Assumption::IsText(true), Assumption::Truthy(!val.is_empty())], + Constant::Null(_) => { + assumption_set![Assumption::IsNull(true), Assumption::Truthy(false)] + }, + Constant::String(val) => assumption_set![ + Assumption::IsText(true), + Assumption::Truthy(!val.is_empty()) + ], Constant::Resource(_) => assumption_set![Assumption::Truthy(true)], - Constant::Float(val) => assumption_set![Assumption::IsNum(true), Assumption::Truthy(*val != 0.0)], + Constant::Float(val) => { + assumption_set![Assumption::IsNum(true), Assumption::Truthy(*val != 0.0)] + }, Constant::List(_) => AssumptionSet::from_valid_instance(objtree.expect("/list")), Constant::Call(func, _) => match func { ConstFn::Icon => AssumptionSet::from_valid_instance(objtree.expect("/icon")), ConstFn::Matrix => AssumptionSet::from_valid_instance(objtree.expect("/matrix")), ConstFn::Newlist => AssumptionSet::from_valid_instance(objtree.expect("/list")), ConstFn::Sound => AssumptionSet::from_valid_instance(objtree.expect("/sound")), - ConstFn::Generator => AssumptionSet::from_valid_instance(objtree.expect("/generator")), + ConstFn::Generator => { + AssumptionSet::from_valid_instance(objtree.expect("/generator")) + }, ConstFn::Filter => AssumptionSet::default(), ConstFn::File => AssumptionSet::default(), }, @@ -172,11 +191,17 @@ impl<'o> AssumptionSet<'o> { } fn from_valid_instance(ty: TypeRef<'o>) -> AssumptionSet<'o> { - assumption_set![Assumption::Truthy(true), Assumption::IsNull(false), Assumption::IsType(true, ty)] + assumption_set![ + Assumption::Truthy(true), + Assumption::IsNull(false), + Assumption::IsType(true, ty) + ] } fn conflicts_with(&self, new: &Assumption) -> Option<&Assumption<'_>> { - self.set.iter().find(|&each| each.oneway_conflict(new) || new.oneway_conflict(each)) + self.set + .iter() + .find(|&each| each.oneway_conflict(new) || new.oneway_conflict(each)) } } @@ -222,7 +247,11 @@ impl<'o> Analysis<'o> { analysis } - fn from_value(objtree: &'o ObjectTree, value: Constant, type_hint: Option>) -> Analysis<'o> { + fn from_value( + objtree: &'o ObjectTree, + value: Constant, + type_hint: Option>, + ) -> Analysis<'o> { Analysis { static_ty: StaticType::None, aset: AssumptionSet::from_constant(objtree, &value, type_hint), @@ -247,7 +276,8 @@ trait WithFixHint { impl WithFixHint for DMError { fn with_fix_hint(mut self, analysis: &Analysis) -> Self { if let Some((loc, desc)) = analysis.fix_hint.clone() { - if !loc.is_builtins() { // Don't try to tell people to edit the builtins. + if !loc.is_builtins() { + // Don't try to tell people to edit the builtins. self.add_note(loc, desc); } } @@ -393,7 +423,12 @@ struct ProcDirective<'o> { } impl<'o> ProcDirective<'o> { - pub fn new(directive_string: &'static str, can_be_disabled: bool, set_at_definition: bool, can_be_global: bool) -> ProcDirective<'o> { + pub fn new( + directive_string: &'static str, + can_be_disabled: bool, + set_at_definition: bool, + can_be_global: bool, + ) -> ProcDirective<'o> { ProcDirective { directive: Default::default(), directive_string, @@ -403,21 +438,41 @@ impl<'o> ProcDirective<'o> { } } - pub fn insert(&mut self, proc: ProcRef<'o>, enable: bool, location: Location) -> Result<(), DMError> { + pub fn insert( + &mut self, + proc: ProcRef<'o>, + enable: bool, + location: Location, + ) -> Result<(), DMError> { if proc.ty().is_root() && !self.can_be_global { - return Err(error(location, format!("{} sets {}, which cannot be set on global procs", proc, self.directive_string)) - .with_errortype("incompatible_directive")) + return Err(error( + location, + format!( + "{} sets {}, which cannot be set on global procs", + proc, self.directive_string + ), + ) + .with_errortype("incompatible_directive")); } if !enable && !self.can_be_disabled { - return Err(error(location, format!("{} sets {} false, but it cannot be disabled.", proc, self.directive_string)) - .with_errortype("disabled_directive") - .set_severity(Severity::Warning)) + return Err(error( + location, + format!( + "{} sets {} false, but it cannot be disabled.", + proc, self.directive_string + ), + ) + .with_errortype("disabled_directive") + .set_severity(Severity::Warning)); } if let Some((_, originallocation)) = self.directive.get(&proc) { - return Err(error(location, format!("{} sets {} twice", proc, self.directive_string)) - .with_note(*originallocation, "first definition here") - .with_errortype("sets_directive_twice") - .set_severity(Severity::Warning)) + return Err(error( + location, + format!("{} sets {} twice", proc, self.directive_string), + ) + .with_note(*originallocation, "first definition here") + .with_errortype("sets_directive_twice") + .set_severity(Severity::Warning)); } self.directive.insert(proc, (enable, location)); Ok(()) @@ -433,7 +488,7 @@ impl<'o> ProcDirective<'o> { let mut next = Some(proc); while let Some(current) = next { if let Some(&(truthy, location)) = self.get(current) { - return Some((current, truthy, location)) + return Some((current, truthy, location)); } next = current.parent_proc(); } @@ -460,7 +515,7 @@ pub fn directive_value_to_truthy(expr: &Expression, location: Location) -> Resul Some(Term::Ident(i)) if i == "FALSE" => Ok(false), Some(Term::Ident(i)) if i == "TRUE" => Ok(true), _ => Err(error(location, format!("invalid value for set {expr:?}")) - .set_severity(Severity::Warning)), + .set_severity(Severity::Warning)), } } @@ -512,7 +567,10 @@ pub struct ViolatingProcs<'o> { impl<'o> ViolatingProcs<'o> { pub fn insert_violator(&mut self, proc: ProcRef<'o>, builtin: &str, location: Location) { - self.violators.entry(proc).or_default().push((builtin.to_string(), location)); + self.violators + .entry(proc) + .or_default() + .push((builtin.to_string(), location)); } pub fn get_violators(&self, proc: ProcRef<'o>) -> Option<&Vec<(String, Location)>> { @@ -566,20 +624,38 @@ pub struct AnalyzeObjectTree<'o> { impl<'o> AnalyzeObjectTree<'o> { pub fn new(context: &'o Context, objtree: &'o ObjectTree) -> Self { let mut return_type = HashMap::default(); - return_type.insert(objtree.root().get_proc("get_step").unwrap(), StaticType::Type(objtree.expect("/turf")).into()); + return_type.insert( + objtree.root().get_proc("get_step").unwrap(), + StaticType::Type(objtree.expect("/turf")).into(), + ); AnalyzeObjectTree { context, objtree, return_type, - must_call_parent: ProcDirective::new("SpacemanDMM_should_call_parent", true, false, false), - must_not_override: ProcDirective::new("SpacemanDMM_should_not_override", false, false, false), + must_call_parent: ProcDirective::new( + "SpacemanDMM_should_call_parent", + true, + false, + false, + ), + must_not_override: ProcDirective::new( + "SpacemanDMM_should_not_override", + false, + false, + false, + ), private: ProcDirective::new("SpacemanDMM_private_proc", false, true, false), protected: ProcDirective::new("SpacemanDMM_protected_proc", false, true, false), must_not_sleep: ProcDirective::new("SpacemanDMM_should_not_sleep", false, true, true), sleep_exempt: ProcDirective::new("SpacemanDMM_allowed_to_sleep", false, true, true), must_be_pure: ProcDirective::new("SpacemanDMM_should_be_pure", false, true, true), - can_be_redefined: ProcDirective::new("SpacemanDMM_can_be_redefined", false, false, false), + can_be_redefined: ProcDirective::new( + "SpacemanDMM_can_be_redefined", + false, + false, + false, + ), used_kwargs: Default::default(), call_tree: Default::default(), sleeping_procs: Default::default(), @@ -599,7 +675,13 @@ impl<'o> AnalyzeObjectTree<'o> { } #[inline] - fn add_directive_or_error(&mut self, proc: ProcRef<'o>, directive: &str, expr: &Expression, location: Location) { + fn add_directive_or_error( + &mut self, + proc: ProcRef<'o>, + directive: &str, + expr: &Expression, + location: Location, + ) { let procdirective = match directive { "SpacemanDMM_should_not_override" => &mut self.must_not_override, "SpacemanDMM_should_call_parent" => &mut self.must_call_parent, @@ -614,17 +696,20 @@ impl<'o> AnalyzeObjectTree<'o> { .with_errortype("unknown_linter_setting") .set_severity(Severity::Warning) .register(self.context); - return - } + return; + }, }; if procdirective.set_at_definition { if let Some(procdef) = &mut proc.get_declaration() { if procdef.location != proc.get().location { - error(location, format!("Can't define procs {directive} outside their initial definition")) - .set_severity(Severity::Warning) - .register(self.context); - return + error( + location, + format!("Can't define procs {directive} outside their initial definition"), + ) + .set_severity(Severity::Warning) + .register(self.context); + return; } } } @@ -635,7 +720,9 @@ impl<'o> AnalyzeObjectTree<'o> { self.context.register_error(error); } }, - Err(error) => self.context.register_error(error.with_errortype("invalid_lint_directive_value")), + Err(error) => self + .context + .register_error(error.with_errortype("invalid_lint_directive_value")), } } @@ -659,16 +746,16 @@ impl<'o> AnalyzeObjectTree<'o> { } while let Some((nextproc, callstack, new_context)) = to_visit.pop_front() { if !visited.insert(nextproc) { - continue + continue; } if self.waitfor_procs.contains(&nextproc) { - continue + continue; } if self.sleep_exempt.get(nextproc).is_some() { - continue + continue; } if new_context { - continue + continue; } if let Some(sleepvec) = self.sleeping_procs.get_violators(nextproc) { error(procref.get().location, format!("{procref} sets SpacemanDMM_should_not_sleep but calls blocking proc {nextproc}")) @@ -677,10 +764,14 @@ impl<'o> AnalyzeObjectTree<'o> { .with_callstack(&callstack) .with_blocking_builtins(sleepvec) .register(self.context) - } else if let Some(overridesleep) = self.sleeping_overrides.get_override_violators(nextproc) { + } else if let Some(overridesleep) = + self.sleeping_overrides.get_override_violators(nextproc) + { for child_violator in overridesleep { - if procref.ty().is_subtype_of(&nextproc.ty()) && !child_violator.ty().is_subtype_of(&procref.ty()) { - continue + if procref.ty().is_subtype_of(&nextproc.ty()) + && !child_violator.ty().is_subtype_of(&procref.ty()) + { + continue; } error(procref.get().location, format!("{procref} calls {nextproc} which has override child proc that sleeps {child_violator}")) .with_note(location, "SpacemanDMM_should_not_sleep set here") @@ -702,11 +793,14 @@ impl<'o> AnalyzeObjectTree<'o> { for (procref, (_, location)) in self.must_be_pure.directive.iter() { if let Some(impurevec) = self.impure_procs.get_violators(*procref) { - error(procref.get().location, format!("{procref} does impure operations")) - .with_errortype("must_be_pure") - .with_note(*location, "SpacemanDMM_should_be_pure set here") - .with_impure_operations(impurevec) - .register(self.context) + error( + procref.get().location, + format!("{procref} does impure operations"), + ) + .with_errortype("must_be_pure") + .with_note(*location, "SpacemanDMM_should_be_pure set here") + .with_impure_operations(impurevec) + .register(self.context) } let mut visited = HashSet::>::new(); let mut to_visit = VecDeque::<(ProcRef<'o>, CallStack)>::new(); @@ -719,7 +813,7 @@ impl<'o> AnalyzeObjectTree<'o> { } while let Some((nextproc, callstack)) = to_visit.pop_front() { if !visited.insert(nextproc) { - continue + continue; } if let Some(impurevec) = self.impure_procs.get_violators(nextproc) { error(procref.get().location, format!("{procref} sets SpacemanDMM_should_be_pure but calls a {nextproc} that does impure operations")) @@ -728,10 +822,14 @@ impl<'o> AnalyzeObjectTree<'o> { .with_callstack(&callstack) .with_impure_operations(impurevec) .register(self.context) - } else if let Some(overrideimpure) = self.impure_overrides.get_override_violators(nextproc) { + } else if let Some(overrideimpure) = + self.impure_overrides.get_override_violators(nextproc) + { for child_violator in overrideimpure { - if procref.ty().is_subtype_of(&nextproc.ty()) && !child_violator.ty().is_subtype_of(&procref.ty()) { - continue + if procref.ty().is_subtype_of(&nextproc.ty()) + && !child_violator.ty().is_subtype_of(&procref.ty()) + { + continue; } error(procref.get().location, format!("{procref} calls {nextproc} which has override child proc that does impure operations {child_violator}")) .with_note(*location, "SpacemanDMM_should_not_pure set here") @@ -774,28 +872,37 @@ impl<'o> AnalyzeObjectTree<'o> { ProcReturnType::InputType(input_type) => { if let Some(path) = input_type.to_typepath() { if let Some(ty) = self.objtree.find(path) { - self.return_type.insert(proc, TypeExpr::from(StaticType::Type(ty))); + self.return_type + .insert(proc, TypeExpr::from(StaticType::Type(ty))); } } - } + }, ProcReturnType::TypePath(bits) => { if let Ok(ty) = crate::static_type(self.objtree, proc_location, bits) { self.return_type.insert(proc, TypeExpr::from(ty)); } - } + }, } } for statement in code.iter() { - if let Statement::Setting { ref name, ref value, .. } = statement.elem { + if let Statement::Setting { + ref name, + ref value, + .. + } = statement.elem + { if name == "SpacemanDMM_return_type" { if let Some(Term::Prefab(fab)) = value.as_term() { - let bits: Vec<_> = fab.path.iter().map(|(_, name)| name.to_owned()).collect(); + let bits: Vec<_> = + fab.path.iter().map(|(_, name)| name.to_owned()).collect(); let ty = self.static_type(statement.location, &bits); self.return_type.insert(proc, TypeExpr::from(ty)); } else { match TypeExpr::compile(proc, statement.location, value) { - Ok(expr) => { self.return_type.insert(proc, expr); }, + Ok(expr) => { + self.return_type.insert(proc, expr); + }, Err(error) => error .with_component(dm::Component::DreamChecker) .register(self.context), @@ -811,10 +918,13 @@ impl<'o> AnalyzeObjectTree<'o> { match name.as_str() { "background" | "waitfor" | "hidden" | "instant" | "popup_menu" => { if directive_value_to_truthy(value, statement.location).is_err() { - error(statement.location, format!("set {} must be 0/1/TRUE/FALSE", name.as_str())) - .set_severity(Severity::Warning) - .with_errortype("invalid_set_value") - .register(self.context); + error( + statement.location, + format!("set {} must be 0/1/TRUE/FALSE", name.as_str()), + ) + .set_severity(Severity::Warning) + .with_errortype("invalid_set_value") + .register(self.context); } }, "name" | "category" | "desc" => { @@ -825,10 +935,16 @@ impl<'o> AnalyzeObjectTree<'o> { // category can be set null to hide it Term::Null if name.as_str() == "category" => {}, other => { - error(statement.location, format!("set {} must have a string value", name.as_str())) - .set_severity(Severity::Warning) - .with_errortype("invalid_set_value") - .register(self.context); + error( + statement.location, + format!( + "set {} must have a string value", + name.as_str() + ), + ) + .set_severity(Severity::Warning) + .with_errortype("invalid_set_value") + .register(self.context); }, } } @@ -855,7 +971,8 @@ impl<'o> AnalyzeObjectTree<'o> { /// Propagate violations make up the inheritence graph pub fn propagate_violations(&mut self, proc: ProcRef<'o>) { - if proc.name() == "New" { // New() propogates via ..() and causes weirdness + if proc.name() == "New" { + // New() propogates via ..() and causes weirdness return; } if self.sleeping_procs.get_violators(proc).is_some() { @@ -894,7 +1011,11 @@ impl<'o> AnalyzeObjectTree<'o> { if !missing.is_empty() { kwargs.bad_overrides_at.insert( proc.ty().path.to_owned(), - BadOverride { missing, location: proc.location }); + BadOverride { + missing, + location: proc.location, + }, + ); } } next = current.parent_proc(); @@ -905,7 +1026,7 @@ impl<'o> AnalyzeObjectTree<'o> { pub fn finish_check_kwargs(&self) { for (base_procname, kwarg_info) in self.used_kwargs.iter() { if kwarg_info.bad_overrides_at.is_empty() { - continue + continue; } // List out the child procs that are missing overrides. @@ -913,13 +1034,18 @@ impl<'o> AnalyzeObjectTree<'o> { 1 => format!("an override of {base_procname} is missing keyword args"), len => format!("{len} overrides of {base_procname} are missing keyword args"), }; - let mut error = error(kwarg_info.location, msg) - .with_errortype("override_missing_keyword_arg"); + let mut error = + error(kwarg_info.location, msg).with_errortype("override_missing_keyword_arg"); let mut missing = HashSet::new(); for (child_procname, bad_override) in kwarg_info.bad_overrides_at.iter() { - error.add_note(bad_override.location, format!("{} is missing \"{}\"", - child_procname, - bad_override.missing.join("\", \""))); + error.add_note( + bad_override.location, + format!( + "{} is missing \"{}\"", + child_procname, + bad_override.missing.join("\", \"") + ), + ); missing.extend(bad_override.missing.iter()); } @@ -927,12 +1053,17 @@ impl<'o> AnalyzeObjectTree<'o> { // there's not gonna be a problem. for (arg_name, called_at) in kwarg_info.called_at.iter() { if !missing.contains(arg_name) { - continue + continue; } if called_at.others > 0 { - error.add_note(called_at.location, format!("called with {:?} here, and {} other places", - arg_name, called_at.others)); + error.add_note( + called_at.location, + format!( + "called with {:?} here, and {} other places", + arg_name, called_at.others + ), + ); } else { error.add_note(called_at.location, format!("called with {arg_name:?} here")); } @@ -948,13 +1079,29 @@ impl<'o> AnalyzeObjectTree<'o> { Err(e) => { e.register(self.context); StaticType::None - } + }, } } } -fn static_type<'o>(objtree: &'o ObjectTree, location: Location, mut of: &[String]) -> Result, DMError> { - while !of.is_empty() && ["static", "global", "const", "tmp", "final", "SpacemanDMM_final", "SpacemanDMM_private", "SpacemanDMM_protected"].contains(&&*of[0]) { +fn static_type<'o>( + objtree: &'o ObjectTree, + location: Location, + mut of: &[String], +) -> Result, DMError> { + while !of.is_empty() + && [ + "static", + "global", + "const", + "tmp", + "final", + "SpacemanDMM_final", + "SpacemanDMM_private", + "SpacemanDMM_protected", + ] + .contains(&&*of[0]) + { of = &of[1..]; } @@ -969,7 +1116,10 @@ fn static_type<'o>(objtree: &'o ObjectTree, location: Location, mut of: &[String } else if let Some(ty) = objtree.type_by_path(of) { Ok(StaticType::Type(ty)) } else { - Err(error(location, format!("undefined type: {}", FormatTreePath(of)))) + Err(error( + location, + format!("undefined type: {}", FormatTreePath(of)), + )) } } @@ -1002,31 +1152,50 @@ pub fn check_var_defs(objtree: &ObjectTree, context: &Context) { continue; } - let Some(parentvar) = parent.vars.get(varname) else { continue }; + let Some(parentvar) = parent.vars.get(varname) else { + continue; + }; - let Some(decl) = &parentvar.declaration else { continue }; + let Some(decl) = &parentvar.declaration else { + continue; + }; if let Some(mydecl) = &typevar.declaration { if typevar.value.location.is_builtins() { continue; } - DMError::new(mydecl.location, format!("{path} redeclares var {varname:?}")) - .with_note(decl.location, format!("declared on {} here", parent.path)) - .register(context); + DMError::new( + mydecl.location, + format!("{path} redeclares var {varname:?}"), + ) + .with_note(decl.location, format!("declared on {} here", parent.path)) + .register(context); } if decl.var_type.flags.is_final() { - DMError::new(typevar.value.location, format!("{path} overrides final var {varname:?}")) - .with_errortype("final_var") - .with_note(decl.location, format!("declared final on {} here", parent.path)) - .register(context); + DMError::new( + typevar.value.location, + format!("{path} overrides final var {varname:?}"), + ) + .with_errortype("final_var") + .with_note( + decl.location, + format!("declared final on {} here", parent.path), + ) + .register(context); } if decl.var_type.flags.is_private() { - DMError::new(typevar.value.location, format!("{path} overrides private var {varname:?}")) - .with_errortype("private_var") - .with_note(decl.location, format!("declared private on {} here", parent.path)) - .register(context); + DMError::new( + typevar.value.location, + format!("{path} overrides private var {varname:?}"), + ) + .with_errortype("private_var") + .with_note( + decl.location, + format!("declared private on {} here", parent.path), + ) + .register(context); } } } @@ -1052,6 +1221,7 @@ impl ControlFlow { fuzzy: false, } } + pub fn allfalse() -> ControlFlow { ControlFlow { returns: false, @@ -1060,12 +1230,13 @@ impl ControlFlow { fuzzy: false, } } + pub fn terminates(&self) -> bool { - !self.fuzzy && ( self.returns || self.continues || self.breaks ) + !self.fuzzy && (self.returns || self.continues || self.breaks) } pub fn terminates_loop(&self) -> bool { - !self.fuzzy && ( self.returns || self.breaks ) + !self.fuzzy && (self.returns || self.breaks) } pub fn no_else(&mut self) { @@ -1129,7 +1300,10 @@ struct LocalVar<'o> { impl<'o> From> for LocalVar<'o> { fn from(analysis: Analysis<'o>) -> Self { - LocalVar { location: Location::default(), analysis } + LocalVar { + location: Location::default(), + analysis, + } } } @@ -1144,7 +1318,12 @@ struct AnalyzeProc<'o, 's> { } impl<'o, 's> AnalyzeProc<'o, 's> { - fn new(env: &'s mut AnalyzeObjectTree<'o>, context: &'o Context, objtree: &'o ObjectTree, proc_ref: ProcRef<'o>) -> Self { + fn new( + env: &'s mut AnalyzeObjectTree<'o>, + context: &'o Context, + objtree: &'o ObjectTree, + proc_ref: ProcRef<'o>, + ) -> Self { let ty = proc_ref.ty(); AnalyzeProc { @@ -1161,28 +1340,47 @@ impl<'o, 's> AnalyzeProc<'o, 's> { pub fn run(&mut self, block: &'o [Spanned]) { let mut local_vars = HashMap::::new(); local_vars.insert(".".to_owned(), Analysis::empty().into()); - local_vars.insert("args".to_owned(), Analysis::from_static_type_impure(self.objtree.expect("/list")).into()); - local_vars.insert("usr".to_owned(), Analysis::from_static_type(self.objtree.expect("/mob")).into()); - local_vars.insert("callee".to_owned(), Analysis::from_static_type(self.objtree.expect("/callee")).into()); - local_vars.insert("caller".to_owned(), Analysis::from_static_type(self.objtree.expect("/callee")).into()); + local_vars.insert( + "args".to_owned(), + Analysis::from_static_type_impure(self.objtree.expect("/list")).into(), + ); + local_vars.insert( + "usr".to_owned(), + Analysis::from_static_type(self.objtree.expect("/mob")).into(), + ); + local_vars.insert( + "callee".to_owned(), + Analysis::from_static_type(self.objtree.expect("/callee")).into(), + ); + local_vars.insert( + "caller".to_owned(), + Analysis::from_static_type(self.objtree.expect("/callee")).into(), + ); if !self.ty.is_root() { local_vars.insert("src".to_owned(), Analysis::from_static_type(self.ty).into()); } - local_vars.insert("global".to_owned(), Analysis { - static_ty: StaticType::Type(self.objtree.root()), - aset: assumption_set![Assumption::IsNull(false)], - value: None, - fix_hint: None, - is_impure: Some(true), - }.into()); + local_vars.insert( + "global".to_owned(), + Analysis { + static_ty: StaticType::Type(self.objtree.root()), + aset: assumption_set![Assumption::IsNull(false)], + value: None, + fix_hint: None, + is_impure: Some(true), + } + .into(), + ); for param in self.proc_ref.get().parameters.iter() { let mut analysis = self.static_type(param.location, ¶m.var_type.type_path); analysis.is_impure = Some(true); // all params are impure - local_vars.insert(param.name.to_owned(), LocalVar { - location: self.proc_ref.location, - analysis, - }); + local_vars.insert( + param.name.to_owned(), + LocalVar { + location: self.proc_ref.location, + analysis, + }, + ); //println!("adding parameters {:#?}", self.local_vars); } @@ -1191,49 +1389,77 @@ impl<'o, 's> AnalyzeProc<'o, 's> { //println!("purity {}", self.is_pure); if let Some(parent) = self.proc_ref.parent_proc() { - if let Some((proc, true, location)) = self.env.private.get_self_or_parent(self.proc_ref) { + if let Some((proc, true, location)) = self.env.private.get_self_or_parent(self.proc_ref) + { if proc != self.proc_ref { - error(self.proc_ref.location, format!("proc overrides private parent, prohibited by {proc}")) + error( + self.proc_ref.location, + format!("proc overrides private parent, prohibited by {proc}"), + ) .with_note(location, "prohibited by this private_proc annotation") .with_errortype("private_proc") .register(self.context); } } - if let Some((proc, true, location)) = self.env.must_not_override.get_self_or_parent(self.proc_ref) { + if let Some((proc, true, location)) = + self.env.must_not_override.get_self_or_parent(self.proc_ref) + { if proc != self.proc_ref { - error(self.proc_ref.location, format!("proc overrides parent, prohibited by {proc}")) - .with_note(location, "prohibited by this must_not_override annotation") - .with_errortype("must_not_override") - .register(self.context); + error( + self.proc_ref.location, + format!("proc overrides parent, prohibited by {proc}"), + ) + .with_note(location, "prohibited by this must_not_override annotation") + .with_errortype("must_not_override") + .register(self.context); } } if !self.calls_parent { - if let Some((proc, true, location)) = self.env.must_call_parent.get_self_or_parent(self.proc_ref) { - error(self.proc_ref.location, format!("proc never calls parent, required by {proc}")) - .with_note(location, "required by this must_call_parent annotation") - .with_errortype("must_call_parent") - .register(self.context); + if let Some((proc, true, location)) = + self.env.must_call_parent.get_self_or_parent(self.proc_ref) + { + error( + self.proc_ref.location, + format!("proc never calls parent, required by {proc}"), + ) + .with_note(location, "required by this must_call_parent annotation") + .with_errortype("must_call_parent") + .register(self.context); } } - if !parent.is_builtin() && self.proc_ref.ty() == parent.ty() - && self.env.can_be_redefined.get_self_or_parent(self.proc_ref).is_none() { - error(self.proc_ref.location, format!("redefining proc {}/{}", self.ty, self.proc_ref.name())) - .with_errortype("redefined_proc") - .with_note(parent.location, "previous definition is here") - .set_severity(Severity::Hint) - .register(self.context); + if !parent.is_builtin() + && self.proc_ref.ty() == parent.ty() + && self + .env + .can_be_redefined + .get_self_or_parent(self.proc_ref) + .is_none() + { + error( + self.proc_ref.location, + format!("redefining proc {}/{}", self.ty, self.proc_ref.name()), + ) + .with_errortype("redefined_proc") + .with_note(parent.location, "previous definition is here") + .set_severity(Severity::Hint) + .register(self.context); } } } - fn visit_block(&mut self, block: &'o [Spanned], local_vars: &mut HashMap>, mut setting_allowed : bool) -> ControlFlow { + fn visit_block( + &mut self, + block: &'o [Spanned], + local_vars: &mut HashMap>, + mut setting_allowed: bool, + ) -> ControlFlow { let mut term = ControlFlow::allfalse(); for stmt in block.iter() { if term.terminates() { - error(stmt.location,"possible unreachable code here") + error(stmt.location, "possible unreachable code here") .with_errortype("unreachable_code") .register(self.context); - return term // stop evaluating + return term; // stop evaluating } match &stmt.elem { Statement::Setting { name, mode, value } => { @@ -1244,10 +1470,10 @@ impl<'o, 's> AnalyzeProc<'o, 's> { .with_errortype("set_has_no_effect") .register(self.context); } - } + }, _ => { setting_allowed = false; - } + }, } let state = self.visit_statement(stmt.location, &stmt.elem, local_vars); term.merge(state); @@ -1258,35 +1484,39 @@ impl<'o, 's> AnalyzeProc<'o, 's> { fn loop_condition_check(&mut self, location: Location, expression: &'o Expression) { match expression.is_truthy() { Some(true) => { - error(location,"loop condition is always true") + error(location, "loop condition is always true") .with_errortype("loop_condition_determinate") .register(self.context); }, Some(false) => { - error(location,"loop condition is always false") + error(location, "loop condition is always false") .with_errortype("loop_condition_determinate") .register(self.context); - } - _ => () + }, + _ => (), }; } fn visit_control_condition(&mut self, location: Location, expression: &'o Expression) { if expression.is_const_eval() { - error(location,"control flow condition is a constant evalutation") + error(location, "control flow condition is a constant evalutation") .with_errortype("control_condition_static") .register(self.context); - } - else if let Some(term) = expression.as_term() { + } else if let Some(term) = expression.as_term() { if term.is_static() { - error(location,"control flow condition is a static term") + error(location, "control flow condition is a static term") .with_errortype("control_condition_static") .register(self.context); } } } - fn visit_statement(&mut self, location: Location, statement: &'o Statement, local_vars: &mut HashMap>) -> ControlFlow { + fn visit_statement( + &mut self, + location: Location, + statement: &'o Statement, + local_vars: &mut HashMap>, + ) -> ControlFlow { match statement { Statement::Expr(expr) => { match expr { @@ -1294,20 +1524,38 @@ impl<'o, 's> AnalyzeProc<'o, 's> { if let Term::Call(call, vec) = &term.elem { if !follow.iter().any(|f| matches!(f.elem, Follow::Call(..))) { if let Some(proc) = self.ty.get_proc(call) { - if let Some((_, _, loc)) = self.env.must_be_pure.get_self_or_parent(proc) { - error(location, format!("call to pure proc {call} discards return value")) - .with_note(loc, "prohibited by this must_be_pure annotation") - .register(self.context); + if let Some((_, _, loc)) = + self.env.must_be_pure.get_self_or_parent(proc) + { + error( + location, + format!( + "call to pure proc {call} discards return value" + ), + ) + .with_note( + loc, + "prohibited by this must_be_pure annotation", + ) + .register(self.context); } } } } }, - Expression::BinaryOp { op: BinaryOp::LShift, lhs, rhs } => { + Expression::BinaryOp { + op: BinaryOp::LShift, + lhs, + rhs, + } => { let lhsanalysis = self.visit_expression(location, lhs, None, local_vars); if let Some(impurity) = lhsanalysis.is_impure { if impurity { - self.env.impure_procs.insert_violator(self.proc_ref, "purity breaking << on expression", location); + self.env.impure_procs.insert_violator( + self.proc_ref, + "purity breaking << on expression", + location, + ); } } }, @@ -1324,36 +1572,63 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } let return_type = self.visit_expression(location, expr, None, local_vars); local_vars.get_mut(".").unwrap().analysis = return_type; - return ControlFlow { returns: true, continues: false, breaks: false, fuzzy: false } + return ControlFlow { + returns: true, + continues: false, + breaks: false, + fuzzy: false, + }; + }, + Statement::Return(None) => { + return ControlFlow { + returns: true, + continues: false, + breaks: false, + fuzzy: false, + } }, - Statement::Return(None) => { return ControlFlow { returns: true, continues: false, breaks: false, fuzzy: false } }, Statement::Crash(expr) => { if let Some(expr) = expr { self.visit_expression(location, expr, None, local_vars); } - return ControlFlow { returns: true, continues: false, breaks: false, fuzzy: false } + return ControlFlow { + returns: true, + continues: false, + breaks: false, + fuzzy: false, + }; + }, + Statement::Throw(expr) => { + self.visit_expression(location, expr, None, local_vars); }, - Statement::Throw(expr) => { self.visit_expression(location, expr, None, local_vars); }, Statement::While { condition, block } => { let mut scoped_locals = local_vars.clone(); // We don't check for static/determine conditions because while(TRUE) is so common. self.visit_expression(location, condition, None, &mut scoped_locals); let mut state = self.visit_block(block, &mut scoped_locals, false); state.end_loop(); - return state + return state; }, Statement::DoWhile { block, condition } => { let mut scoped_locals = local_vars.clone(); let mut state = self.visit_block(block, &mut scoped_locals, false); if state.terminates_loop() { - error(location,"do while terminates without ever reaching condition") - .register(self.context); - return state + error( + location, + "do while terminates without ever reaching condition", + ) + .register(self.context); + return state; } - self.visit_expression(condition.location, &condition.elem, None, &mut scoped_locals); + self.visit_expression( + condition.location, + &condition.elem, + None, + &mut scoped_locals, + ); state.end_loop(); - return state + return state; }, Statement::If { arms, else_arm } => { let mut allterm = ControlFlow::alltrue(); @@ -1366,22 +1641,27 @@ impl<'o, 's> AnalyzeProc<'o, 's> { .with_errortype("unreachable_code") .register(self.context); } - self.visit_expression(condition.location, &condition.elem, None, &mut scoped_locals); + self.visit_expression( + condition.location, + &condition.elem, + None, + &mut scoped_locals, + ); let state = self.visit_block(block, &mut scoped_locals, false); match condition.elem.is_truthy() { Some(true) => { - error(condition.location,"if condition is always true") + error(condition.location, "if condition is always true") .with_errortype("if_condition_determinate") .register(self.context); allterm.merge_false(state); alwaystrue = true; }, Some(false) => { - error(condition.location,"if condition is always false") + error(condition.location, "if condition is always false") .with_errortype("if_condition_determinate") .register(self.context); }, - None => allterm.merge_false(state) + None => allterm.merge_false(state), }; } if let Some(else_arm) = else_arm { @@ -1396,18 +1676,23 @@ impl<'o, 's> AnalyzeProc<'o, 's> { allterm.merge_false(state); } else { allterm.no_else(); - return allterm + return allterm; } allterm.finalize(); - return allterm + return allterm; }, Statement::ForInfinite { block } => { let mut scoped_locals = local_vars.clone(); let mut state = self.visit_block(block, &mut scoped_locals, false); state.end_loop(); - return state - } - Statement::ForLoop { init, test, inc, block } => { + return state; + }, + Statement::ForLoop { + init, + test, + inc, + block, + } => { let mut scoped_locals = local_vars.clone(); if let Some(init) = init { self.visit_statement(location, init, &mut scoped_locals); @@ -1422,10 +1707,16 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } let mut state = self.visit_block(block, &mut scoped_locals, false); state.end_loop(); - return state + return state; }, Statement::ForList(for_list) => { - let ForListStatement { var_type, name, input_type, in_list, block } = &**for_list; + let ForListStatement { + var_type, + name, + input_type, + in_list, + block, + } = &**for_list; let mut scoped_locals = local_vars.clone(); if let Some(in_list) = in_list { let list = self.visit_expression(location, in_list, None, &mut scoped_locals); @@ -1433,10 +1724,13 @@ impl<'o, 's> AnalyzeProc<'o, 's> { StaticType::None => { // Occurs extremely often due to DM not complaining about this, with // over 800 detections on /tg/. Maybe a future lint. - } - StaticType::List { .. } => {/* OK */} + }, + StaticType::List { .. } => { /* OK */ }, StaticType::Type(ty) => { - if ty != self.objtree.expect("/world") && ty != self.objtree.expect("/list") && ty != self.objtree.expect("/alist") { + if ty != self.objtree.expect("/world") + && ty != self.objtree.expect("/list") + && ty != self.objtree.expect("/alist") + { let atom = self.objtree.expect("/atom"); if ty.is_subtype_of(&atom) { // Fine. @@ -1444,20 +1738,32 @@ impl<'o, 's> AnalyzeProc<'o, 's> { // Iffy conceptually, but the only detections on /tg/ are false positives in the // component system, where we loop over `var/datum/parent` that is known to be an // atom in a way that's hard for Dreamchecker to capture. - error(location, "iterating over a /datum which might not be an /atom") - .set_severity(Severity::Hint) - .register(self.context); + error( + location, + "iterating over a /datum which might not be an /atom", + ) + .set_severity(Severity::Hint) + .register(self.context); } else { // The type is a /datum/foo subtype that definitely can't be looped over. - error(location, format!("iterating over a {} which cannot be iterated", ty.path)) - .register(self.context); + error( + location, + format!( + "iterating over a {} which cannot be iterated", + ty.path + ), + ) + .register(self.context); } } - } + }, StaticType::Proc => { - error(location, "iterating over a procpath which cannot be iterated".to_string()) - .register(self.context); - } + error( + location, + "iterating over a procpath which cannot be iterated".to_string(), + ) + .register(self.context); + }, } } if let Some(var_type) = var_type { @@ -1465,10 +1771,17 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } let mut state = self.visit_block(block, &mut scoped_locals, false); state.end_loop(); - return state + return state; }, Statement::ForRange(for_range) => { - let ForRangeStatement { var_type, name, start, end, step, block } = &**for_range; + let ForRangeStatement { + var_type, + name, + start, + end, + step, + block, + } = &**for_range; let mut scoped_locals = local_vars.clone(); self.visit_expression(location, end, None, &mut scoped_locals); if let Some(step) = step { @@ -1482,16 +1795,19 @@ impl<'o, 's> AnalyzeProc<'o, 's> { if let Some(endterm) = end.as_term() { if let Some(validity) = startterm.valid_for_range(endterm, step.as_ref()) { if !validity { - error(location,"for range loop body is never reached due to invalid range") - .register(self.context); + error( + location, + "for range loop body is never reached due to invalid range", + ) + .register(self.context); } else { - return state + return state; } } } } state.end_loop(); - return state + return state; }, Statement::Var(var) => self.visit_var_stmt(location, var, local_vars), Statement::Vars(vars) => { @@ -1499,9 +1815,13 @@ impl<'o, 's> AnalyzeProc<'o, 's> { self.visit_var_stmt(location, each, local_vars); } }, - Statement::Setting { name, mode: SettingMode::Assign, value } => { + Statement::Setting { + name, + mode: SettingMode::Assign, + value, + } => { if name != "waitfor" { - return ControlFlow::allfalse() + return ControlFlow::allfalse(); } if match value.as_term() { Some(Term::Int(0)) => true, @@ -1521,25 +1841,44 @@ impl<'o, 's> AnalyzeProc<'o, 's> { self.visit_block(block, &mut scoped_locals, false); self.inside_newcontext = self.inside_newcontext.wrapping_sub(1); }, - Statement::Switch { input, cases, default } => { + Statement::Switch { + input, + cases, + default, + } => { check_switch_rand_range(input, cases, default, location, self.context); let mut allterm = ControlFlow::alltrue(); self.visit_control_condition(location, input); self.visit_expression(location, input, None, local_vars); for (case, ref block) in cases.iter() { let mut scoped_locals = local_vars.clone(); - if let [dm::ast::Case::Exact(Expression::BinaryOp{op: BinaryOp::Or, ..})] = case.elem[..] { + if let [dm::ast::Case::Exact(Expression::BinaryOp { + op: BinaryOp::Or, .. + })] = case.elem[..] + { error(case.location, "Elements in a switch-case branch separated by ||, this is likely in error and should be replaced by a comma") .set_severity(Severity::Warning) .register(self.context); } for case_part in case.elem.iter() { match case_part { - dm::ast::Case::Exact(expr) => { self.visit_expression(case.location, expr, None, &mut scoped_locals); }, + dm::ast::Case::Exact(expr) => { + self.visit_expression( + case.location, + expr, + None, + &mut scoped_locals, + ); + }, dm::ast::Case::Range(start, end) => { - self.visit_expression(case.location, start, None, &mut scoped_locals); + self.visit_expression( + case.location, + start, + None, + &mut scoped_locals, + ); self.visit_expression(case.location, end, None, &mut scoped_locals); - } + }, } } let state = self.visit_block(block, &mut scoped_locals, false); @@ -1550,40 +1889,75 @@ impl<'o, 's> AnalyzeProc<'o, 's> { allterm.merge_false(state); } else { allterm.no_else(); - return allterm + return allterm; } allterm.finalize(); - return allterm + return allterm; }, - Statement::TryCatch { try_block, catch_params, catch_block } => { + Statement::TryCatch { + try_block, + catch_params, + catch_block, + } => { self.visit_block(try_block, &mut local_vars.clone(), false); if catch_params.len() > 1 { - error(location, format!("Expected 0 or 1 catch parameters, got {}", catch_params.len())) - .set_severity(Severity::Warning) - .register(self.context); + error( + location, + format!( + "Expected 0 or 1 catch parameters, got {}", + catch_params.len() + ), + ) + .set_severity(Severity::Warning) + .register(self.context); } let mut catch_locals = local_vars.clone(); for caught in catch_params.iter() { let (var_name, mut type_path) = match caught.split_last() { Some(x) => x, - None => continue + None => continue, }; match type_path.split_first() { Some((first, rest)) if first == "var" => type_path = rest, - _ => {} + _ => {}, } let var_type: VarType = type_path.iter().map(ToOwned::to_owned).collect(); self.visit_var(location, &var_type, var_name, None, &mut catch_locals); } self.visit_block(catch_block, &mut catch_locals, false); }, - Statement::Continue(_) => { return ControlFlow { returns: false, continues: true, breaks: false, fuzzy: true } }, - Statement::Break(_) => { return ControlFlow { returns: false, continues: false, breaks: true, fuzzy: true } }, + Statement::Continue(_) => { + return ControlFlow { + returns: false, + continues: true, + breaks: false, + fuzzy: true, + } + }, + Statement::Break(_) => { + return ControlFlow { + returns: false, + continues: false, + breaks: true, + fuzzy: true, + } + }, Statement::Goto(_) => {}, - Statement::Label { name: _, block } => { self.visit_block(block, &mut local_vars.clone(), false); }, - Statement::Del(expr) => { self.visit_expression(location, expr, None, local_vars); }, + Statement::Label { name: _, block } => { + self.visit_block(block, &mut local_vars.clone(), false); + }, + Statement::Del(expr) => { + self.visit_expression(location, expr, None, local_vars); + }, Statement::ForKeyValue(for_key_value) => { - let ForKeyValueStatement { var_type, key, key_input_type: _, value, in_list, block } = &**for_key_value; + let ForKeyValueStatement { + var_type, + key, + key_input_type: _, + value, + in_list, + block, + } = &**for_key_value; let mut scoped_locals = local_vars.clone(); if let Some(in_list) = in_list { let list = self.visit_expression(location, in_list, None, &mut scoped_locals); @@ -1591,10 +1965,13 @@ impl<'o, 's> AnalyzeProc<'o, 's> { StaticType::None => { // Occurs extremely often due to DM not complaining about this, with // over 800 detections on /tg/. Maybe a future lint. - } - StaticType::List { .. } => {/* OK */} + }, + StaticType::List { .. } => { /* OK */ }, StaticType::Type(ty) => { - if ty != self.objtree.expect("/world") && ty != self.objtree.expect("/list") && ty != self.objtree.expect("/alist") { + if ty != self.objtree.expect("/world") + && ty != self.objtree.expect("/list") + && ty != self.objtree.expect("/alist") + { let atom = self.objtree.expect("/atom"); if ty.is_subtype_of(&atom) { // Fine. @@ -1602,20 +1979,32 @@ impl<'o, 's> AnalyzeProc<'o, 's> { // Iffy conceptually, but the only detections on /tg/ are false positives in the // component system, where we loop over `var/datum/parent` that is known to be an // atom in a way that's hard for Dreamchecker to capture. - error(location, "iterating over a /datum which might not be an /atom") - .set_severity(Severity::Hint) - .register(self.context); + error( + location, + "iterating over a /datum which might not be an /atom", + ) + .set_severity(Severity::Hint) + .register(self.context); } else { // The type is a /datum/foo subtype that definitely can't be looped over. - error(location, format!("iterating over a {} which cannot be iterated", ty.path)) - .register(self.context); + error( + location, + format!( + "iterating over a {} which cannot be iterated", + ty.path + ), + ) + .register(self.context); } } - } + }, StaticType::Proc => { - error(location, "iterating over a procpath which cannot be iterated".to_string()) - .register(self.context); - } + error( + location, + "iterating over a procpath which cannot be iterated".to_string(), + ) + .register(self.context); + }, } } // This quite ugly but DM doesn't let you do for (var/k, var/v) @@ -1633,22 +2022,42 @@ impl<'o, 's> AnalyzeProc<'o, 's> { self.visit_var(location, &var_type_value, value, None, &mut scoped_locals); let mut state = self.visit_block(block, &mut scoped_locals, false); state.end_loop(); - return state - } + return state; + }, } ControlFlow::allfalse() } - fn visit_var_stmt(&mut self, location: Location, var: &'o VarStatement, local_vars: &mut HashMap>) { - self.visit_var(location, &var.var_type, &var.name, var.value.as_ref(), local_vars) + fn visit_var_stmt( + &mut self, + location: Location, + var: &'o VarStatement, + local_vars: &mut HashMap>, + ) { + self.visit_var( + location, + &var.var_type, + &var.name, + var.value.as_ref(), + local_vars, + ) } - fn visit_var(&mut self, location: Location, var_type: &VarType, name: &str, value: Option<&'o Expression>, local_vars: &mut HashMap>) { + fn visit_var( + &mut self, + location: Location, + var_type: &VarType, + name: &str, + value: Option<&'o Expression>, + local_vars: &mut HashMap>, + ) { // Calculate type hint let static_type = self.env.static_type(location, &var_type.type_path); // Visit the expression if it's there let mut analysis = match value { - Some(expr) => self.visit_expression(location, expr, static_type.basic_type(), local_vars), + Some(expr) => { + self.visit_expression(location, expr, static_type.basic_type(), local_vars) + }, None => Analysis::null(), }; analysis.static_ty = static_type; @@ -1657,80 +2066,145 @@ impl<'o, 's> AnalyzeProc<'o, 's> { local_vars.insert(name.to_owned(), LocalVar { location, analysis }); } - fn visit_expression(&mut self, location: Location, expression: &'o Expression, type_hint: Option>, local_vars: &mut HashMap>) -> Analysis<'o> { + fn visit_expression( + &mut self, + location: Location, + expression: &'o Expression, + type_hint: Option>, + local_vars: &mut HashMap>, + ) -> Analysis<'o> { match expression { Expression::Base { term, follow } => { - let base_type_hint = if follow.is_empty() { - type_hint - } else { - None - }; + let base_type_hint = if follow.is_empty() { type_hint } else { None }; let mut ty = self.visit_term(term.location, &term.elem, base_type_hint, local_vars); for each in follow.iter() { ty = self.visit_follow(each.location, ty, &each.elem, local_vars); } ty }, - Expression::BinaryOp { op: BinaryOp::LShift, lhs, rhs } => { + Expression::BinaryOp { + op: BinaryOp::LShift, + lhs, + rhs, + } => { let lty = self.visit_expression(location, lhs, None, local_vars); if lty.static_ty == StaticType::Type(self.objtree.expect("/mob")) { - self.env.impure_procs.insert_violator(self.proc_ref, "LShift onto mob", location); + self.env.impure_procs.insert_violator( + self.proc_ref, + "LShift onto mob", + location, + ); } else if lty.static_ty == StaticType::Type(self.objtree.expect("/savefile")) { - self.env.impure_procs.insert_violator(self.proc_ref, "LShift onto savefile", location); + self.env.impure_procs.insert_violator( + self.proc_ref, + "LShift onto savefile", + location, + ); } else if lty.static_ty == StaticType::Type(self.objtree.expect("/list")) { - self.env.impure_procs.insert_violator(self.proc_ref, "LShift onto list", location); + self.env.impure_procs.insert_violator( + self.proc_ref, + "LShift onto list", + location, + ); } let rty = self.visit_expression(location, rhs, None, local_vars); self.visit_binary(lty, rty, BinaryOp::LShift) }, - Expression::BinaryOp { op: BinaryOp::In, lhs, rhs } => { + Expression::BinaryOp { + op: BinaryOp::In, + lhs, + rhs, + } => { // check for incorrect/ambiguous in statements match &**lhs { Expression::Base { term, follow } => { for each in follow.iter() { if let Follow::Unary(unary) = each.elem { - error(location, format!("ambiguous `{}` on left side of an `in`", unary.name())) - .set_severity(Severity::Warning) - .with_errortype("ambiguous_in_lhs") - .with_note(location, format!("add parentheses to fix: `{}`", unary.around("(a in b)"))) - .with_note(location, format!("add parentheses to disambiguate: `({}) in b`", unary.around("a"))) - .register(self.context); + error( + location, + format!("ambiguous `{}` on left side of an `in`", unary.name()), + ) + .set_severity(Severity::Warning) + .with_errortype("ambiguous_in_lhs") + .with_note( + location, + format!( + "add parentheses to fix: `{}`", + unary.around("(a in b)") + ), + ) + .with_note( + location, + format!( + "add parentheses to disambiguate: `({}) in b`", + unary.around("a") + ), + ) + .register(self.context); break; } } }, Expression::BinaryOp { op, lhs, rhs } => { - error(location, format!("ambiguous `{op}` on left side of an `in`")) - .set_severity(Severity::Warning) - .with_errortype("ambiguous_in_lhs") - .with_note(location, format!("add parentheses to fix: `a {op} (b in c)`")) - .with_note(location, format!("add parentheses to disambiguate: `(a {op} b) in c`")) - .register(self.context); + error( + location, + format!("ambiguous `{op}` on left side of an `in`"), + ) + .set_severity(Severity::Warning) + .with_errortype("ambiguous_in_lhs") + .with_note( + location, + format!("add parentheses to fix: `a {op} (b in c)`"), + ) + .with_note( + location, + format!("add parentheses to disambiguate: `(a {op} b) in c`"), + ) + .register(self.context); }, Expression::AssignOp { op, lhs, rhs } => { - error(location, format!("ambiguous `{op}` on left side of an `in`")) - .set_severity(Severity::Warning) - .with_errortype("ambiguous_in_lhs") - .with_note(location, format!("add parentheses to fix: `a {op} (b in c)`")) - .with_note(location, format!("add parentheses to disambiguate: `(a {op} b) in c`")) - .register(self.context); + error( + location, + format!("ambiguous `{op}` on left side of an `in`"), + ) + .set_severity(Severity::Warning) + .with_errortype("ambiguous_in_lhs") + .with_note( + location, + format!("add parentheses to fix: `a {op} (b in c)`"), + ) + .with_note( + location, + format!("add parentheses to disambiguate: `(a {op} b) in c`"), + ) + .register(self.context); }, Expression::TernaryOp { cond, if_, else_ } => { - error(location, "ambiguous ternary on left side of an `in`".to_string()) - .set_severity(Severity::Warning) - .with_errortype("ambiguous_in_lhs") - .with_note(location, "add parentheses to fix: `a ? b : (c in d)`") - .with_note(location, "add parentheses to disambiguate: `(a ? b : c) in d`") - .register(self.context); + error( + location, + "ambiguous ternary on left side of an `in`".to_string(), + ) + .set_severity(Severity::Warning) + .with_errortype("ambiguous_in_lhs") + .with_note(location, "add parentheses to fix: `a ? b : (c in d)`") + .with_note( + location, + "add parentheses to disambiguate: `(a ? b : c) in d`", + ) + .register(self.context); }, }; let lty = self.visit_expression(location, lhs, None, local_vars); let rty = self.visit_expression(location, rhs, None, local_vars); self.visit_binary(lty, rty, BinaryOp::In) }, - Expression::BinaryOp { op: BinaryOp::Or, lhs, rhs } => { + Expression::BinaryOp { + op: BinaryOp::Or, + lhs, + rhs, + } => { // It appears that DM does this in more cases than this, but // this is the only case I've seen it used in the wild. // ex: var/datum/cache_entry/E = cache[key] || new @@ -1742,17 +2216,27 @@ impl<'o, 's> AnalyzeProc<'o, 's> { let lty = self.visit_expression(location, lhs, None, local_vars); let rty = self.visit_expression(location, rhs, None, local_vars); match op { - BinaryOp::BitAnd => self.check_negated_bitwise(lhs, location, BinaryOp::BitAnd, BinaryOp::And), - BinaryOp::BitOr => self.check_negated_bitwise(lhs, location, BinaryOp::BitOr, BinaryOp::Or), - BinaryOp::BitXor => self.check_negated_bitwise(lhs, location, BinaryOp::BitXor, BinaryOp::NotEq), - _ => {} + BinaryOp::BitAnd => { + self.check_negated_bitwise(lhs, location, BinaryOp::BitAnd, BinaryOp::And) + }, + BinaryOp::BitOr => { + self.check_negated_bitwise(lhs, location, BinaryOp::BitOr, BinaryOp::Or) + }, + BinaryOp::BitXor => { + self.check_negated_bitwise(lhs, location, BinaryOp::BitXor, BinaryOp::NotEq) + }, + _ => {}, } self.visit_binary(lty, rty, *op) }, Expression::AssignOp { lhs, rhs, .. } => { let lhs = self.visit_expression(location, lhs, None, local_vars); if let Some(true) = lhs.is_impure { - self.env.impure_procs.insert_violator(self.proc_ref, "Assignment on purity breaking expression", location); + self.env.impure_procs.insert_violator( + self.proc_ref, + "Assignment on purity breaking expression", + location, + ); } self.visit_expression(location, rhs, lhs.static_ty.basic_type(), local_vars) }, @@ -1762,28 +2246,54 @@ impl<'o, 's> AnalyzeProc<'o, 's> { let ty = self.visit_expression(location, if_, type_hint, local_vars); self.visit_expression(location, else_, type_hint, local_vars); ty - } + }, } } - fn visit_term(&mut self, location: Location, term: &'o Term, type_hint: Option>, local_vars: &mut HashMap>) -> Analysis<'o> { + fn visit_term( + &mut self, + location: Location, + term: &'o Term, + type_hint: Option>, + local_vars: &mut HashMap>, + ) -> Analysis<'o> { match term { Term::Null => Analysis::null(), - Term::Int(number) => Analysis::from_value(self.objtree, Constant::from(*number), type_hint), - Term::Float(number) => Analysis::from_value(self.objtree, Constant::from(*number), type_hint), - Term::String(text) => Analysis::from_value(self.objtree, Constant::String(text.as_str().into()), type_hint), - Term::Resource(text) => Analysis::from_value(self.objtree, Constant::Resource(text.as_str().into()), type_hint), + Term::Int(number) => { + Analysis::from_value(self.objtree, Constant::from(*number), type_hint) + }, + Term::Float(number) => { + Analysis::from_value(self.objtree, Constant::from(*number), type_hint) + }, + Term::String(text) => Analysis::from_value( + self.objtree, + Constant::String(text.as_str().into()), + type_hint, + ), + Term::Resource(text) => Analysis::from_value( + self.objtree, + Constant::Resource(text.as_str().into()), + type_hint, + ), Term::As(_) => assumption_set![Assumption::IsNum(true)].into(), Term::Ident(unscoped_name) => { if let Some(var) = local_vars.get(unscoped_name) { - var.analysis.clone() + var.analysis + .clone() .with_fix_hint(var.location, "add additional type info here") } else if unscoped_name == "type" { // Strictly speaking "type" might be any subset of our current type, but let's return something useful // so that `nameof(type::foo)` is sensible. let ty = self.ty; - let pop = dm::constants::Pop::from(ty.path.split('/').skip(1).map(ToOwned::to_owned).collect::>().into_boxed_slice()); + let pop = dm::constants::Pop::from( + ty.path + .split('/') + .skip(1) + .map(ToOwned::to_owned) + .collect::>() + .into_boxed_slice(), + ); Analysis { static_ty: StaticType::None, aset: assumption_set![Assumption::IsPath(true, ty)], @@ -1792,7 +2302,8 @@ impl<'o, 's> AnalyzeProc<'o, 's> { is_impure: None, } } else if let Some(decl) = self.ty.get_var_declaration(unscoped_name) { - let mut ana = self.static_type(location, &decl.var_type.type_path) + let mut ana = self + .static_type(location, &decl.var_type.type_path) .with_fix_hint(decl.location, "add additional type info here"); ana.is_impure = Some(true); ana @@ -1804,7 +2315,8 @@ impl<'o, 's> AnalyzeProc<'o, 's> { }, Term::GlobalIdent(global_name) => { if let Some(decl) = self.objtree.root().get_var_declaration(global_name) { - let mut ana = self.static_type(location, &decl.var_type.type_path) + let mut ana = self + .static_type(location, &decl.var_type.type_path) .with_fix_hint(decl.location, "add additional type info here"); ana.is_impure = Some(true); ana @@ -1818,8 +2330,15 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Term::Expr(expr) => self.visit_expression(location, expr, type_hint, local_vars), Term::Prefab(prefab) => { if let Some(nav) = self.ty.navigate_path(&prefab.path) { - let ty = nav.ty(); // TODO: handle proc/verb paths here - let pop = dm::constants::Pop::from(ty.path.split('/').skip(1).map(ToOwned::to_owned).collect::>().into_boxed_slice()); + let ty = nav.ty(); // TODO: handle proc/verb paths here + let pop = dm::constants::Pop::from( + ty.path + .split('/') + .skip(1) + .map(ToOwned::to_owned) + .collect::>() + .into_boxed_slice(), + ); Analysis { static_ty: StaticType::None, aset: assumption_set![Assumption::IsPath(true, nav.ty())], @@ -1828,8 +2347,11 @@ impl<'o, 's> AnalyzeProc<'o, 's> { is_impure: None, } } else { - error(location, format!("failed to resolve path {}", FormatTypePath(&prefab.path))) - .register(self.context); + error( + location, + format!("failed to resolve path {}", FormatTypePath(&prefab.path)), + ) + .register(self.context); Analysis::empty() } }, @@ -1843,13 +2365,15 @@ impl<'o, 's> AnalyzeProc<'o, 's> { }, Term::Call(unscoped_name, args) => { - if self.inside_newcontext == 0 && matches!(unscoped_name.as_str(), - "sleep" - | "alert" - | "shell" - | "winexists" - | "winget") { - self.env.sleeping_procs.insert_violator(self.proc_ref, unscoped_name, location); + if self.inside_newcontext == 0 + && matches!( + unscoped_name.as_str(), + "sleep" | "alert" | "shell" | "winexists" | "winget" + ) + { + self.env + .sleeping_procs + .insert_violator(self.proc_ref, unscoped_name, location); } self.check_type_sleepers(self.ty, location, unscoped_name); let src = self.ty; @@ -1864,12 +2388,18 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } else if unscoped_name == "SpacemanDMM_debug" { eprintln!("SpacemanDMM_debug:"); for arg in args.iter() { - eprintln!(" {:?}", self.visit_expression(location, arg, None, local_vars)); + eprintln!( + " {:?}", + self.visit_expression(location, arg, None, local_vars) + ); } Analysis::empty() } else { - error(location, format!("undefined proc: {:?} on {}", unscoped_name, self.ty)) - .register(self.context); + error( + location, + format!("undefined proc: {:?} on {}", unscoped_name, self.ty), + ) + .register(self.context); Analysis::empty() } }, @@ -1918,9 +2448,12 @@ impl<'o, 's> AnalyzeProc<'o, 's> { // TODO: handle proc/verb paths here self.visit_new(location, nav.ty(), args, local_vars) } else { - error(location, format!("failed to resolve path {}", FormatTypePath(&prefab.path))) - .register(self.context); - Analysis::empty() + error( + location, + format!("failed to resolve path {}", FormatTypePath(&prefab.path)), + ) + .register(self.context); + Analysis::empty() } }, Term::NewMiniExpr { .. } => { @@ -1932,9 +2465,15 @@ impl<'o, 's> AnalyzeProc<'o, 's> { self.visit_arguments(location, args, local_vars); Analysis::from_static_type(self.objtree.expect("/list")) }, - Term::Input { args, input_type, in_list } => { + Term::Input { + args, + input_type, + in_list, + } => { if self.inside_newcontext == 0 { - self.env.sleeping_procs.insert_violator(self.proc_ref, "input", location); + self.env + .sleeping_procs + .insert_violator(self.proc_ref, "input", location); } // TODO: deal with in_list self.visit_arguments(location, args, local_vars); @@ -1954,7 +2493,13 @@ impl<'o, 's> AnalyzeProc<'o, 's> { assumption_set![Assumption::IsType(true, self.objtree.expect("/area"))].into() } else if without_null == InputType::TURF { assumption_set![Assumption::IsType(true, self.objtree.expect("/turf"))].into() - } else if without_null == InputType::TEXT || without_null == InputType::MESSAGE || without_null == InputType::KEY || without_null == InputType::PASSWORD || without_null == InputType::COLOR || without_null.is_empty() { + } else if without_null == InputType::TEXT + || without_null == InputType::MESSAGE + || without_null == InputType::KEY + || without_null == InputType::PASSWORD + || without_null == InputType::COLOR + || without_null.is_empty() + { assumption_set![Assumption::IsText(true)].into() } else if without_null == InputType::NUM { assumption_set![Assumption::IsNum(true)].into() @@ -1973,7 +2518,8 @@ impl<'o, 's> AnalyzeProc<'o, 's> { self.visit_expression(location, expr, None, local_vars); } - if args.len() == 3 { // X,Y,Z - it's gotta be a turf + if args.len() == 3 { + // X,Y,Z - it's gotta be a turf assumption_set![Assumption::IsType(true, self.objtree.expect("/turf"))].into() } else { Analysis::empty() @@ -1993,19 +2539,31 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Term::DynamicCall(lhs_args, rhs_args) => { self.visit_arguments(location, lhs_args, local_vars); self.visit_arguments(location, rhs_args, local_vars); - Analysis::empty() // TODO + Analysis::empty() // TODO }, - Term::ExternalCall { library, function, args } => { + Term::ExternalCall { + library, + function, + args, + } => { if let Some(library) = library { self.visit_expression(location, library, None, local_vars); } self.visit_expression(location, function, None, local_vars); self.visit_arguments(location, args, local_vars); - Analysis::empty() // TODO + Analysis::empty() // TODO }, Term::__TYPE__ => { - let pop = dm::constants::Pop::from(self.ty.path.split('/').skip(1).map(ToOwned::to_owned).collect::>().into_boxed_slice()); + let pop = dm::constants::Pop::from( + self.ty + .path + .split('/') + .skip(1) + .map(ToOwned::to_owned) + .collect::>() + .into_boxed_slice(), + ); Analysis { static_ty: StaticType::None, aset: assumption_set![Assumption::IsPath(true, self.ty)], @@ -2020,9 +2578,17 @@ impl<'o, 's> AnalyzeProc<'o, 's> { }, Term::__IMPLIED_TYPE__ => { let Some(implied_type) = type_hint else { - return Analysis::empty() + return Analysis::empty(); }; - let pop = dm::constants::Pop::from(implied_type.path.split('/').skip(1).map(ToOwned::to_owned).collect::>().into_boxed_slice()); + let pop = dm::constants::Pop::from( + implied_type + .path + .split('/') + .skip(1) + .map(ToOwned::to_owned) + .collect::>() + .into_boxed_slice(), + ); Analysis { static_ty: StaticType::None, aset: assumption_set![Assumption::IsPath(true, self.ty)], @@ -2034,7 +2600,13 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } - fn visit_new(&mut self, location: Location, typepath: TypeRef<'o>, args: &'o Option>, local_vars: &mut HashMap>) -> Analysis<'o> { + fn visit_new( + &mut self, + location: Location, + typepath: TypeRef<'o>, + args: &'o Option>, + local_vars: &mut HashMap>, + ) -> Analysis<'o> { if let Some(new_proc) = typepath.get_proc("New") { self.visit_call( location, @@ -2044,45 +2616,73 @@ impl<'o, 's> AnalyzeProc<'o, 's> { // New calls are exact: `new /datum()` will always call // `/datum/New()` and never an override. true, - local_vars); - } else if typepath.path != "/list" && typepath.path != "/alist" && typepath.path != "/vector" && typepath.path != "/pixloc" { - error(location, format!("couldn't find {}/proc/New", typepath.path)) - .register(self.context); + local_vars, + ); + } else if typepath.path != "/list" + && typepath.path != "/alist" + && typepath.path != "/vector" + && typepath.path != "/pixloc" + { + error( + location, + format!("couldn't find {}/proc/New", typepath.path), + ) + .register(self.context); } assumption_set![Assumption::IsType(true, typepath)].into() } fn check_type_sleepers(&mut self, ty: TypeRef<'o>, location: Location, unscoped_name: &str) { match ty.get().path.as_str() { - "/client" => if self.inside_newcontext == 0 && matches!(unscoped_name, - "SoundQuery" - | "MeasureText") { - self.env.sleeping_procs.insert_violator(self.proc_ref, format!("client.{unscoped_name}").as_str(), location); + "/client" => { + if self.inside_newcontext == 0 + && matches!(unscoped_name, "SoundQuery" | "MeasureText") + { + self.env.sleeping_procs.insert_violator( + self.proc_ref, + format!("client.{unscoped_name}").as_str(), + location, + ); + } }, - "/world" => if self.inside_newcontext == 0 && matches!(unscoped_name, - "Import" - | "Export") { - self.env.sleeping_procs.insert_violator(self.proc_ref, format!("world.{unscoped_name}").as_str(), location); + "/world" => { + if self.inside_newcontext == 0 && matches!(unscoped_name, "Import" | "Export") { + self.env.sleeping_procs.insert_violator( + self.proc_ref, + format!("world.{unscoped_name}").as_str(), + location, + ); + } }, _ => {}, } } - fn visit_follow(&mut self, location: Location, lhs: Analysis<'o>, rhs: &'o Follow, local_vars: &mut HashMap>) -> Analysis<'o> { + fn visit_follow( + &mut self, + location: Location, + lhs: Analysis<'o>, + rhs: &'o Follow, + local_vars: &mut HashMap>, + ) -> Analysis<'o> { match rhs { Follow::Unary(op) => self.visit_unary(lhs, op, location, local_vars), Follow::Field(PropertyAccessKind::Colon, _) => Analysis::empty(), Follow::Field(PropertyAccessKind::SafeColon, _) => Analysis::empty(), - Follow::Call(PropertyAccessKind::Colon, _, args) | - Follow::Call(PropertyAccessKind::SafeColon, _, args) => { + Follow::Call(PropertyAccessKind::Colon, _, args) + | Follow::Call(PropertyAccessKind::SafeColon, _, args) => { // No analysis yet, but be sure to visit the arguments for arg in args.iter() { let mut argument_value = arg; - if let Expression::AssignOp { op: AssignOp::Assign, lhs, rhs } = arg { + if let Expression::AssignOp { + op: AssignOp::Assign, + lhs, + rhs, + } = arg + { match lhs.as_term() { - Some(Term::Ident(name)) | - Some(Term::String(name)) => { + Some(Term::Ident(name)) | Some(Term::String(name)) => { // Don't visit_expression the kwarg key. argument_value = rhs; }, @@ -2101,7 +2701,8 @@ impl<'o, 's> AnalyzeProc<'o, 's> { StaticType::List { keys, .. } => { let mut res = Analysis::from(*keys); if let Some((loc, _)) = lhs.fix_hint { - res.fix_hint = Some((loc, "add a type annotation after /list here".to_owned())) + res.fix_hint = + Some((loc, "add a type annotation after /list here".to_owned())) } res }, @@ -2113,7 +2714,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } lhs.clone() }, - _ => lhs.clone() // carry through fix_hint + _ => lhs.clone(), // carry through fix_hint } }, Follow::Field(kind, name) => { @@ -2123,7 +2724,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { _ => { error(location, format!("undefined field: {name:?} on procpath")) .register(self.context); - } + }, } Analysis::empty() } else if let Some(ty) = lhs.static_ty.basic_type() { @@ -2133,17 +2734,25 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Analysis::from(StaticType::Proc) } else if let Some(decl) = ty.get_var_declaration(name) { if ty != self.ty && decl.var_type.flags.is_private() { - error(location, format!("field {name:?} on {ty} is declared as private")) - .with_errortype("private_var") - .set_severity(Severity::Warning) - .with_note(decl.location, "definition is here") - .register(self.context); - } else if !self.ty.is_subtype_of(ty.get()) && decl.var_type.flags.is_protected() { - error(location, format!("field {name:?} on {ty} is declared as protected")) - .with_errortype("protected_var") - .set_severity(Severity::Warning) - .with_note(decl.location, "definition is here") - .register(self.context); + error( + location, + format!("field {name:?} on {ty} is declared as private"), + ) + .with_errortype("private_var") + .set_severity(Severity::Warning) + .with_note(decl.location, "definition is here") + .register(self.context); + } else if !self.ty.is_subtype_of(ty.get()) + && decl.var_type.flags.is_protected() + { + error( + location, + format!("field {name:?} on {ty} is declared as protected"), + ) + .with_errortype("protected_var") + .set_severity(Severity::Warning) + .with_note(decl.location, "definition is here") + .register(self.context); } self.static_type(location, &decl.var_type.type_path) .with_fix_hint(decl.location, "add additional type info here") @@ -2153,11 +2762,14 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Analysis::empty() } } else { - error(location, format!("field access requires static type: {name:?}")) - .set_severity(Severity::Warning) - .with_errortype("field_access_static_type") - .with_fix_hint(&lhs) - .register(self.context); + error( + location, + format!("field access requires static type: {name:?}"), + ) + .set_severity(Severity::Warning) + .with_errortype("field_access_static_type") + .with_fix_hint(&lhs) + .register(self.context); Analysis::empty() } }, @@ -2168,31 +2780,34 @@ impl<'o, 's> AnalyzeProc<'o, 's> { let Some(to_our_side) = lhs.value else { error(location, format!("no typepath found for: {name:?}")) .register(self.context); - return Analysis::empty() + return Analysis::empty(); }; let Constant::Prefab(typepop) = to_our_side else { error(location, format!("static access requires a static typepath, {to_our_side} found instead")) .register(self.context); - return Analysis::empty() + return Analysis::empty(); }; if !typepop.vars.is_empty() { error(location, format!("static access requires a static typepath, {typepop} found instead")) .register(self.context); - return Analysis::empty() + return Analysis::empty(); } let typepath = dm::ast::FormatTreePath(&typepop.path).to_string(); let Some(found_type) = self.objtree.find(typepath.as_str()) else { error(location, format!("static access requires an existing typepath, {typepath} found instead")) .register(self.context); - return Analysis::empty() + return Analysis::empty(); }; found_type - } + }, }; let Some(decl) = real_type.get_var_declaration(name) else { - error(location, format!("undefined field: {name:?} on {real_type}")) - .register(self.context); - return Analysis::empty() + error( + location, + format!("undefined field: {name:?} on {real_type}"), + ) + .register(self.context); + return Analysis::empty(); }; self.static_type(location, &decl.var_type.type_path) @@ -2203,21 +2818,43 @@ impl<'o, 's> AnalyzeProc<'o, 's> { if let Some(ty) = lhs.static_ty.basic_type() { self.check_type_sleepers(ty, location, name); if let Some(proc) = ty.get_proc(name) { - if let Some((privateproc, true, decllocation)) = self.env.private.get_self_or_parent(proc) { + if let Some((privateproc, true, decllocation)) = + self.env.private.get_self_or_parent(proc) + { if ty != privateproc.ty() { - error(location, format!("{} attempting to call private proc {}, types do not match", self.proc_ref, privateproc)) - .with_errortype("private_proc") - .with_note(decllocation, "prohibited by this private_proc annotation") - .register(self.context); - return Analysis::empty() // dont double up with visit_call() + error( + location, + format!( + "{} attempting to call private proc {}, types do not match", + self.proc_ref, privateproc + ), + ) + .with_errortype("private_proc") + .with_note( + decllocation, + "prohibited by this private_proc annotation", + ) + .register(self.context); + return Analysis::empty(); // dont double up with visit_call() } } - if let Some((protectedproc, true, decllocation)) = self.env.protected.get_self_or_parent(proc) { + if let Some((protectedproc, true, decllocation)) = + self.env.protected.get_self_or_parent(proc) + { if !self.ty.is_subtype_of(protectedproc.ty().get()) { - error(location, format!("{} attempting to call protected proc {}", self.proc_ref, protectedproc)) - .with_errortype("protected_proc") - .with_note(decllocation, "prohibited by this protected_proc annotation") - .register(self.context); + error( + location, + format!( + "{} attempting to call protected proc {}", + self.proc_ref, protectedproc + ), + ) + .with_errortype("protected_proc") + .with_note( + decllocation, + "prohibited by this protected_proc annotation", + ) + .register(self.context); } } self.visit_call(location, ty, proc, arguments, false, local_vars) @@ -2227,11 +2864,14 @@ impl<'o, 's> AnalyzeProc<'o, 's> { Analysis::empty() } } else { - error(location, format!("proc call requires static type: {name:?}")) - .set_severity(Severity::Warning) - .with_errortype("proc_call_static_type") - .with_fix_hint(&lhs) - .register(self.context); + error( + location, + format!("proc call requires static type: {name:?}"), + ) + .set_severity(Severity::Warning) + .with_errortype("proc_call_static_type") + .with_fix_hint(&lhs) + .register(self.context); Analysis::empty() } }, @@ -2242,35 +2882,41 @@ impl<'o, 's> AnalyzeProc<'o, 's> { let Some(to_our_side) = lhs.value else { error(location, format!("no typepath found for: {name:?}")) .register(self.context); - return Analysis::empty() + return Analysis::empty(); }; let Constant::Prefab(typepop) = to_our_side else { error(location, format!("static proc reference requires a static typepath, {to_our_side} found instead")) .register(self.context); - return Analysis::empty() + return Analysis::empty(); }; if !&typepop.vars.is_empty() { error(location, format!("static proc reference requires a static typepath, {typepop} found instead")) .register(self.context); - return Analysis::empty() + return Analysis::empty(); } let typepath = dm::ast::FormatTreePath(&typepop.path).to_string(); let Some(found_type) = self.objtree.find(typepath.as_str()) else { error(location, format!("static proc reference requires an existing typepath, {typepath} found instead")) .register(self.context); - return Analysis::empty() + return Analysis::empty(); }; found_type - } + }, }; let Some(decl) = real_type.get_proc(name) else { error(location, format!("undefined proc: {name:?} on {real_type}")) .register(self.context); - return Analysis::empty() + return Analysis::empty(); }; // Gonna build the proc's path - let mut path_elements: Vec = real_type.get().path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect(); + let mut path_elements: Vec = real_type + .get() + .path + .split('/') + .filter(|elem| !elem.is_empty()) + .map(|segment| segment.to_string()) + .collect(); // Only tricky bit is adding on the type if required if let Some(declaration) = decl.get_declaration() { path_elements.push(declaration.kind.name().to_string()); @@ -2289,37 +2935,52 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } // checks operatorX overloads on types - fn check_operator_overload(&mut self, rhs: Analysis<'o>, location: Location, operator: &str, local_vars: &mut HashMap>) -> Analysis<'o> { + fn check_operator_overload( + &mut self, + rhs: Analysis<'o>, + location: Location, + operator: &str, + local_vars: &mut HashMap>, + ) -> Analysis<'o> { if let Some(impurity) = rhs.is_impure { if impurity { - self.env.impure_procs.insert_violator(self.proc_ref, &format!("{operator} done on non-local var"), location); + self.env.impure_procs.insert_violator( + self.proc_ref, + &format!("{operator} done on non-local var"), + location, + ); } } let typeerror; match rhs.static_ty { - StaticType::None => { - return Analysis::empty() - }, + StaticType::None => return Analysis::empty(), StaticType::Type(typeref) => { // Its been overloaded, assume they really know they want to do this if let Some(proc) = typeref.get_proc(operator) { - return self.visit_call(location, typeref, proc, &[], true, local_vars) + return self.visit_call(location, typeref, proc, &[], true, local_vars); } typeerror = typeref.get().pretty_path(); }, StaticType::List { list, .. } => { typeerror = "list"; }, - StaticType::Proc => { - return Analysis::empty() - } + StaticType::Proc => return Analysis::empty(), }; - error(location, format!("Attempting {operator} on a {typeerror} which does not overload {operator}")) - .register(self.context); + error( + location, + format!("Attempting {operator} on a {typeerror} which does not overload {operator}"), + ) + .register(self.context); Analysis::empty() } - fn visit_unary(&mut self, rhs: Analysis<'o>, op: &UnaryOp, location: Location, local_vars: &mut HashMap>) -> Analysis<'o> { + fn visit_unary( + &mut self, + rhs: Analysis<'o>, + op: &UnaryOp, + location: Location, + local_vars: &mut HashMap>, + ) -> Analysis<'o> { match op { // !x just evaluates the "truthiness" of x and negates it, returning 1 or 0 UnaryOp::Not => Analysis::from(assumption_set![Assumption::IsNum(true)]), @@ -2338,17 +2999,30 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } // checks for bitwise operations on a negated LHS - fn check_negated_bitwise(&mut self, lhs: &dm::ast::Expression, location: Location, bit_op: BinaryOp, bool_op: BinaryOp) { - let Expression::Base { follow, .. } = lhs else { return }; - let any_not = follow.iter().any(|f| matches!(f.elem, Follow::Unary(UnaryOp::Not))); + fn check_negated_bitwise( + &mut self, + lhs: &dm::ast::Expression, + location: Location, + bit_op: BinaryOp, + bool_op: BinaryOp, + ) { + let Expression::Base { follow, .. } = lhs else { + return; + }; + let any_not = follow + .iter() + .any(|f| matches!(f.elem, Follow::Unary(UnaryOp::Not))); if any_not { - error(location, format!("Ambiguous `!` on left side of bitwise `{bit_op}` operator")) - .with_errortype("ambiguous_not_bitwise") - .set_severity(Severity::Warning) - .with_note(location, format!("Did you mean `!(x {bit_op} y)`?")) - .with_note(location, format!("Did you mean `!x {bool_op} y`?")) - .with_note(location, format!("Did you mean `~x {bit_op} y`?")) - .register(self.context); + error( + location, + format!("Ambiguous `!` on left side of bitwise `{bit_op}` operator"), + ) + .with_errortype("ambiguous_not_bitwise") + .set_severity(Severity::Warning) + .with_note(location, format!("Did you mean `!(x {bit_op} y)`?")) + .with_note(location, format!("Did you mean `!x {bool_op} y`?")) + .with_note(location, format!("Did you mean `~x {bit_op} y`?")) + .register(self.context); } } @@ -2357,12 +3031,12 @@ impl<'o, 's> AnalyzeProc<'o, 's> { if lhs.static_ty.is_list() { // If the LHS of these operators is a list, so is the result. match op { - BinaryOp::Add | - BinaryOp::Sub | - BinaryOp::BitOr | - BinaryOp::BitAnd | - BinaryOp::BitXor => return lhs.static_ty.into(), - _ => {} + BinaryOp::Add + | BinaryOp::Sub + | BinaryOp::BitOr + | BinaryOp::BitAnd + | BinaryOp::BitXor => return lhs.static_ty.into(), + _ => {}, } } Analysis::empty() @@ -2370,24 +3044,56 @@ impl<'o, 's> AnalyzeProc<'o, 's> { // It's fine. #[allow(clippy::too_many_arguments)] - fn check_filter_flag(&mut self, expr: &'o Expression, can_be_zero: bool, location: Location, typevalue: &str, valid_flags: &[&str], flagfieldname: &str, exclusive: bool) { + fn check_filter_flag( + &mut self, + expr: &'o Expression, + can_be_zero: bool, + location: Location, + typevalue: &str, + valid_flags: &[&str], + flagfieldname: &str, + exclusive: bool, + ) { match expr { - Expression::BinaryOp{ op: BinaryOp::BitOr, lhs, rhs } => { + Expression::BinaryOp { + op: BinaryOp::BitOr, + lhs, + rhs, + } => { if exclusive { error(location, format!("filter(type=\"{typevalue}\") '{flagfieldname}' parameter must have one value, found bitwise OR")) .with_filter_args(location, typevalue) .register(self.context); - return + return; } // recurse - self.check_filter_flag(lhs, can_be_zero, location, typevalue, valid_flags, flagfieldname, exclusive); - self.check_filter_flag(rhs, can_be_zero, location, typevalue, valid_flags, flagfieldname, exclusive); + self.check_filter_flag( + lhs, + can_be_zero, + location, + typevalue, + valid_flags, + flagfieldname, + exclusive, + ); + self.check_filter_flag( + rhs, + can_be_zero, + location, + typevalue, + valid_flags, + flagfieldname, + exclusive, + ); }, - Expression::Base{ term, follow } => { + Expression::Base { term, follow } => { if !follow.is_empty() { - error(location, "filter() flag fields cannot have unary ops or field accesses") - .register(self.context); - return + error( + location, + "filter() flag fields cannot have unary ops or field accesses", + ) + .register(self.context); + return; } match &term.elem { Term::Ident(flagname) => { @@ -2409,18 +3115,36 @@ impl<'o, 's> AnalyzeProc<'o, 's> { error(location, format!("filter(type=\"{typevalue}\"), extremely invalid value passed to '{flagfieldname}' field")) .with_filter_args(location, typevalue) .register(self.context); - } + }, } } - fn visit_call(&mut self, location: Location, src: TypeRef<'o>, proc: ProcRef<'o>, args: &'o [Expression], is_exact: bool, local_vars: &mut HashMap>) -> Analysis<'o> { - self.env.call_tree.entry(self.proc_ref).or_default().push((proc, location, self.inside_newcontext != 0)); + fn visit_call( + &mut self, + location: Location, + src: TypeRef<'o>, + proc: ProcRef<'o>, + args: &'o [Expression], + is_exact: bool, + local_vars: &mut HashMap>, + ) -> Analysis<'o> { + self.env.call_tree.entry(self.proc_ref).or_default().push(( + proc, + location, + self.inside_newcontext != 0, + )); if let Some((privateproc, true, decllocation)) = self.env.private.get_self_or_parent(proc) { if self.ty != privateproc.ty() { - error(location, format!("{} attempting to call private proc {}, types do not match", self.proc_ref, privateproc)) - .with_errortype("private_proc") - .with_note(decllocation, "prohibited by this private_proc annotation") - .register(self.context); + error( + location, + format!( + "{} attempting to call private proc {}, types do not match", + self.proc_ref, privateproc + ), + ) + .with_errortype("private_proc") + .with_note(decllocation, "prohibited by this private_proc annotation") + .register(self.context); } } @@ -2437,10 +3161,13 @@ impl<'o, 's> AnalyzeProc<'o, 's> { let mut argument_value = arg; let mut this_kwarg = None; match arg { - Expression::AssignOp { op: AssignOp::Assign, lhs, rhs } => { + Expression::AssignOp { + op: AssignOp::Assign, + lhs, + rhs, + } => { match lhs.as_term() { - Some(Term::Ident(name)) | - Some(Term::String(name)) => { + Some(Term::Ident(name)) | Some(Term::String(name)) => { // Don't visit_expression the kwarg key. any_kwargs_yet = true; this_kwarg = Some(name); @@ -2449,12 +3176,19 @@ impl<'o, 's> AnalyzeProc<'o, 's> { // Check that that kwarg actually exists. if !proc.parameters.iter().any(|p| p.name == *name) { // Search for a child proc that does have this keyword argument. - let mut error = error(location, - format!("bad keyword argument {name:?} to {proc}")); + let mut error = error( + location, + format!("bad keyword argument {name:?} to {proc}"), + ); proc.recurse_children(&mut |child_proc| { - if child_proc.ty() == proc.ty() { return } + if child_proc.ty() == proc.ty() { + return; + } if child_proc.parameters.iter().any(|p| p.name == *name) { - error.add_note(child_proc.location, format!("an override has this parameter: {child_proc}")); + error.add_note( + child_proc.location, + format!("an override has this parameter: {child_proc}"), + ); } }); error.register(self.context); @@ -2464,10 +3198,12 @@ impl<'o, 's> AnalyzeProc<'o, 's> { // type the proc actually appears on, so that // calling /datum/foo() on a /datum/A won't // complain about /datum/B/foo(). - self.env.used_kwargs.entry(format!("{}/proc/{}", src, proc.name())) + self.env + .used_kwargs + .entry(format!("{}/proc/{}", src, proc.name())) .or_insert_with(|| KwargInfo { location: proc.location, - .. Default::default() + ..Default::default() }) .called_at // TODO: use a more accurate location @@ -2478,24 +3214,36 @@ impl<'o, 's> AnalyzeProc<'o, 's> { others: 0, }); } - } - _ => {} + }, + _ => {}, } }, expr => { if let Some(Term::Call(callname, _)) = expr.as_term() { // only interested in the first expression being arglist - if callname.as_str() == "arglist" && param_name_map.is_empty() && param_idx == 0 { + if callname.as_str() == "arglist" + && param_name_map.is_empty() + && param_idx == 0 + { arglist_used = true; } } }, } - if any_kwargs_yet && this_kwarg.is_none() && !(proc.ty().is_root() && proc.name() == "animate") { + if any_kwargs_yet + && this_kwarg.is_none() + && !(proc.ty().is_root() && proc.name() == "animate") + { // TODO: don't hardcode the animate() exception - error(location, format!("proc called with non-kwargs after kwargs: {}()", proc.name())) - .register(self.context); + error( + location, + format!( + "proc called with non-kwargs after kwargs: {}()", + proc.name() + ), + ) + .register(self.context); } let analysis = self.visit_expression(location, argument_value, None, local_vars); @@ -2511,7 +3259,12 @@ impl<'o, 's> AnalyzeProc<'o, 's> { if proc.ty().is_root() && proc.name() == "astype" { if let Some(type_val) = param_idx_map.get(&1) { if let Some(Constant::Prefab(path)) = type_val.clone().value { - let type_val = path.path.iter().map(|x| "/".to_owned() + x).collect::>().join(""); + let type_val = path + .path + .iter() + .map(|x| "/".to_owned() + x) + .collect::>() + .join(""); if let Some(path) = self.objtree.find(&type_val) { return Analysis::from_static_type(path); @@ -2530,20 +3283,34 @@ impl<'o, 's> AnalyzeProc<'o, 's> { if proc.ty().is_root() && proc.name() == "filter" { let Some(typename) = param_name_map.get("type") else { if !arglist_used { - error(location, "filter() called without mandatory keyword parameter 'type'") - .register(self.context); + error( + location, + "filter() called without mandatory keyword parameter 'type'", + ) + .register(self.context); } // regardless, we're done here - return Analysis::empty() + return Analysis::empty(); }; let Some(Constant::String(typevalue)) = &typename.value else { - error(location, format!("filter() called with non-string type keyword parameter value '{:?}'", typename.value)) - .register(self.context); - return Analysis::empty() + error( + location, + format!( + "filter() called with non-string type keyword parameter value '{:?}'", + typename.value + ), + ) + .register(self.context); + return Analysis::empty(); }; let Some(arglist) = VALID_FILTER_TYPES.get(typevalue) else { - error(location, format!("filter() called with invalid type keyword parameter value '{typevalue}'")) - .register(self.context); - return Analysis::empty() + error( + location, + format!( + "filter() called with invalid type keyword parameter value '{typevalue}'" + ), + ) + .register(self.context); + return Analysis::empty(); }; for arg in param_name_map.keys() { if *arg != "type" && *arg != "name" && !arglist.contains(arg) { @@ -2552,9 +3319,19 @@ impl<'o, 's> AnalyzeProc<'o, 's> { .register(self.context); } } - if let Some((flagfieldname, exclusive, can_be_zero, valid_flags)) = VALID_FILTER_FLAGS.get(typevalue) { + if let Some((flagfieldname, exclusive, can_be_zero, valid_flags)) = + VALID_FILTER_FLAGS.get(typevalue) + { if let Some(flagsvalue) = param_expr_map.get(flagfieldname) { - self.check_filter_flag(flagsvalue, *can_be_zero, location, typevalue, valid_flags, flagfieldname, *exclusive); + self.check_filter_flag( + flagsvalue, + *can_be_zero, + location, + typevalue, + valid_flags, + flagfieldname, + *exclusive, + ); } } } @@ -2576,25 +3353,36 @@ impl<'o, 's> AnalyzeProc<'o, 's> { err.with_component(dm::Component::DreamChecker) .register(self.context); Analysis::empty() - } + }, } } else { - Analysis::empty() - .with_fix_hint(proc.location, format!("add a return type annotation to {proc}")) + Analysis::empty().with_fix_hint( + proc.location, + format!("add a return type annotation to {proc}"), + ) } } - fn visit_arguments(&mut self, location: Location, args: &'o [Expression], local_vars: &mut HashMap>) { + fn visit_arguments( + &mut self, + location: Location, + args: &'o [Expression], + local_vars: &mut HashMap>, + ) { for arg in args { let mut argument_value = arg; - if let Expression::AssignOp { op: AssignOp::Assign, lhs, rhs } = arg { + if let Expression::AssignOp { + op: AssignOp::Assign, + lhs, + rhs, + } = arg + { match lhs.as_term() { - Some(Term::Ident(_name)) | - Some(Term::String(_name)) => { + Some(Term::Ident(_name)) | Some(Term::String(_name)) => { // Don't visit_expression the kwarg key. argument_value = rhs; - } - _ => {} + }, + _ => {}, } } diff --git a/crates/dreamchecker/src/main.rs b/crates/dreamchecker/src/main.rs index 4f1fd5e0..2ba5ec6c 100644 --- a/crates/dreamchecker/src/main.rs +++ b/crates/dreamchecker/src/main.rs @@ -17,14 +17,17 @@ fn main() { let mut parse_only = false; let mut args = std::env::args(); - let _ = args.next(); // skip executable name + let _ = args.next(); // skip executable name while let Some(arg) = args.next() { if arg == "-V" || arg == "--version" { println!( "dreamchecker {} Copyright (C) 2017-2025 Tad Hardesty", env!("CARGO_PKG_VERSION") ); - println!("{}", include_str!(concat!(env!("OUT_DIR"), "/build-info.txt"))); + println!( + "{}", + include_str!(concat!(env!("OUT_DIR"), "/build-info.txt")) + ); println!("This program comes with ABSOLUTELY NO WARRANTY. This is free software,"); println!("and you are welcome to redistribute it under the conditions of the GNU"); println!("General Public License version 3."); @@ -45,9 +48,11 @@ fn main() { let dme = environment .map(std::path::PathBuf::from) - .unwrap_or_else(|| dm::detect_environment_default() - .expect("error detecting .dme") - .expect("no .dme found")); + .unwrap_or_else(|| { + dm::detect_environment_default() + .expect("error detecting .dme") + .expect("no .dme found") + }); let mut context = dm::Context::default(); context.set_print_severity(Some(dm::Severity::Info)); @@ -59,8 +64,7 @@ fn main() { println!("============================================================"); println!("Parsing {}...\n", dme.display()); - let pp = dm::preprocessor::Preprocessor::new(&context, dme) - .expect("i/o error opening .dme"); + let pp = dm::preprocessor::Preprocessor::new(&context, dme).expect("i/o error opening .dme"); let indents = dm::indents::IndentProcessor::new(&context, pp); let mut parser = dm::parser::Parser::new(&context, indents); parser.enable_procs(); @@ -71,7 +75,11 @@ fn main() { } println!("============================================================"); - let errors = context.errors().iter().filter(|each| each.severity() <= dm::Severity::Info).count(); + let errors = context + .errors() + .iter() + .filter(|each| each.severity() <= dm::Severity::Info) + .count(); println!("Found {errors} diagnostics"); if json { diff --git a/crates/dreamchecker/src/switch_rand_range.rs b/crates/dreamchecker/src/switch_rand_range.rs index f898797c..6627e1db 100644 --- a/crates/dreamchecker/src/switch_rand_range.rs +++ b/crates/dreamchecker/src/switch_rand_range.rs @@ -76,21 +76,18 @@ fn get_case_range(case: &Case, location: Location) -> Option<(f32, f32)> { .ok()? .to_float()?; Some((value, value)) - } + }, Case::Range(ref min, ref max) => { let min = min.to_owned().simple_evaluate(location).ok()?.to_float()?; let max = max.to_owned().simple_evaluate(location).ok()?.to_float()?; Some((min, max)) - } + }, } } fn get_rand_range(maybe_rand: &Expression) -> Option<(i32, i32)> { let (term, location) = match maybe_rand { - Expression::Base { - term, - follow, - } if follow.is_empty() => (&term.elem, term.location), + Expression::Base { term, follow } if follow.is_empty() => (&term.elem, term.location), _ => return None, }; diff --git a/crates/dreamchecker/src/test_helpers.rs b/crates/dreamchecker/src/test_helpers.rs index 0252c57d..5102e7f2 100644 --- a/crates/dreamchecker/src/test_helpers.rs +++ b/crates/dreamchecker/src/test_helpers.rs @@ -8,7 +8,11 @@ pub const NO_ERRORS: &[(u32, u16, &str)] = &[]; pub fn parse_a_file_for_test>>(buffer: S) -> Context { let context = Context::default(); - let pp = dm::preprocessor::Preprocessor::from_buffer(&context, "unit_tests.rs".into(), buffer.into()); + let pp = dm::preprocessor::Preprocessor::from_buffer( + &context, + "unit_tests.rs".into(), + buffer.into(), + ); let indents = dm::indents::IndentProcessor::new(&context, pp); diff --git a/crates/dreamchecker/src/type_expr.rs b/crates/dreamchecker/src/type_expr.rs index cd7ce2ac..e7386a5c 100644 --- a/crates/dreamchecker/src/type_expr.rs +++ b/crates/dreamchecker/src/type_expr.rs @@ -84,7 +84,7 @@ impl<'o> TypeExpr<'o> { } else { else_.evaluate(location, ec) } - } + }, TypeExpr::ParamTypepath { name, @@ -100,7 +100,7 @@ impl<'o> TypeExpr<'o> { } else { Ok(StaticType::None) } - } + }, TypeExpr::ParamStaticType { name, @@ -112,7 +112,7 @@ impl<'o> TypeExpr<'o> { } else { Ok(StaticType::None) } - } + }, } } } @@ -135,16 +135,13 @@ impl<'o> TypeExprCompiler<'o> { expr: &Expression, ) -> Result, DMError> { match expr { - Expression::Base { - term, - follow, - } => { + Expression::Base { term, follow } => { let mut ty = self.visit_term(term.location, &term.elem)?; for each in follow.iter() { ty = self.visit_follow(each.location, ty, &each.elem)?; } Ok(ty) - } + }, Expression::BinaryOp { op: BinaryOp::Or, lhs, @@ -158,7 +155,7 @@ impl<'o> TypeExprCompiler<'o> { if_: Box::new(lty), else_: Box::new(rty), }) - } + }, Expression::BinaryOp { op: BinaryOp::And, lhs, @@ -172,7 +169,7 @@ impl<'o> TypeExprCompiler<'o> { if_: Box::new(rty), else_: Box::new(lty), }) - } + }, Expression::TernaryOp { cond, if_, else_ } => Ok(TypeExpr::Condition { cond: Box::new(self.visit_expression(location, cond)?), if_: Box::new(self.visit_expression(location, if_)?), @@ -200,7 +197,7 @@ impl<'o> TypeExprCompiler<'o> { location, format!("type expr: no such parameter {unscoped_name:?}"), )) - } + }, Term::Expr(expr) => self.visit_expression(location, expr), @@ -208,7 +205,7 @@ impl<'o> TypeExprCompiler<'o> { let bits: Vec<_> = fab.path.iter().map(|(_, name)| name.to_owned()).collect(); let ty = crate::static_type(self.objtree, location, &bits)?; Ok(TypeExpr::from(ty)) - } + }, _ => Err(DMError::new(location, "type expr: bad term node")), } @@ -261,7 +258,10 @@ impl<'o> TypeExprCompiler<'o> { )), }, - _ => Err(DMError::new(location, format!("type expr: bad follow node {rhs:?}"))), + _ => Err(DMError::new( + location, + format!("type expr: bad follow node {rhs:?}"), + )), } } } diff --git a/crates/dreamchecker/tests/branch_eval_tests.rs b/crates/dreamchecker/tests/branch_eval_tests.rs index 4268dfaf..098b7b5f 100644 --- a/crates/dreamchecker/tests/branch_eval_tests.rs +++ b/crates/dreamchecker/tests/branch_eval_tests.rs @@ -14,13 +14,12 @@ fn const_eval() { if(1) return return -"##.trim(); +"## + .trim(); check_errors_match(code, CONST_EVAL_ERRORS); } -pub const IF_ELSE_ERRORS: &[(u32, u16, &str)] = &[ - (6, 5, "possible unreachable code here"), -]; +pub const IF_ELSE_ERRORS: &[(u32, u16, &str)] = &[(6, 5, "possible unreachable code here")]; #[test] fn if_else() { @@ -31,16 +30,25 @@ fn if_else() { else return return -"##.trim(); +"## + .trim(); check_errors_match(code, IF_ELSE_ERRORS); } pub const IF_ARMS_ERRORS: &[(u32, u16, &str)] = &[ (2, 7, "control flow condition is a static term"), (2, 7, "if condition is always true"), - (4, 12, "unreachable if block, preceeding if/elseif condition(s) are always true"), + ( + 4, + 12, + "unreachable if block, preceeding if/elseif condition(s) are always true", + ), // TODO: fix location reporting on this - (7, 9, "unreachable else block, preceeding if/elseif condition(s) are always true"), + ( + 7, + 9, + "unreachable else block, preceeding if/elseif condition(s) are always true", + ), ]; #[test] @@ -53,13 +61,13 @@ fn if_arms() { return else return -"##.trim(); +"## + .trim(); check_errors_match(code, IF_ARMS_ERRORS); } -pub const DO_WHILE_ERRORS: &[(u32, u16, &str)] = &[ - (2, 5, "do while terminates without ever reaching condition"), -]; +pub const DO_WHILE_ERRORS: &[(u32, u16, &str)] = + &[(2, 5, "do while terminates without ever reaching condition")]; #[test] fn do_while() { @@ -68,7 +76,8 @@ fn do_while() { do return while(prob(50)) -"##.trim(); +"## + .trim(); check_errors_match(code, DO_WHILE_ERRORS); } @@ -91,7 +100,8 @@ fn for_loop_condition() { for(var/z = 1; z <= 6; z++) // Legit, should have no error break return -"##.trim(); +"## + .trim(); check_errors_match(code, FOR_LOOP_CONDITION_ERRORS); } @@ -104,13 +114,13 @@ fn for_kv_check() { world.log << k world.log << v -"##.trim(); +"## + .trim(); check_errors_match(code, NO_ERRORS); } -pub const FOR_KV_VAR_ERROR: &[(u32, u16, &str)] = &[ - (3, 19, "for (var/key, value) requires a 'var' keyword"), -]; +pub const FOR_KV_VAR_ERROR: &[(u32, u16, &str)] = + &[(3, 19, "for (var/key, value) requires a 'var' keyword")]; #[test] fn for_kv_var_check() { @@ -121,13 +131,16 @@ fn for_kv_var_check() { world.log << k world.log << v -"##.trim(); +"## + .trim(); check_errors_match(code, FOR_KV_VAR_ERROR); } -pub const FOR_KV_VALUE_ERROR: &[(u32, u16, &str)] = &[ - (3, 23, "value must be a variable in a for (var/key, value) statement"), -]; +pub const FOR_KV_VALUE_ERROR: &[(u32, u16, &str)] = &[( + 3, + 23, + "value must be a variable in a for (var/key, value) statement", +)]; #[test] fn for_kv_value_check() { @@ -136,13 +149,16 @@ fn for_kv_value_check() { var/alist/A = alist() for (var/k, 0 in A) world.log << k -"##.trim(); +"## + .trim(); check_errors_match(code, FOR_KV_VALUE_ERROR); } -pub const FOR_KV_KEY_ERROR: &[(u32, u16, &str)] = &[ - (3, 27, "cannot assigned a value to var/key in a for(var/key, value) statement"), -]; +pub const FOR_KV_KEY_ERROR: &[(u32, u16, &str)] = &[( + 3, + 27, + "cannot assigned a value to var/key in a for(var/key, value) statement", +)]; #[test] fn for_kv_key_check() { @@ -151,6 +167,7 @@ fn for_kv_key_check() { var/alist/A = alist() for (var/k = 5, v in A) world.log << k -"##.trim(); +"## + .trim(); check_errors_match(code, FOR_KV_KEY_ERROR); } diff --git a/crates/dreamchecker/tests/call_ext_tests.rs b/crates/dreamchecker/tests/call_ext_tests.rs index 13ed9fc9..bd8a816f 100644 --- a/crates/dreamchecker/tests/call_ext_tests.rs +++ b/crates/dreamchecker/tests/call_ext_tests.rs @@ -2,15 +2,15 @@ extern crate dreamchecker as dc; use dc::test_helpers::*; -pub const CALL_EXT_MISSING_CALL_ERRORS: &[(u32, u16, &str)] = &[ - (2, 19, "got ';', expected one of: '('"), -]; +pub const CALL_EXT_MISSING_CALL_ERRORS: &[(u32, u16, &str)] = + &[(2, 19, "got ';', expected one of: '('")]; #[test] fn call_ext_missing_call() { let code = r##" /proc/f() call_ext(1, 2) -"##.trim(); +"## + .trim(); check_errors_match(code, CALL_EXT_MISSING_CALL_ERRORS); } diff --git a/crates/dreamchecker/tests/directive_tests.rs b/crates/dreamchecker/tests/directive_tests.rs index a671e9a3..09b3fccf 100644 --- a/crates/dreamchecker/tests/directive_tests.rs +++ b/crates/dreamchecker/tests/directive_tests.rs @@ -2,9 +2,8 @@ extern crate dreamchecker as dc; use dc::test_helpers::*; -pub const TRUE_SUB_ERRORS: &[(u32, u16, &str)] = &[ - (4, 18, "proc never calls parent, required by /mob/proc/test"), -]; +pub const TRUE_SUB_ERRORS: &[(u32, u16, &str)] = + &[(4, 18, "proc never calls parent, required by /mob/proc/test")]; #[test] fn true_substitution() { @@ -14,7 +13,8 @@ fn true_substitution() { /mob/subtype/test() return -"##.trim(); +"## + .trim(); check_errors_match(code, TRUE_SUB_ERRORS); } @@ -28,7 +28,8 @@ fn call_parent() { return /mob/anothertype/test() ..() -"##.trim(); +"## + .trim(); check_errors_match(code, TRUE_SUB_ERRORS); } @@ -41,13 +42,13 @@ fn call_parent_disable() { /mob/subtype/test() set SpacemanDMM_should_call_parent = 0 return -"##.trim(); +"## + .trim(); check_errors_match(code, NO_ERRORS); } -pub const NO_OVERRIDE_ERRORS: &[(u32, u16, &str)] = &[ - (4, 18, "proc overrides parent, prohibited by /mob/proc/test"), -]; +pub const NO_OVERRIDE_ERRORS: &[(u32, u16, &str)] = + &[(4, 18, "proc overrides parent, prohibited by /mob/proc/test")]; #[test] fn no_override() { @@ -57,11 +58,11 @@ fn no_override() { /mob/subtype/test() return -"##.trim(); +"## + .trim(); check_errors_match(code, NO_OVERRIDE_ERRORS); } - #[test] fn final_proc() { let code = r##" @@ -70,7 +71,8 @@ fn final_proc() { /mob/subtype/test() return -"##.trim(); +"## + .trim(); check_errors_match(code, NO_OVERRIDE_ERRORS); } @@ -79,7 +81,6 @@ pub const NO_OVERRIDE_DISABLE_ERRORS: &[(u32, u16, &str)] = &[ (4, 18, "proc overrides parent, prohibited by /mob/proc/test"), ]; - #[test] fn no_override_disable() { let code = r##" @@ -89,7 +90,8 @@ fn no_override_disable() { /mob/subtype/test() set SpacemanDMM_should_not_override = 0 return -"##.trim(); +"## + .trim(); check_errors_match(code, NO_OVERRIDE_DISABLE_ERRORS); } @@ -102,7 +104,8 @@ fn final_proc_intermix() { /mob/subtype/test() set SpacemanDMM_should_not_override = 0 return -"##.trim(); +"## + .trim(); check_errors_match(code, NO_OVERRIDE_DISABLE_ERRORS); } @@ -115,13 +118,12 @@ fn can_be_redefined() { /mob/test() return -"##.trim(); +"## + .trim(); check_errors_match(code, NO_ERRORS); } -pub const NO_CAN_BE_REDEFINED_ERRORS: &[(u32, u16, &str)] = &[ - (4, 10, "redefining proc /mob/test"), -]; +pub const NO_CAN_BE_REDEFINED_ERRORS: &[(u32, u16, &str)] = &[(4, 10, "redefining proc /mob/test")]; #[test] fn no_can_be_redefined() { @@ -131,6 +133,7 @@ fn no_can_be_redefined() { /mob/test() return -"##.trim(); +"## + .trim(); check_errors_match(code, NO_CAN_BE_REDEFINED_ERRORS); } diff --git a/crates/dreamchecker/tests/kwargs_tests.rs b/crates/dreamchecker/tests/kwargs_tests.rs index abb75226..8c5171a0 100644 --- a/crates/dreamchecker/tests/kwargs_tests.rs +++ b/crates/dreamchecker/tests/kwargs_tests.rs @@ -2,9 +2,8 @@ extern crate dreamchecker as dc; use dc::test_helpers::*; -pub const AFTER_KWARG_ERRORS: &[(u32, u16, &str)] = &[ - (3, 5, "proc called with non-kwargs after kwargs: foo()"), -]; +pub const AFTER_KWARG_ERRORS: &[(u32, u16, &str)] = + &[(3, 5, "proc called with non-kwargs after kwargs: foo()")]; #[test] fn after_kwarg() { @@ -12,18 +11,47 @@ fn after_kwarg() { /proc/foo(arg1, arg2, arg3) /proc/test() foo(arg2=1, 1) -"##.trim(); +"## + .trim(); check_errors_match(code, AFTER_KWARG_ERRORS); } pub const FILTER_KWARGS_ERRORS: &[(u32, u16, &str)] = &[ - (4, 5, "filter(type=\"color\") called with invalid 'space' value 'Null'"), - (15, 5, "filter(type=\"alpha\") called with invalid keyword parameter 'color'"), - (16, 5, "filter(type=\"blur\") called with invalid keyword parameter 'x'"), - (17, 5, "filter() called with invalid type keyword parameter value 'fakename'"), - (18, 5, "filter() called without mandatory keyword parameter 'type'"), - (19, 5, "filter() called without mandatory keyword parameter 'type'"), - (20, 5, "filter(type=\"wave\") called with invalid keyword parameter 'color'"), + ( + 4, + 5, + "filter(type=\"color\") called with invalid 'space' value 'Null'", + ), + ( + 15, + 5, + "filter(type=\"alpha\") called with invalid keyword parameter 'color'", + ), + ( + 16, + 5, + "filter(type=\"blur\") called with invalid keyword parameter 'x'", + ), + ( + 17, + 5, + "filter() called with invalid type keyword parameter value 'fakename'", + ), + ( + 18, + 5, + "filter() called without mandatory keyword parameter 'type'", + ), + ( + 19, + 5, + "filter() called without mandatory keyword parameter 'type'", + ), + ( + 20, + 5, + "filter(type=\"wave\") called with invalid keyword parameter 'color'", + ), ]; #[test] diff --git a/crates/dreamchecker/tests/local_vars_tests.rs b/crates/dreamchecker/tests/local_vars_tests.rs index 6bb3187e..a04e1886 100644 --- a/crates/dreamchecker/tests/local_vars_tests.rs +++ b/crates/dreamchecker/tests/local_vars_tests.rs @@ -24,6 +24,7 @@ fn local_scope() { alabel: var/bar bar++ -"##.trim(); +"## + .trim(); check_errors_match(code, LOCAL_SCOPE_ERRORS); } diff --git a/crates/dreamchecker/tests/new_tests.rs b/crates/dreamchecker/tests/new_tests.rs index 0f74f3f1..18c6aad9 100644 --- a/crates/dreamchecker/tests/new_tests.rs +++ b/crates/dreamchecker/tests/new_tests.rs @@ -2,9 +2,11 @@ extern crate dreamchecker as dc; use dc::test_helpers::*; -pub const NEW_DOT_ERRORS: &[(u32, u16, &str)] = &[ - (12, 14, "got '(', expected one of: operator, field access, ';'"), -]; +pub const NEW_DOT_ERRORS: &[(u32, u16, &str)] = &[( + 12, + 14, + "got '(', expected one of: operator, field access, ';'", +)]; #[test] fn new_dot() { @@ -23,13 +25,16 @@ fn new_dot() { new foo()() new /obj[0]() // TODO: see parser.rs new 2 + 2() // TODO: see parser.rs -"#.trim(); +"# + .trim(); check_errors_match(code, NEW_DOT_ERRORS); } -pub const NEW_PRECEDENCE_ERRORS: &[(u32, u16, &str)] = &[ - (4, 13, "got '(', expected one of: operator, field access, ';'"), -]; +pub const NEW_PRECEDENCE_ERRORS: &[(u32, u16, &str)] = &[( + 4, + 13, + "got '(', expected one of: operator, field access, ';'", +)]; #[test] fn new_precedence() { @@ -38,6 +43,7 @@ fn new_precedence() { /mob/proc/foo() /mob/proc/test() new L[1]() -"##.trim(); +"## + .trim(); check_errors_match(code, NEW_PRECEDENCE_ERRORS); } diff --git a/crates/dreamchecker/tests/operator_tests.rs b/crates/dreamchecker/tests/operator_tests.rs index 94907d6f..2dd1efa9 100644 --- a/crates/dreamchecker/tests/operator_tests.rs +++ b/crates/dreamchecker/tests/operator_tests.rs @@ -30,13 +30,16 @@ fn in_ambig() { return if((i ? 1 : 2) in list()) return -"##.trim(); +"## + .trim(); check_errors_match(code, IN_AMBIG_ERRORS); } -pub const TERNARY_IN_AMBIG_ERRORS: &[(u32, u16, &str)] = &[ - (2, 14, "got \'in\', expected one of: operator, field access, \':\'"), -]; +pub const TERNARY_IN_AMBIG_ERRORS: &[(u32, u16, &str)] = &[( + 2, + 14, + "got \'in\', expected one of: operator, field access, \':\'", +)]; #[test] fn ambig_in_ternary_cond() { @@ -44,13 +47,16 @@ fn ambig_in_ternary_cond() { /proc/test() if(i ? 1 in list() : 2) return -"##.trim(); +"## + .trim(); check_errors_match(code, TERNARY_IN_AMBIG_ERRORS); } -pub const OP_OVERLOAD_ERRORS: &[(u32, u16, &str)] = &[ - (6, 6, "Attempting operator++ on a /mob which does not overload operator++"), -]; +pub const OP_OVERLOAD_ERRORS: &[(u32, u16, &str)] = &[( + 6, + 6, + "Attempting operator++ on a /mob which does not overload operator++", +)]; #[test] fn operator_overload() { @@ -63,7 +69,8 @@ fn operator_overload() { M++ var/mob/test/T = new T++ -"##.trim(); +"## + .trim(); check_errors_match(code, OP_OVERLOAD_ERRORS); } @@ -87,6 +94,7 @@ fn ambigous_not_bitwise() { return if (1++ & 1) return -"##.trim(); +"## + .trim(); check_errors_match(code, NOT_AMBIG_BITWISE_ERRORS); } diff --git a/crates/dreamchecker/tests/private_tests.rs b/crates/dreamchecker/tests/private_tests.rs index aca74d15..a12a6ee6 100644 --- a/crates/dreamchecker/tests/private_tests.rs +++ b/crates/dreamchecker/tests/private_tests.rs @@ -30,14 +30,19 @@ fn private_proc() { M.private2() var/mob/subtype/S = new S.private() -"##.trim(); +"## + .trim(); check_errors_match(code, PRIVATE_PROC_ERRORS); } pub const PRIVATE_VAR_ERRORS: &[(u32, u16, &str)] = &[ (5, 9, "/mob/subtype overrides private var \"foo\""), (12, 6, "field \"bar\" on /mob is declared as private"), - (14, 6, "field \"foo\" on /mob/subtype is declared as private"), + ( + 14, + 6, + "field \"foo\" on /mob/subtype is declared as private", + ), ]; #[test] @@ -57,13 +62,22 @@ fn private_var() { M.bar = TRUE var/mob/subtype/S = new S.foo = TRUE -"##.trim(); +"## + .trim(); check_errors_match(code, PRIVATE_VAR_ERRORS); } pub const PROTECTED_PROC_ERRORS: &[(u32, u16, &str)] = &[ - (15, 6, "/obj/proc/test attempting to call protected proc /mob/proc/protected2"), - (17, 6, "/obj/proc/test attempting to call protected proc /mob/proc/protected"), + ( + 15, + 6, + "/obj/proc/test attempting to call protected proc /mob/proc/protected2", + ), + ( + 17, + 6, + "/obj/proc/test attempting to call protected proc /mob/proc/protected", + ), ]; #[test] @@ -86,13 +100,18 @@ fn protected_proc() { M.protected2() var/mob/subtype/S = new S.protected() -"##.trim(); +"## + .trim(); check_errors_match(code, PROTECTED_PROC_ERRORS); } pub const PROTECTED_VAR_ERRORS: &[(u32, u16, &str)] = &[ (12, 6, "field \"bar\" on /mob is declared as protected"), - (14, 6, "field \"foo\" on /mob/subtype is declared as protected"), + ( + 14, + 6, + "field \"foo\" on /mob/subtype is declared as protected", + ), ]; #[test] @@ -112,6 +131,7 @@ fn protected_var() { M.bar = TRUE var/mob/subtype/S = new S.foo = TRUE -"##.trim(); +"## + .trim(); check_errors_match(code, PROTECTED_VAR_ERRORS); } diff --git a/crates/dreamchecker/tests/proc_tests.rs b/crates/dreamchecker/tests/proc_tests.rs index 8edca7a2..f5c4d7f0 100644 --- a/crates/dreamchecker/tests/proc_tests.rs +++ b/crates/dreamchecker/tests/proc_tests.rs @@ -3,9 +3,7 @@ extern crate dreamchecker as dc; use dc::test_helpers::check_errors_match; use dc::test_helpers::parse_a_file_for_test; -pub const NO_PARENT_ERRORS: &[(u32, u16, &str)] = &[ - (2, 5, "proc has no parent: /mob/proc/test"), -]; +pub const NO_PARENT_ERRORS: &[(u32, u16, &str)] = &[(2, 5, "proc has no parent: /mob/proc/test")]; #[test] fn no_parent() { @@ -13,7 +11,8 @@ fn no_parent() { /mob/proc/test() ..() return -"##.trim(); +"## + .trim(); check_errors_match(code, NO_PARENT_ERRORS); } @@ -25,9 +24,14 @@ fn return_type() { /mob/proc/test2() as num return -"##.trim(); +"## + .trim(); let context = parse_a_file_for_test(code); - let error_text: Vec = context.errors().iter().map(|error| format!("{error}")).collect(); + let error_text: Vec = context + .errors() + .iter() + .map(|error| format!("{error}")) + .collect(); if !error_text.is_empty() { panic!("\n{}", error_text.join("\n")) } @@ -49,6 +53,7 @@ fn return_type_failure() { /mob/proc/test2() as incorrect return -"##.trim(); +"## + .trim(); check_errors_match(code, RETURN_TYPE_FAILURE_ERRORS); } diff --git a/crates/dreamchecker/tests/sleep_pure_tests.rs b/crates/dreamchecker/tests/sleep_pure_tests.rs index c709d9bd..722dba1d 100644 --- a/crates/dreamchecker/tests/sleep_pure_tests.rs +++ b/crates/dreamchecker/tests/sleep_pure_tests.rs @@ -2,9 +2,11 @@ extern crate dreamchecker as dc; use dc::test_helpers::check_errors_match; -pub const SLEEP_ERRORS: &[(u32, u16, &str)] = &[ - (16, 16, "/mob/proc/test3 sets SpacemanDMM_should_not_sleep but calls blocking proc /proc/sleepingproc"), -]; +pub const SLEEP_ERRORS: &[(u32, u16, &str)] = &[( + 16, + 16, + "/mob/proc/test3 sets SpacemanDMM_should_not_sleep but calls blocking proc /proc/sleepingproc", +)]; #[test] fn sleep() { @@ -40,7 +42,8 @@ fn sleep() { /mob/proc/test6() set SpacemanDMM_should_not_sleep = TRUE spawnthensleepproc() -"##.trim(); +"## + .trim(); check_errors_match(code, SLEEP_ERRORS); } @@ -74,7 +77,8 @@ fn sleep2() { sleep(1) /mob/living/thing() . = ..() -"##.trim(); +"## + .trim(); check_errors_match(code, SLEEP_ERRORS2); } @@ -105,7 +109,8 @@ fn sleep3() { sleep(1) /atom/movable/thing() . = ..() -"##.trim(); +"## + .trim(); check_errors_match(code, &[ (8, 23, "/atom/movable/proc/bar calls /atom/movable/proc/foo which has override child proc that sleeps /mob/proc/foo"), ]); @@ -144,7 +149,8 @@ fn sleep4() { /mob/proc/test2() var/client/C = new /client C.MeasureText() -"##.trim(); +"## + .trim(); check_errors_match(code, SLEEP_ERROR4); } @@ -170,7 +176,8 @@ fn sleep5() { /datum/hijack/proxy() sleep(1) -"##.trim(); +"## + .trim(); check_errors_match(code, SLEEP_ERROR5); } @@ -195,15 +202,15 @@ fn pure() { /mob/proc/test2() set SpacemanDMM_should_be_pure = TRUE bar() -"#.trim(); +"# + .trim(); check_errors_match(code, PURE_ERRORS); } // these tests are separate because the ordering the errors are reported in isn't determinate and I CBF figuring out why -spookydonut Jan 2020 // TODO: find out why -pub const PURE2_ERRORS: &[(u32, u16, &str)] = &[ - (5, 5, "call to pure proc test discards return value"), -]; +pub const PURE2_ERRORS: &[(u32, u16, &str)] = + &[(5, 5, "call to pure proc test discards return value")]; #[test] fn pure2() { @@ -215,6 +222,7 @@ fn pure2() { test() /mob/proc/test3() return test() -"##.trim(); +"## + .trim(); check_errors_match(code, PURE2_ERRORS); } diff --git a/crates/dreamchecker/tests/static_type_tests.rs b/crates/dreamchecker/tests/static_type_tests.rs index 4da1e0c3..d874c89d 100644 --- a/crates/dreamchecker/tests/static_type_tests.rs +++ b/crates/dreamchecker/tests/static_type_tests.rs @@ -16,7 +16,8 @@ fn field_access() { L?[1].name var/atom/movable/particle_holder = new particle_holder.particles.height -"##.trim(); +"## + .trim(); check_errors_match(code, FIELD_ACCESS_ERRORS); } @@ -33,13 +34,12 @@ fn proc_call() { L[1].foo() L?[1].foo() /mob/proc/foo() -"##.trim(); +"## + .trim(); check_errors_match(code, PROC_CALL_ERRORS); } -pub const RETURN_TYPE_ERRORS: &[(u32, u16, &str)] = &[ - (3, 16, "undefined proc: \"foo\" on /atom"), -]; +pub const RETURN_TYPE_ERRORS: &[(u32, u16, &str)] = &[(3, 16, "undefined proc: \"foo\" on /atom")]; #[test] fn return_type() { @@ -48,6 +48,7 @@ fn return_type() { viewers()[1].foo() orange()[1].foo() /mob/proc/foo() -"##.trim(); +"## + .trim(); check_errors_match(code, RETURN_TYPE_ERRORS); } diff --git a/crates/dreamchecker/tests/switch_rand_range_tests.rs b/crates/dreamchecker/tests/switch_rand_range_tests.rs index dbcb26ed..d38b5d20 100644 --- a/crates/dreamchecker/tests/switch_rand_range_tests.rs +++ b/crates/dreamchecker/tests/switch_rand_range_tests.rs @@ -3,8 +3,16 @@ extern crate dreamchecker as dc; use dc::test_helpers::*; pub const SWITCH_RAND_INCOMPLETE_ERRORS: &[(u32, u16, &str)] = &[ - (4, 19, "Case range '0 to 0' will never trigger as it is outside the rand() range 1 to 3"), - (2, 5, "Switch branches on rand() with range 1 to 3 but no case branch triggers for 3"), + ( + 4, + 19, + "Case range '0 to 0' will never trigger as it is outside the rand() range 1 to 3", + ), + ( + 2, + 5, + "Switch branches on rand() with range 1 to 3 but no case branch triggers for 3", + ), ]; #[test] @@ -18,14 +26,16 @@ fn switch_rand_incomplete() { return if(2) return -"##.trim(); +"## + .trim(); check_errors_match(code, SWITCH_RAND_INCOMPLETE_ERRORS); } - -pub const SWITCH_RAND_WITH_EVALUATION_ERRORS: &[(u32, u16, &str)] = &[ - (2, 5, "Switch branches on rand() with range 2 to 3 but no case branch triggers for 3"), -]; +pub const SWITCH_RAND_WITH_EVALUATION_ERRORS: &[(u32, u16, &str)] = &[( + 2, + 5, + "Switch branches on rand() with range 2 to 3 but no case branch triggers for 3", +)]; #[test] fn switch_rand_with_evaluation() { @@ -34,11 +44,11 @@ fn switch_rand_with_evaluation() { switch(rand(1 + 1, 4 - 1)) if(3 - 1) return -"##.trim(); +"## + .trim(); check_errors_match(code, SWITCH_RAND_WITH_EVALUATION_ERRORS); } - #[test] fn switch_rand_case_ranges() { let code = r##" @@ -48,14 +58,16 @@ fn switch_rand_case_ranges() { return if(3, 4) return -"##.trim(); +"## + .trim(); check_errors_match(code, &[]); } - -pub const SWITCH_RAND_DEFAULT_ERRORS: &[(u32, u16, &str)] = &[ - (4, 19, "Case range '5 to 5' will never trigger as it is outside the rand() range 1 to 4"), -]; +pub const SWITCH_RAND_DEFAULT_ERRORS: &[(u32, u16, &str)] = &[( + 4, + 19, + "Case range '5 to 5' will never trigger as it is outside the rand() range 1 to 4", +)]; #[test] fn switch_rand_default() { @@ -68,12 +80,11 @@ fn switch_rand_default() { return else return -"##.trim(); +"## + .trim(); check_errors_match(code, SWITCH_RAND_DEFAULT_ERRORS); } - - #[test] fn switch_rand_floats() { let code = r##" @@ -85,12 +96,11 @@ fn switch_rand_floats() { return if(2.5 to 400) return -"##.trim(); +"## + .trim(); check_errors_match(code, &[]); } - - #[test] fn switch_rand_out_of_order() { let code = r##" @@ -102,6 +112,7 @@ fn switch_rand_out_of_order() { return if(1) return -"##.trim(); +"## + .trim(); check_errors_match(code, &[]); } diff --git a/crates/dreamchecker/tests/var_declare_tests.rs b/crates/dreamchecker/tests/var_declare_tests.rs index 3f175487..67fbfca7 100644 --- a/crates/dreamchecker/tests/var_declare_tests.rs +++ b/crates/dreamchecker/tests/var_declare_tests.rs @@ -2,9 +2,7 @@ extern crate dreamchecker as dc; use dc::test_helpers::*; -pub const VAR_DEC_ERRORS: &[(u32, u16, &str)] = &[ - (5, 12, "/mob/subtype redeclares var \"foo\""), -]; +pub const VAR_DEC_ERRORS: &[(u32, u16, &str)] = &[(5, 12, "/mob/subtype redeclares var \"foo\"")]; #[test] fn var_redec() { @@ -14,13 +12,13 @@ fn var_redec() { /mob/subtype var/foo -"##.trim(); +"## + .trim(); check_errors_match(code, VAR_DEC_ERRORS); } -pub const VAR_FINAL_ERRORS: &[(u32, u16, &str)] = &[ - (5, 9, "/mob/subtype overrides final var \"foo\""), -]; +pub const VAR_FINAL_ERRORS: &[(u32, u16, &str)] = + &[(5, 9, "/mob/subtype overrides final var \"foo\"")]; #[test] fn var_spaceman_final() { @@ -30,7 +28,8 @@ fn var_spaceman_final() { /mob/subtype foo = 1 -"##.trim(); +"## + .trim(); check_errors_match(code, VAR_FINAL_ERRORS); } @@ -42,13 +41,12 @@ fn var_final() { /mob/subtype foo = 1 -"##.trim(); +"## + .trim(); check_errors_match(code, VAR_FINAL_ERRORS); } -pub const VAR_UNDECL_ERRORS: &[(u32, u16, &str)] = &[ - (6, 5, "undefined var: \"bar\""), -]; +pub const VAR_UNDECL_ERRORS: &[(u32, u16, &str)] = &[(6, 5, "undefined var: \"bar\"")]; #[test] fn var_undecl() { @@ -59,7 +57,7 @@ fn var_undecl() { /mob/proc/test() foo++ bar++ -"##.trim(); +"## + .trim(); check_errors_match(code, VAR_UNDECL_ERRORS); } - diff --git a/crates/dreammaker/examples/count-vars.rs b/crates/dreammaker/examples/count-vars.rs index 82d78cab..81a486ea 100644 --- a/crates/dreammaker/examples/count-vars.rs +++ b/crates/dreammaker/examples/count-vars.rs @@ -7,8 +7,7 @@ fn main() { let env = dm::detect_environment_default() .expect("error detecting .dme") .expect("no .dme found"); - let pp = dm::preprocessor::Preprocessor::new(&context, env) - .expect("i/o error opening .dme"); + let pp = dm::preprocessor::Preprocessor::new(&context, env).expect("i/o error opening .dme"); let indents = dm::indents::IndentProcessor::new(&context, pp); let mut parser = dm::parser::Parser::new(&context, indents); parser.enable_procs(); @@ -25,5 +24,10 @@ fn main() { } } }); - println!("decls: {}\noverrides: {}\ntotal: {}", decls, overrides, decls + overrides); + println!( + "decls: {}\noverrides: {}\ntotal: {}", + decls, + overrides, + decls + overrides + ); } diff --git a/crates/dreammaker/examples/flags.rs b/crates/dreammaker/examples/flags.rs index 8a13026f..a8dc283c 100644 --- a/crates/dreammaker/examples/flags.rs +++ b/crates/dreammaker/examples/flags.rs @@ -32,29 +32,24 @@ fn main() { .unwrap_or(0); // Migrate old flags_1 values to their item_flags equivalents - let lhs = - if flags_1 & (1<<1) != 0 { 1<<8 } else { 0 } | - if flags_1 & (1<<2) != 0 { 1<<7 } else { 0 } | - if flags_1 & (1<<6) != 0 { 1<<9 } else { 0 } | - if flags_1 & (1<<10) != 0 { 1<<6 } else { 0 }; - flags_1 &= !((1<<1) | (1<<2) | (1<<6) | (1<<10)); + let lhs = if flags_1 & (1 << 1) != 0 { 1 << 8 } else { 0 } + | if flags_1 & (1 << 2) != 0 { 1 << 7 } else { 0 } + | if flags_1 & (1 << 6) != 0 { 1 << 9 } else { 0 } + | if flags_1 & (1 << 10) != 0 { 1 << 6 } else { 0 }; + flags_1 &= !((1 << 1) | (1 << 2) | (1 << 6) | (1 << 10)); - let rhs = item_flags & ((1<<6) | (1<<7) | (1<<8) | (1<<9)); + let rhs = item_flags & ((1 << 6) | (1 << 7) | (1 << 8) | (1 << 9)); item_flags &= !rhs; let crossover = if rhs != 0 && lhs != 0 { - panic!( - "flags_1={flags_1}, item_flags={item_flags}, lhs={lhs}, rhs={rhs}" - ); + panic!("flags_1={flags_1}, item_flags={item_flags}, lhs={lhs}, rhs={rhs}"); } else if lhs != 0 { lhs } else { rhs }; - println!( - "flags_1={flags_1}, item_flags={item_flags}, crossover={crossover}" - ); + println!("flags_1={flags_1}, item_flags={item_flags}, crossover={crossover}"); }); println!("---- anchored example ----"); @@ -68,17 +63,22 @@ fn main() { println!("{} -> {}", ty.path, anch); // print location info for any type with a redundant `anchored = TRUE` - if anch && ty - .parent_type() - .unwrap() - .get_value("anchored") - .unwrap() - .constant - .as_ref() - .unwrap() - .to_bool() + if anch + && ty + .parent_type() + .unwrap() + .get_value("anchored") + .unwrap() + .constant + .as_ref() + .unwrap() + .to_bool() { - println!("{}:{}", ctx.file_path(var.location.file).display(), var.location.line); + println!( + "{}:{}", + ctx.file_path(var.location.file).display(), + var.location.line + ); } }); } diff --git a/crates/dreammaker/examples/lint.rs b/crates/dreammaker/examples/lint.rs index 74ea3fc1..3dc2be53 100644 --- a/crates/dreammaker/examples/lint.rs +++ b/crates/dreammaker/examples/lint.rs @@ -9,8 +9,7 @@ fn main() { let env = dm::detect_environment_default() .expect("error detecting .dme") .expect("no .dme found"); - let pp = dm::preprocessor::Preprocessor::new(&context, env) - .expect("i/o error opening .dme"); + let pp = dm::preprocessor::Preprocessor::new(&context, env).expect("i/o error opening .dme"); let indents = dm::indents::IndentProcessor::new(&context, pp); let mut parser = dm::parser::Parser::new(&context, indents); parser.enable_procs(); diff --git a/crates/dreammaker/src/annotation.rs b/crates/dreammaker/src/annotation.rs index 3ee0877a..a43c3b67 100644 --- a/crates/dreammaker/src/annotation.rs +++ b/crates/dreammaker/src/annotation.rs @@ -27,9 +27,9 @@ pub enum Annotation { UnscopedVar(Ident), ScopedCall(Vec, Ident), ScopedVar(Vec, Ident), - ParentCall, // .. - ReturnVal, // . - InSequence(usize), // where in TreePath or TypePath is this ident + ParentCall, // .. + ReturnVal, // . + InSequence(usize), // where in TreePath or TypePath is this ident // a macro is called here, which is defined at this location MacroDefinition(Ident), @@ -43,12 +43,12 @@ pub enum Annotation { Resource(std::path::PathBuf), // error annotations, mostly for autocompletion - ScopedMissingIdent(Vec), // when a . is followed by a non-ident + ScopedMissingIdent(Vec), // when a . is followed by a non-ident IncompleteTypePath(TypePath, PathOp), IncompleteTreePath(bool, Vec), - ProcArguments(Vec, String, usize), // Vec empty for unscoped call - ProcArgument(usize), // where in the prog arguments we are + ProcArguments(Vec, String, usize), // Vec empty for unscoped call + ProcArgument(usize), // where in the prog arguments we are } #[derive(Debug)] @@ -68,7 +68,8 @@ impl Default for AnnotationTree { impl AnnotationTree { pub fn insert(&mut self, place: std::ops::Range, value: Annotation) { - self.tree.insert(range(place.start, place.end.pred()), value); + self.tree + .insert(range(place.start, place.end.pred()), value); self.len += 1; } diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 27864c9b..ad9921fe 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -134,7 +134,7 @@ pub enum BinaryOp { And, Or, In, - To, // only appears in RHS of `In` + To, // only appears in RHS of `In` } impl fmt::Display for BinaryOp { @@ -331,7 +331,10 @@ pub struct ProcDeclBuilder { impl ProcDeclBuilder { pub fn new(kind: ProcDeclKind, flags: Option) -> ProcDeclBuilder { - ProcDeclBuilder { kind, flags: flags.unwrap_or_default() } + ProcDeclBuilder { + kind, + flags: flags.unwrap_or_default(), + } } pub fn kind(self) -> &'static str { @@ -415,14 +418,18 @@ impl ProcFlags { pub fn to_vec(&self) -> Vec<&'static str> { let mut v = Vec::new(); - if self.is_final() { v.push("final"); } + if self.is_final() { + v.push("final"); + } v } } impl fmt::Display for ProcFlags { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - if self.is_final() { fmt.write_str("/final")?; } + if self.is_final() { + fmt.write_str("/final")?; + } Ok(()) } } @@ -627,7 +634,8 @@ impl VarTypeFlags { #[inline] pub fn is_const_evaluable(&self) -> bool { - self.contains(VarTypeFlags::CONST) || !self.intersects(VarTypeFlags::STATIC | VarTypeFlags::PROTECTED) + self.contains(VarTypeFlags::CONST) + || !self.intersects(VarTypeFlags::STATIC | VarTypeFlags::PROTECTED) } #[inline] @@ -637,12 +645,24 @@ impl VarTypeFlags { pub fn to_vec(&self) -> Vec<&'static str> { let mut v = Vec::new(); - if self.is_static() { v.push("static"); } - if self.is_const() { v.push("const"); } - if self.is_tmp() { v.push("tmp"); } - if self.is_final() { v.push("final"); } - if self.is_private() { v.push("SpacemanDMM_private"); } - if self.is_protected() { v.push("SpacemanDMM_protected"); } + if self.is_static() { + v.push("static"); + } + if self.is_const() { + v.push("const"); + } + if self.is_tmp() { + v.push("tmp"); + } + if self.is_final() { + v.push("final"); + } + if self.is_private() { + v.push("SpacemanDMM_private"); + } + if self.is_protected() { + v.push("SpacemanDMM_protected"); + } v } } @@ -813,7 +833,7 @@ pub struct FormatVars<'a, T>(pub &'a T); impl<'a, T, K, V> fmt::Display for FormatVars<'a, T> where - &'a T: IntoIterator, + &'a T: IntoIterator, K: fmt::Display, V: fmt::Display, { @@ -867,7 +887,7 @@ pub enum Expression { if_: Box, /// The value otherwise. else_: Box, - } + }, } impl Expression { @@ -897,25 +917,28 @@ impl Expression { match self { Expression::BinaryOp { op, lhs, rhs } => { let Some(lhterm) = lhs.as_term() else { - return false + return false; }; let Some(rhterm) = rhs.as_term() else { - return false + return false; }; if !lhterm.is_static() { - return false + return false; } if !rhterm.is_static() { - return false + return false; } - matches!(op, BinaryOp::Eq | - BinaryOp::NotEq | - BinaryOp::Less | - BinaryOp::Greater | - BinaryOp::LessEq | - BinaryOp::GreaterEq | - BinaryOp::And | - BinaryOp::Or) + matches!( + op, + BinaryOp::Eq + | BinaryOp::NotEq + | BinaryOp::Less + | BinaryOp::Greater + | BinaryOp::LessEq + | BinaryOp::GreaterEq + | BinaryOp::And + | BinaryOp::Or + ) }, _ => false, } @@ -959,7 +982,7 @@ impl Expression { } else { else_.is_truthy() } - } + }, } } @@ -971,8 +994,8 @@ impl Expression { } else { term.elem.nameof() } - } - _ => None + }, + _ => None, } } } @@ -1012,7 +1035,7 @@ pub enum Term { __PROC__, /// A reference to the current proc/scope's type __TYPE__, - /// If rhs of an assignment op, this is a reference to the lhs var's type + /// If rhs of an assignment op, this is a reference to the lhs var's type /// If we're used as the second arg of an istype then it's the implied type of the first arg /// Second case takes precedence over the first, but we don't properly implement because it would be impossible to /// Tell. You can't DO anything to the __IMPLIED_TYPE__ so we don't really need to care about it @@ -1057,7 +1080,7 @@ pub enum Term { /// An `input` call. Input { args: Box<[Expression]>, - input_type: Option, // as + input_type: Option, // as in_list: Option>, // in }, /// A `locate` call. @@ -1083,12 +1106,9 @@ pub enum Term { impl Term { pub fn is_static(&self) -> bool { - matches!(self, - Term::Null - | Term::Int(_) - | Term::Float(_) - | Term::String(_) - | Term::Prefab(_) + matches!( + self, + Term::Null | Term::Int(_) | Term::Float(_) | Term::String(_) | Term::Prefab(_) ) } @@ -1130,18 +1150,18 @@ impl Term { if let Term::Int(o) = *other { // edge case if i == 0 && o == 0 { - return Some(false) + return Some(false); } if let Some(stepexp) = step { if let Some(stepterm) = stepexp.as_term() { if let Term::Int(_s) = stepterm { - return Some(true) + return Some(true); } } else { - return Some(true) + return Some(true); } } - return Some(i <= o) + return Some(i <= o); } } None @@ -1161,13 +1181,15 @@ impl Term { impl From for Term { fn from(expr: Expression) -> Term { match expr { - Expression::Base { term, follow } => if follow.is_empty() { - match term.elem { - Term::Expr(expr) => Term::from(*expr), - other => other, + Expression::Base { term, follow } => { + if follow.is_empty() { + match term.elem { + Term::Expr(expr) => Term::from(*expr), + other => other, + } + } else { + Term::Expr(Box::new(Expression::Base { term, follow })) } - } else { - Term::Expr(Box::new(Expression::Base { term, follow })) }, other => Term::Expr(Box::new(other)), } @@ -1269,7 +1291,7 @@ impl VarType { } impl FromIterator for VarType { - fn from_iter>(iter: T) -> Self { + fn from_iter>(iter: T) -> Self { VarTypeBuilder::from_iter(iter).build() } } @@ -1310,7 +1332,7 @@ impl VarTypeBuilder { } impl FromIterator for VarTypeBuilder { - fn from_iter>(iter: T) -> Self { + fn from_iter>(iter: T) -> Self { let mut flags = VarTypeFlags::default(); let type_path = iter .into_iter() @@ -1380,7 +1402,7 @@ pub enum Statement { }, If { arms: Vec<(Spanned, Block)>, - else_arm: Option + else_arm: Option, }, ForInfinite { block: Block, @@ -1399,7 +1421,7 @@ pub enum Statement { Setting { name: Ident2, mode: SettingMode, - value: Expression + value: Expression, }, Spawn { delay: Option, diff --git a/crates/dreammaker/src/builtins.rs b/crates/dreammaker/src/builtins.rs index 1506d2d5..d76042ee 100644 --- a/crates/dreammaker/src/builtins.rs +++ b/crates/dreammaker/src/builtins.rs @@ -18,48 +18,60 @@ pub fn default_defines(defines: &mut DefineMap) { let location = Location::builtins(); // #define EXCEPTION(value) new /exception(value) - defines.insert("EXCEPTION".to_owned(), (location, Define::Function { - params: vec!["value".to_owned()], - variadic: false, - subst: vec![ - Ident("new".to_owned(), true), - Punct(Punctuation::Slash), - Ident("exception".to_owned(), false), - Punct(Punctuation::LParen), - Ident("value".to_owned(), false), - Punct(Punctuation::RParen), - ], - docs: Default::default(), - })); + defines.insert( + "EXCEPTION".to_owned(), + ( + location, + Define::Function { + params: vec!["value".to_owned()], + variadic: false, + subst: vec![ + Ident("new".to_owned(), true), + Punct(Punctuation::Slash), + Ident("exception".to_owned(), false), + Punct(Punctuation::LParen), + Ident("value".to_owned(), false), + Punct(Punctuation::RParen), + ], + docs: Default::default(), + }, + ), + ); // #define ASSERT(expression) if (!(expression)) { CRASH("[__FILE__]:[__LINE__]:Assertion Failed: [#X]") } - defines.insert("ASSERT".to_owned(), (location, Define::Function { - params: vec!["expression".to_owned()], - variadic: false, - subst: vec![ - Ident("if".to_owned(), true), - Punct(Punctuation::LParen), - Punct(Punctuation::Not), - Punct(Punctuation::LParen), - Ident("expression".to_owned(), false), - Punct(Punctuation::RParen), - Punct(Punctuation::RParen), - Punct(Punctuation::LBrace), - Ident("CRASH".to_owned(), false), - Punct(Punctuation::LParen), - InterpStringBegin("".to_owned()), - Ident("__FILE__".to_owned(), false), - InterpStringPart(":".to_owned()), - Ident("__LINE__".to_owned(), false), - InterpStringPart(":Assertion Failed: ".to_owned()), - Punct(Punctuation::Hash), - Ident("expression".to_owned(), false), - InterpStringEnd("".to_owned()), - Punct(Punctuation::RParen), - Punct(Punctuation::RBrace), - ], - docs: Default::default(), - })); + defines.insert( + "ASSERT".to_owned(), + ( + location, + Define::Function { + params: vec!["expression".to_owned()], + variadic: false, + subst: vec![ + Ident("if".to_owned(), true), + Punct(Punctuation::LParen), + Punct(Punctuation::Not), + Punct(Punctuation::LParen), + Ident("expression".to_owned(), false), + Punct(Punctuation::RParen), + Punct(Punctuation::RParen), + Punct(Punctuation::LBrace), + Ident("CRASH".to_owned(), false), + Punct(Punctuation::LParen), + InterpStringBegin("".to_owned()), + Ident("__FILE__".to_owned(), false), + InterpStringPart(":".to_owned()), + Ident("__LINE__".to_owned(), false), + InterpStringPart(":Assertion Failed: ".to_owned()), + Punct(Punctuation::Hash), + Ident("expression".to_owned(), false), + InterpStringEnd("".to_owned()), + Punct(Punctuation::RParen), + Punct(Punctuation::RBrace), + ], + docs: Default::default(), + }, + ), + ); // constants macro_rules! c { diff --git a/crates/dreammaker/src/config.rs b/crates/dreammaker/src/config.rs index 29f9946d..c4668c53 100644 --- a/crates/dreammaker/src/config.rs +++ b/crates/dreammaker/src/config.rs @@ -123,7 +123,7 @@ impl Config { fn config_warninglevel(&self, error: &DMError) -> Option<&WarningLevel> { if let Some(errortype) = error.errortype() { - return self.diagnostics.get(errortype) + return self.diagnostics.get(errortype); } None } @@ -176,11 +176,13 @@ impl From for WarningLevel { impl PartialEq for WarningLevel { fn eq(&self, other: &Severity) -> bool { - matches!((self, other), + matches!( + (self, other), (WarningLevel::Error, Severity::Error) - | (WarningLevel::Warning, Severity::Warning) - | (WarningLevel::Info, Severity::Info) - | (WarningLevel::Hint, Severity::Hint)) + | (WarningLevel::Warning, Severity::Warning) + | (WarningLevel::Info, Severity::Info) + | (WarningLevel::Hint, Severity::Hint) + ) } } diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index cb67c96b..86cc891f 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -6,8 +6,8 @@ use std::path::Path; use get_size::GetSize; use get_size_derive::GetSize; -use foldhash::fast::RandomState; use color_space::{Hsl, Hsv, Lch, Rgb}; +use foldhash::fast::RandomState; use indexmap::IndexMap; use ordered_float::OrderedFloat; @@ -60,7 +60,12 @@ impl From for Pop { impl fmt::Display for Pop { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}{}", FormatTreePath(&self.path), FormatVars(&self.vars)) + write!( + f, + "{}{}", + FormatTreePath(&self.path), + FormatVars(&self.vars) + ) } } @@ -123,7 +128,16 @@ impl std::cmp::PartialEq for Constant { fn eq(&self, other: &Constant) -> bool { match (self, other) { (Constant::Null(p1), Constant::Null(p2)) => p1 == p2, - (Constant::New { type_: type1, args: args1 }, Constant::New { type_: type2, args: args2 }) => (type1, args1) == (type2, args2), + ( + Constant::New { + type_: type1, + args: args1, + }, + Constant::New { + type_: type2, + args: args2, + }, + ) => (type1, args1) == (type2, args2), (Constant::List(l1), Constant::List(l2)) => l1 == l2, (Constant::Call(f1, args1), Constant::Call(f2, args2)) => (f1, args1) == (f2, args2), (Constant::Prefab(pop1), Constant::Prefab(pop2)) => pop1 == pop2, @@ -213,8 +227,7 @@ impl Constant { pub fn as_path_str(&self) -> Option<&str> { match *self { - Constant::String(ref s) | - Constant::Resource(ref s) => Some(s), + Constant::String(ref s) | Constant::Resource(ref s) => Some(s), _ => None, } } @@ -236,8 +249,7 @@ impl Constant { pub fn eq_resource(&self, resource: &str) -> bool { match self { - Constant::String(ref s) | - Constant::Resource(ref s) => &**s == resource, + Constant::String(ref s) | Constant::Resource(ref s) => &**s == resource, _ => false, } } @@ -259,13 +271,17 @@ impl Constant { pub fn index(&self, key: &Constant) -> Option<&Constant> { match (self, key) { // Narrowing conversion is intentional. - (Constant::List(elements), &Constant::Float(i)) => return elements.get(i as usize).map(|(k, _)| k), - (Constant::List(elements), key) => for (k, v) in elements.iter() { - if key == k { - return v.as_ref(); + (Constant::List(elements), &Constant::Float(i)) => { + return elements.get(i as usize).map(|(k, _)| k) + }, + (Constant::List(elements), key) => { + for (k, v) in elements.iter() { + if key == k { + return v.as_ref(); + } } }, - _ => {} + _ => {}, } None } @@ -308,8 +324,7 @@ impl From for Constant { impl PartialEq for Constant { fn eq(&self, other: &str) -> bool { match self { - Constant::String(ref s) | - Constant::Resource(ref s) => &**s == other, + Constant::String(ref s) | Constant::Resource(ref s) => &**s == other, _ => false, } } @@ -335,7 +350,10 @@ impl fmt::Display for Constant { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Constant::Null(_) => f.write_str("null"), - Constant::New { ref type_, ref args } => { + Constant::New { + ref type_, + ref args, + } => { f.write_str("new")?; if let Some(prefab) = type_ { write!(f, " {prefab}")?; @@ -419,14 +437,21 @@ impl fmt::Display for ConstFn { // The constant evaluator pub fn evaluate_str(location: Location, input: &[u8]) -> Result { - use super::lexer::{Lexer, LocationTracker, from_utf8_or_latin1_borrowed}; + use super::lexer::{from_utf8_or_latin1_borrowed, Lexer, LocationTracker}; let ctx = Context::default(); let mut lexer = Lexer::from_input(&ctx, LocationTracker::from_location(location, input.into())); let expr = crate::parser::parse_expression(&ctx, location, &mut lexer)?; let leftover = lexer.remaining(); if !leftover.is_empty() { - return Err(DMError::new(location, format!("leftover: {:?} {}", from_utf8_or_latin1_borrowed(input), leftover.len()))); + return Err(DMError::new( + location, + format!( + "leftover: {:?} {}", + from_utf8_or_latin1_borrowed(input), + leftover.len() + ), + )); } expr.simple_evaluate(location) } @@ -440,19 +465,26 @@ impl Expression { location, ty: NodeIndex::new(0), defines: None, - }.expr(self, None) + } + .expr(self, None) } } /// Evaluate an expression in the preprocessor, with `defined()` available. -pub fn preprocessor_evaluate(location: Location, expr: Expression, defines: &DefineMap, context: Option<&Context>) -> Result { +pub fn preprocessor_evaluate( + location: Location, + expr: Expression, + defines: &DefineMap, + context: Option<&Context>, +) -> Result { ConstantFolder { context, tree: None, location, ty: NodeIndex::new(0), defines: Some(defines), - }.expr(expr, None) + } + .expr(expr, None) } /// Evaluate all the type-level variables in an object tree into constants. @@ -460,27 +492,21 @@ pub(crate) fn evaluate_all(context: &Context, tree: &mut ObjectTree) { for ty in tree.node_indices() { let keys: Vec = tree[ty].vars.keys().cloned().collect(); for key in keys { - if !tree[ty] - .get_var_declaration(&key, tree) - .is_none_or(|x| { - x.var_type.is_const_evaluable() && (x.var_type.flags.is_const() || ty != NodeIndex::new(0)) - }) - { - continue; // skip non-constant-evaluable vars + if !tree[ty].get_var_declaration(&key, tree).is_none_or(|x| { + x.var_type.is_const_evaluable() + && (x.var_type.flags.is_const() || ty != NodeIndex::new(0)) + }) { + continue; // skip non-constant-evaluable vars } match constant_ident_lookup(tree, ty, &key, false, Some(context)) { Err(err) => context.register_error(err), - Ok(ConstLookup::Found(_)) => {} + Ok(ConstLookup::Found(_)) => {}, Ok(ConstLookup::Continue(_)) => { context.register_error(DMError::new( tree[ty].vars[&key].value.location, - format!( - "undefined var '{}' on type '{}'", - key, - tree[ty].path, - ), + format!("undefined var '{}' on type '{}'", key, tree[ty].path,), )); - } + }, } } } @@ -501,10 +527,7 @@ fn constant_ident_lookup( // try to read the currently-set value if we can and // substitute that in, otherwise try to evaluate it. let (location, type_hint, expr) = { - let decl = match tree[ty] - .get_var_declaration(ident, tree) - .cloned() - { + let decl = match tree[ty].get_var_declaration(ident, tree).cloned() { Some(decl) => decl, None => return Ok(ConstLookup::Continue(None)), // definitely doesn't exist }; @@ -514,7 +537,11 @@ fn constant_ident_lookup( match type_.vars.get_mut(ident) { None => return Ok(ConstLookup::Continue(parent)), Some(var) => match var.value.constant.clone() { - Some(constant) => return Ok(ConstLookup::Found(/*decl.var_type.type_path,*/ constant)), + Some(constant) => { + return Ok(ConstLookup::Found( + /*decl.var_type.type_path,*/ constant, + )); + }, None => match var.value.expression.clone() { Some(expr) => { if var.value.being_evaluated { @@ -535,12 +562,12 @@ fn constant_ident_lookup( } var.value.being_evaluated = true; (var.value.location, decl.var_type.type_path, expr) - } + }, None => { let c = Constant::Null(Some(decl.var_type.type_path.clone())); var.value.constant = Some(c.clone()); return Ok(ConstLookup::Found(/*decl.var_type.type_path,*/ c)); - } + }, }, }, } @@ -552,7 +579,15 @@ fn constant_ident_lookup( defines: None, location, ty, - }.expr(expr, if type_hint.is_empty() { None } else { Some(&type_hint) })?; + } + .expr( + expr, + if type_hint.is_empty() { + None + } else { + Some(&type_hint) + }, + )?; // and store it into 'value', then return it let var = tree[ty].vars.get_mut(ident).unwrap(); var.value.constant = Some(value.clone()); @@ -575,14 +610,14 @@ impl<'a> HasLocation for ConstantFolder<'a> { } impl<'a> ConstantFolder<'a> { - fn expr(&mut self, expression: Expression, type_hint: Option<&TreePath>) -> Result { + fn expr( + &mut self, + expression: Expression, + type_hint: Option<&TreePath>, + ) -> Result { Ok(match expression { Expression::Base { term, follow } => { - let base_type_hint = if follow.is_empty() { - type_hint - } else { - None - }; + let base_type_hint = if follow.is_empty() { type_hint } else { None }; let mut term = self.term(term.elem, base_type_hint)?; for each in Vec::from(follow).into_iter() { term = self.follow(term, each.elem)?; @@ -594,11 +629,9 @@ impl<'a> ConstantFolder<'a> { let rhs = self.expr(*rhs, None)?; self.binary(lhs, rhs, op)? }, - Expression::TernaryOp { cond, if_, else_ } => { - match self.expr(*cond, None)?.to_bool() { - true => self.expr(*if_, type_hint)?, - false => self.expr(*else_, type_hint)?, - } + Expression::TernaryOp { cond, if_, else_ } => match self.expr(*cond, None)?.to_bool() { + true => self.expr(*if_, type_hint)?, + false => self.expr(*else_, type_hint)?, }, Expression::AssignOp { .. } => return Err(self.error("non-constant assignment")), }) @@ -651,43 +684,60 @@ impl<'a> ConstantFolder<'a> { full_path.push('/'); full_path.push_str(each); } - match self.tree.as_mut().and_then(|t| t.find(&full_path)).map(|t| t.index()) { + match self + .tree + .as_mut() + .and_then(|t| t.find(&full_path)) + .map(|t| t.index()) + { Some(idx) => self.recursive_lookup(idx, &field_name, true), None => Err(self.error(format!("unknown typepath {full_path}"))), } - } + }, (term, Follow::Unary(op)) => self.unary(term, op), (term, Follow::StaticField(field)) => { let Constant::Prefab(read_from) = term else { - return Err(self.error(format!("non typepath {term} used with ::"))) + return Err(self.error(format!("non typepath {term} used with ::"))); }; if !read_from.vars.is_empty() { - return Err(self.error(format!("non typepath {read_from} used with ::"))) + return Err(self.error(format!("non typepath {read_from} used with ::"))); } let Some(ref tree) = self.tree else { - return Err(self.error("no type tree available")) + return Err(self.error("no type tree available")); }; - let Some(real_type) = tree.find(FormatTreePath(&read_from.path).to_string().as_str()) else { - return Err(self.error(format!("{} was not a valid type", FormatTreePath(&read_from.path)))) + let Some(real_type) = + tree.find(FormatTreePath(&read_from.path).to_string().as_str()) + else { + return Err(self.error(format!( + "{} was not a valid type", + FormatTreePath(&read_from.path) + ))); }; self.recursive_lookup(real_type.index(), &field, false) }, (term, Follow::ProcReference(field)) => { let Constant::Prefab(read_from) = term else { - return Err(self.error(format!("non typepath {term} used with ::"))) + return Err(self.error(format!("non typepath {term} used with ::"))); }; if !read_from.vars.is_empty() { - return Err(self.error(format!("non typepath {read_from} used with ::"))) + return Err(self.error(format!("non typepath {read_from} used with ::"))); } let Some(ref tree) = self.tree else { - return Err(self.error("no type tree available")) + return Err(self.error("no type tree available")); }; - let Some(real_type) = tree.find(FormatTreePath(&read_from.path).to_string().as_str()) else { - return Err(self.error(format!("{} was not a valid type", FormatTreePath(&read_from.path)))) + let Some(real_type) = + tree.find(FormatTreePath(&read_from.path).to_string().as_str()) + else { + return Err(self.error(format!( + "{} was not a valid type", + FormatTreePath(&read_from.path) + ))); }; self.proc_ref_lookup(real_type.index(), &field) }, - (term, follow) => Err(self.error(format!("non-constant expression follower: {term} {follow:?}"))), + (term, follow) => Err(self.error(format!( + "non-constant expression follower: {term} {follow:?}" + ))), } } @@ -701,11 +751,21 @@ impl<'a> ConstantFolder<'a> { (UnaryOp::Not, c) => Constant::from(!c.to_bool()), // float ops // unsupported - (op, term) => return Err(self.error(format!("non-constant unary operation: {}", op.around(&term)))), + (op, term) => { + return Err(self.error(format!( + "non-constant unary operation: {}", + op.around(&term) + ))) + }, }) } - fn binary(&mut self, mut lhs: Constant, mut rhs: Constant, op: BinaryOp) -> Result { + fn binary( + &mut self, + mut lhs: Constant, + mut rhs: Constant, + op: BinaryOp, + ) -> Result { use self::Constant::*; macro_rules! numeric { @@ -726,11 +786,13 @@ impl<'a> ConstantFolder<'a> { numeric!(Greater >); numeric!(GreaterEq >=); match (op, lhs, rhs) { - (BinaryOp::FloatMod, Float(lhs), Float(rhs)) => return Ok(Constant::from(lhs - ((lhs / rhs).floor() * rhs))), + (BinaryOp::FloatMod, Float(lhs), Float(rhs)) => { + return Ok(Constant::from(lhs - ((lhs / rhs).floor() * rhs))) + }, (_, lhs_, rhs_) => { lhs = lhs_; rhs = rhs_; - } + }, } match (op, lhs, rhs) { @@ -738,7 +800,7 @@ impl<'a> ConstantFolder<'a> { (_, lhs_, rhs_) => { lhs = lhs_; rhs = rhs_; - } + }, } macro_rules! integer { @@ -756,7 +818,9 @@ impl<'a> ConstantFolder<'a> { integer!(RShift >>); match (op, lhs, rhs) { - (BinaryOp::Add, String(lhs), String(rhs)) => Ok(String((std::string::String::from(lhs) + &rhs).into())), + (BinaryOp::Add, String(lhs), String(rhs)) => { + Ok(String((std::string::String::from(lhs) + &rhs).into())) + }, (BinaryOp::Eq, lhs, rhs) => Ok(Constant::from(lhs == rhs)), (BinaryOp::NotEq, lhs, rhs) => Ok(Constant::from(lhs != rhs)), (BinaryOp::And, lhs, rhs) => Ok(if lhs.to_bool() { rhs } else { lhs }), @@ -800,27 +864,43 @@ impl<'a> ConstantFolder<'a> { "arccos" => self.trig_op(args, f32::acos)?, "rgb" => Constant::String(self.rgb(args)?.into()), "defined" if self.defines.is_some() => { - let defines = self.defines.unwrap(); // annoying, but keeps the match clean + let defines = self.defines.unwrap(); // annoying, but keeps the match clean if args.len() != 1 { - return Err(self.error(format!("malformed defined() call, must have 1 argument and instead has {}", args.len()))); + return Err(self.error(format!( + "malformed defined() call, must have 1 argument and instead has {}", + args.len() + ))); } match args[0].as_term() { Some(Term::Ident(ref ident)) => Constant::from(defines.contains_key(ident)), - _ => return Err(self.error("malformed defined() call, argument given isn't an Ident.")), + _ => { + return Err(self + .error("malformed defined() call, argument given isn't an Ident.")) + }, } - } + }, "nameof" => { if args.len() != 1 { - return Err(self.error(format!("malformed nameof() call, must have 1 argument and instead has {}", args.len()))); + return Err(self.error(format!( + "malformed nameof() call, must have 1 argument and instead has {}", + args.len() + ))); } match args[0].nameof() { Some(name) => Constant::string(name), - None => return Err(self.error("malformed nameof() call, expression appears to have no name")), + None => { + return Err(self.error( + "malformed nameof() call, expression appears to have no name", + )) + }, } - } + }, "fexists" if self.defines.is_some() && self.context.is_some() => { if args.len() != 1 { - return Err(self.error(format!("malformed fexists() call, must have 1 argument and instead has {}", args.len()))); + return Err(self.error(format!( + "malformed fexists() call, must have 1 argument and instead has {}", + args.len() + ))); } match args[0].as_term() { Some(Term::String(passed_path)) => { @@ -831,10 +911,13 @@ impl<'a> ConstantFolder<'a> { ))); }; current_dir.join(passed_path).exists().into() - } - _ => return Err(self.error("malformed fexists() call, argument given isn't a string.")), + }, + _ => { + return Err(self + .error("malformed fexists() call, argument given isn't a string.")) + }, } - } + }, // other functions are no-goes _ => return Err(self.error(format!("non-constant function call: {ident}"))), }, @@ -846,24 +929,38 @@ impl<'a> ConstantFolder<'a> { "type" => { if let Some(obj_tree) = &self.tree { let typeval = TypeRef::new(obj_tree, self.ty).get(); - let pop = Pop::from(typeval.path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect::()); + let pop = Pop::from( + typeval + .path + .split('/') + .filter(|elem| !elem.is_empty()) + .map(|segment| segment.to_string()) + .collect::(), + ); Constant::Prefab(Box::new(pop)) } else { - return Err(self.error("no type context".to_owned())) + return Err(self.error("no type context".to_owned())); } }, "parent_type" => { if let Some(obj_tree) = &self.tree { let typeref = TypeRef::new(obj_tree, self.ty); let Some(parent_type) = typeref.parent_type() else { - return Err(self.error(format!("no parent type for {typeref}"))) + return Err(self.error(format!("no parent type for {typeref}"))); }; - let pop = Pop::from(parent_type.path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect::()); + let pop = Pop::from( + parent_type + .path + .split('/') + .filter(|elem| !elem.is_empty()) + .map(|segment| segment.to_string()) + .collect::(), + ); Constant::Prefab(Box::new(pop)) } else { - return Err(self.error("no type context".to_owned())) + return Err(self.error("no type context".to_owned())); } - } + }, _ => self.ident(ident, false)?, }, Term::String(v) => Constant::String(v.into()), @@ -874,26 +971,40 @@ impl<'a> ConstantFolder<'a> { Term::__TYPE__ => { if let Some(obj_tree) = &self.tree { let typeval = TypeRef::new(obj_tree, self.ty).get(); - let pop = Pop::from(typeval.path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect::()); + let pop = Pop::from( + typeval + .path + .split('/') + .filter(|elem| !elem.is_empty()) + .map(|segment| segment.to_string()) + .collect::(), + ); Constant::Prefab(Box::new(pop)) } else { - return Err(self.error("No type context".to_owned())) + return Err(self.error("No type context".to_owned())); } }, Term::__IMPLIED_TYPE__ => { if let Some(lhs_type) = type_hint { Constant::Prefab(Box::new(Pop::from(lhs_type.clone()))) } else { - return Err(self.error("No type hint".to_owned())) + return Err(self.error("No type hint".to_owned())); } }, _ => return Err(self.error("non-constant expression".to_owned())), }) } - fn trig_op(&mut self, args: Box<[Expression]>, op: fn(f32) -> f32) -> Result { + fn trig_op( + &mut self, + args: Box<[Expression]>, + op: fn(f32) -> f32, + ) -> Result { if args.len() != 1 { - Err(self.error(format!("trig function requires exactly 1 argument, instead found {}", args.len()))) + Err(self.error(format!( + "trig function requires exactly 1 argument, instead found {}", + args.len() + ))) } else if let Some(f) = self.expr(Vec::from(args).swap_remove(0), None)?.to_float() { Ok(Constant::Float(op(f))) } else { @@ -907,30 +1018,45 @@ impl<'a> ConstantFolder<'a> { // If the path is all slashes, it's absolute, and doesn't need to be // further resolved. if prefab.path.iter().all(|&(op, _)| op == PathOp::Slash) { - let path: TreePath = prefab.path.iter().map(|(_, name)| name.to_owned()).collect(); - return Ok(Pop { path, vars }) + let path: TreePath = prefab + .path + .iter() + .map(|(_, name)| name.to_owned()) + .collect(); + return Ok(Pop { path, vars }); } // Otherwise, resolve it against our object tree, then stringify it. let tree = match self.tree.as_ref() { Some(tree) => tree, - None => return Err(self.error(format!( - "cannot resolve relative type path without an object tree: {}", - FormatTypePath(&prefab.path)))), + None => { + return Err(self.error(format!( + "cannot resolve relative type path without an object tree: {}", + FormatTypePath(&prefab.path) + ))) + }, }; let relative_to = TypeRef::new(tree, self.ty); let found = match relative_to.navigate_path(&prefab.path) { Some(found) => found, - None => return Err(self.error(format!("could not resolve {} relative to {}", - FormatTypePath(&prefab.path), relative_to))), + None => { + return Err(self.error(format!( + "could not resolve {} relative to {}", + FormatTypePath(&prefab.path), + relative_to + ))) + }, }; let path = found.to_path().into_boxed_slice(); Ok(Pop { path, vars }) } - fn vars(&mut self, input: Vec<(Ident2, Expression)>) -> Result, DMError> { + fn vars( + &mut self, + input: Vec<(Ident2, Expression)>, + ) -> Result, DMError> { // Visit the vars recursively. let mut vars = IndexMap::with_hasher(RandomState::default()); for (k, v) in input { @@ -945,12 +1071,19 @@ impl<'a> ConstantFolder<'a> { self.recursive_lookup(ty, &ident, must_be_const) } - fn recursive_lookup(&mut self, ty: NodeIndex, ident: &str, must_be_const: bool) -> Result { + fn recursive_lookup( + &mut self, + ty: NodeIndex, + ident: &str, + must_be_const: bool, + ) -> Result { let mut idx = Some(ty); while let Some(ty) = idx { let location = self.location; if self.tree.is_none() { - return Err(self.error(format!("cannot reference variable {ident:?} in this context"))); + return Err(self.error(format!( + "cannot reference variable {ident:?} in this context" + ))); } let tree = self.tree.as_mut().unwrap(); match constant_ident_lookup(tree, ty, ident, must_be_const, self.context) @@ -967,16 +1100,24 @@ impl<'a> ConstantFolder<'a> { let tree = self.tree.as_mut().unwrap(); let proc_type = TypeRef::new(tree, ty); let Some(proc_ref) = proc_type.get_proc(name) else { - return Err(self.error(format!("unknown proc: {name}"))) + return Err(self.error(format!("unknown proc: {name}"))); }; // Gonna build the proc's path - let mut path_elements: Vec = proc_type.get().path.split('/').filter(|elem| !elem.is_empty()).map(|segment| segment.to_string()).collect(); + let mut path_elements: Vec = proc_type + .get() + .path + .split('/') + .filter(|elem| !elem.is_empty()) + .map(|segment| segment.to_string()) + .collect(); // Only tricky bit is adding on the type if required if let Some(declaration) = proc_ref.get_declaration() { path_elements.push(declaration.kind.name().to_string()); } path_elements.push(proc_ref.name().to_string()); - Ok(Constant::Prefab(Box::new(Pop::from(Box::from(path_elements))))) + Ok(Constant::Prefab(Box::new(Pop::from(Box::from( + path_elements, + ))))) } fn rgb(&mut self, args: Box<[Expression]>) -> Result { @@ -1002,7 +1143,10 @@ impl<'a> ConstantFolder<'a> { } if args.len() != 3 && args.len() != 4 && args.len() != 5 { - return Err(self.error(format!("malformed rgb() call, must have 3, 4, or 5 arguments and instead has {}", args.len()))); + return Err(self.error(format!( + "malformed rgb() call, must have 3, 4, or 5 arguments and instead has {}", + args.len() + ))); } let arguments = self.arguments(args)?; @@ -1025,21 +1169,27 @@ impl<'a> ConstantFolder<'a> { "c" | "chroma" => color_args.c = true, "y" => color_args.y = true, "a" | "alpha" => color_args.a = kwarg_value.to_int(), - "space" => match kwarg_value.to_int() { // Do we have an actual colorspace specified? Set the values. + "space" => match kwarg_value.to_int() { + // Do we have an actual colorspace specified? Set the values. Some(0) => space = Some(ColorSpace::Rgb), Some(1) => space = Some(ColorSpace::Hsv), Some(2) => space = Some(ColorSpace::Hsl), Some(3) => space = Some(ColorSpace::Hcy), _ => { - return Err(self.error(format!("malformed rgb() call, bad color space: {kwarg_value}"))) - } - } + return Err(self.error(format!( + "malformed rgb() call, bad color space: {kwarg_value}" + ))) + }, + }, _ => { - return Err(self.error(format!("malformed rgb() call, bad kwarg passed: {kwarg}"))) - } + return Err(self + .error(format!("malformed rgb() call, bad kwarg passed: {kwarg}"))) + }, } } else { - return Err(self.error(format!("malformed rgb() call, kwarg is not string: {value}"))); + return Err(self.error(format!( + "malformed rgb() call, kwarg is not string: {value}" + ))); } } } @@ -1059,13 +1209,17 @@ impl<'a> ConstantFolder<'a> { } else if color_args.l { ColorSpace::Hsl } else { - return Err(self.error("malformed rgb() call, could not determine space: only h & s specified")); + return Err(self.error( + "malformed rgb() call, could not determine space: only h & s specified", + )); } } else { - return Err(self.error("malformed rgb() call, could not determine space: only h specified")); + return Err( + self.error("malformed rgb() call, could not determine space: only h specified") + ); } } else { - ColorSpace::Rgb // Default + ColorSpace::Rgb // Default }; let mut value_vec: Vec = vec![]; @@ -1111,20 +1265,28 @@ impl<'a> ConstantFolder<'a> { "a" | "alpha" => 0..=255, "space" => continue, // Don't range-check the value of the space _ => { - return Err(self.error(format!("malformed rgb() call, bad kwarg passed: {kwarg}"))) - } + return Err(self + .error(format!("malformed rgb() call, bad kwarg passed: {kwarg}"))) + }, }; } else { - return Err(self.error(format!("malformed rgb() call, kwarg is not string: {value}"))); + return Err(self.error(format!( + "malformed rgb() call, kwarg is not string: {value}" + ))); } } if let Some(i) = to_check.to_int() { if !range.contains(&i) { - return Err(self.error(format!("malformed rgb() call, {} is not within the valid range ({}..{})", i, range.start(), range.end())) + return Err(self + .error(format!( + "malformed rgb() call, {} is not within the valid range ({}..{})", + i, + range.start(), + range.end() + )) .set_severity(Severity::Warning) - .with_location(self.location) - ); + .with_location(self.location)); } let clamped = std::cmp::max(::std::cmp::min(i, *range.end()), *range.start()); value_vec.push(clamped.into()); @@ -1138,8 +1300,12 @@ impl<'a> ConstantFolder<'a> { // Convert our color given a space to a rgb hexcode let color: Rgb = match space { ColorSpace::Rgb => Rgb::new(value_vec[0], value_vec[1], value_vec[2]), - ColorSpace::Hsv => Hsv::new(value_vec[0], value_vec[1] * 0.01, value_vec[2] * 0.01).into(), - ColorSpace::Hsl => Hsl::new(value_vec[0], value_vec[1] * 0.01, value_vec[2] * 0.01).into(), + ColorSpace::Hsv => { + Hsv::new(value_vec[0], value_vec[1] * 0.01, value_vec[2] * 0.01).into() + }, + ColorSpace::Hsl => { + Hsl::new(value_vec[0], value_vec[1] * 0.01, value_vec[2] * 0.01).into() + }, ColorSpace::Hcy => Lch::new(value_vec[2], value_vec[1], value_vec[0]).into(), }; @@ -1148,9 +1314,20 @@ impl<'a> ConstantFolder<'a> { // APPARENTLY the author thinks fractional rgb is a thing, hence the rounding if let Some(alpha) = alpha { - Ok(format!("#{:02x}{:02x}{:02x}{:02x}", color.r.round() as u8, color.g.round() as u8, color.b.round() as u8, alpha)) + Ok(format!( + "#{:02x}{:02x}{:02x}{:02x}", + color.r.round() as u8, + color.g.round() as u8, + color.b.round() as u8, + alpha + )) } else { - Ok(format!("#{:02x}{:02x}{:02x}", color.r.round() as u8, color.g.round() as u8, color.b.round() as u8)) + Ok(format!( + "#{:02x}{:02x}{:02x}", + color.r.round() as u8, + color.g.round() as u8, + color.b.round() as u8 + )) } } } diff --git a/crates/dreammaker/src/dmi.rs b/crates/dreammaker/src/dmi.rs index dcbce34a..e4b9d6ea 100644 --- a/crates/dreammaker/src/dmi.rs +++ b/crates/dreammaker/src/dmi.rs @@ -1,7 +1,7 @@ //! DMI metadata parsing and representation. -use std::collections::BTreeMap; use foldhash::{HashMap, HashMapExt}; +use std::collections::BTreeMap; use std::fmt::Display; use std::io; use std::path::Path; @@ -38,8 +38,7 @@ impl From<&str> for StateIndex { } /// The two-dimensional facing subset of BYOND's direction type. -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[derive(Default)] +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Default)] pub enum Dir { North = 1, #[default] @@ -54,8 +53,22 @@ pub enum Dir { impl Dir { pub const CARDINALS: &'static [Dir] = &[Dir::North, Dir::South, Dir::East, Dir::West]; - pub const DIAGONALS: &'static [Dir] = &[Dir::Northeast, Dir::Northwest, Dir::Southeast, Dir::Southwest]; - pub const ALL: &'static [Dir] = &[Dir::North, Dir::South, Dir::East, Dir::West, Dir::Northeast, Dir::Northwest, Dir::Southeast, Dir::Southwest]; + pub const DIAGONALS: &'static [Dir] = &[ + Dir::Northeast, + Dir::Northwest, + Dir::Southeast, + Dir::Southwest, + ]; + pub const ALL: &'static [Dir] = &[ + Dir::North, + Dir::South, + Dir::East, + Dir::West, + Dir::Northeast, + Dir::Northwest, + Dir::Southeast, + Dir::Southwest, + ]; /// Attempt to build a direction from its integer representation. pub fn from_int(int: i32) -> Option { @@ -82,11 +95,7 @@ impl Dir { } pub fn is_diagonal(self) -> bool { - !matches!(self, - Dir::North - | Dir::South - | Dir::East - | Dir::West) + !matches!(self, Dir::North | Dir::South | Dir::East | Dir::West) } pub fn flip(self) -> Dir { @@ -294,7 +303,13 @@ impl Metadata { parse_metadata(data) } - pub fn rect_of(&self, bitmap_width: u32, icon_state: &StateIndex, dir: Dir, frame: u32) -> Option<(u32, u32, u32, u32)> { + pub fn rect_of( + &self, + bitmap_width: u32, + icon_state: &StateIndex, + dir: Dir, + frame: u32, + ) -> Option<(u32, u32, u32, u32)> { if self.states.is_empty() { return Some((0, 0, self.width, self.height)); } @@ -405,12 +420,10 @@ fn parse_metadata(data: &str) -> io::Result { let header = (lines.next(), lines.next()); let expected_header = (Some("# BEGIN DMI"), Some(EXPECTED_VERSION_LINE)); if header != expected_header { - return Err( - io::Error::new( - io::ErrorKind::InvalidData, - format!("Wrong dmi metadata header. Expected {expected_header:?}, got {header:?}" ) - ) - ); + return Err(io::Error::new( + io::ErrorKind::InvalidData, + format!("Wrong dmi metadata header. Expected {expected_header:?}, got {header:?}"), + )); } let mut state: Option = None; @@ -449,14 +462,16 @@ fn parse_metadata(data: &str) -> io::Result { let key = new_state.get_state_name_index(); - if let std::collections::btree_map::Entry::Vacant(e) = metadata.state_names.entry(key) { + if let std::collections::btree_map::Entry::Vacant(e) = + metadata.state_names.entry(key) + { e.insert(metadata.states.len()); } state = Some(new_state); *count += 1; - } + }, "dirs" => { let state = state.as_mut().unwrap(); let n: u8 = value.parse().unwrap(); @@ -466,7 +481,7 @@ fn parse_metadata(data: &str) -> io::Result { 8 => Dirs::Eight, _ => panic!(), }; - } + }, "frames" => { let state = state.as_mut().unwrap(); match state.frames { @@ -474,15 +489,21 @@ fn parse_metadata(data: &str) -> io::Result { _ => panic!(), } state.frames = Frames::Count(value.parse().unwrap()); - } + }, "delay" => { let state = state.as_mut().unwrap(); - let mut vector: Vec = value.split(',').map(str::parse).collect::, _>>().unwrap(); + let mut vector: Vec = value + .split(',') + .map(str::parse) + .collect::, _>>() + .unwrap(); match state.frames { - Frames::One => if vector.iter().all(|&n| n == 1.) { - state.frames = Frames::Count(vector.len()); - } else { - state.frames = Frames::Delays(vector); + Frames::One => { + if vector.iter().all(|&n| n == 1.) { + state.frames = Frames::Count(vector.len()); + } else { + state.frames = Frames::Delays(vector); + } }, Frames::Count(n) => { vector.truncate(n); @@ -492,10 +513,10 @@ fn parse_metadata(data: &str) -> io::Result { }, Frames::Delays(_) => panic!(), } - } + }, "loop" => state.as_mut().unwrap().loop_ = value.parse().unwrap(), "rewind" => state.as_mut().unwrap().rewind = value.parse::().unwrap() != 0, - "hotspot" => { /* TODO */ } + "hotspot" => { /* TODO */ }, "movement" => state.as_mut().unwrap().movement = value.parse::().unwrap() != 0, _ => panic!(), } @@ -526,7 +547,8 @@ state = "duplicate" dirs = 1 frames = 1 # END DMI -"#.trim(); +"# + .trim(); let metadata = parse_metadata(description).expect("Metadata is valid"); assert_eq!(metadata.state_names.len(), 3); @@ -548,7 +570,13 @@ state = "duplicate" } // Note: using `no` here only works by virtue of the test data being only composed of duplicates - assert_eq!(no, *metadata.state_names.get(&state.get_state_name_index()).unwrap()) + assert_eq!( + no, + *metadata + .state_names + .get(&state.get_state_name_index()) + .unwrap() + ) } } @@ -573,10 +601,13 @@ state = "one" frames = 2 delay = 1,1,0.5,0.5 # END DMI -"#.trim(); +"# + .trim(); let metadata = parse_metadata(description).expect("Metadata is valid"); - let state = metadata.get_icon_state(&StateIndex("one".to_owned(), 0)).expect("Only one state, named one, should be found"); + let state = metadata + .get_icon_state(&StateIndex("one".to_owned(), 0)) + .expect("Only one state, named one, should be found"); assert_eq!(state.frames, Frames::Count(2)); } } diff --git a/crates/dreammaker/src/docs.rs b/crates/dreammaker/src/docs.rs index 9e49c2be..3c4dc144 100644 --- a/crates/dreammaker/src/docs.rs +++ b/crates/dreammaker/src/docs.rs @@ -19,7 +19,7 @@ impl DocCollection { } /// Combine another collection into this one. - pub fn extend(&mut self, collection: impl IntoIterator) { + pub fn extend(&mut self, collection: impl IntoIterator) { self.elems.extend(collection); } @@ -100,8 +100,8 @@ impl DocComment { match (self.kind, self.target) { (CommentKind::Block, DocTarget::FollowingItem) => "/**", (CommentKind::Block, DocTarget::EnclosingItem) => "/*!", - (CommentKind::Line, DocTarget::FollowingItem) => "///", - (CommentKind::Line, DocTarget::EnclosingItem) => "//!", + (CommentKind::Line, DocTarget::FollowingItem) => "///", + (CommentKind::Line, DocTarget::EnclosingItem) => "//!", } } } @@ -111,8 +111,8 @@ impl fmt::Display for DocComment { match (self.kind, self.target) { (CommentKind::Block, DocTarget::FollowingItem) => write!(f, "/**{}*/", self.text), (CommentKind::Block, DocTarget::EnclosingItem) => write!(f, "/*!{}*/", self.text), - (CommentKind::Line, DocTarget::FollowingItem) => write!(f, "///{}", self.text), - (CommentKind::Line, DocTarget::EnclosingItem) => write!(f, "//!{}", self.text), + (CommentKind::Line, DocTarget::FollowingItem) => write!(f, "///{}", self.text), + (CommentKind::Line, DocTarget::EnclosingItem) => write!(f, "//!{}", self.text), } } } @@ -149,9 +149,10 @@ fn simplify(out: &mut String, text: &str, ignore_char: char) -> bool { continue; } - let this_prefix = &line[..line.len() - line - .trim_start_matches(|c: char| c.is_whitespace() || c == ignore_char) - .len()]; + let this_prefix = &line[..line.len() + - line + .trim_start_matches(|c: char| c.is_whitespace() || c == ignore_char) + .len()]; match prefix { None => prefix = Some(this_prefix), Some(ref mut prefix) => { @@ -160,17 +161,21 @@ fn simplify(out: &mut String, text: &str, ignore_char: char) -> bool { loop { no_match = chars.as_str(); match chars.next() { - Some(ch) => if Some(ch) != this_chars.next() { - break; + Some(ch) => { + if Some(ch) != this_chars.next() { + break; + } }, None => break, } } *prefix = &prefix[..prefix.len() - no_match.len()]; - } + }, } - let this_suffix = &line[line.trim_end_matches(|c: char| c.is_whitespace() || c == ignore_char).len()..]; + let this_suffix = &line[line + .trim_end_matches(|c: char| c.is_whitespace() || c == ignore_char) + .len()..]; match suffix { None => suffix = Some(this_suffix), Some(ref mut suffix) => { @@ -179,14 +184,16 @@ fn simplify(out: &mut String, text: &str, ignore_char: char) -> bool { loop { no_match = chars.as_str(); match chars.next_back() { - Some(ch) => if Some(ch) != this_chars.next_back() { - break; + Some(ch) => { + if Some(ch) != this_chars.next_back() { + break; + } }, None => break, } } *suffix = &suffix[no_match.len()..]; - } + }, } } @@ -229,8 +236,7 @@ pub enum DocTarget { } /// Information about where builtin docs can be found. -#[derive(Clone, Debug, PartialEq, GetSize)] -#[derive(Default)] +#[derive(Clone, Debug, PartialEq, GetSize, Default)] pub enum BuiltinDocs { #[default] None, diff --git a/crates/dreammaker/src/error.rs b/crates/dreammaker/src/error.rs index 7cc585ab..cb45a278 100644 --- a/crates/dreammaker/src/error.rs +++ b/crates/dreammaker/src/error.rs @@ -1,7 +1,7 @@ //! Error, warning, and other diagnostics handling. -use std::cell::{Ref, RefCell, RefMut}; use foldhash::HashMap; +use std::cell::{Ref, RefCell, RefMut}; use std::path::{Path, PathBuf}; use std::{error, fmt, io}; @@ -130,10 +130,13 @@ impl Context { Err(io_error) => { let file = self.register_file(toml); let (line, column) = io_error.line_col().unwrap_or((1, 1)); - DMError::new(Location { file, line, column }, "Error reading configuration file") - .with_boxed_cause(io_error.into_boxed_error()) - .register(self); - } + DMError::new( + Location { file, line, column }, + "Error reading configuration file", + ) + .with_boxed_cause(io_error.into_boxed_error()) + .register(self); + }, } } @@ -174,11 +177,11 @@ impl Context { /// Push an error or other diagnostic to the context. pub fn register_error(&self, error: DMError) { let Some(error) = self.config.set_configured_severity(error) else { - return // errortype is disabled + return; // errortype is disabled }; // ignore errors with severity above configured level if !self.config.registerable_error(&error) { - return + return; } if let Some(print_severity) = self.print_severity { if error.severity() <= print_severity { @@ -202,7 +205,11 @@ impl Context { } /// Pretty-print a `DMError` to the given output. - pub fn pretty_print_error(&self, w: &mut W, error: &DMError) -> io::Result<()> { + pub fn pretty_print_error( + &self, + w: &mut W, + error: &DMError, + ) -> io::Result<()> { writeln!( w, "{}, line {}, column {}:", @@ -218,14 +225,12 @@ impl Context { for note in error.notes().iter() { if note.location == error.location { - writeln!(w, "- {}", note.description, )?; + writeln!(w, "- {}", note.description,)?; } else if note.location.file == error.location.file { writeln!( w, "- {}:{}: {}", - note.location.line, - note.location.column, - note.description, + note.location.line, note.location.column, note.description, )?; } else { writeln!( @@ -241,7 +246,11 @@ impl Context { writeln!(w) } - pub fn pretty_print_error_nocolor(&self, w: &mut W, error: &DMError) -> io::Result<()> { + pub fn pretty_print_error_nocolor( + &self, + w: &mut W, + error: &DMError, + ) -> io::Result<()> { self.pretty_print_error(&mut termcolor::NoColor::new(w), error) } @@ -255,7 +264,8 @@ impl Context { let mut printed = false; for err in errors.iter() { if err.severity <= min_severity { - self.pretty_print_error(stderr, err).expect("error writing to stderr"); + self.pretty_print_error(stderr, err) + .expect("error writing to stderr"); printed = true; } } @@ -287,7 +297,11 @@ pub struct Location { impl Location { pub fn builtins() -> Location { - Location { file: FILEID_BUILTINS, line: 1, column: 1 } + Location { + file: FILEID_BUILTINS, + line: 1, + column: 1, + } } /// Pack this Location for use in `u64`-keyed structures. @@ -342,8 +356,7 @@ pub(crate) trait HasLocation { // Error handling /// The possible diagnostic severities available. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] -#[derive(Default)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default)] pub enum Severity { #[default] Error = 1, @@ -356,9 +369,15 @@ impl Severity { fn style(self) -> ColorSpec { let mut spec = ColorSpec::new(); match self { - Severity::Error => { spec.set_fg(Some(Color::Red)); } - Severity::Warning => { spec.set_fg(Some(Color::Yellow)); } - Severity::Info => { spec.set_fg(Some(Color::White)).set_intense(true); } + Severity::Error => { + spec.set_fg(Some(Color::Red)); + }, + Severity::Warning => { + spec.set_fg(Some(Color::Yellow)); + }, + Severity::Info => { + spec.set_fg(Some(Color::White)).set_intense(true); + }, Severity::Hint => {}, } spec @@ -377,8 +396,7 @@ impl fmt::Display for Severity { } /// A component which generated a diagnostic, when separation is desired. -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -#[derive(Default)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)] pub enum Component { #[default] Unspecified, @@ -518,17 +536,19 @@ impl DMError { impl fmt::Display for DMError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Like `pretty_print_error` above, but without filename information. - write!(f, "{}:{}: {}: {}", self.location.line, self.location.column, self.severity, self.description)?; + write!( + f, + "{}:{}: {}: {}", + self.location.line, self.location.column, self.severity, self.description + )?; for note in self.notes.iter() { if note.location == self.location { - write!(f, "\n- {}", note.description, )?; + write!(f, "\n- {}", note.description,)?; } else { write!( f, "\n- {}:{}: {}", - note.location.line, - note.location.column, - note.description, + note.location.line, note.location.column, note.description, )?; } } @@ -554,7 +574,7 @@ impl Clone for DMError { component: self.component, description: self.description.clone(), notes: self.notes.clone(), - cause: None, // not trivially cloneable + cause: None, // not trivially cloneable errortype: self.errortype, } } diff --git a/crates/dreammaker/src/indents.rs b/crates/dreammaker/src/indents.rs index 06a0760e..8487b4ba 100644 --- a/crates/dreammaker/src/indents.rs +++ b/crates/dreammaker/src/indents.rs @@ -23,10 +23,14 @@ pub struct IndentProcessor<'ctx, I> { eof_yielded: bool, } -impl<'ctx, I> IndentProcessor<'ctx, I> where - I: Iterator +impl<'ctx, I> IndentProcessor<'ctx, I> +where + I: Iterator, { - pub fn new>(context: &'ctx Context, inner: J) -> Self { + pub fn new>( + context: &'ctx Context, + inner: J, + ) -> Self { IndentProcessor { context, inner: inner.into_iter(), @@ -47,12 +51,16 @@ impl<'ctx, I> IndentProcessor<'ctx, I> where #[inline] fn push(&mut self, tok: Token) { - self.output.push_back(LocatedToken::new(self.last_input_loc, tok)); + self.output + .push_back(LocatedToken::new(self.last_input_loc, tok)); } #[inline] fn push_eol(&mut self, tok: Token) { - self.output.push_back(LocatedToken::new(self.eol_location.unwrap_or(self.last_input_loc), tok)); + self.output.push_back(LocatedToken::new( + self.eol_location.unwrap_or(self.last_input_loc), + tok, + )); } #[inline] @@ -72,15 +80,14 @@ impl<'ctx, I> IndentProcessor<'ctx, I> where self.eol_location = Some(self.last_input_loc); } return; - } - Token::Punct(Punctuation::Tab) | - Token::Punct(Punctuation::Space) => { + }, + Token::Punct(Punctuation::Tab) | Token::Punct(Punctuation::Space) => { if let Some(spaces) = self.current_spaces.as_mut() { *spaces += 1; } return; - } - _ => {} + }, + _ => {}, } // handle pre-existing braces @@ -88,8 +95,8 @@ impl<'ctx, I> IndentProcessor<'ctx, I> where Token::Punct(Punctuation::LBrace) => self.current_spaces = None, Token::Punct(Punctuation::RBrace) => { self.current_spaces = None; - } - _ => {} + }, + _ => {}, } // handle indentation @@ -105,7 +112,7 @@ impl<'ctx, I> IndentProcessor<'ctx, I> where new_indents = 1; self.current = Some((spaces, 1)); } - } + }, Some((spaces_per_indent, indents_)) => { indents = indents_; if spaces == 0 { @@ -116,14 +123,18 @@ impl<'ctx, I> IndentProcessor<'ctx, I> where // Register the error, but cross our fingers and // hope that truncating division will approximate // a sane situation. - DMError::new(self.last_input_loc, format!( - "inconsistent indentation: {spaces} % {spaces_per_indent} != 0", - )).register(self.context) + DMError::new( + self.last_input_loc, + format!( + "inconsistent indentation: {spaces} % {spaces_per_indent} != 0", + ), + ) + .register(self.context) } new_indents = spaces / spaces_per_indent; self.current = Some((spaces_per_indent, new_indents)); } - } + }, } if indents + 1 == new_indents { @@ -131,10 +142,14 @@ impl<'ctx, I> IndentProcessor<'ctx, I> where self.push_eol(Token::Punct(Punctuation::LBrace)); } else if indents < new_indents { // multiple indent is an error, register it but let it work - DMError::new(self.last_input_loc, format!( - "inconsistent multiple indentation: {} > 1", - new_indents - indents, - )).register(self.context); + DMError::new( + self.last_input_loc, + format!( + "inconsistent multiple indentation: {} > 1", + new_indents - indents, + ), + ) + .register(self.context); for _ in indents..new_indents { self.push_eol(Token::Punct(Punctuation::LBrace)); } @@ -159,24 +174,25 @@ impl<'ctx, I> IndentProcessor<'ctx, I> where None => Some((1, 1)), Some((x, y)) => Some((x, y + 1)), }; - } + }, Token::Punct(Punctuation::RBrace) => { self.current = match self.current { None => { - DMError::new(self.last_input_loc, "unmatched right brace").register(self.context); + DMError::new(self.last_input_loc, "unmatched right brace") + .register(self.context); None - } + }, Some((_, 1)) => None, Some((x, y)) => Some((x, y - 1)), }; - } + }, Token::Punct(Punctuation::LParen) => { self.parentheses += 1; - } + }, Token::Punct(Punctuation::RParen) => { self.parentheses = self.parentheses.saturating_sub(1); - } - _ => {} + }, + _ => {}, } self.eol_location = None; @@ -184,8 +200,9 @@ impl<'ctx, I> IndentProcessor<'ctx, I> where } } -impl<'ctx, I> Iterator for IndentProcessor<'ctx, I> where - I: Iterator +impl<'ctx, I> Iterator for IndentProcessor<'ctx, I> +where + I: Iterator, { type Item = LocatedToken; diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index f0a2fee2..961830b0 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -190,7 +190,10 @@ fn make_speedy_table() { } if let Some(prev) = prev { - assert!(each > prev, "out-of-order: {each:?} is not greater than {prev:?}"); + assert!( + each > prev, + "out-of-order: {each:?} is not greater than {prev:?}" + ); } prev = Some(each); @@ -224,7 +227,10 @@ fn filter_punct_table(filter: u8) -> &'static [(&'static str, Punctuation)] { } #[inline] -fn filter_punct<'a>(input: &'a [(&'static str, Punctuation)], filter: &[u8]) -> &'a [(&'static str, Punctuation)] { +fn filter_punct<'a>( + input: &'a [(&'static str, Punctuation)], + filter: &[u8], +) -> &'a [(&'static str, Punctuation)] { // requires that PUNCT_TABLE be ordered, shorter entries be first, // and all entries with >1 character also have their prefix in the table let mut start = 0; @@ -278,66 +284,37 @@ impl Token { _ => continue, }; match p { - In | - Eq | - NotEq | - Mod | - FloatMod | - And | - BitAndAssign | - AndAssign | - Mul | - Pow | - MulAssign | - Add | - AddAssign | - Sub | - SubAssign | - DivAssign | - Colon | - AssignInto | - Less | - LShift | - LShiftAssign | - LessEq | - LessGreater | - Assign | - Greater | - GreaterEq | - RShift | - RShiftAssign | - QuestionMark | - BitXorAssign | - BitOrAssign | - OrAssign | - Or => return true, - _ => {} + In | Eq | NotEq | Mod | FloatMod | And | BitAndAssign | AndAssign | Mul | Pow + | MulAssign | Add | AddAssign | Sub | SubAssign | DivAssign | Colon + | AssignInto | Less | LShift | LShiftAssign | LessEq | LessGreater | Assign + | Greater | GreaterEq | RShift | RShiftAssign | QuestionMark | BitXorAssign + | BitOrAssign | OrAssign | Or => return true, + _ => {}, } } // space match (prev, self) { - (&Token::Ident(_, true), _) | - (&Token::Punct(Comma), _) => true, - (&Token::Ident(..), &Token::Punct(_)) | - (&Token::Ident(..), &Token::InterpStringEnd(_)) | - (&Token::Ident(..), &Token::InterpStringPart(_)) | - (&Token::Punct(_), &Token::Ident(..)) | - (&Token::InterpStringBegin(_), &Token::Ident(..)) | - (&Token::InterpStringPart(_), &Token::Ident(..)) => false, - (&Token::Ident(..), _) | - (_, &Token::Ident(..)) => true, + (&Token::Ident(_, true), _) | (&Token::Punct(Comma), _) => true, + (&Token::Ident(..), &Token::Punct(_)) + | (&Token::Ident(..), &Token::InterpStringEnd(_)) + | (&Token::Ident(..), &Token::InterpStringPart(_)) + | (&Token::Punct(_), &Token::Ident(..)) + | (&Token::InterpStringBegin(_), &Token::Ident(..)) + | (&Token::InterpStringPart(_), &Token::Ident(..)) => false, + (&Token::Ident(..), _) | (_, &Token::Ident(..)) => true, _ => false, } } /// Check whether this token is whitespace. pub fn is_whitespace(&self) -> bool { - matches!(*self, + matches!( + *self, Token::Punct(Punctuation::Tab) - | Token::Punct(Punctuation::Newline) - | Token::Punct(Punctuation::Space) - | Token::Eof + | Token::Punct(Punctuation::Newline) + | Token::Punct(Punctuation::Space) + | Token::Eof ) } @@ -421,7 +398,9 @@ impl fmt::Display for FormatFloat { if exp >= 6.0 || exp <= -5.0 { let n2 = (n * factor).round() * 1.0e-5; let mut precision = 0; - while precision < 5 && (n2 * 10.0f32.powi(precision)) != (n2 * 10.0f32.powi(precision)).round() { + while precision < 5 + && (n2 * 10.0f32.powi(precision)) != (n2 * 10.0f32.powi(precision)).round() + { precision += 1; } write!(f, "{:.*}e{:+04}", precision as usize, n2, exp) @@ -519,7 +498,17 @@ pub fn buffer_file(file: FileId, path: &std::path::Path) -> Result, DMEr let mut read = match std::fs::File::open(path) { Ok(read) => read, - Err(error) => return Err(DMError::new(Location { file, line: 1, column: 1 }, "i/o error opening file").with_cause(error)), + Err(error) => { + return Err(DMError::new( + Location { + file, + line: 1, + column: 1, + }, + "i/o error opening file", + ) + .with_cause(error)) + }, }; if let Err(error) = read.read_to_end(&mut buffer) { @@ -678,12 +667,20 @@ impl<'ctx> Lexer<'ctx> { } /// Create a new lexer from a byte stream. - pub fn new>>(context: &'ctx Context, file_number: FileId, input: I) -> Self { + pub fn new>>( + context: &'ctx Context, + file_number: FileId, + input: I, + ) -> Self { Lexer::from_input(context, LocationTracker::new(file_number, input.into())) } /// Create a new lexer from a reader. - pub fn from_read(context: &'ctx Context, file: FileId, read: R) -> Result { + pub fn from_read( + context: &'ctx Context, + file: FileId, + read: R, + ) -> Result { let start_time = std::time::Instant::now(); let input = buffer_read(file, read)?; context.add_io_time(start_time.elapsed()); @@ -691,7 +688,11 @@ impl<'ctx> Lexer<'ctx> { } /// Create a new lexer from a reader. - pub fn from_file(context: &'ctx Context, file: FileId, path: &std::path::Path) -> Result { + pub fn from_file( + context: &'ctx Context, + file: FileId, + path: &std::path::Path, + ) -> Result { let start_time = std::time::Instant::now(); let input = buffer_file(file, path)?; context.add_io_time(start_time.elapsed()); @@ -720,7 +721,7 @@ impl<'ctx> Lexer<'ctx> { self.at_line_head = false; } Some(ch) - } + }, } } @@ -742,14 +743,22 @@ impl<'ctx> Lexer<'ctx> { // '*' must be tracked to accurately end the block comment, and // will be stripped by the documentation parser. Some(b'*') => { - comment = Some(DocComment::new(CommentKind::Block, DocTarget::FollowingItem)); + comment = Some(DocComment::new( + CommentKind::Block, + DocTarget::FollowingItem, + )); buffer[1] = b'*'; - } + }, // '!' will not be skipped by the documentation parser, and is not // important to checking when the block comment has ended. - Some(b'!') => comment = Some(DocComment::new(CommentKind::Block, DocTarget::EnclosingItem)), + Some(b'!') => { + comment = Some(DocComment::new( + CommentKind::Block, + DocTarget::EnclosingItem, + )) + }, Some(other) => buffer[1] = other, - None => {} + None => {}, } loop { @@ -758,9 +767,10 @@ impl<'ctx> Lexer<'ctx> { match self.next() { Some(val) => buffer[1] = val, None => { - self.context.register_error(self.error("still skipping comments at end of file")); + self.context + .register_error(self.error("still skipping comments at end of file")); break; - } + }, } if buffer == *b"/*" { @@ -790,14 +800,18 @@ impl<'ctx> Lexer<'ctx> { let mut comment = None; let mut comment_text = Vec::new(); match self.next() { - Some(b'/') => comment = Some(DocComment::new(CommentKind::Line, DocTarget::FollowingItem)), - Some(b'!') => comment = Some(DocComment::new(CommentKind::Line, DocTarget::EnclosingItem)), + Some(b'/') => { + comment = Some(DocComment::new(CommentKind::Line, DocTarget::FollowingItem)) + }, + Some(b'!') => { + comment = Some(DocComment::new(CommentKind::Line, DocTarget::EnclosingItem)) + }, Some(b'\n') => { self.put_back(Some(b'\n')); return None; - } + }, Some(b'\\') => backslash = true, - _ => {} + _ => {}, } while let Some(ch) = self.next() { @@ -809,9 +823,11 @@ impl<'ctx> Lexer<'ctx> { // not listening } else if backslash { if ch == b'\n' { - self.error("backslash in line comment may be commenting out the following line") - .set_severity(Severity::Warning) - .register(self.context); + self.error( + "backslash in line comment may be commenting out the following line", + ) + .set_severity(Severity::Warning) + .register(self.context); } backslash = false; } else if ch == b'\n' { @@ -838,7 +854,7 @@ impl<'ctx> Lexer<'ctx> { if first == b'.' { integer = false; } else if first == b'0' { - radix = 8; // hate. let me tell you... + radix = 8; // hate. let me tell you... match self.next() { Some(b'x') => radix = 16, ch => self.put_back(ch), @@ -855,12 +871,12 @@ impl<'ctx> Lexer<'ctx> { exponent |= ch == b'e' || ch == b'E'; } buf.push(ch as char); - } + }, Some(ch) if (ch == b'+' || ch == b'-') && exponent => { buf.push(ch as char); - } + }, Some(b'#') => { - buf.push('#'); // Keep pushing to `buf` in case of error. + buf.push('#'); // Keep pushing to `buf` in case of error. let start = buf.len(); for _ in 0..3 { if let Some(ch) = self.next() { @@ -880,15 +896,15 @@ impl<'ctx> Lexer<'ctx> { // Got "1.#IND", change it to "NaN" for read_number. return (false, 10, "NaN".into()); } - } + }, Some(ch) if (ch as char).is_digit(::std::cmp::max(radix, 10)) => { exponent = false; buf.push(ch as char); - } + }, ch => { self.put_back(ch); return (integer, radix, buf.into()); - } + }, } } } @@ -907,26 +923,29 @@ impl<'ctx> Lexer<'ctx> { if let Ok(val) = f32::from_str(&buf) { let val_str = val.to_string(); if val_str != buf { - self.error(format!("precision loss of integer constant: \"{buf}\" to {val}")) - .set_severity(Severity::Warning) - .with_errortype("integer_precision_loss") - .register(self.context); + self.error(format!( + "precision loss of integer constant: \"{buf}\" to {val}" + )) + .set_severity(Severity::Warning) + .with_errortype("integer_precision_loss") + .register(self.context); } - return Token::Float(val) + return Token::Float(val); } } - self.context.register_error(self.error( - format!("bad base-{radix} integer \"{buf}\": {original_error}"))); - Token::Int(0) // fallback + self.context.register_error(self.error(format!( + "bad base-{radix} integer \"{buf}\": {original_error}" + ))); + Token::Int(0) // fallback } else { // ignore radix match f32::from_str(&buf) { Ok(val) => Token::Float(val), Err(e) => { - self.context.register_error(self.error( - format!("bad float \"{buf}\": {e}"))); - Token::Float(0.0) // fallback - } + self.context + .register_error(self.error(format!("bad float \"{buf}\": {e}"))); + Token::Float(0.0) // fallback + }, } } } @@ -945,7 +964,7 @@ impl<'ctx> Lexer<'ctx> { ws = ch == Some(b' ') || ch == Some(b'\t'); self.put_back(ch); break; - } + }, } } let ident = &self.input.inner[start..end]; @@ -966,9 +985,10 @@ impl<'ctx> Lexer<'ctx> { Some(b'\'') => break, Some(ch) => buf.push(ch), None => { - self.context.register_error(DMError::new(start_loc, "unterminated resource literal")); + self.context + .register_error(DMError::new(start_loc, "unterminated resource literal")); break; - } + }, } } from_utf8_or_latin1(buf) @@ -985,9 +1005,10 @@ impl<'ctx> Lexer<'ctx> { let ch = match self.next() { Some(ch) => ch, None => { - self.context.register_error(DMError::new(start_loc, "unterminated string literal")); + self.context + .register_error(DMError::new(start_loc, "unterminated string literal")); break; - } + }, }; if ch == end[idx] && !backslash { idx += 1; @@ -1019,7 +1040,7 @@ impl<'ctx> Lexer<'ctx> { backslash = false; buf.push(b'\\'); buf.push(ch); - } + }, // `backslash` is false hereafter b'[' => { self.interp_stack.push(Interpolation { @@ -1028,7 +1049,7 @@ impl<'ctx> Lexer<'ctx> { }); interp_opened = true; break; - } + }, b'\\' => backslash = true, ch => buf.push(ch), } @@ -1050,10 +1071,9 @@ impl<'ctx> Lexer<'ctx> { match self.next() { Some(ch) => buf.push(ch), None => { - DMError::new(start_loc, "unterminated raw string") - .register(self.context); + DMError::new(start_loc, "unterminated raw string").register(self.context); break; - } + }, } if buf.ends_with(terminator) { let len = buf.len() - terminator.len(); @@ -1068,8 +1088,7 @@ impl<'ctx> Lexer<'ctx> { // We just got the '@'. Let's see what the next character is. match self.next() { // @ - error - Some(b'\n') | - None => { + Some(b'\n') | None => { self.error("unterminated raw string").register(self.context); Token::String(String::new()) }, @@ -1082,14 +1101,16 @@ impl<'ctx> Lexer<'ctx> { Some(b')') => break, Some(ch) => terminator.push(ch), None => { - self.error("unterminated raw string terminator").register(self.context); - return Token::String(String::new()) - } + self.error("unterminated raw string terminator") + .register(self.context); + return Token::String(String::new()); + }, } } if terminator.is_empty() { - self.error("empty raw string terminator").register(self.context); - return Token::String(String::new()) + self.error("empty raw string terminator") + .register(self.context); + return Token::String(String::new()); } self.read_raw_string_inner(&terminator) }, @@ -1100,7 +1121,7 @@ impl<'ctx> Lexer<'ctx> { other => { self.put_back(other); self.read_raw_string_inner(b"{") - } + }, }, // @ Some(terminator) => self.read_raw_string_inner(&[terminator]), @@ -1108,7 +1129,7 @@ impl<'ctx> Lexer<'ctx> { } fn read_punct(&mut self, first: u8) -> Option { - let mut needle = [first, 0, 0, 0, 0, 0, 0, 0]; // poor man's StackVec + let mut needle = [first, 0, 0, 0, 0, 0, 0, 0]; // poor man's StackVec let mut needle_idx = 1; let mut items = filter_punct_table(first); @@ -1126,7 +1147,7 @@ impl<'ctx> Lexer<'ctx> { needle[needle_idx] = b; needle_idx += 1; }, - None => return candidate, // EOF + None => return candidate, // EOF } items = filter_punct(items, &needle[..needle_idx]); } @@ -1141,10 +1162,7 @@ impl<'ctx> Lexer<'ctx> { if punct != close { let next = self.next(); match next { - Some(b'\r') | - Some(b' ') | - Some(b'\t') | - Some(b'\n') => {} + Some(b'\r') | Some(b' ') | Some(b'\t') | Some(b'\n') => {}, _ => punct = close, } self.put_back(next); @@ -1157,10 +1175,14 @@ impl<'ctx> Lexer<'ctx> { loop { match self.next() { Some(b'\r') => {}, - Some(b' ') | - Some(b'\t') if !self.at_line_head || skip_newlines > 0 => { self.close_allowed = false; }, - Some(b'\n') if skip_newlines == 2 => { skip_newlines = 1; self.close_allowed = true; }, - ch => return ch + Some(b' ') | Some(b'\t') if !self.at_line_head || skip_newlines > 0 => { + self.close_allowed = false; + }, + Some(b'\n') if skip_newlines == 2 => { + skip_newlines = 1; + self.close_allowed = true; + }, + ch => return ch, } } } @@ -1170,8 +1192,8 @@ impl<'ctx> Iterator for Lexer<'ctx> { type Item = LocatedToken; fn next(&mut self) -> Option { - use self::Token::*; use self::Punctuation::*; + use self::Token::*; let mut skip_newlines = false; let mut found_illegal = false; loop { @@ -1190,7 +1212,7 @@ impl<'ctx> Iterator for Lexer<'ctx> { } else { return None; } - } + }, }; skip_newlines = false; @@ -1211,19 +1233,19 @@ impl<'ctx> Iterator for Lexer<'ctx> { Some(Hash) if self.directive == Directive::None => { self.directive = Directive::Hash; Some(locate(Punct(Hash))) - } + }, Some(BlockComment) => { if let Some(t) = self.skip_block_comments() { return Some(locate(t)); } continue; - } + }, Some(LineComment) => { if let Some(t) = self.skip_line_comment() { return Some(locate(t)); } continue; - } + }, Some(SingleQuote) => Some(locate(Resource(self.read_resource()))), Some(DoubleQuote) => Some(locate(self.read_string(b"\"", false))), Some(BlockString) => Some(locate(self.read_string(b"\"}", false))), @@ -1232,7 +1254,7 @@ impl<'ctx> Iterator for Lexer<'ctx> { interp.bracket_depth += 1; } Some(locate(Punct(lbr))) - } + }, Some(RBracket) => { if let Some(mut interp) = self.interp_stack.pop() { interp.bracket_depth -= 1; @@ -1243,11 +1265,11 @@ impl<'ctx> Iterator for Lexer<'ctx> { } self.close_allowed = true; Some(locate(Punct(RBracket))) - } + }, Some(RParen) => { self.close_allowed = true; Some(locate(Punct(RParen))) - } + }, Some(v) => Some(locate(Punct(v))), None => match first { b'0'..=b'9' => Some(locate(self.read_number(first))), @@ -1266,12 +1288,12 @@ impl<'ctx> Iterator for Lexer<'ctx> { } self.close_allowed = true; Some(locate(Ident(ident, ws))) - } + }, b'\\' => { self.at_line_head = false; skip_newlines = true; continue; - } + }, b'@' => Some(locate(self.read_raw_string())), _ => { if !found_illegal { @@ -1284,7 +1306,7 @@ impl<'ctx> Iterator for Lexer<'ctx> { found_illegal = true; } continue; - } + }, }, }; } diff --git a/crates/dreammaker/src/lib.rs b/crates/dreammaker/src/lib.rs index 43d02abd..50781037 100644 --- a/crates/dreammaker/src/lib.rs +++ b/crates/dreammaker/src/lib.rs @@ -43,10 +43,12 @@ impl Context { /// return a best-effort parse. Call `print_all_errors` to pretty-print /// errors to standard error. pub fn parse_environment(&self, dme: &Path) -> Result { - Ok(parser::parse(self, - indents::IndentProcessor::new(self, - preprocessor::Preprocessor::new(self, dme.to_owned())? - ) + Ok(parser::parse( + self, + indents::IndentProcessor::new( + self, + preprocessor::Preprocessor::new(self, dme.to_owned())?, + ), )) } } @@ -58,9 +60,10 @@ impl Context { /// /// If `show_ws` is true, braces and semicolons are included directly in the /// output rather than only being implied by the indentation. -pub fn pretty_print(w: &mut W, input: I, show_ws: bool) -> std::fmt::Result where +pub fn pretty_print(w: &mut W, input: I, show_ws: bool) -> std::fmt::Result +where W: std::fmt::Write, - I: IntoIterator + I: IntoIterator, { let mut indents = 0; let mut needs_newline = false; @@ -73,22 +76,22 @@ pub fn pretty_print(w: &mut W, input: I, show_ws: bool) -> std::fmt::Resul if show_ws { write!(w, "{{")?; } - } + }, lexer::Token::Punct(lexer::Punctuation::RBrace) => { indents -= 1; needs_newline = true; if show_ws { write!(w, "}}")?; } - } - lexer::Token::Punct(lexer::Punctuation::Semicolon) | - lexer::Token::Punct(lexer::Punctuation::Newline) => { + }, + lexer::Token::Punct(lexer::Punctuation::Semicolon) + | lexer::Token::Punct(lexer::Punctuation::Newline) => { needs_newline = true; if show_ws { write!(w, ";")?; } - } - lexer::Token::DocComment(_) => {} + }, + lexer::Token::DocComment(_) => {}, other => { if needs_newline { const SPACES: &str = " "; @@ -106,7 +109,7 @@ pub fn pretty_print(w: &mut W, input: I, show_ws: bool) -> std::fmt::Resul } write!(w, "{other}")?; prev = Some(other); - } + }, } } if needs_newline { @@ -165,7 +168,10 @@ pub const DEFAULT_ENV: &str = "tgstation.dme"; /// Autodetect any `.dme` file in the current folder, or fall back to default. /// /// If multiple environments exist, the first non-default is preferred. -pub fn detect_environment(root: &Path, default: &str) -> std::io::Result> { +pub fn detect_environment( + root: &Path, + default: &str, +) -> std::io::Result> { let mut result = None; for entry in std::fs::read_dir(root)?.flatten() { let name = entry.file_name(); @@ -185,10 +191,12 @@ pub fn detect_environment(root: &Path, default: &str) -> std::io::Result std::io::Result> { // Return a path in the current directory `.` ... - detect_environment(".".as_ref(), DEFAULT_ENV).map(|o| o.map(|path| { - // ... but without `./` preceding it. - path.strip_prefix(".").map(|p| p.to_owned()).unwrap_or(path) - })) + detect_environment(".".as_ref(), DEFAULT_ENV).map(|o| { + o.map(|path| { + // ... but without `./` preceding it. + path.strip_prefix(".").map(|p| p.to_owned()).unwrap_or(path) + }) + }) } fn heap_size_of_index_map(index_map: &IndexMap) -> usize diff --git a/crates/dreammaker/src/objtree.rs b/crates/dreammaker/src/objtree.rs index ce6811cf..9763189f 100644 --- a/crates/dreammaker/src/objtree.rs +++ b/crates/dreammaker/src/objtree.rs @@ -2,20 +2,20 @@ use std::collections::BTreeMap; use std::fmt; -use std::ops::Range; use std::mem::size_of; +use std::ops::Range; use get_size::GetSize; use get_size_derive::GetSize; -use indexmap::IndexMap; use foldhash::fast::RandomState; +use indexmap::IndexMap; use crate::heap_size_of_index_map; use super::ast::{ - ProcReturnType, Block, Expression, Ident, Parameter, PathOp, ProcDeclBuilder, ProcDeclKind, ProcFlags, - VarSuffix, VarType, VarTypeBuilder, + Block, Expression, Ident, Parameter, PathOp, ProcDeclBuilder, ProcDeclKind, ProcFlags, + ProcReturnType, VarSuffix, VarType, VarTypeBuilder, }; use super::constants::Constant; use super::docs::DocCollection; @@ -186,7 +186,11 @@ impl Type { // Used in the constant evaluator which holds an &mut ObjectTree and thus // can't be used with TypeRef. - pub(crate) fn get_value<'a>(&'a self, name: &str, objtree: &'a ObjectTree) -> Option<&'a VarValue> { + pub(crate) fn get_value<'a>( + &'a self, + name: &str, + objtree: &'a ObjectTree, + ) -> Option<&'a VarValue> { let mut current = Some(self); while let Some(ty) = current { if let Some(var) = ty.vars.get(name) { @@ -197,7 +201,11 @@ impl Type { None } - pub(crate) fn get_var_declaration<'a>(&'a self, name: &str, objtree: &'a ObjectTree) -> Option<&'a VarDeclaration> { + pub(crate) fn get_var_declaration<'a>( + &'a self, + name: &str, + objtree: &'a ObjectTree, + ) -> Option<&'a VarDeclaration> { let mut current = Some(self); while let Some(ty) = current { if let Some(var) = ty.vars.get(name) { @@ -261,7 +269,10 @@ impl<'a> TypeRef<'a> { /// Find the parent **type** based on `parent_type` var, or parent path if unspecified. pub fn parent_type(&self) -> Option> { let idx = self.parent_type; - self.tree.graph.get(idx.index()).map(|_| TypeRef::new(self.tree, idx)) + self.tree + .graph + .get(idx.index()) + .map(|_| TypeRef::new(self.tree, idx)) } /// Find the parent type of this without returning root. @@ -270,17 +281,24 @@ impl<'a> TypeRef<'a> { if idx == NodeIndex::new(0) { return None; } - self.tree.graph.get(idx.index()).map(|_| TypeRef::new(self.tree, idx)) + self.tree + .graph + .get(idx.index()) + .map(|_| TypeRef::new(self.tree, idx)) } /// Find a child **path** with the given name, if it exists. pub fn child(&self, name: &str) -> Option> { - self.children.get(name).map(|&idx| TypeRef::new(self.tree, idx)) + self.children + .get(name) + .map(|&idx| TypeRef::new(self.tree, idx)) } /// Iterate over all child **paths**. - pub fn children<'b>(&'b self) -> impl Iterator> + 'b { - self.children.values().map(move |&idx| TypeRef::new(self.tree, idx)) + pub fn children<'b>(&'b self) -> impl Iterator> + 'b { + self.children + .values() + .map(move |&idx| TypeRef::new(self.tree, idx)) } /// Recursively visit this and all child **paths**. @@ -300,7 +318,7 @@ impl<'a> TypeRef<'a> { } } - pub fn iter_parent_types(&self) -> impl Iterator> { + pub fn iter_parent_types(&self) -> impl Iterator> { struct ParentTypeIter<'a>(Option>); impl<'a> Iterator for ParentTypeIter<'a> { type Item = TypeRef<'a>; @@ -348,7 +366,8 @@ impl<'a> TypeRef<'a> { return Some(child); } for &idx in self.children.values() { - if let Some(child) = TypeRef::new(self.tree, idx).navigate(PathOp::Colon, name) { + if let Some(child) = TypeRef::new(self.tree, idx).navigate(PathOp::Colon, name) + { // Yes, simply returning the first thing that matches // is the correct behavior. return Some(child); @@ -360,7 +379,10 @@ impl<'a> TypeRef<'a> { } /// Find another type relative to this type. - pub fn navigate_path>(self, pieces: &[(PathOp, S)]) -> Option> { + pub fn navigate_path>( + self, + pieces: &[(PathOp, S)], + ) -> Option> { let mut next = Some(self); if let Some(&(PathOp::Slash, _)) = pieces.first() { next = Some(self.tree.root()); @@ -449,7 +471,7 @@ impl<'a> TypeRef<'a> { None } - pub fn iter_self_procs(self) -> impl Iterator> { + pub fn iter_self_procs(self) -> impl Iterator> { self.get().procs.iter().flat_map(move |(name, type_proc)| { let list = &type_proc.value; (0..list.len()).map(move |idx| ProcRef { @@ -512,14 +534,20 @@ impl<'o> NavigatePathResult<'o> { } pub fn to_path(self) -> Vec { - let mut path: Vec = self.ty().path.split('/').skip(1).map(ToOwned::to_owned).collect(); + let mut path: Vec = self + .ty() + .path + .split('/') + .skip(1) + .map(ToOwned::to_owned) + .collect(); match self { NavigatePathResult::Type(_) => {}, NavigatePathResult::ProcGroup(_, kind) => path.push(kind.to_string()), NavigatePathResult::ProcPath(proc, kind) => { path.push(kind.to_string()); path.push(proc.name().to_owned()); - } + }, } path } @@ -616,7 +644,14 @@ impl<'a> std::ops::Deref for ProcRef<'a> { impl<'a> fmt::Debug for ProcRef<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}/proc/{}[{}/{}]", self.ty, self.name, self.idx, self.list.len()) + write!( + f, + "{:?}/proc/{}[{}/{}]", + self.ty, + self.name, + self.idx, + self.list.len() + ) } } @@ -665,11 +700,11 @@ impl ObjectTree { // ------------------------------------------------------------------------ // Access - pub fn node_indices(&self) -> impl Iterator { + pub fn node_indices(&self) -> impl Iterator { (0..self.graph.len()).map(NodeIndex::new) } - pub fn iter_types(&self) -> impl Iterator> + '_ { + pub fn iter_types(&self) -> impl Iterator> + '_ { self.node_indices().map(move |idx| TypeRef::new(self, idx)) } @@ -762,7 +797,9 @@ impl std::ops::Index for ObjectTree { impl std::ops::IndexMut for ObjectTree { fn index_mut(&mut self, ix: NodeIndex) -> &mut Type { - self.graph.get_mut(ix.index()).expect("node index out of range") + self.graph + .get_mut(ix.index()) + .expect("node index out of range") } } @@ -891,7 +928,7 @@ impl ObjectTreeBuilder { Ok(constant) => { constant_buf = constant; Ok(&constant_buf) - } + }, Err(e) => Err(e), } } else if path == "/client" { @@ -899,13 +936,16 @@ impl ObjectTreeBuilder { Ok(&empty_string) } else { // A weird situation which should not happen. - Err(DMError::new(location, format!("missing {path}/parent_type"))) + Err(DMError::new( + location, + format!("missing {path}/parent_type"), + )) }; match constant { Ok(Constant::String(s)) => { parent_type = s; - } + }, Ok(Constant::Prefab(ref pop)) if pop.vars.is_empty() => { parent_type_buf = String::new(); for piece in pop.path.iter() { @@ -913,13 +953,13 @@ impl ObjectTreeBuilder { parent_type_buf.push_str(piece); } parent_type = &parent_type_buf; - } + }, Ok(other) => { context.register_error(DMError::new(location, format!("value of {path}/parent_type must be a string or typepath, got {other}"))); - } + }, Err(e) => { context.register_error(e); - } + }, } } parent_type @@ -935,7 +975,7 @@ impl ObjectTreeBuilder { location, format!("bad parent type for {path}: {parent_type}"), )); - NodeIndex::new(0) // on bad parent_type, fall back to the root + NodeIndex::new(0) // on bad parent_type, fall back to the root } }; @@ -946,7 +986,13 @@ impl ObjectTreeBuilder { // ------------------------------------------------------------------------ // Parsing - pub(crate) fn subtype_or_add(&mut self, location: Location, parent: NodeIndex, child: &str, len: usize) -> NodeIndex { + pub(crate) fn subtype_or_add( + &mut self, + location: Location, + parent: NodeIndex, + child: &str, + len: usize, + ) -> NodeIndex { if let Some(&target) = self.inner[parent].children.get(child) { let node = &mut self.inner[target]; if node.location_specificity > len { @@ -986,9 +1032,7 @@ impl ObjectTreeBuilder { ) -> &mut TypeVar { // TODO: warn and merge docs for repeats match self.inner[ty].vars.entry(name.to_owned()) { - indexmap::map::Entry::Vacant(slot) => { - slot.insert(TypeVar { value, declaration }) - }, + indexmap::map::Entry::Vacant(slot) => slot.insert(TypeVar { value, declaration }), indexmap::map::Entry::Occupied(slot) => { let type_var = slot.into_mut(); if let Some(declaration) = declaration { @@ -1010,17 +1054,22 @@ impl ObjectTreeBuilder { expression: Option, ) -> &mut TypeVar { let id = self.symbols.allocate(); - self.insert_var(ty, name, VarValue { - location, - expression, - docs, - constant: None, - being_evaluated: false, - }, Some(VarDeclaration { - var_type, - location, - id, - })) + self.insert_var( + ty, + name, + VarValue { + location, + expression, + docs, + constant: None, + being_evaluated: false, + }, + Some(VarDeclaration { + var_type, + location, + id, + }), + ) } pub(crate) fn override_var( @@ -1031,16 +1080,21 @@ impl ObjectTreeBuilder { docs: DocCollection, expression: Expression, ) -> &mut TypeVar { - self.insert_var(ty, name, VarValue { - location, - expression: Some(expression), - docs, - constant: None, - being_evaluated: false, - }, None) + self.insert_var( + ty, + name, + VarValue { + location, + expression: Some(expression), + docs, + constant: None, + being_evaluated: false, + }, + None, + ) } - fn get_from_path<'a, I: Iterator>( + fn get_from_path<'a, I: Iterator>( &mut self, location: Location, mut path: I, @@ -1075,7 +1129,7 @@ impl ObjectTreeBuilder { suffix: VarSuffix, ) -> Result, DMError> where - I: Iterator, + I: Iterator, { use super::ast::VarTypeFlags; let mut is_declaration = false; @@ -1114,24 +1168,26 @@ impl ObjectTreeBuilder { let symbols = &mut self.symbols; let node = &mut self.inner.graph[parent.index()]; // TODO: warn and merge docs for repeats - Ok(Some(node.vars.entry(prev.to_owned()).or_insert_with(|| TypeVar { - value: VarValue { - location, - expression: suffix.into_initializer(), - constant: None, - being_evaluated: false, - docs: comment, - }, - declaration: if is_declaration { - Some(VarDeclaration { - var_type: var_type.build(), + Ok(Some(node.vars.entry(prev.to_owned()).or_insert_with( + || TypeVar { + value: VarValue { location, - id: symbols.allocate(), - }) - } else { - None + expression: suffix.into_initializer(), + constant: None, + being_evaluated: false, + docs: comment, + }, + declaration: if is_declaration { + Some(VarDeclaration { + var_type: var_type.build(), + location, + id: symbols.allocate(), + }) + } else { + None + }, }, - }))) + ))) } // It's fine. @@ -1149,15 +1205,21 @@ impl ObjectTreeBuilder { body_range: Option>, ) -> Result<(usize, &mut ProcValue), DMError> { let node = &mut self.inner.graph[parent.index()]; - let proc = node.procs.entry(name.to_owned()).or_insert_with(|| TypeProc { - value: Vec::with_capacity(1), - declaration: None, - }); + let proc = node + .procs + .entry(name.to_owned()) + .or_insert_with(|| TypeProc { + value: Vec::with_capacity(1), + declaration: None, + }); if let Some(decl_builder) = declaration { if let Some(ref decl) = proc.declaration { - DMError::new(location, format!("duplicate definition of {}/{}", decl_builder.kind, name)) - .with_note(decl.location, "previous definition") - .register(context); + DMError::new( + location, + format!("duplicate definition of {}/{}", decl_builder.kind, name), + ) + .with_note(decl.location, "previous definition") + .register(context); } else { proc.declaration = Some(ProcDeclaration { location, @@ -1189,31 +1251,35 @@ impl ObjectTreeBuilder { // Show the hint now, make up for it by putting the original // at the beginning of the list (so `..()` finds it). // Configuration can be used to upgrade this above a hint. - DMError::new(proc.value[0].location, format!("override of {}/{} precedes definition", node.path, name)) - .set_severity(Severity::Hint) - .with_errortype("override_precedes_definition") - .with_note(location, format!("{}/{}/{} is defined here", node.path, decl, name)) - .register(context); + DMError::new( + proc.value[0].location, + format!("override of {}/{} precedes definition", node.path, name), + ) + .set_severity(Severity::Hint) + .with_errortype("override_precedes_definition") + .with_note( + location, + format!("{}/{}/{} is defined here", node.path, decl, name), + ) + .register(context); proc.value.insert(0, value); Ok((len, proc.value.first_mut().unwrap())) }, _ => { proc.value.push(value); Ok((len, proc.value.last_mut().unwrap())) - } + }, } } - pub(crate) fn add_builtin_type( - &mut self, - elems: &[&'static str], - ) -> &mut Type { + pub(crate) fn add_builtin_type(&mut self, elems: &[&'static str]) -> &mut Type { self.add_type( Location::builtins(), elems.iter().cloned(), elems.len() + 1, Default::default(), - ).unwrap() + ) + .unwrap() } // an entry which may be anything depending on the path @@ -1241,7 +1307,17 @@ impl ObjectTreeBuilder { let len = elems.len() + 1; let (parent, initial) = self.get_from_path(location, &mut path, len).unwrap(); - if let Some(type_var) = self.register_var(location, parent, initial, path, Default::default(), Default::default()).unwrap() { + if let Some(type_var) = self + .register_var( + location, + parent, + initial, + path, + Default::default(), + Default::default(), + ) + .unwrap() + { type_var.value.location = location; type_var.value.constant = value; &mut type_var.value @@ -1260,10 +1336,19 @@ impl ObjectTreeBuilder { Location::builtins(), elems.iter().copied(), elems.len() + 1, - params.iter().copied().map(|param| Parameter { name: param.into(), .. Default::default() }).collect(), + params + .iter() + .copied() + .map(|param| Parameter { + name: param.into(), + ..Default::default() + }) + .collect(), None, None, - ).unwrap().1 + ) + .unwrap() + .1 } // an entry which is definitely a proc because an argument list is specified @@ -1302,7 +1387,17 @@ impl ObjectTreeBuilder { )); } - self.register_proc(context, location, parent, proc_name, declaration, parameters, ProcReturnType::default(), code, body_range) + self.register_proc( + context, + location, + parent, + proc_name, + declaration, + parameters, + ProcReturnType::default(), + code, + body_range, + ) } } diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index fc0f27f7..8219364b 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -95,7 +95,7 @@ macro_rules! take_match { /// be registered with the provided `Context`. pub fn parse(context: &Context, iter: I) -> ObjectTree where - I: IntoIterator, + I: IntoIterator, { Parser::new(context, iter).parse_object_tree() } @@ -104,9 +104,13 @@ where /// /// Fatal errors will be directly returned and miscellaneous diagnostics will /// be registered with the provided `Context`. -pub fn parse_expression(context: &Context, location: Location, iter: I) -> Result +pub fn parse_expression( + context: &Context, + location: Location, + iter: I, +) -> Result where - I: IntoIterator, + I: IntoIterator, { let mut parser = Parser::new(context, iter); parser.location = location; @@ -307,10 +311,11 @@ impl TTKind { } fn is_end(self, token: &Token) -> bool { - matches!((self, token), + matches!( + (self, token), (TTKind::Paren, &Token::Punct(Punctuation::RParen)) - | (TTKind::Brace, &Token::Punct(Punctuation::RBrace)) - | (TTKind::Bracket, &Token::Punct(Punctuation::RBracket)) + | (TTKind::Brace, &Token::Punct(Punctuation::RBrace)) + | (TTKind::Bracket, &Token::Punct(Punctuation::RBracket)) ) } } @@ -339,7 +344,7 @@ pub struct Parser<'ctx, 'an, 'inp> { tree: ObjectTreeBuilder, fatal_errored: bool, - input: Box + 'inp>, + input: Box + 'inp>, eof: bool, possible_indentation_error: bool, next: Option, @@ -363,7 +368,10 @@ impl<'ctx, 'an, 'inp> HasLocation for Parser<'ctx, 'an, 'inp> { impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { /// Construct a new parser using the given input stream. - pub fn new + 'inp>(context: &'ctx Context, input: I) -> Self { + pub fn new + 'inp>( + context: &'ctx Context, + input: I, + ) -> Self { Parser { context, annotations: None, @@ -414,7 +422,9 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { self.tree.skip_finish() } - pub fn parse_with_module_docs(mut self) -> (ObjectTree, BTreeMap>) { + pub fn parse_with_module_docs( + mut self, + ) -> (ObjectTree, BTreeMap>) { self.tree.register_builtins(); self.run(); let docs = std::mem::take(&mut self.module_docs); @@ -472,7 +482,10 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let mut loc = error.location(); loc.line += 1; loc.column = 1; - error.add_note(loc, "check for extra indentation at the start of the next line"); + error.add_note( + loc, + "check for extra indentation at the start of the next line", + ); self.possible_indentation_error = false; } error @@ -506,13 +519,16 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { break next; } match self.input.next() { - Some(LocatedToken { location, token: Token::DocComment(comment) }) => { + Some(LocatedToken { + location, + token: Token::DocComment(comment), + }) => { self.doc_comments_pending.push_back((location, comment)); - } + }, Some(LocatedToken { location, token }) => { self.location = location; self.next = Some(token); - } + }, None => { if !self.eof { self.eof = true; @@ -520,7 +536,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } else { panic!("internal parser error: kept parsing after EOF"); } - } + }, } } } @@ -550,7 +566,10 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { return Ok(None); } match self.input.next() { - Some(LocatedToken { location, token: Token::DocComment(comment) }) => { + Some(LocatedToken { + location, + token: Token::DocComment(comment), + }) => { if comment.target == target { self.location = location; return success(comment); @@ -559,12 +578,12 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { self.doc_comments_pending.push_front((location, comment)); return Ok(None); } - } + }, Some(other) => { self.location = other.location; self.next = Some(other.token); return Ok(None); - } + }, None => return Ok(None), } } @@ -643,7 +662,13 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { self.tree_entries(self.tree.root_index(), None, None, Token::Eof) } - fn tree_entries(&mut self, current: NodeIndex, proc_builder: Option, var_type: Option, terminator: Token) -> Status<()> { + fn tree_entries( + &mut self, + current: NodeIndex, + proc_builder: Option, + var_type: Option, + terminator: Token, + ) -> Status<()> { loop { self.expected("';'"); if terminator != Token::Eof { @@ -696,9 +721,10 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { self.annotate_precise(slash_loc..slash_loc, || { Annotation::IncompleteTreePath(absolute, parts.clone()) }); - self.context.register_error(self.error("path has no effect")); + self.context + .register_error(self.error("path has no effect")); return success((absolute, Vec::new())); - } + }, } // followed by ('/' ident)* while self.slash()?.is_some() { @@ -720,7 +746,9 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } } - self.annotate(start, || Annotation::TreePath(absolute || always_absolute, parts.clone())); + self.annotate(start, || { + Annotation::TreePath(absolute || always_absolute, parts.clone()) + }); success((absolute, parts)) } @@ -758,15 +786,20 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } else try_another()) } - fn tree_entry(&mut self, mut current: NodeIndex, mut proc_builder: Option, mut var_type: Option) -> Status<()> { + fn tree_entry( + &mut self, + mut current: NodeIndex, + mut proc_builder: Option, + mut var_type: Option, + ) -> Status<()> { // tree_entry :: path ';' // tree_entry :: path '{' tree_entry* '}' // tree_entry :: path '=' expression ';' // tree_entry :: path '(' argument_list ')' ';' // tree_entry :: path '(' argument_list ')' code_block - use super::lexer::Token::*; use super::lexer::Punctuation::*; + use super::lexer::Token::*; let entry_start = self.updated_location(); @@ -783,9 +816,15 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { }; if absolute && current != self.tree.root_index() { - DMError::new(entry_start, format!("nested absolute path inside {}", self.tree.get_path(current))) - .set_severity(Severity::Warning) - .register(self.context); + DMError::new( + entry_start, + format!( + "nested absolute path inside {}", + self.tree.get_path(current) + ), + ) + .set_severity(Severity::Warning) + .register(self.context); current = self.tree.root_index(); } @@ -796,7 +835,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { self.error("tree entry appears to have no name") .register(self.context); return SUCCESS; - } + }, }; let mut relative_type_location = None; @@ -817,20 +856,31 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let flags = ProcFlags::from_name(each); if let Some(found) = flags { builder.flags |= found - } - else { + } else { self.error("cannot have sub-blocks of `proc/` block") .register(self.context); } } else { - let len = self.tree.get_path(current).chars().filter(|&c| c == '/').count() + path_len; + let len = self + .tree + .get_path(current) + .chars() + .filter(|&c| c == '/') + .count() + + path_len; current = self.tree.subtype_or_add(self.location, current, each, len); - if !absolute && self.context.config().code_standards.disallow_relative_type_definitions { + if !absolute + && self + .context + .config() + .code_standards + .disallow_relative_type_definitions + { relative_type_location = Some(self.location); } } - } + }; } macro_rules! handle_relative_type_error { () => { @@ -839,7 +889,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { .set_severity(Severity::Warning) .register(self.context); } - } + }; } for each in traverse { @@ -881,18 +931,33 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } if !docs.is_empty() && (proc_builder.is_some() || var_type.is_some()) { // Can't apply docs to `var/` or `proc/` blocks. - DMError::new(start, "docs on `var/` or `proc/` block will be applied to their type") - .set_severity(Severity::Warning) - .register(self.context); + DMError::new( + start, + "docs on `var/` or `proc/` block will be applied to their type", + ) + .set_severity(Severity::Warning) + .register(self.context); } self.tree.extend_docs(current, docs); - require!(self.tree_entries(current, proc_builder, var_type.clone(), Token::Punct(Punctuation::RBrace))); + require!(self.tree_entries( + current, + proc_builder, + var_type.clone(), + Token::Punct(Punctuation::RBrace) + )); let node = self.tree.get_path(current).to_owned(); - self.annotate(start, || Annotation::TreeBlock(reconstruct_path(&node, proc_builder, var_type.as_ref(), ""))); + self.annotate(start, || { + Annotation::TreeBlock(reconstruct_path( + &node, + proc_builder, + var_type.as_ref(), + "", + )) + }); SUCCESS - } + }, Punct(Assign) => { self.take(); // `something=` - var @@ -906,7 +971,14 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // We have to annotate prior to consuming the statement terminator, as we // will otherwise consume following whitespace resulting in a bad annotation range let node = self.tree.get_path(current).to_owned(); - self.annotate(entry_start, || Annotation::Variable(reconstruct_path(&node, proc_builder, var_type.as_ref(), last_part))); + self.annotate(entry_start, || { + Annotation::Variable(reconstruct_path( + &node, + proc_builder, + var_type.as_ref(), + last_part, + )) + }); // Allow `//!` doc comments at the end of the line. while let Some(comment) = self.enclosing_doc_comment()? { @@ -918,18 +990,33 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { if let Some(mut var_type) = var_type { var_type.suffix(&var_suffix); var_type.input_type = input_type; - self.tree.declare_var(current, last_part, location, docs, var_type.build(), Some(expression)); + self.tree.declare_var( + current, + last_part, + location, + docs, + var_type.build(), + Some(expression), + ); } else { - self.tree.override_var(current, last_part, location, docs, expression); + self.tree + .override_var(current, last_part, location, docs, expression); } SUCCESS - } + }, Punct(LParen) => { // `something(` - proc - require!(self.proc_params_and_body(current, proc_builder, last_part, entry_start, absolute, docs)); + require!(self.proc_params_and_body( + current, + proc_builder, + last_part, + entry_start, + absolute, + docs + )); SUCCESS - } + }, _ => { // usually `thing;` - a contentless declaration @@ -958,8 +1045,22 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { var_type.suffix(&var_suffix); var_type.input_type = input_type; let node = self.tree.get_path(current).to_owned(); - self.annotate(entry_start, || Annotation::Variable(reconstruct_path(&node, proc_builder, Some(&var_type), last_part))); - self.tree.declare_var(current, last_part, self.location, docs, var_type.build(), var_suffix.into_initializer()); + self.annotate(entry_start, || { + Annotation::Variable(reconstruct_path( + &node, + proc_builder, + Some(&var_type), + last_part, + )) + }); + self.tree.declare_var( + current, + last_part, + self.location, + docs, + var_type.build(), + var_suffix.into_initializer(), + ); } } else if ProcDeclKind::from_name(last_part).is_some() { self.error("`proc;` item has no effect") @@ -970,13 +1071,21 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { .register(self.context); } else { handle_relative_type_error!(); - let len = self.tree.get_path(current).chars().filter(|&c| c == '/').count() + path_len; - current = self.tree.subtype_or_add(self.location, current, last_part, len); + let len = self + .tree + .get_path(current) + .chars() + .filter(|&c| c == '/') + .count() + + path_len; + current = self + .tree + .subtype_or_add(self.location, current, last_part, len); self.tree.extend_docs(current, docs); } SUCCESS - } + }, } } @@ -987,8 +1096,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // Object tree - Procs fn try_read_operator_name(&mut self, last_part: &mut String) -> Result<(), DMError> { - use super::lexer::Token::Punct; use super::lexer::Punctuation::*; + use super::lexer::Token::Punct; if self.exact(Punct(Mod))?.is_some() { last_part.push('%'); @@ -1070,9 +1179,17 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { Ok(()) } - fn proc_params_and_body(&mut self, current: NodeIndex, proc_builder: Option, name: &str, entry_start: Location, absolute: bool, mut docs: DocCollection) -> Status<()> { - use super::lexer::Token::*; + fn proc_params_and_body( + &mut self, + current: NodeIndex, + proc_builder: Option, + name: &str, + entry_start: Location, + absolute: bool, + mut docs: DocCollection, + ) -> Status<()> { use super::lexer::Punctuation::*; + use super::lexer::Token::*; leading!(self.exact(Punct(LParen))); @@ -1134,29 +1251,50 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { self.context.register_error(err); None }, - Ok(code) => { - Some(code) - } + Ok(code) => Some(code), } } else { None }; - match self.tree.register_proc(self.context, location, current, name, proc_builder, parameters, return_type, code, Some(body_start..self.location)) { + match self.tree.register_proc( + self.context, + location, + current, + name, + proc_builder, + parameters, + return_type, + code, + Some(body_start..self.location), + ) { Ok((idx, proc)) => { proc.docs.extend(docs); // manually performed for borrowck reasons if let Some(dest) = self.annotations.as_mut() { - let new_stack = reconstruct_path(self.tree.get_path(current), proc_builder, None, name); - dest.insert(entry_start..body_start, Annotation::ProcHeader(new_stack.to_vec(), idx)); - dest.insert(body_start..self.location, Annotation::ProcBody(new_stack.to_vec(), idx)); + let new_stack = + reconstruct_path(self.tree.get_path(current), proc_builder, None, name); + dest.insert( + entry_start..body_start, + Annotation::ProcHeader(new_stack.to_vec(), idx), + ); + dest.insert( + body_start..self.location, + Annotation::ProcBody(new_stack.to_vec(), idx), + ); } - if !absolute && self.context.config().code_standards.disallow_relative_proc_definitions { + if !absolute + && self + .context + .config() + .code_standards + .disallow_relative_proc_definitions + { DMError::new(location, "relatively pathed proc defined here") .set_severity(Severity::Warning) .register(self.context); } - } + }, Err(e) => self.context.register_error(e), }; @@ -1164,14 +1302,14 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } fn proc_parameter(&mut self) -> Status { - use super::lexer::Token::*; use super::lexer::Punctuation::*; + use super::lexer::Token::*; if let Some(()) = self.exact(Punct(Ellipsis))? { return success(Parameter { name: "...".to_owned(), location: self.location, - .. Default::default() + ..Default::default() }); } @@ -1183,7 +1321,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { None => { self.describe_parse_error().register(self.context); "".to_owned() - } + }, }; if path.first().is_some_and(|i| i == "var") { path.remove(0); @@ -1233,8 +1371,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { /// Parse list size declarations. fn var_suffix(&mut self) -> Status { - use super::lexer::Token::Punct; use super::lexer::Punctuation::*; + use super::lexer::Token::Punct; let mut list = Vec::new(); while let Some(()) = self.exact(Punct(LBracket))? { @@ -1288,9 +1426,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // Option two: a typepath. require!(self.exact(Token::Punct(Punctuation::Slash))); - let mut path_vec = vec![ - require!(self.ident()), - ]; + let mut path_vec = vec![require!(self.ident())]; while let Some(()) = self.exact(Token::Punct(Punctuation::Slash))? { path_vec.push(require!(self.ident())); } @@ -1310,17 +1446,19 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let mut as_what = match InputType::from_str(&ident) { Ok(what) => what, Err(()) => { - self.context.register_error(self.error(format!("bad input type: '{ident}'"))); + self.context + .register_error(self.error(format!("bad input type: '{ident}'"))); InputType::empty() - } + }, }; while let Some(()) = self.exact(Token::Punct(Punctuation::BitOr))? { let ident = require!(self.ident()); match InputType::from_str(&ident) { Ok(what) => as_what |= what, Err(()) => { - self.context.register_error(self.error(format!("bad input type: '{ident}'"))); - } + self.context + .register_error(self.error(format!("bad input type: '{ident}'"))); + }, } } success(as_what) @@ -1355,7 +1493,11 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { success(result.into_boxed_slice()) } - fn statement(&mut self, loop_ctx: &LoopContext, vars: &mut Vec<(Location, VarType, Ident)>) -> Status> { + fn statement( + &mut self, + loop_ctx: &LoopContext, + vars: &mut Vec<(Location, VarType, Ident)>, + ) -> Status> { let start = self.location(); let spanned = |v| success(Spanned::new(start, v)); @@ -1401,7 +1543,10 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let condition = Spanned::new(self.location(), require!(self.expression())); require!(self.exact(Token::Punct(Punctuation::RParen))); require!(self.statement_terminator()); - spanned(Statement::DoWhile { block, condition: Box::new(condition) }) + spanned(Statement::DoWhile { + block, + condition: Box::new(condition), + }) } else if let Some(()) = self.exact_ident("for")? { // for () // for (Var [as Type] [in List]) Statement @@ -1490,7 +1635,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { in_list: Some(*rhs), // We'll assume the rhs of [v in x] is a list. Any other case, DM will catch anyway. block: require!(self.block(&LoopContext::ForLoop)), }))) - } + }, // We will just assume everything else for(k, [...]) is a two-pronged for loop // for (init, test) {...} _ => { @@ -1501,7 +1646,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { inc: inc.map(Box::new), block: require!(self.block(&LoopContext::ForLoop)), }) - } + }, } } } else if let Some(init) = init { @@ -1514,8 +1659,13 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // for(var/a = 1 to require!(self.exact_ident("to")); let rhs = require!(self.expression()); - return spanned(require!(self.for_range(Some(vs.var_type), vs.name, value, rhs))); - } + return spanned(require!(self.for_range( + Some(vs.var_type), + vs.name, + value, + rhs + ))); + }, }, Statement::Expr(Expression::AssignOp { op: AssignOp::Assign, @@ -1530,7 +1680,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { require!(self.exact_ident("to")); let to_rhs = require!(self.expression()); return spanned(require!(self.for_range(None, name, *rhs, to_rhs))); - } + }, Statement::Expr(Expression::BinaryOp { op: BinaryOp::In, lhs, @@ -1541,7 +1691,11 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { _ => return Err(self.error("for-list must start with variable")), }; match *rhs { - Expression::BinaryOp { op: BinaryOp::To, lhs, rhs } => { + Expression::BinaryOp { + op: BinaryOp::To, + lhs, + rhs, + } => { return spanned(require!(self.for_range(None, name, *lhs, *rhs))); }, rhs => { @@ -1554,7 +1708,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { in_list: Some(rhs), block: require!(self.block(&LoopContext::ForList)), }))); - } + }, } }, Statement::Expr(expr) => match expr.into_term() { @@ -1606,7 +1760,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } spanned(Statement::Spawn { delay: expr, - block: require!(self.block(&LoopContext::None)) + block: require!(self.block(&LoopContext::None)), }) } else if let Some(()) = self.exact_ident("switch")? { require!(self.exact(Token::Punct(Punctuation::LParen))); @@ -1617,9 +1771,15 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let default = loop { if let Some(()) = self.exact_ident("if")? { require!(self.exact(Token::Punct(Punctuation::LParen))); - let what = require!(self.separated(Punctuation::Comma, Punctuation::RParen, None, Parser::case)); + let what = require!(self.separated( + Punctuation::Comma, + Punctuation::RParen, + None, + Parser::case + )); if what.is_empty() { - self.context.register_error(self.error("switch case cannot be empty")); + self.context + .register_error(self.error("switch case cannot be empty")); } let block = require!(self.block(loop_ctx)); cases.push((Spanned::new(self.location(), what), block)); @@ -1643,10 +1803,12 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { self.skip_phantom_semicolons()?; require!(self.exact_ident("catch")); let catch_params = if let Some(()) = self.exact(Token::Punct(Punctuation::LParen))? { - require!(self.separated(Punctuation::Comma, Punctuation::RParen, None, |this| { - // TODO: improve upon this cheap approximation - success(leading!(this.tree_path(true)).1.into_boxed_slice()) - })) + require!( + self.separated(Punctuation::Comma, Punctuation::RParen, None, |this| { + // TODO: improve upon this cheap approximation + success(leading!(this.tree_path(true)).1.into_boxed_slice()) + }) + ) } else { Vec::new() }; @@ -1668,7 +1830,11 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { }; let value = require!(self.expression()); require!(self.statement_terminator()); - spanned(Statement::Setting { name: name.into(), mode, value }) + spanned(Statement::Setting { + name: name.into(), + mode, + value, + }) } else if let Some(()) = self.exact_ident("break")? { let label = self.ident()?; require!(self.statement_terminator()); @@ -1710,14 +1876,12 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { SUCCESS }, // Handle if(1){a=1;b=2} without a trailing semicolon - Token::Punct(Punctuation::RBrace) => { - SUCCESS - }, + Token::Punct(Punctuation::RBrace) => SUCCESS, Token::Punct(Punctuation::LBrace) => { self.possible_indentation_error = true; try_another() }, - _ => try_another() + _ => try_another(), } } @@ -1735,7 +1899,11 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } // Single-line statements. Can appear in for loops. Followed by a semicolon. - fn simple_statement(&mut self, in_for: bool, vars: &mut Vec<(Location, VarType, Ident)>) -> Status { + fn simple_statement( + &mut self, + in_for: bool, + vars: &mut Vec<(Location, VarType, Ident)>, + ) -> Status { if let Some(()) = self.exact_ident("var")? { // statement :: 'var' type_path name ('=' value) let mut var_stmts = Vec::new(); @@ -1761,16 +1929,22 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { .register(self.context); } if var_type.flags.is_private() { - DMError::new(type_path_start, "var/SpacemanDMM_private has no effect here") - .with_errortype("private_var") - .set_severity(Severity::Warning) - .register(self.context); + DMError::new( + type_path_start, + "var/SpacemanDMM_private has no effect here", + ) + .with_errortype("private_var") + .set_severity(Severity::Warning) + .register(self.context); } if var_type.flags.is_protected() { - DMError::new(type_path_start, "var/SpacemanDMM_protected has no effect here") - .with_errortype("protected_var") - .set_severity(Severity::Warning) - .register(self.context); + DMError::new( + type_path_start, + "var/SpacemanDMM_protected has no effect here", + ) + .with_errortype("protected_var") + .set_severity(Severity::Warning) + .register(self.context); } let var_suffix = require!(self.var_suffix()); var_type.suffix(&var_suffix); @@ -1796,7 +1970,11 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { .register(self.context); } - var_stmts.push(VarStatement { var_type: var_type.build(), name, value }); + var_stmts.push(VarStatement { + var_type: var_type.build(), + name, + value, + }); if in_for || self.exact(Token::Punct(Punctuation::Comma))?.is_none() { break; } @@ -1949,23 +2127,35 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // parse vars if we find them let mut vars = Vec::new(); if let Some(()) = self.exact(Token::Punct(Punctuation::LBrace))? { - self.separated(Punctuation::Semicolon, Punctuation::RBrace, Some(()), |this| { - let key = require!(this.ident()); - require!(this.exact(Token::Punct(Punctuation::Assign))); - let value = require!(this.expression()); - vars.push((key.into(), value)); - SUCCESS - })?; + self.separated( + Punctuation::Semicolon, + Punctuation::RBrace, + Some(()), + |this| { + let key = require!(this.ident()); + require!(this.exact(Token::Punct(Punctuation::Assign))); + let value = require!(this.expression()); + vars.push((key.into(), value)); + SUCCESS + }, + )?; } - success(Box::new(Prefab { path: parts, vars: vars.into_boxed_slice() })) + success(Box::new(Prefab { + path: parts, + vars: vars.into_boxed_slice(), + })) } fn expression(&mut self) -> Status { self.expression_ex(None, false) } - fn expression_ex(&mut self, strength: Option, in_ternary: bool) -> Status { + fn expression_ex( + &mut self, + strength: Option, + in_ternary: bool, + ) -> Status { let mut expr = leading!(self.group(in_ternary)); loop { // try to read the next operator @@ -1985,14 +2175,24 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { self.take(); // trampoline high-strength expression parts as the lhs of the newly found op - expr = require!(self.expression_part(expr, info, strength, - in_ternary || info.strength == Strength::Conditional)); + expr = require!(self.expression_part( + expr, + info, + strength, + in_ternary || info.strength == Strength::Conditional + )); } success(expr) } #[allow(clippy::only_used_in_recursion)] - fn expression_part(&mut self, lhs: Expression, prev_op: OpInfo, strength: Option, in_ternary: bool) -> Status { + fn expression_part( + &mut self, + lhs: Expression, + prev_op: OpInfo, + strength: Option, + in_ternary: bool, + ) -> Status { use std::cmp::Ordering; let mut bits = vec![lhs]; @@ -2011,20 +2211,24 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { Ordering::Less => { // the operator is stronger than us... recurse down self.take(); - rhs = require!(self.expression_part(rhs, info, strength, - in_ternary || info.strength == Strength::Conditional)); - } + rhs = require!(self.expression_part( + rhs, + info, + strength, + in_ternary || info.strength == Strength::Conditional + )); + }, Ordering::Greater => { // the operator is weaker than us... return up break; - } + }, Ordering::Equal => { // the same strength... push it to the list self.take(); ops.push(info.oper); bits.push(rhs); rhs = require!(self.group(in_ternary)); - } + }, } } @@ -2058,7 +2262,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { .set_severity(Severity::Warning) .register(self.context); Expression::from(Term::Null) - } + }, }; // Compose the result. result = Expression::TernaryOp { @@ -2084,7 +2288,10 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { for (item, op) in iter.zip(&mut ops_iter) { result = op.build(Box::new(result), Box::new(item)); } - ops_iter.next().unwrap().build(Box::new(result), Box::new(rhs)) + ops_iter + .next() + .unwrap() + .build(Box::new(result), Box::new(rhs)) }) } @@ -2451,7 +2658,10 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { belongs_to.clear(); let expr = require!(self.expression()); require!(self.exact(Token::Punct(Punctuation::RBracket))); - success(Spanned::new(first_location, Follow::Index(kind, Box::new(expr)))) + success(Spanned::new( + first_location, + Follow::Index(kind, Box::new(expr)), + )) } fn follow(&mut self, belongs_to: &mut Vec, in_ternary: bool) -> Status> { @@ -2484,7 +2694,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // register the parse error, but keep going self.context.register_error(self.describe_parse_error()); String::new() - } + }, }; let end = self.updated_location(); @@ -2492,29 +2702,25 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { Some(args) => { if !belongs_to.is_empty() { let past = std::mem::take(belongs_to); - self.annotate_precise(start..end, || Annotation::ScopedCall(past, ident.clone())); + self.annotate_precise(start..end, || { + Annotation::ScopedCall(past, ident.clone()) + }); } match kind { - PropertyAccessKind::Scope => { - Follow::ProcReference(ident.into()) - } - _ => { - Follow::Call(kind, ident.into(), args) - } + PropertyAccessKind::Scope => Follow::ProcReference(ident.into()), + _ => Follow::Call(kind, ident.into(), args), } }, None => { if !belongs_to.is_empty() { - self.annotate_precise(start..end, || Annotation::ScopedVar(belongs_to.clone(), ident.clone())); + self.annotate_precise(start..end, || { + Annotation::ScopedVar(belongs_to.clone(), ident.clone()) + }); belongs_to.push(ident.clone()); } match kind { - PropertyAccessKind::Scope => { - Follow::StaticField(ident.into()) - } - _ => { - Follow::Field(kind, ident.into()) - } + PropertyAccessKind::Scope => Follow::StaticField(ident.into()), + _ => Follow::Field(kind, ident.into()), } }, }; @@ -2546,15 +2752,20 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // register the parse error, but keep going self.context.register_error(self.describe_parse_error()); String::new() - } + }, }; let end = self.updated_location(); if !belongs_to.is_empty() { - self.annotate_precise(start..end, || Annotation::ScopedVar(belongs_to.clone(), ident.clone())); + self.annotate_precise(start..end, || { + Annotation::ScopedVar(belongs_to.clone(), ident.clone()) + }); belongs_to.push(ident.clone()); } - success(Field { kind, ident: ident.into() }) + success(Field { + kind, + ident: ident.into(), + }) } /// a parenthesized, comma-separated list of expressions @@ -2572,12 +2783,12 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { Ok(Some(expr)) => { arguments.push(expr); SUCCESS - } + }, Ok(None) => Ok(None), Err(e) => Err(e), } }); - let end = self.location; // location of the closing parenthesis + let end = self.location; // location of the closing parenthesis self.annotate_precise(start..end, || { Annotation::ProcArguments(parents.to_owned(), proc.to_owned(), arguments.len()) }); @@ -2590,19 +2801,19 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { fn pick_arguments(&mut self) -> Status> { leading!(self.exact(Token::Punct(Punctuation::LParen))); - success(require!(self.separated( - Punctuation::Comma, - Punctuation::RParen, - None, - |this| { - let expr = leading!(this.expression()); - if let Some(()) = this.exact(Token::Punct(Punctuation::Semicolon))? { - success((Some(expr), require!(this.expression()))) - } else { - success((None, expr)) - } - } - )).into()) + success( + require!( + self.separated(Punctuation::Comma, Punctuation::RParen, None, |this| { + let expr = leading!(this.expression()); + if let Some(()) = this.exact(Token::Punct(Punctuation::Semicolon))? { + success((Some(expr), require!(this.expression()))) + } else { + success((None, expr)) + } + }) + ) + .into(), + ) } fn separated Status>( @@ -2665,14 +2876,23 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } } -fn reconstruct_path(node: &str, proc_deets: Option, var_type: Option<&VarTypeBuilder>, last: &str) -> Vec { +fn reconstruct_path( + node: &str, + proc_deets: Option, + var_type: Option<&VarTypeBuilder>, + last: &str, +) -> Vec { let mut result = Vec::new(); for entry in node.split('/').skip(1) { result.push(entry.to_owned()); } if let Some(deets) = proc_deets { result.push(deets.kind.to_string()); - deets.flags.to_vec().into_iter().for_each(|elem| result.push(elem.to_string())); + deets + .flags + .to_vec() + .into_iter() + .for_each(|elem| result.push(elem.to_string())); } if let Some(var) = var_type { result.extend(var.flags.to_vec().into_iter().map(ToOwned::to_owned)); diff --git a/crates/dreammaker/src/preprocessor.rs b/crates/dreammaker/src/preprocessor.rs index a670f1f1..2d3538b3 100644 --- a/crates/dreammaker/src/preprocessor.rs +++ b/crates/dreammaker/src/preprocessor.rs @@ -95,8 +95,16 @@ pub struct DefineHistory { impl DefineHistory { /// Branch a child preprocessor from this preprocessor's historic state at /// the start of the given file. - pub fn branch_at_file<'ctx2>(&self, file: FileId, context: &'ctx2 Context) -> Preprocessor<'ctx2> { - let location = Location { file, line: 0, column: 0 }; + pub fn branch_at_file<'ctx2>( + &self, + file: FileId, + context: &'ctx2 Context, + ) -> Preprocessor<'ctx2> { + let location = Location { + file, + line: 0, + column: 0, + }; let defines = DefineMap::from_history(self, location); Preprocessor { @@ -105,12 +113,12 @@ impl DefineHistory { include_stack: Default::default(), include_locations: Default::default(), multiple_locations: Default::default(), - history: Default::default(), // TODO: support branching a second time + history: Default::default(), // TODO: support branching a second time defines, maps: Default::default(), skins: Default::default(), scripts: Default::default(), - ifdef_stack: Default::default(), // should be fine + ifdef_stack: Default::default(), // should be fine ifdef_history: Default::default(), last_input_loc: location, last_printable_input_loc: location, @@ -130,12 +138,12 @@ impl DefineHistory { include_stack: Default::default(), include_locations: Default::default(), multiple_locations: Default::default(), - history: Default::default(), // TODO: support branching a second time + history: Default::default(), // TODO: support branching a second time defines: DefineMap::from_history(self, self.last_input_loc), maps: Default::default(), skins: Default::default(), scripts: Default::default(), - ifdef_stack: Default::default(), // should be fine + ifdef_stack: Default::default(), // should be fine ifdef_history: Default::default(), last_input_loc: self.last_input_loc, last_printable_input_loc: self.last_input_loc, @@ -206,7 +214,10 @@ impl DefineMap { /// Returns `None` if the key was not present, or its most recent location /// if it was. pub fn insert(&mut self, key: String, value: (Location, Define)) -> Option { - let stack = self.inner.entry(key).or_insert_with(|| Vec::with_capacity(1)); + let stack = self + .inner + .entry(key) + .or_insert_with(|| Vec::with_capacity(1)); let result = stack.last().map(|&(loc, _)| loc); stack.push(value); result @@ -221,7 +232,7 @@ impl DefineMap { Some(stack) => { result = stack.pop(); remove = stack.is_empty(); - } + }, } if remove { self.inner.remove(key); @@ -284,7 +295,11 @@ impl<'ctx> Include<'ctx> { }) } - fn from_buffer(context: &'ctx Context, path: PathBuf, buffer: Cow<'ctx, [u8]>) -> Include<'ctx> { + fn from_buffer( + context: &'ctx Context, + path: PathBuf, + buffer: Cow<'ctx, [u8]>, + ) -> Include<'ctx> { let idx = context.register_file(&path); Include::File { //file: idx, @@ -412,7 +427,7 @@ impl<'ctx> HasLocation for Preprocessor<'ctx> { match self.include_stack.stack.last() { Some(Include::File { lexer, .. }) => lexer.location(), Some(&Include::Expansion { location, .. }) => location, - None => Location::default() + None => Location::default(), } } } @@ -427,7 +442,9 @@ impl<'ctx> Preprocessor<'ctx> { Ok(Preprocessor { context, env_file, - include_stack: IncludeStack { stack: vec![include] }, + include_stack: IncludeStack { + stack: vec![include], + }, include_locations: Default::default(), multiple_locations: Default::default(), history: Default::default(), @@ -447,7 +464,11 @@ impl<'ctx> Preprocessor<'ctx> { }) } - pub fn from_buffer>>(context: &'ctx Context, env_file: PathBuf, buffer: S) -> Self { + pub fn from_buffer>>( + context: &'ctx Context, + env_file: PathBuf, + buffer: S, + ) -> Self { let cow_u8 = match buffer.into() { Cow::Borrowed(s) => Cow::Borrowed(s.as_bytes()), Cow::Owned(s) => Cow::Owned(s.into_bytes()), @@ -456,7 +477,9 @@ impl<'ctx> Preprocessor<'ctx> { Preprocessor { context, env_file, - include_stack: IncludeStack { stack: vec![include] }, + include_stack: IncludeStack { + stack: vec![include], + }, include_locations: Default::default(), multiple_locations: Default::default(), history: Default::default(), @@ -489,7 +512,8 @@ impl<'ctx> Preprocessor<'ctx> { line: !0, column: i, }; - self.history.insert(range(start, end), (name.clone(), define)); + self.history + .insert(range(start, end), (name.clone(), define)); } } DefineHistory { @@ -515,7 +539,11 @@ impl<'ctx> Preprocessor<'ctx> { */ /// Push a DM file to the top of this preprocessor's stack. - pub fn push_file(&mut self, path: PathBuf, read: R) -> Result { + pub fn push_file( + &mut self, + path: PathBuf, + read: R, + ) -> Result { let idx = self.context.register_file(&path); self.include_stack.stack.push(Include::File { lexer: Lexer::from_read(self.context, idx, read)?, @@ -538,19 +566,24 @@ impl<'ctx> Preprocessor<'ctx> { // ------------------------------------------------------------------------ // Macro definition handling - fn annotate_macro(&mut self, ident: &str, definition_location: Location, docs: Option>) { + fn annotate_macro( + &mut self, + ident: &str, + definition_location: Location, + docs: Option>, + ) { if self.include_stack.in_expansion() { return; } if let Some(annotations) = self.annotations.as_mut() { annotations.insert( - self.last_input_loc .. self.last_input_loc.add_columns(ident.len() as u16), + self.last_input_loc..self.last_input_loc.add_columns(ident.len() as u16), Annotation::MacroUse { name: ident.to_owned(), definition_location, docs, - } + }, ); } } @@ -572,7 +605,8 @@ impl<'ctx> Preprocessor<'ctx> { } fn move_to_history(&mut self, name: String, previous: (Location, Define)) { - self.history.insert(range(previous.0, self.last_input_loc), (name, previous.1)); + self.history + .insert(range(previous.0, self.last_input_loc), (name, previous.1)); } // ------------------------------------------------------------------------ @@ -584,7 +618,8 @@ impl<'ctx> Preprocessor<'ctx> { fn pop_ifdef(&mut self) -> Option { self.ifdef_stack.pop().inspect(|ifdef| { - self.ifdef_history.insert(range(ifdef.location, self.last_input_loc), ifdef.active); + self.ifdef_history + .insert(range(ifdef.location, self.last_input_loc), ifdef.active); }) } @@ -610,12 +645,16 @@ impl<'ctx> Preprocessor<'ctx> { return Ok(false); } - let expr = crate::parser::parse_expression( - self.context, - start, - self.output.drain(..), - )?; - Ok(crate::constants::preprocessor_evaluate(start, expr, &self.defines, Some(self.context))?.to_bool()) + let expr = crate::parser::parse_expression(self.context, start, self.output.drain(..))?; + Ok( + crate::constants::preprocessor_evaluate( + start, + expr, + &self.defines, + Some(self.context), + )? + .to_bool(), + ) } fn evaluate(&mut self) -> bool { @@ -625,7 +664,7 @@ impl<'ctx> Preprocessor<'ctx> { Err(err) => { self.context.register_error(err); false - } + }, } } @@ -648,22 +687,30 @@ impl<'ctx> Preprocessor<'ctx> { fn prepare_include_file(&mut self, path: PathBuf) -> Result, DMError> { // Attempt to open the file. - let read = io::BufReader::new(File::open(&path).map_err(|e| - DMError::new(self.last_input_loc, format!("failed to open file: #include {path:?}")) - .with_cause(e))?); + let read = io::BufReader::new(File::open(&path).map_err(|e| { + DMError::new( + self.last_input_loc, + format!("failed to open file: #include {path:?}"), + ) + .with_cause(e) + })?); // Get the path relative to the environment root, for easy lookup later. - let register = path.strip_prefix(self.env_file.parent().unwrap()).unwrap_or(&path); + let register = path + .strip_prefix(self.env_file.parent().unwrap()) + .unwrap_or(&path); // Make sure the file hasn't already been included. // All DM source is effectively `#pragma once`. let file_id = self.context.register_file(register); if let Some(&loc) = self.include_locations.get(&file_id) { if !self.multiple_locations.contains_key(&file_id) { - Err(DMError::new(self.last_input_loc, format!("duplicate #include {path:?}")) - .set_severity(Severity::Warning) - .with_note(loc, "previously included here") - .with_errortype("duplicate_include")) + Err( + DMError::new(self.last_input_loc, format!("duplicate #include {path:?}")) + .set_severity(Severity::Warning) + .with_note(loc, "previously included here") + .with_errortype("duplicate_include"), + ) } else { Ok(Include::File { path, @@ -682,7 +729,8 @@ impl<'ctx> Preprocessor<'ctx> { } fn push_output(&mut self, token: Token) { - self.output.push_back(LocatedToken::new(self.last_input_loc, token)); + self.output + .push_back(LocatedToken::new(self.last_input_loc, token)); } fn inner_next(&mut self) -> Option { @@ -698,7 +746,7 @@ impl<'ctx> Preprocessor<'ctx> { Some(x) => { _last_expected_loc = x.location; x.token - } + }, None => return Err(self.error("unexpected EOF")), } }; @@ -725,41 +773,47 @@ impl<'ctx> Preprocessor<'ctx> { match &ident[..] { // ifdefs "endif" => { - self.pop_ifdef().ok_or_else(|| - DMError::new(self.last_input_loc, "unmatched #endif"))?; - } + self.pop_ifdef() + .ok_or_else(|| DMError::new(self.last_input_loc, "unmatched #endif"))?; + }, "else" => { - let last = self.pop_ifdef().ok_or_else(|| - DMError::new(self.last_input_loc, "unmatched #else"))?; + let last = self + .pop_ifdef() + .ok_or_else(|| DMError::new(self.last_input_loc, "unmatched #else"))?; self.ifdef_stack.push(last.else_(self.last_input_loc)); - } + }, "ifdef" => { expect_token!((define_name) = Token::Ident(define_name, _)); expect_token!(() = Token::Punct(Punctuation::Newline)); let enabled = self.is_defined(&define_name); - self.ifdef_stack.push(Ifdef::new(self.last_input_loc, enabled)); - } + self.ifdef_stack + .push(Ifdef::new(self.last_input_loc, enabled)); + }, "ifndef" => { expect_token!((define_name) = Token::Ident(define_name, _)); expect_token!(() = Token::Punct(Punctuation::Newline)); let enabled = !self.is_defined(&define_name); - self.ifdef_stack.push(Ifdef::new(self.last_input_loc, enabled)); - } + self.ifdef_stack + .push(Ifdef::new(self.last_input_loc, enabled)); + }, "if" => { let enabled = self.evaluate(); - self.ifdef_stack.push(Ifdef::new(self.last_input_loc, enabled)); - } + self.ifdef_stack + .push(Ifdef::new(self.last_input_loc, enabled)); + }, "elif" => { - let last = self.pop_ifdef().ok_or_else(|| - DMError::new(self.last_input_loc, "unmatched #elif"))?; + let last = self + .pop_ifdef() + .ok_or_else(|| DMError::new(self.last_input_loc, "unmatched #elif"))?; let enabled = self.evaluate(); - self.ifdef_stack.push(last.else_if(self.last_input_loc, enabled)); - } + self.ifdef_stack + .push(last.else_if(self.last_input_loc, enabled)); + }, // -------------------------------------------------------- // anything other than ifdefs may be ifdef'd out // -------------------------------------------------------- // include searches relevant paths for files - "include" if disabled => {} + "include" if disabled => {}, "include" => { expect_token!((path_str) = Token::String(path_str)); let include_loc = _last_expected_loc; @@ -768,9 +822,13 @@ impl<'ctx> Preprocessor<'ctx> { for candidate in [ // 1. relative to file in which `#include` appears. - self.include_stack.top_file_path().parent().unwrap().join(&path), + self.include_stack + .top_file_path() + .parent() + .unwrap() + .join(&path), // 2. relative to root `.dme` file. - self.env_file.parent().unwrap().join(&path) + self.env_file.parent().unwrap().join(&path), ] { if !candidate.exists() { continue; @@ -797,17 +855,21 @@ impl<'ctx> Preprocessor<'ctx> { format!("unknown extension {ext:?}"), )); return Ok(()); - } + }, None => { - self.context.register_error(DMError::new(self.last_input_loc, "filename has no extension")); + self.context.register_error(DMError::new( + self.last_input_loc, + "filename has no extension", + )); return Ok(()); - } + }, }; if let Some(annotations) = self.annotations.as_mut() { annotations.insert( - include_loc .. include_loc.add_columns(2 + path_str.len() as u16), - Annotation::Include(candidate.clone())); + include_loc..include_loc.add_columns(2 + path_str.len() as u16), + Annotation::Include(candidate.clone()), + ); } match file_type { @@ -829,19 +891,22 @@ impl<'ctx> Preprocessor<'ctx> { return Ok(()); } - self.context.register_error(DMError::new(self.last_input_loc, format!("failed to find #include {path:?}"))); + self.context.register_error(DMError::new( + self.last_input_loc, + format!("failed to find #include {path:?}"), + )); return Ok(()); - } + }, // both constant and function defines "define" if disabled => { // Skip to the end of the line, or else we'll catch // stringify operators `#X` as unknown directives. loop { if let Token::Punct(Punctuation::Newline) = next!() { - break + break; } } - } + }, "define" => { // accumulate just-seen Following doc comments let mut docs = DocCollection::default(); @@ -851,8 +916,10 @@ impl<'ctx> Preprocessor<'ctx> { let define_name_loc = _last_expected_loc; if let Some(annotations) = self.annotations.as_mut() { annotations.insert( - define_name_loc .. define_name_loc.add_columns(define_name.len() as u16), - Annotation::MacroDefinition(define_name.to_owned())); + define_name_loc + ..define_name_loc.add_columns(define_name.len() as u16), + Annotation::MacroDefinition(define_name.to_owned()), + ); } let mut params = Vec::new(); let mut subst = Vec::new(); @@ -867,13 +934,17 @@ impl<'ctx> Preprocessor<'ctx> { match next!() { Token::Ident(name, _) => params.push(name), Token::Punct(Punctuation::Ellipsis) => { - params.push("__VA_ARGS__".to_owned()); // default + params.push("__VA_ARGS__".to_owned()); // default variadic = true; - } - _ => return Err(self.error("malformed macro parameters, expected name")), + }, + _ => { + return Err(self.error( + "malformed macro parameters, expected name", + )) + }, } match next!() { - Token::Punct(Punctuation::Comma) => {} + Token::Punct(Punctuation::Comma) => {}, Token::Punct(Punctuation::RParen) => break, Token::Punct(Punctuation::Ellipsis) => { variadic = true; @@ -881,27 +952,35 @@ impl<'ctx> Preprocessor<'ctx> { Token::Punct(Punctuation::RParen) => break, _ => return Err(self.error("only the last parameter of a macro may be variadic")) } - } - _ => return Err(self.error("malformed macro parameters, expected comma")), + }, + _ => { + return Err(self.error( + "malformed macro parameters, expected comma", + )) + }, } } - } + }, Token::Punct(Punctuation::Newline) => break 'outer, Token::DocComment(doc) => { if doc.target != DocTarget::EnclosingItem { let message = match doc.kind { - CommentKind::Block => "after a #define, should be `/*!` instead of `/**`", - CommentKind::Line => "after a #define, should be `//!` instead of `///`", + CommentKind::Block => { + "after a #define, should be `/*!` instead of `/**`" + }, + CommentKind::Line => { + "after a #define, should be `//!` instead of `///`" + }, }; self.error(message) .set_severity(Severity::Hint) .register(self.context); } docs.push(doc); - } + }, other => { subst.push(other); - } + }, } loop { match next!() { @@ -917,32 +996,49 @@ impl<'ctx> Preprocessor<'ctx> { .register(self.context); } docs.push(doc); - } + }, other => subst.push(other), } } } let define = if params.is_empty() { - Define::Constant { subst, docs: Rc::new(docs) } + Define::Constant { + subst, + docs: Rc::new(docs), + } } else { - Define::Function { params, subst, variadic, docs: Rc::new(docs) } + Define::Function { + params, + subst, + variadic, + docs: Rc::new(docs), + } }; // DEBUG can only be defined in the root .dme file if define_name != "DEBUG" || self.in_environment() { - if let Some(previous_loc) = self.defines.insert(define_name.clone(), (define_name_loc, define)) { + if let Some(previous_loc) = self + .defines + .insert(define_name.clone(), (define_name_loc, define)) + { // DM doesn't issue a warning for this, but it's usually a mistake, so let's. // FILE_DIR is handled specially and sometimes makes sense to define multiple times. if define_name != "FILE_DIR" { - DMError::new(define_name_loc, format!("macro redefined: {define_name}")) - .set_severity(Severity::Warning) - .with_note(previous_loc, format!("previous definition of {define_name}")) - .with_errortype("macro_redefined") - .register(self.context); + DMError::new( + define_name_loc, + format!("macro redefined: {define_name}"), + ) + .set_severity(Severity::Warning) + .with_note( + previous_loc, + format!("previous definition of {define_name}"), + ) + .with_errortype("macro_redefined") + .register(self.context); } } } - } - "undef" if disabled => {} + }, + "undef" if disabled => {}, "undef" => { expect_token!((define_name) = Token::Ident(define_name, _)); let define_name_loc = _last_expected_loc; @@ -950,32 +1046,42 @@ impl<'ctx> Preprocessor<'ctx> { if let Some(previous) = self.defines.remove(&define_name) { self.move_to_history(define_name, previous); } else { - DMError::new(define_name_loc, format!("macro undefined while not defined: {define_name}")) - .with_errortype("macro_undefined_no_definition") - .set_severity(Severity::Warning) - .register(self.context); - } - } - "warn" if disabled => {} - "warn" => { - expect_token!((text) = Token::String(text)); - DMError::new(self.last_input_loc, format!("#{} {}", ident, text.trim_end_matches(['\r', '\n']))) + DMError::new( + define_name_loc, + format!("macro undefined while not defined: {define_name}"), + ) + .with_errortype("macro_undefined_no_definition") .set_severity(Severity::Warning) .register(self.context); - } - "error" if disabled => {} + } + }, + "warn" if disabled => {}, + "warn" => { + expect_token!((text) = Token::String(text)); + DMError::new( + self.last_input_loc, + format!("#{} {}", ident, text.trim_end_matches(['\r', '\n'])), + ) + .set_severity(Severity::Warning) + .register(self.context); + }, + "error" if disabled => {}, "error" => { expect_token!((text) = Token::String(text)); - self.context.register_error(DMError::new(self.last_input_loc, format!("#{} {}", ident, text.trim_end_matches(['\r', '\n'])))); - } - "pragma" if disabled => {} + self.context.register_error(DMError::new( + self.last_input_loc, + format!("#{} {}", ident, text.trim_end_matches(['\r', '\n'])), + )); + }, + "pragma" if disabled => {}, "pragma" => { expect_token!((text) = Token::Ident(text, _)); let pragma_use_loc = _last_expected_loc; if text.as_str() == "multiple" { - self.multiple_locations.insert(pragma_use_loc.file, pragma_use_loc); + self.multiple_locations + .insert(pragma_use_loc.file, pragma_use_loc); } - } + }, // none of this other stuff should even exist other => { let mut meant = ""; @@ -984,14 +1090,25 @@ impl<'ctx> Preprocessor<'ctx> { meant = each; } } - return Err(DMError::new(self.last_input_loc, format!("unknown directive: #{}{}{}", ident, - if !meant.is_empty() { ", did you mean #" } else { "" }, meant))); - } + return Err(DMError::new( + self.last_input_loc, + format!( + "unknown directive: #{}{}{}", + ident, + if !meant.is_empty() { + ", did you mean #" + } else { + "" + }, + meant + ), + )); + }, } // yield a newline self.push_output(Token::Punct(Punctuation::Newline)); return Ok(()); - } + }, // anything other than directives may be ifdef'd out _ if disabled => return Ok(()), // identifiers may be macros @@ -1000,7 +1117,8 @@ impl<'ctx> Preprocessor<'ctx> { // lint for BYOND bug if self.in_interp_string > 0 { - self.danger_idents.insert(ident.clone(), self.last_input_loc); + self.danger_idents + .insert(ident.clone(), self.last_input_loc); } // substitute special macros @@ -1021,9 +1139,17 @@ impl<'ctx> Preprocessor<'ctx> { } // special case for inside a defined() call - if let Some(LocatedToken { token: Token::Punct(Punctuation::LParen), .. }) = self.output.back() { + if let Some(LocatedToken { + token: Token::Punct(Punctuation::LParen), + .. + }) = self.output.back() + { if let Some(idx) = self.output.len().checked_sub(2) { - if let Some(LocatedToken { token: Token::Ident(identname, _), .. }) = self.output.get(idx) { + if let Some(LocatedToken { + token: Token::Ident(identname, _), + .. + }) = self.output.get(idx) + { if identname.as_str() == "defined" { self.push_output(Token::Ident(ident.to_owned(), whitespace)); return Ok(()); @@ -1033,7 +1159,7 @@ impl<'ctx> Preprocessor<'ctx> { } // if it's a define, perform the substitution - let mut expansion = self.defines.get(ident).cloned(); // TODO: don't clone? + let mut expansion = self.defines.get(ident).cloned(); // TODO: don't clone? if expansion.is_some() && self.include_stack.stack.len() > MAX_RECURSION_DEPTH { self.error(format!("expanding {ident:?} would exceed max recursion depth of {MAX_RECURSION_DEPTH} levels")).register(self.context); expansion = None; @@ -1048,21 +1174,29 @@ impl<'ctx> Preprocessor<'ctx> { location: self.last_input_loc, }); return Ok(()); - } - Some((location, Define::Function { ref params, ref subst, variadic, docs })) => { + }, + Some(( + location, + Define::Function { + ref params, + ref subst, + variadic, + docs, + }, + )) => { // if it's not followed by an LParen, it isn't really a function call match next!() { - Token::Punct(Punctuation::LParen) => {} + Token::Punct(Punctuation::LParen) => {}, other => { self.push_output(Token::Ident(ident.to_owned(), false)); match other { Token::InterpStringBegin(_) => self.in_interp_string += 1, Token::InterpStringEnd(_) => self.in_interp_string -= 1, - _ => {} + _ => {}, } self.push_output(other); return Ok(()); - } + }, } self.annotate_macro(ident, location, Some(docs)); @@ -1077,7 +1211,7 @@ impl<'ctx> Preprocessor<'ctx> { Token::Punct(Punctuation::LParen) => { parens += 1; this_arg.push(token); - } + }, Token::Punct(Punctuation::RParen) => { if parens == 0 { args.push(this_arg); @@ -1085,11 +1219,11 @@ impl<'ctx> Preprocessor<'ctx> { } parens -= 1; this_arg.push(token); - } + }, Token::Punct(Punctuation::Comma) if parens == 0 => { args.push(this_arg); this_arg = Vec::new(); - } + }, _ => this_arg.push(token), } } @@ -1097,7 +1231,9 @@ impl<'ctx> Preprocessor<'ctx> { // check for correct number of arguments if variadic { if args.len() > params.len() { - let new_arg = args.split_off(params.len() - 1).join(&Token::Punct(Punctuation::Comma)); + let new_arg = args + .split_off(params.len() - 1) + .join(&Token::Punct(Punctuation::Comma)); args.push(new_arg); } else if args.len() + 1 == params.len() { args.push(Vec::new()); @@ -1113,59 +1249,69 @@ impl<'ctx> Preprocessor<'ctx> { while let Some(token) = input.next() { match token { // just an ident = expand it - Token::Ident(ident, ws) => match params.iter().position(|x| *x == ident) { - Some(i) => expansion.extend(args[i].iter().cloned()), - None => expansion.push_back(Token::Ident(ident, ws)), + Token::Ident(ident, ws) => { + match params.iter().position(|x| *x == ident) { + Some(i) => expansion.extend(args[i].iter().cloned()), + None => expansion.push_back(Token::Ident(ident, ws)), + } }, // token paste = concat two idents together, if at all possible Token::Punct(Punctuation::TokenPaste) => { match (expansion.pop_back(), input.next()) { - (Some(Token::Ident(first, ws1)), Some(Token::Ident(param_name, ws))) => { - match params.iter().position(|x| *x == param_name) { - Some(i) => { - let mut arg = args[i].iter().cloned(); - match arg.next() { - Some(Token::Ident(param_ident, ws)) => { - expansion.push_back(Token::Ident( - format!("{first}{param_ident}"), - ws, - )); - } - Some(Token::Int(param_int)) => { - expansion.push_back(Token::Ident( - format!("{first}{param_int}"), - ws, - )) - } - Some(other) => { - expansion.push_back(Token::Ident(first, ws1)); - expansion.push_back(other); - } - None => {} - } - expansion.extend(arg); + ( + Some(Token::Ident(first, ws1)), + Some(Token::Ident(param_name, ws)), + ) => match params.iter().position(|x| *x == param_name) { + Some(i) => { + let mut arg = args[i].iter().cloned(); + match arg.next() { + Some(Token::Ident(param_ident, ws)) => { + expansion.push_back(Token::Ident( + format!("{first}{param_ident}"), + ws, + )); + }, + Some(Token::Int(param_int)) => expansion + .push_back(Token::Ident( + format!("{first}{param_int}"), + ws, + )), + Some(other) => { + expansion + .push_back(Token::Ident(first, ws1)); + expansion.push_back(other); + }, + None => {}, } - None => expansion.push_back(Token::Ident(format!("{first}{param_name}"), ws)), - } - } + expansion.extend(arg); + }, + None => expansion.push_back(Token::Ident( + format!("{first}{param_name}"), + ws, + )), + }, (non_ident_first, Some(Token::Ident(second, ws))) => { expansion.extend(non_ident_first); match params.iter().position(|x| *x == second) { - Some(i) => expansion.extend(args[i].iter().cloned()), - None => expansion.push_back(Token::Ident(second, ws)), + Some(i) => { + expansion.extend(args[i].iter().cloned()) + }, + None => { + expansion.push_back(Token::Ident(second, ws)) + }, } - } + }, (non_ident_first, non_ident_second) => { expansion.extend(non_ident_first); expansion.extend(non_ident_second); - } + }, } // read the next ident and concat it into the previous ident }, // hash = must be followed by a param name, stringify the whole argument - Token::Punct(Punctuation::Hash) => { - match input.next() { - Some(Token::Ident(argname, _)) => match params.iter().position(|x| *x == argname) { + Token::Punct(Punctuation::Hash) => match input.next() { + Some(Token::Ident(argname, _)) => { + match params.iter().position(|x| *x == argname) { Some(i) => { let mut string = String::new(); for each in &args[i] { @@ -1174,18 +1320,36 @@ impl<'ctx> Preprocessor<'ctx> { string.push(' '); } let _e = write!(string, "{each}"); - #[cfg(debug_assertions)] { + #[cfg(debug_assertions)] + { _e.unwrap(); } } expansion.push_back(Token::String(string)); - } - None => return Err(DMError::new(self.last_input_loc, format!("can't stringify non-argument ident {argname:?}"))), + }, + None => { + return Err(DMError::new( + self.last_input_loc, + format!( + "can't stringify non-argument ident {argname:?}" + ), + )) + }, } - Some(tok) => return Err(DMError::new(self.last_input_loc, format!("can't stringify non-ident '{tok}'"))), - None => return Err(DMError::new(self.last_input_loc, "can't stringify EOF")), - } - } + }, + Some(tok) => { + return Err(DMError::new( + self.last_input_loc, + format!("can't stringify non-ident '{tok}'"), + )) + }, + None => { + return Err(DMError::new( + self.last_input_loc, + "can't stringify EOF", + )) + }, + }, _ => expansion.push_back(token), } } @@ -1195,10 +1359,10 @@ impl<'ctx> Preprocessor<'ctx> { location: self.last_input_loc, }); return Ok(()); - } - None => {} + }, + None => {}, } - } + }, Token::InterpStringBegin(_) => self.in_interp_string += 1, Token::InterpStringEnd(_) => self.in_interp_string -= 1, // documentation is accumulated, and flushed if no #define follows @@ -1207,7 +1371,7 @@ impl<'ctx> Preprocessor<'ctx> { return Ok(()); }, // everything else is itself - _ => {} + _ => {}, } if !read.is_whitespace() { self.flush_docs(); @@ -1229,8 +1393,8 @@ impl<'ctx> Iterator for Preprocessor<'ctx> { if let Some(tok) = self.inner_next() { // linting for https://www.byond.com/forum/?post=2072419 if !tok.token.is_whitespace() && tok.token != Token::Punct(Punctuation::Hash) { - if tok.location.file != self.last_printable_input_loc.file || - tok.location.line > self.last_printable_input_loc.line + if tok.location.file != self.last_printable_input_loc.file + || tok.location.line > self.last_printable_input_loc.line { self.danger_idents.clear(); } @@ -1244,7 +1408,8 @@ impl<'ctx> Iterator for Preprocessor<'ctx> { } } else { while let Some(ifdef) = self.pop_ifdef() { - self.context.register_error(DMError::new(ifdef.location, "unterminated #if/#ifdef")); + self.context + .register_error(DMError::new(ifdef.location, "unterminated #if/#ifdef")); } return None; } diff --git a/crates/dreammaker/tests/annotation_tests.rs b/crates/dreammaker/tests/annotation_tests.rs index 7d0685a7..e98c95bc 100644 --- a/crates/dreammaker/tests/annotation_tests.rs +++ b/crates/dreammaker/tests/annotation_tests.rs @@ -19,7 +19,8 @@ fn annotation_basic() { proc/Init() world.log << new/obj() -"#.trim(); +"# + .trim(); let context = Default::default(); let lexer = Lexer::new(&context, Default::default(), code.as_bytes()); diff --git a/crates/dreammaker/tests/ast_tests.rs b/crates/dreammaker/tests/ast_tests.rs index bc4482be..b9ac8111 100644 --- a/crates/dreammaker/tests/ast_tests.rs +++ b/crates/dreammaker/tests/ast_tests.rs @@ -20,27 +20,33 @@ fn with_code(code: &'static str, f: F) { f(context, _tree) } - #[test] fn check_semicolon_in_proc_parameters() { - with_code(" + with_code( + " #define DEF1 0x01; #define DEF2 \"asdf\" as text; /proc/darn(foo = DEF1, bar = DEF2, anotherarg = 1) -", |context, _| { - let errors = context.errors(); - assert_eq!(errors.len(), 2); +", + |context, _| { + let errors = context.errors(); + assert_eq!(errors.len(), 2); - for error in errors.iter() { - assert_eq!(error.errortype().expect("No errortype set!"), "semicolon_in_proc_parameter"); - } - }); + for error in errors.iter() { + assert_eq!( + error.errortype().expect("No errortype set!"), + "semicolon_in_proc_parameter" + ); + } + }, + ); } #[test] fn process_scope() { - with_code(" + with_code( + " /datum/test var/hell = type::base var/base = 10 @@ -66,248 +72,306 @@ var/global/bill = 1 x = ::bill /proc/extra() -", |context, tree| { - let errors = context.errors(); +", + |context, tree| { + let errors = context.errors(); - // Check for errors - let mut sum_errors: Vec = vec![]; - for error in errors.iter() { - sum_errors.push(format!("{error}")); - } - if !sum_errors.is_empty() { - panic!("\n{}", sum_errors.join("\n").as_str()); - } - // test type::var in typedef - let parent_type = tree.find("/datum/test").unwrap(); - let type_read = parent_type.get_value("heck").unwrap(); - let Some(constant) = type_read.constant.as_ref() else { - panic!("Failed to constant evaluate :: operator") - }; - if let Constant::Float(value) = constant { - assert_eq!(*value, 10f32) - } else { - panic!("{} was expected to be a float, but it wasn't!", type_read.constant.as_ref().unwrap()) - } - // test type::proc() in typedef - let parent_type = tree.find("/datum/test").unwrap(); - let type_read = parent_type.get_value("proc_holder").unwrap(); - let Some(constant) = type_read.constant.as_ref() else { - panic!("Failed to constant evaluate :: proc operator") - }; - if let Constant::Prefab(value) = constant { - let pop_list = FormatTreePath(&value.path).to_string(); - assert_eq!(pop_list, "/datum/test/proc/reference") - } else { - panic!("{} was expected to be a path, but it wasn't!", type_read.constant.as_ref().unwrap()) - } - // parent_type::var in a subtype - let child_type = tree.find("/datum/test/sub").unwrap(); - let type_read = child_type.get_value("base").unwrap(); - let Some(constant) = type_read.constant.as_ref() else { - panic!("Failed to constant evaluate :: operator") - }; - if let Constant::Float(value) = constant { - assert_eq!(*value, 10f32 + 10f32) - } else { - panic!("{} was expected to be a float, but it wasn't!", type_read.constant.as_ref().unwrap()) - } - // /datum/explicit::var in a type - let child_type = tree.find("/datum/test/sub").unwrap(); - let type_read = child_type.get_value("heck").unwrap(); - let Some(constant) = type_read.constant.as_ref() else { - panic!("Failed to constant evaluate :: operator") - }; - if let Constant::Float(value) = constant { - assert_eq!(*value, 10f32 + 2f32) - } else { - panic!("{} was expected to be a float, but it wasn't!", type_read.constant.as_ref().unwrap()) - } - let global_procs = tree.root(); - let work_proc = global_procs.get_proc("work").unwrap(); - let work_code = work_proc.code.as_ref().unwrap().iter().map(|statement| { - &statement.elem - }).collect::>(); - // /datum/explicit::var - let Statement::Var(x_init) = work_code.first().unwrap() else { - panic!("First statement was not an expression") - }; - let Expression::Base { term: _, follow } = x_init.value.as_ref().unwrap() else { - panic!("/datum/test::base was NOT evaluated as a base expression") - }; - match &follow.first().unwrap().elem { - Follow::StaticField(field) => { - if field != "base" { - panic!("/datum/test::base did not eval base as the var to read") - } + // Check for errors + let mut sum_errors: Vec = vec![]; + for error in errors.iter() { + sum_errors.push(format!("{error}")); } - _ => panic!("/datum/test::base failed to eval :: as a static field") - } - // implicit_type::variable - let Statement::Expr(larrys_read) = work_code.get(2).unwrap() else { - panic!("Third statement was not an expression") - }; - - let Expression::AssignOp { op: _, lhs: _, rhs } = larrys_read else { - panic!("x = larry::stat was NOT evaluated as an assignment expression") - }; - let Expression::Base { term: _, ref follow } = **rhs else { - panic!("larry::stat was NOT evaluated as a base expression") - }; - match &follow.first().unwrap().elem { - Follow::StaticField(field) => { - if field != "stat" { - panic!("larry::stat did not eval stat as the var to read") - } + if !sum_errors.is_empty() { + panic!("\n{}", sum_errors.join("\n").as_str()); } - _ => panic!("larry::stat failed to eval :: as a static field") - } - - // /datum/explicit::proc() - let Statement::Expr(proc_ref) = work_code.get(3).unwrap() else { - panic!("Fourth statement was not an expression") - }; - - let Expression::AssignOp { op: _, lhs: _, rhs } = proc_ref else { - panic!("x = /datum/test::reference() was NOT evaluated as an assignment expression") - }; - let Expression::Base { term: _, ref follow } = **rhs else { - panic!("/datum/test::reference() was NOT evaluated as a base expression") - }; - match &follow.first().unwrap().elem { - Follow::ProcReference(proc_name) => { - if proc_name != "reference" { - panic!("/datum/test::reference() did not eval reference() as the ref to read") - } + // test type::var in typedef + let parent_type = tree.find("/datum/test").unwrap(); + let type_read = parent_type.get_value("heck").unwrap(); + let Some(constant) = type_read.constant.as_ref() else { + panic!("Failed to constant evaluate :: operator") + }; + if let Constant::Float(value) = constant { + assert_eq!(*value, 10f32) + } else { + panic!( + "{} was expected to be a float, but it wasn't!", + type_read.constant.as_ref().unwrap() + ) } - _ => panic!("/datum/test::reference() failed to eval :: as a proc reference") - } - // /datum/explicit::static_var = value - let Statement::Expr(static_set) = work_code.get(4).unwrap() else { - panic!("Fifth statement was not an expression") - }; - - let Expression::AssignOp { op: _, lhs, rhs: _ } = static_set else { - panic!("/datum/test::stat = 2 was NOT evaluated as an assignment expression") - }; - let Expression::Base { term: _, ref follow } = **lhs else { - panic!("/datum/test::stat was NOT evaluated as a base expression") - }; - match &follow.first().unwrap().elem { - Follow::StaticField(field) => { - if field != "stat" { - panic!("/datum/test::stat did not eval stat as the var to set") - } + // test type::proc() in typedef + let parent_type = tree.find("/datum/test").unwrap(); + let type_read = parent_type.get_value("proc_holder").unwrap(); + let Some(constant) = type_read.constant.as_ref() else { + panic!("Failed to constant evaluate :: proc operator") + }; + if let Constant::Prefab(value) = constant { + let pop_list = FormatTreePath(&value.path).to_string(); + assert_eq!(pop_list, "/datum/test/proc/reference") + } else { + panic!( + "{} was expected to be a path, but it wasn't!", + type_read.constant.as_ref().unwrap() + ) } - _ => panic!("/datum/test::stat failed to eval :: as a static field") - } - // ::global_proc() - let Statement::Expr(static_set) = work_code.get(5).unwrap() else { - panic!("Sixth statement was not an expression") - }; - - let Expression::Base { term, follow: _ } = static_set else { - panic!("::extra() was NOT evaluated as a base expression") - }; - match &term.elem { - Term::GlobalCall(function, _) => { - if function != "extra" { - panic!("::extra() did not eval extra as the proc to call") - } + // parent_type::var in a subtype + let child_type = tree.find("/datum/test/sub").unwrap(); + let type_read = child_type.get_value("base").unwrap(); + let Some(constant) = type_read.constant.as_ref() else { + panic!("Failed to constant evaluate :: operator") + }; + if let Constant::Float(value) = constant { + assert_eq!(*value, 10f32 + 10f32) + } else { + panic!( + "{} was expected to be a float, but it wasn't!", + type_read.constant.as_ref().unwrap() + ) } - _ => panic!("::extra() failed to eval :: as a global call") - } - // ::global_var - let Statement::Expr(proc_ref) = work_code.get(6).unwrap() else { - panic!("Seventh statement was not an expression") - }; - - let Expression::AssignOp { op: _, lhs: _, rhs } = proc_ref else { - panic!("x = ::bill was NOT evaluated as an assignment expression") - }; - let Expression::Base { ref term, follow: _ } = **rhs else { - panic!("::bill was NOT evaluated as a base expression") - }; - match &term.elem { - Term::GlobalIdent(field) => { - if field != "bill" { - panic!("::bill did not eval bill as the global var to read") - } + // /datum/explicit::var in a type + let child_type = tree.find("/datum/test/sub").unwrap(); + let type_read = child_type.get_value("heck").unwrap(); + let Some(constant) = type_read.constant.as_ref() else { + panic!("Failed to constant evaluate :: operator") + }; + if let Constant::Float(value) = constant { + assert_eq!(*value, 10f32 + 2f32) + } else { + panic!( + "{} was expected to be a float, but it wasn't!", + type_read.constant.as_ref().unwrap() + ) } - _ => panic!("::bill failed to eval :: as a global var read") - } - }) + let global_procs = tree.root(); + let work_proc = global_procs.get_proc("work").unwrap(); + let work_code = work_proc + .code + .as_ref() + .unwrap() + .iter() + .map(|statement| &statement.elem) + .collect::>(); + // /datum/explicit::var + let Statement::Var(x_init) = work_code.first().unwrap() else { + panic!("First statement was not an expression") + }; + let Expression::Base { term: _, follow } = x_init.value.as_ref().unwrap() else { + panic!("/datum/test::base was NOT evaluated as a base expression") + }; + match &follow.first().unwrap().elem { + Follow::StaticField(field) => { + if field != "base" { + panic!("/datum/test::base did not eval base as the var to read") + } + }, + _ => panic!("/datum/test::base failed to eval :: as a static field"), + } + // implicit_type::variable + let Statement::Expr(larrys_read) = work_code.get(2).unwrap() else { + panic!("Third statement was not an expression") + }; + + let Expression::AssignOp { op: _, lhs: _, rhs } = larrys_read else { + panic!("x = larry::stat was NOT evaluated as an assignment expression") + }; + let Expression::Base { + term: _, + ref follow, + } = **rhs + else { + panic!("larry::stat was NOT evaluated as a base expression") + }; + match &follow.first().unwrap().elem { + Follow::StaticField(field) => { + if field != "stat" { + panic!("larry::stat did not eval stat as the var to read") + } + }, + _ => panic!("larry::stat failed to eval :: as a static field"), + } + + // /datum/explicit::proc() + let Statement::Expr(proc_ref) = work_code.get(3).unwrap() else { + panic!("Fourth statement was not an expression") + }; + + let Expression::AssignOp { op: _, lhs: _, rhs } = proc_ref else { + panic!("x = /datum/test::reference() was NOT evaluated as an assignment expression") + }; + let Expression::Base { + term: _, + ref follow, + } = **rhs + else { + panic!("/datum/test::reference() was NOT evaluated as a base expression") + }; + match &follow.first().unwrap().elem { + Follow::ProcReference(proc_name) => { + if proc_name != "reference" { + panic!( + "/datum/test::reference() did not eval reference() as the ref to read" + ) + } + }, + _ => panic!("/datum/test::reference() failed to eval :: as a proc reference"), + } + // /datum/explicit::static_var = value + let Statement::Expr(static_set) = work_code.get(4).unwrap() else { + panic!("Fifth statement was not an expression") + }; + + let Expression::AssignOp { op: _, lhs, rhs: _ } = static_set else { + panic!("/datum/test::stat = 2 was NOT evaluated as an assignment expression") + }; + let Expression::Base { + term: _, + ref follow, + } = **lhs + else { + panic!("/datum/test::stat was NOT evaluated as a base expression") + }; + match &follow.first().unwrap().elem { + Follow::StaticField(field) => { + if field != "stat" { + panic!("/datum/test::stat did not eval stat as the var to set") + } + }, + _ => panic!("/datum/test::stat failed to eval :: as a static field"), + } + // ::global_proc() + let Statement::Expr(static_set) = work_code.get(5).unwrap() else { + panic!("Sixth statement was not an expression") + }; + + let Expression::Base { term, follow: _ } = static_set else { + panic!("::extra() was NOT evaluated as a base expression") + }; + match &term.elem { + Term::GlobalCall(function, _) => { + if function != "extra" { + panic!("::extra() did not eval extra as the proc to call") + } + }, + _ => panic!("::extra() failed to eval :: as a global call"), + } + // ::global_var + let Statement::Expr(proc_ref) = work_code.get(6).unwrap() else { + panic!("Seventh statement was not an expression") + }; + + let Expression::AssignOp { op: _, lhs: _, rhs } = proc_ref else { + panic!("x = ::bill was NOT evaluated as an assignment expression") + }; + let Expression::Base { + ref term, + follow: _, + } = **rhs + else { + panic!("::bill was NOT evaluated as a base expression") + }; + match &term.elem { + Term::GlobalIdent(field) => { + if field != "bill" { + panic!("::bill did not eval bill as the global var to read") + } + }, + _ => panic!("::bill failed to eval :: as a global var read"), + } + }, + ) } #[test] fn return_type_union() { // https://github.com/SpaceManiac/SpacemanDMM/issues/385 - with_code(" + with_code( + " /proc/returns_num_or_text() as num | text - ", |context, tree| { - context.assert_success(); + ", + |context, tree| { + context.assert_success(); - assert_eq!( - tree.root().get_proc("returns_num_or_text").unwrap().get_declaration().unwrap().return_type, - ProcReturnType::InputType(InputType::NUM | InputType::TEXT), - ); - }); + assert_eq!( + tree.root() + .get_proc("returns_num_or_text") + .unwrap() + .get_declaration() + .unwrap() + .return_type, + ProcReturnType::InputType(InputType::NUM | InputType::TEXT), + ); + }, + ); } #[test] fn return_type_list() { // https://github.com/SpaceManiac/SpacemanDMM/issues/399 - with_code(" + with_code( + " /proc/returns_list() as list - ", |context, tree| { - context.assert_success(); + ", + |context, tree| { + context.assert_success(); - assert_eq!( - tree.root().get_proc("returns_list").unwrap().get_declaration().unwrap().return_type, - ProcReturnType::InputType(InputType::LIST), - ); - }); + assert_eq!( + tree.root() + .get_proc("returns_list") + .unwrap() + .get_declaration() + .unwrap() + .return_type, + ProcReturnType::InputType(InputType::LIST), + ); + }, + ); } #[test] fn proc_operator_slash() { // https://github.com/SpaceManiac/SpacemanDMM/issues/399 - with_code(" + with_code( + " /datum/operator/proc/foo() /datum/operator/() /datum/operator/=() /datum/operator proc/bar() - ", |context, tree| { - context.assert_success(); + ", + |context, tree| { + context.assert_success(); - eprintln!("{:#?}", tree.expect("/datum").procs); + eprintln!("{:#?}", tree.expect("/datum").procs); - tree.expect("/datum/operator").get_proc("foo").unwrap(); - tree.expect("/datum").get_proc("operator/").unwrap(); - tree.expect("/datum").get_proc("operator/=").unwrap(); - tree.expect("/datum/operator").get_proc("bar").unwrap(); - }); + tree.expect("/datum/operator").get_proc("foo").unwrap(); + tree.expect("/datum").get_proc("operator/").unwrap(); + tree.expect("/datum").get_proc("operator/=").unwrap(); + tree.expect("/datum/operator").get_proc("bar").unwrap(); + }, + ); } #[test] fn for_key_value_with_as() { // https://github.com/SpaceManiac/SpacemanDMM/issues/421 - 'as' keyword in for-key-value loops - with_code(" + with_code( + " /proc/test() var/alist/foo = list() for (var/index as num, C in foo) world << index - ", |context, tree| { - context.assert_success(); + ", + |context, tree| { + context.assert_success(); - let proc = tree.root().get_proc("test").unwrap(); - let code = proc.get().code.as_ref().unwrap(); + let proc = tree.root().get_proc("test").unwrap(); + let code = proc.get().code.as_ref().unwrap(); - if let Statement::ForKeyValue(ref fkv) = code[1].elem { - assert!(fkv.key_input_type.is_some()); - assert_eq!(fkv.key_input_type.unwrap(), InputType::NUM); - } else { - panic!("Expected ForKeyValue statement, got {:?}", code[1].elem); - } - }); + if let Statement::ForKeyValue(ref fkv) = code[1].elem { + assert!(fkv.key_input_type.is_some()); + assert_eq!(fkv.key_input_type.unwrap(), InputType::NUM); + } else { + panic!("Expected ForKeyValue statement, got {:?}", code[1].elem); + } + }, + ); } diff --git a/crates/dreammaker/tests/constants_tests.rs b/crates/dreammaker/tests/constants_tests.rs index 13c43f72..152ea72f 100644 --- a/crates/dreammaker/tests/constants_tests.rs +++ b/crates/dreammaker/tests/constants_tests.rs @@ -17,10 +17,7 @@ fn floating_point_rgb() { #[test] fn rgb_base() { - assert_eq!( - eval("rgb(0, 255, 0)").unwrap(), - Constant::string("#00ff00"), - ); + assert_eq!(eval("rgb(0, 255, 0)").unwrap(), Constant::string("#00ff00"),); assert_eq!( eval("rgb(50, 50, 50)").unwrap(), Constant::string("#323232"), @@ -93,7 +90,6 @@ fn rgb_hsl() { ); } - #[test] fn rgb_hcy() { assert_eq!( diff --git a/crates/dreammaker/tests/format_tests.rs b/crates/dreammaker/tests/format_tests.rs index 0b69e0bb..a16511ac 100644 --- a/crates/dreammaker/tests/format_tests.rs +++ b/crates/dreammaker/tests/format_tests.rs @@ -40,12 +40,26 @@ fn floats() { fn lists() { use dm::constants::Constant::{self, *}; - assert_eq!(List(vec![ - (Constant::string("KNOCKDOWN"), Some(Float(0.))), - (Constant::string("THROW"), Some(Float(0.))), - ].into()).to_string(), r#"list("KNOCKDOWN" = 0, "THROW" = 0)"#); - assert_eq!(List(vec![ - (Constant::string("neutral"), None), - (Constant::string("Syndicate"), None), - ].into()).to_string(), r#"list("neutral","Syndicate")"#); + assert_eq!( + List( + vec![ + (Constant::string("KNOCKDOWN"), Some(Float(0.))), + (Constant::string("THROW"), Some(Float(0.))), + ] + .into() + ) + .to_string(), + r#"list("KNOCKDOWN" = 0, "THROW" = 0)"# + ); + assert_eq!( + List( + vec![ + (Constant::string("neutral"), None), + (Constant::string("Syndicate"), None), + ] + .into() + ) + .to_string(), + r#"list("neutral","Syndicate")"# + ); } diff --git a/crates/dreammaker/tests/lexer_tests.rs b/crates/dreammaker/tests/lexer_tests.rs index 7566ef7c..6e947205 100644 --- a/crates/dreammaker/tests/lexer_tests.rs +++ b/crates/dreammaker/tests/lexer_tests.rs @@ -33,10 +33,14 @@ fn number_literals() { assert_eq!(lex("0xABCDE"), vec![Int(703710), Punct(Newline)]); assert_eq!(lex("1e4"), vec![Float(10000.0), Punct(Newline)]); - let f = float("1.#INF"); assert!(f.is_infinite() && f > 0.); - let f = float("1.#IND"); assert!(f.is_nan()); - let f = float("1#INF"); assert!(f.is_infinite() && f > 0.); - let f = float("1#IND"); assert!(f.is_nan()); + let f = float("1.#INF"); + assert!(f.is_infinite() && f > 0.); + let f = float("1.#IND"); + assert!(f.is_nan()); + let f = float("1#INF"); + assert!(f.is_infinite() && f > 0.); + let f = float("1#IND"); + assert!(f.is_nan()); } #[test] @@ -59,10 +63,7 @@ fn empty_block_comment() { // This is legal. It should not do either of the following: // - Error with "still skipping comments at end of file" // - Yield a DocComment { text: "", .. } - assert_eq!( - lex(r#"/**/"#), - vec![Punct(Newline)] - ) + assert_eq!(lex(r#"/**/"#), vec![Punct(Newline)]) } #[test] @@ -79,7 +80,9 @@ fn raw_strings() { @{content{ "#); for each in stuff.iter() { - if each == &Punct(Newline) { continue } + if each == &Punct(Newline) { + continue; + } assert_eq!(each, &desired); } } diff --git a/crates/dreammaker/tests/location_tests.rs b/crates/dreammaker/tests/location_tests.rs index 08110080..d979369b 100644 --- a/crates/dreammaker/tests/location_tests.rs +++ b/crates/dreammaker/tests/location_tests.rs @@ -15,10 +15,12 @@ fn simple_location_test() { world.log << new/ obj() /var/foo = bar -"#.trim(); +"# + .trim(); let context = Default::default(); - let located_tokens: Vec<_> = Lexer::new(&context, Default::default(), code.as_bytes()).collect(); + let located_tokens: Vec<_> = + Lexer::new(&context, Default::default(), code.as_bytes()).collect(); context.assert_success(); assert_eq!(located_tokens[0].location.line, 1); @@ -26,7 +28,10 @@ fn simple_location_test() { println!("---- lexer ----"); for token in located_tokens.iter() { - println!("{}:{}: {:?}", token.location.line, token.location.column, token.token); + println!( + "{}:{}: {:?}", + token.location.line, token.location.column, token.token + ); } let reconstructed = reconstruct(&located_tokens, false); @@ -36,10 +41,14 @@ fn simple_location_test() { } println!("---- indent processor ----"); - let indented_tokens: Vec<_> = dm::indents::IndentProcessor::new(&context, located_tokens).collect(); + let indented_tokens: Vec<_> = + dm::indents::IndentProcessor::new(&context, located_tokens).collect(); context.assert_success(); for token in indented_tokens.iter() { - println!("{}:{}: {:?}", token.location.line, token.location.column, token.token); + println!( + "{}:{}: {:?}", + token.location.line, token.location.column, token.token + ); } let reconstructed = reconstruct(&indented_tokens, true); println!("{reconstructed}"); diff --git a/crates/dreammaker/tests/macro_tests.rs b/crates/dreammaker/tests/macro_tests.rs index 2d30ee45..08f34b63 100644 --- a/crates/dreammaker/tests/macro_tests.rs +++ b/crates/dreammaker/tests/macro_tests.rs @@ -9,7 +9,8 @@ fn process(source: &'static str) -> Vec { let pp = Preprocessor::from_buffer(&ctx, "macro_tests.rs".into(), source); // collect tokens, strip leading and trailing newlines - let mut tokens: Vec<_> = pp.map(|loctok| loctok.token) + let mut tokens: Vec<_> = pp + .map(|loctok| loctok.token) .skip_while(|tok| *tok == Punct(Newline)) .collect(); ctx.assert_success(); @@ -22,67 +23,86 @@ fn process(source: &'static str) -> Vec { #[test] fn clamp_inside_clamp() { // check that both the inner and outer "CLAMP" calls became "clamp" calls - assert_eq!(process(r#" + assert_eq!( + process( + r#" #define CLAMP(VAL, MIN, MAX) clamp(VAL, MIN, MAX) CLAMP(alpha - CLAMP(beta - 2, 0, beta), 3, alpha) -"#), &[ - Ident("clamp".into(), false), - Punct(LParen), +"# + ), + &[ + Ident("clamp".into(), false), + Punct(LParen), Ident("alpha".into(), true), Punct(Sub), Ident("clamp".into(), false), Punct(LParen), - Ident("beta".into(), true), - Punct(Sub), - Int(2), - Punct(Comma), - Int(0), - Punct(Comma), - Ident("beta".into(), false), + Ident("beta".into(), true), + Punct(Sub), + Int(2), + Punct(Comma), + Int(0), + Punct(Comma), + Ident("beta".into(), false), Punct(RParen), Punct(Comma), Int(3), Punct(Comma), Ident("alpha".into(), false), - Punct(RParen), - ]); + Punct(RParen), + ] + ); } #[test] fn defined_function() { - assert_eq!(process(r#" + assert_eq!( + process( + r#" #define FOO #if defined(FOO) ok1 #endif -"#), &[ - Ident("ok1".into(), false), - ]); +"# + ), + &[Ident("ok1".into(), false),] + ); - assert_eq!(process(r#" + assert_eq!( + process( + r#" #define A multiple.tokens() #if defined(C) || defined(A) && !defined(B) ok2 #endif -"#), &[ - Ident("ok2".into(), false), - ]); +"# + ), + &[Ident("ok2".into(), false),] + ); } #[test] fn fexists_function() { - assert_eq!(process(r#" + assert_eq!( + process( + r#" #if fexists("README.md") exists #endif -"#), &[ - Ident("exists".into(), false), - ]); +"# + ), + &[Ident("exists".into(), false),] + ); - assert_eq!(process(r#" + assert_eq!( + process( + r#" #if fexists("this file does not exist") exists #endif -"#), &[]); +"# + ), + &[] + ); } diff --git a/crates/dreammaker/tests/pipeline_tests.rs b/crates/dreammaker/tests/pipeline_tests.rs index 821497c5..e99fb1e2 100644 --- a/crates/dreammaker/tests/pipeline_tests.rs +++ b/crates/dreammaker/tests/pipeline_tests.rs @@ -11,7 +11,7 @@ fn with_test_dme(context: &Context, f: F) { None => { println!("Set TEST_DME to check full pipeline"); return; - } + }, }; f(Preprocessor::new(context, PathBuf::from(dme)).expect("failed to open test file")) } @@ -35,7 +35,8 @@ fn check_indentor() { &mut string, indents::IndentProcessor::new(&context, &mut preprocessor).map(|t| t.token), true, - ).unwrap(); + ) + .unwrap(); context.assert_success(); }); } @@ -44,7 +45,10 @@ fn check_indentor() { fn check_parser() { let context = Context::default(); with_test_dme(&context, |mut preprocessor| { - let mut parser = parser::Parser::new(&context, indents::IndentProcessor::new(&context, &mut preprocessor)); + let mut parser = parser::Parser::new( + &context, + indents::IndentProcessor::new(&context, &mut preprocessor), + ); parser.enable_procs(); let _tree = parser.parse_object_tree(); context.assert_success(); diff --git a/crates/interval-tree/src/iterators.rs b/crates/interval-tree/src/iterators.rs index 2e6c74f9..f1c9682a 100644 --- a/crates/interval-tree/src/iterators.rs +++ b/crates/interval-tree/src/iterators.rs @@ -40,7 +40,7 @@ impl<'a, K: Ord, V> RangePairIter<'a, K, V> { } { self.stack.push((&**lsucc, Visiting::Left)) } - } + }, None => self.stack.push((node, Visiting::Center)), } } @@ -80,7 +80,7 @@ impl<'a, K: Ord, V> RangePairIter<'a, K, V> { self.stack.push((node, Visiting::Middle(i + 1))); return Some((node, i)); } - } + }, } } None diff --git a/crates/interval-tree/src/node.rs b/crates/interval-tree/src/node.rs index d3c34577..000ea447 100644 --- a/crates/interval-tree/src/node.rs +++ b/crates/interval-tree/src/node.rs @@ -169,13 +169,13 @@ impl Node { self.right = succ.delete(key); return Some(self.updated_node()); } - } + }, Ordering::Greater => { if let Some(succ) = self.left.take() { self.left = succ.delete(key); return Some(self.updated_node()); } - } + }, } Some(self) } @@ -202,7 +202,7 @@ impl Node { Ordering::Equal => { self.data.push(data); return self; - } + }, Ordering::Less => self.right = Node::insert_in_successor(self.right.take(), key, data), Ordering::Greater => self.left = Node::insert_in_successor(self.left.take(), key, data), } diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..8c795ae5 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +match_block_trailing_comma = true From 0db42988758656d53bed6b7c8c1370200331f967 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 18 Dec 2025 21:20:14 -0800 Subject: [PATCH 196/197] Add more #[rustfmt::skip]s --- crates/dmdoc/src/main.rs | 1 + crates/dmm-tools-cli/src/main.rs | 3 +-- crates/dmm-tools/src/minimap.rs | 6 ++++-- crates/dreammaker/src/constants.rs | 1 + crates/dreammaker/src/parser.rs | 1 - 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/crates/dmdoc/src/main.rs b/crates/dmdoc/src/main.rs index 64470035..b45333a1 100644 --- a/crates/dmdoc/src/main.rs +++ b/crates/dmdoc/src/main.rs @@ -23,6 +23,7 @@ use dm::docs::*; use markdown::DocBlock; +#[rustfmt::skip] const BUILD_INFO: &str = concat!( "dmdoc ", env!("CARGO_PKG_VERSION"), " Copyright (C) 2017-2025 Tad Hardesty\n", include_str!(concat!(env!("OUT_DIR"), "/build-info.txt")), "\n", diff --git a/crates/dmm-tools-cli/src/main.rs b/crates/dmm-tools-cli/src/main.rs index cc4bdace..2ebf4f3d 100644 --- a/crates/dmm-tools-cli/src/main.rs +++ b/crates/dmm-tools-cli/src/main.rs @@ -435,8 +435,7 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) { let result = render_many(context, command); let stdout = std::io::stdout(); serde_json::to_writer(stdout.lock(), &result).unwrap(); - } - // -------------------------------------------------------------------- + }, } } diff --git a/crates/dmm-tools/src/minimap.rs b/crates/dmm-tools/src/minimap.rs index 881ef7f6..880d5875 100644 --- a/crates/dmm-tools/src/minimap.rs +++ b/crates/dmm-tools/src/minimap.rs @@ -95,11 +95,13 @@ pub fn generate(ctx: Context, icon_cache: &IconCache) -> Result { // smoothing time let mut neighborhood = [&[][..]; 9]; - for (i, (dx, dy)) in [ + #[rustfmt::skip] + const GRID: [(i32, i32); 9] = [ (-1, 1), (0, 1), (1, 1), (-1, 0), (0, 0), (1, 0), (-1, -1), (0, -1), (1, -1), - ].iter().enumerate() { + ]; + for (i, (dx, dy)) in GRID.iter().enumerate() { let new_x = x as i32 + dx; let new_y = y as i32 - dy; let (dim_y, dim_x) = ctx.level.grid.dim(); diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index 86cc891f..1708f8ad 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -776,6 +776,7 @@ impl<'a> ConstantFolder<'a> { } } } + #[rustfmt::skip] numeric!(Add +); numeric!(Sub -); numeric!(Mul *); diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 8219364b..7335e27a 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -544,7 +544,6 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { /// Consume next token unconditionally. Cannot be undone. Try `take_match!` instead. fn take(&mut self) -> Token { self.peek(); // Always populates self.next, so .take().unwrap() is OK - //assert_ne!(self.peek(), &Token::Eof, "internal parser error: EOF token was consumed"); self.doc_comments_pending.clear(); self.expected.clear(); self.next.take().unwrap() From 213284aa5157643d13e238cc40e4ada9c0a4bd0c Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Thu, 18 Dec 2025 22:02:24 -0800 Subject: [PATCH 197/197] Fix clippy::needless_late_init warning --- crates/dreamchecker/src/lib.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/dreamchecker/src/lib.rs b/crates/dreamchecker/src/lib.rs index 77a1754d..15380223 100644 --- a/crates/dreamchecker/src/lib.rs +++ b/crates/dreamchecker/src/lib.rs @@ -2951,18 +2951,17 @@ impl<'o, 's> AnalyzeProc<'o, 's> { ); } } - let typeerror; - match rhs.static_ty { + let typeerror = match rhs.static_ty { StaticType::None => return Analysis::empty(), StaticType::Type(typeref) => { // Its been overloaded, assume they really know they want to do this if let Some(proc) = typeref.get_proc(operator) { return self.visit_call(location, typeref, proc, &[], true, local_vars); } - typeerror = typeref.get().pretty_path(); + typeref.get().pretty_path() }, StaticType::List { list, .. } => { - typeerror = "list"; + "list" }, StaticType::Proc => return Analysis::empty(), };