From fbc832408d189e12eda4eab50598951184609b42 Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Thu, 1 Jan 2026 00:43:58 -0600 Subject: [PATCH] sqf: use wiki 0.5 --- Cargo.lock | 8 +- Cargo.toml | 2 +- bin/src/modules/git.rs | 4 +- libs/sqf/src/analyze/inspector/commands.rs | 2 +- .../analyze/inspector/external_functions.rs | 4 +- libs/sqf/src/analyze/inspector/game_value.rs | 171 ++++++++++++++++-- libs/sqf/src/analyze/inspector/mod.rs | 13 +- .../analyze/lints/s07_select_parse_number.rs | 4 +- .../inspector__tests__code_usage.snap | 2 +- .../inspector__tests__iteration.snap | 2 +- .../snapshots/inspector__tests__main.snap | 2 +- .../inspector__tests__variable_usage.snap | 2 +- .../lints__simple_s12_invalid_args.snap | 2 +- 13 files changed, 178 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f20fe8532..a55ae30a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -237,9 +237,9 @@ dependencies = [ [[package]] name = "arma3-wiki" -version = "0.4.5" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95f79de9794487f9f324e911bafa01ddba0e69a242530813768c598a4d411cc4" +checksum = "8af553c7c61e977b0c2261bae15cc40caca52b4edf391b812f93a548bda2c091" dependencies = [ "directories", "fs-err", @@ -5651,9 +5651,9 @@ checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" [[package]] name = "zmij" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3280a1b827474fcd5dbef4b35a674deb52ba5c312363aef9135317df179d81b" +checksum = "aac060176f7020d62c3bcc1cdbcec619d54f48b07ad1963a3f80ce7a0c17755f" [[package]] name = "zopfli" diff --git a/Cargo.toml b/Cargo.toml index 94c812457..73c39f98f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ future_incompatible = "warn" nonstandard_style = "warn" [workspace.dependencies] -arma3-wiki = "0.4.5" +arma3-wiki = "0.5.1" automod = "1.0.15" byteorder = "1.5.0" chumsky = "0.9.3" diff --git a/bin/src/modules/git.rs b/bin/src/modules/git.rs index 844f65855..12bf37d8f 100644 --- a/bin/src/modules/git.rs +++ b/bin/src/modules/git.rs @@ -10,11 +10,13 @@ impl Module for Git { } fn check(&self, ctx: &Context) -> Result { + let mut using_private_key = false; if let Ok(repo) = Repository::discover(".") { for entry in walkdir::WalkDir::new(ctx.project_folder()) { let entry = entry?; let name = entry.file_name().to_string_lossy(); if name.ends_with(".hemttprivatekey") || name.ends_with(".biprivatekey") { + using_private_key = true; let rel_path = entry .path() .strip_prefix(ctx.project_folder()) @@ -66,7 +68,7 @@ impl Module for Git { } let gitignore = ctx.project_folder().join(".gitignore"); - if gitignore.exists() { + if using_private_key && gitignore.exists() { let mut search = false; let content = fs_err::read_to_string(&gitignore)?; if !content.contains(".hemttprivatekey") { diff --git a/libs/sqf/src/analyze/inspector/commands.rs b/libs/sqf/src/analyze/inspector/commands.rs index 8b0319d88..2fcab9cba 100644 --- a/libs/sqf/src/analyze/inspector/commands.rs +++ b/libs/sqf/src/analyze/inspector/commands.rs @@ -272,7 +272,7 @@ impl Inspector { self.var_assign( var.as_ref(), true, - IndexSet::from([GameValue::Number(None)]), + IndexSet::from([GameValue::Number(None, None)]), VarSource::ForLoop(source.clone()), ); } diff --git a/libs/sqf/src/analyze/inspector/external_functions.rs b/libs/sqf/src/analyze/inspector/external_functions.rs index 38a32ff72..f3d0325fc 100644 --- a/libs/sqf/src/analyze/inspector/external_functions.rs +++ b/libs/sqf/src/analyze/inspector/external_functions.rs @@ -110,7 +110,7 @@ impl Inspector { &gv_array[2], &vec![ ("_thisType", GameValue::String(None)), - ("_thisId", GameValue::Number(None)), + ("_thisId", GameValue::Number(None, None)), ("_thisFnc", GameValue::Code(None)), ("_thisArgs", GameValue::Anything), ], @@ -124,7 +124,7 @@ impl Inspector { &gv_array[1], &vec![ ("_thisType", GameValue::String(None)), - ("_thisId", GameValue::Number(None)), + ("_thisId", GameValue::Number(None, None)), ("_thisFnc", GameValue::Code(None)), ("_thisArgs", GameValue::Anything), ], diff --git a/libs/sqf/src/analyze/inspector/game_value.rs b/libs/sqf/src/analyze/inspector/game_value.rs index bf8425140..274a4b3a5 100644 --- a/libs/sqf/src/analyze/inspector/game_value.rs +++ b/libs/sqf/src/analyze/inspector/game_value.rs @@ -1,6 +1,6 @@ //! Game Values and mapping them from commands -use std::ops::Range; +use std::ops::{Range, RangeInclusive}; use arma3_wiki::model::{Arg, Call, Param, Value}; use indexmap::IndexSet; @@ -28,7 +28,7 @@ pub enum GameValue { IfType, Location, Namespace, - Number(Option), + Number(Option, Option>), Nothing(NilSource), Object, ScriptHandle, @@ -44,7 +44,10 @@ pub enum GameValue { #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub enum ArrayType { + Unsized(Box), + Color, + // Pos2d, PosAGL, // PosAGLS, @@ -54,6 +57,8 @@ pub enum ArrayType { /// from object's center `getPosWorld` PosWorld, PosRelative, + + Vector3D, } #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -150,7 +155,7 @@ impl GameValue { } } } - let value = &syntax.ret().0; + let value = syntax.ret().typ(); let game_value = Self::from_wiki_value(value, NilSource::CommandReturn); // println!("match syntax {syntax:?}"); return_types.extend(game_value); @@ -283,27 +288,141 @@ impl GameValue { // println!("array mismatch {lpos:?}!={rpos:?}"); // return false; } + if matches!(left, Self::Array(_, _)) && matches!(right, Self::Array(_, _)) { + return Self::compatible_array(left, right) || Self::compatible_array(right, left); + } + if matches!(left, Self::Number(_, _)) && matches!(right, Self::Number(_, _)) { + return Self::compatible_number(left, right); + } std::mem::discriminant(left) == std::mem::discriminant(right) } + + pub fn compatible_number(left: &Self, right: &Self) -> bool { + let Self::Number(left_expr, left_range) = left else { + return true; + }; + let Self::Number(_, right_range) = right else { + return true; + }; + let Some(right_range) = right_range else { + return true; + }; + // Check static values + if let Some(Expression::Number(left_value, _)) = left_expr { + let left_value = f64::from(left_value.0); + if left_value < f64::from(*right_range.start()) + || left_value > f64::from(*right_range.end()) + { + return false; + } + } + // ensure that the right range encompasses the left + if let Some(left_range) = left_range + && (left_range.start() < right_range.start() || left_range.end() > right_range.end()) + { + return false; + } + true + } + + pub fn compatible_array(left: &Self, right: &Self) -> bool { + let (template, value) = if let ( + Self::Array(_, Some(type_data)), + Self::Array(right_value, None), + ) = (left, right) + { + (type_data, right_value) + } else if let (Self::Array(left_value, None), Self::Array(_, Some(type_data))) = + (left, right) + { + (type_data, left_value) + } else { + return true; + }; + if value.is_none() { + return true; + } + match template { + ArrayType::Color => { + // Color arrays must have 3 or 4 number elements + let data = value.as_ref().expect("color array data"); + Self::matches_array_length( + data, + 3..=4, + &Self::Number(None, Some(RangeInclusive::new(0, 3000))), + ) // 3000 because drawLaser allows it + } + ArrayType::Unsized(expected_type) => { + let data = value.as_ref().expect("unsized array data"); + for outer in data { + for (inner, _) in outer { + if !Self::match_values(inner, expected_type) { + return false; + } + } + } + true + } + ArrayType::PosAGL + | ArrayType::PosASL + | ArrayType::PosASLW + | ArrayType::PosATL + | ArrayType::PosWorld + | ArrayType::PosRelative => { + // Position arrays must have 3 number elements + let data = value.as_ref().expect("position array data"); + Self::matches_array_length(data, 3..=3, &Self::Number(None, None)) + } + ArrayType::Vector3D => { + // Vector3D arrays must have 3 number elements + let data = value.as_ref().expect("vector3d array data"); + Self::matches_array_length(data, 3..=3, &Self::Number(None, None)) + } + } + } + + pub fn matches_array_length( + value: &Vec)>>, + length: RangeInclusive, + inner_type: &Self, + ) -> bool { + if value.len() < *length.start() || value.len() > *length.end() { + return false; + } + for outer in value { + outer.iter().any(|(inner, _)| { + if !Self::match_values(inner, inner_type) { + return false; + } + true + }); + } + true + } + #[must_use] /// Maps from `Wiki:Value` to Set of `GameValues` pub fn from_wiki_value(value: &Value, nil_type: NilSource) -> IndexSet { match value { - Value::Anything | Value::EdenEntity => IndexSet::from([Self::Anything]), - Value::ArrayColor - | Value::ArrayColorRgb - | Value::ArrayColorRgba - | Value::ArrayDate + Value::Anything | Value::EdenEntity => IndexSet::from([Self::Anything]), // TODO EdenEntity + Value::ArrayDate | Value::ArraySized { .. } | Value::ArrayUnknown | Value::ArrayUnsized { .. } | Value::Position // position is often too generic to match? - | Value::Waypoint => IndexSet::from([Self::Array(None, None)]), - // Value::Position3dAGLS => Self::Array(None, Some(ArrayType::PosAGLS)), - Value::Position3dAGLS | Value::Position3dAGL => IndexSet::from([Self::Array(None, Some(ArrayType::PosAGL))]), // merge + | Value::Waypoint | Value::ArrayEdenEntities => IndexSet::from([Self::Array(None, None)]), + Value::ArrayEmpty => IndexSet::from([Self::Array(Some(vec![]), None)]), + Value::ArrayColor + | Value::ArrayColorRgb + | Value::ArrayColorRgba => { + IndexSet::from([Self::Array(None, Some(ArrayType::Color))]) + } + Value::Position3dAGLS | Value::Position3dAGL => IndexSet::from([Self::Array(None, Some(ArrayType::PosAGL))]), Value::Position3dASL => IndexSet::from([Self::Array(None, Some(ArrayType::PosASL))]), Value::Position3DASLW => IndexSet::from([Self::Array(None, Some(ArrayType::PosASLW))]), Value::Position3dATL => IndexSet::from([Self::Array(None, Some(ArrayType::PosATL))]), + Value::Position3dRelative => IndexSet::from([Self::Array(None, Some(ArrayType::PosRelative))]), + Value::Vector3d => IndexSet::from([Self::Array(None, Some(ArrayType::Vector3D))]), Value::Boolean => IndexSet::from([Self::Boolean(None)]), Value::Code => IndexSet::from([Self::Code(None)]), Value::Config => IndexSet::from([Self::Config]), @@ -317,7 +436,10 @@ impl GameValue { Value::Location => IndexSet::from([Self::Location]), Value::Namespace => IndexSet::from([Self::Namespace]), Value::Nothing => IndexSet::from([Self::Nothing(nil_type)]), - Value::Number => IndexSet::from([Self::Number(None)]), + Value::Number | Value::EdenID => IndexSet::from([Self::Number(None, None)]), + Value::NumberRange(min, max) => { + IndexSet::from([Self::Number(None, Some(RangeInclusive::new(*min, *max)))]) + } Value::Object => IndexSet::from([Self::Object]), Value::ScriptHandle => IndexSet::from([Self::ScriptHandle]), Value::Side => IndexSet::from([Self::Side]), @@ -330,8 +452,8 @@ impl GameValue { Value::WithType => IndexSet::from([Self::WithType]), Value::OneOf(vec) => { let mut set = IndexSet::new(); - for (v, _) in vec { - set.extend(Self::from_wiki_value(v, nil_type.clone())); + for oneofvalue in vec { + set.extend(Self::from_wiki_value(&oneofvalue.typ, nil_type.clone())); } set } @@ -340,12 +462,22 @@ impl GameValue { trace!("wiki has syntax with [unknown] type"); IndexSet::from([Self::Anything]) } - _ => { - warn!("wiki type [{value:?}] not matched"); + Value::ExceptionHandle + | Value::HashMapKnownKeys(_) + | Value::HashMapKey + | Value::NumberEnum(_) + | Value::StringEnum(_) + | Value::TurretPath + | Value::UnitLoadoutArray + | Value::Position2d + | Value::Position3d => { + #[cfg(debug_assertions)] + trace!("wiki has syntax with unsupported type: {value:?}"); IndexSet::from([Self::Anything]) } } } + #[must_use] /// Gets a generic version of a type pub fn make_generic(&self) -> Self { @@ -354,7 +486,7 @@ impl GameValue { Self::Boolean(_) => Self::Boolean(None), Self::Code(_) => Self::Code(None), Self::ForType(_) => Self::ForType(None), - Self::Number(_) => Self::Number(None), + Self::Number(_, _) => Self::Number(None, None), Self::String(_) => Self::String(None), Self::Nothing(_) => Self::Nothing(NilSource::Generic), _ => self.clone(), @@ -440,6 +572,9 @@ impl std::fmt::Display for GameValue { if let Self::Array(_, Some(array_type)) = self { return write!(f, "Array<{array_type:?}>"); } + if let Self::Number(_, Some(range)) = self { + return write!(f, "Number<{}..{}>", range.start(), range.end()); + } write!( f, "{}", @@ -459,7 +594,7 @@ impl std::fmt::Display for GameValue { Self::IfType => "IfType", Self::Location => "Location", Self::Namespace => "Namespace", - Self::Number(_) => "Number", + Self::Number(_, _) => "Number", Self::Nothing(_) => "Nil", Self::Object => "Object", Self::ScriptHandle => "ScriptHandle", diff --git a/libs/sqf/src/analyze/inspector/mod.rs b/libs/sqf/src/analyze/inspector/mod.rs index 03a7765f4..d3c31b783 100644 --- a/libs/sqf/src/analyze/inspector/mod.rs +++ b/libs/sqf/src/analyze/inspector/mod.rs @@ -380,9 +380,10 @@ impl Inspector { let mut debug_type = String::new(); let possible_values = match expression { Expression::Variable(var, source) => self.var_retrieve(var, source, false), - Expression::Number(_, source) => { - IndexSet::from([(GameValue::Number(Some(expression.clone())), source.clone())]) - } + Expression::Number(_, source) => IndexSet::from([( + GameValue::Number(Some(expression.clone()), None), + source.clone(), + )]), Expression::Boolean(_, source) => { IndexSet::from([(GameValue::Boolean(Some(expression.clone())), source.clone())]) } @@ -462,7 +463,7 @@ impl Inspector { &vec![ ("_this", GameValue::Anything), ("_thisEvent", GameValue::String(None)), - ("_thisEventHandler", GameValue::Number(None)), + ("_thisEventHandler", GameValue::Number(None, None)), ("_thisArgs", GameValue::Anything), // gv_array[2]? ], database, @@ -574,7 +575,7 @@ impl Inspector { "foreach" | "foreachreversed" => { let mut magic = vec![ ("_x", GameValue::get_array_value_type(&rhs_set)), - ("_forEachIndex", GameValue::Number(None)), + ("_forEachIndex", GameValue::Number(None, None)), ]; if !rhs_set.iter().all(|gv| matches!(gv, GameValue::Array(..))) { magic.push(("_y", GameValue::Anything)); @@ -632,7 +633,7 @@ impl Inspector { &vec![ ("_this", GameValue::Anything), ("_thisEvent", GameValue::String(None)), - ("_thisEventHandler", GameValue::Number(None)), + ("_thisEventHandler", GameValue::Number(None, None)), ], database, ); diff --git a/libs/sqf/src/analyze/lints/s07_select_parse_number.rs b/libs/sqf/src/analyze/lints/s07_select_parse_number.rs index 2dd9b9a51..41d78bbb7 100644 --- a/libs/sqf/src/analyze/lints/s07_select_parse_number.rs +++ b/libs/sqf/src/analyze/lints/s07_select_parse_number.rs @@ -129,11 +129,11 @@ fn safe_command(command: &str, database: &Database) -> bool { let Some(cmd) = database.wiki().commands().get(command) else { return false; }; - cmd.syntax().iter().all(|s| match &s.ret().0 { + cmd.syntax().iter().all(|s| match s.ret().typ() { Value::Boolean | Value::String => true, Value::OneOf(rets) => rets .iter() - .all(|(r, _)| matches!(r, Value::String | Value::Boolean)), + .all(|r| matches!(r.typ, Value::String | Value::Boolean)), _ => false, }) } diff --git a/libs/sqf/tests/snapshots/inspector__tests__code_usage.snap b/libs/sqf/tests/snapshots/inspector__tests__code_usage.snap index 3bfbb4ed1..440f556d6 100644 --- a/libs/sqf/tests/snapshots/inspector__tests__code_usage.snap +++ b/libs/sqf/tests/snapshots/inspector__tests__code_usage.snap @@ -2,4 +2,4 @@ source: libs/sqf/tests/inspector.rs expression: "(issues.len(), issues)" --- -(2, [InvalidArgs { command: "[B:/]", span: 208..209, variant: TypeNotExpected { expected: [Number(None), Config], found: [String(Some(String("a", 175..178, DoubleQuote)))], span: 194..207 } }, InvalidArgs { command: "[B:/]", span: 208..209, variant: TypeNotExpected { expected: [Number(None), String(None)], found: [Number(Some(Number(FloatOrd(2.0), 210..211)))], span: 210..211 } }]) +(2, [InvalidArgs { command: "[B:/]", span: 208..209, variant: TypeNotExpected { expected: [Number(None, None), Config], found: [String(Some(String("a", 175..178, DoubleQuote)))], span: 194..207 } }, InvalidArgs { command: "[B:/]", span: 208..209, variant: TypeNotExpected { expected: [Number(None, None), String(None)], found: [Number(Some(Number(FloatOrd(2.0), 210..211)), None)], span: 210..211 } }]) diff --git a/libs/sqf/tests/snapshots/inspector__tests__iteration.snap b/libs/sqf/tests/snapshots/inspector__tests__iteration.snap index 9b8a12f31..980a3918c 100644 --- a/libs/sqf/tests/snapshots/inspector__tests__iteration.snap +++ b/libs/sqf/tests/snapshots/inspector__tests__iteration.snap @@ -2,4 +2,4 @@ source: libs/sqf/tests/inspector.rs expression: "(issues.len(), issues)" --- -(10, [Undefined("_y", 123..125, false), Undefined("_y", 200..202, false), Undefined("_forEachIndex", 237..250, false), InvalidArgs { command: "[B:+]", span: 268..269, variant: TypeNotExpected { expected: [Number(None), Array(None, None), String(None)], found: [Number(None)], span: 265..267 } }, InvalidArgs { command: "[B:+]", span: 268..269, variant: TypeNotExpected { expected: [Number(None), Array(None, None), String(None)], found: [String(Some(String("A", 270..273, DoubleQuote)))], span: 270..273 } }, InvalidArgs { command: "[B:+]", span: 306..307, variant: TypeNotExpected { expected: [Number(None), Array(None, None), String(None)], found: [Number(None)], span: 303..305 } }, InvalidArgs { command: "[B:+]", span: 306..307, variant: TypeNotExpected { expected: [Number(None), Array(None, None), String(None)], found: [String(Some(String("B", 308..311, DoubleQuote)))], span: 308..311 } }, Undefined("_forEachIndex", 532..545, false), Undefined("_y", 570..572, false), InvalidArgs { command: "[B:forEachReversed]", span: 759..774, variant: TypeNotExpected { expected: [Array(None, None)], found: [HashMap], span: 775..778 } }]) +(10, [Undefined("_y", 123..125, false), Undefined("_y", 200..202, false), Undefined("_forEachIndex", 237..250, false), InvalidArgs { command: "[B:+]", span: 268..269, variant: TypeNotExpected { expected: [Number(None, None), Array(None, None), String(None)], found: [Number(None, None)], span: 265..267 } }, InvalidArgs { command: "[B:+]", span: 268..269, variant: TypeNotExpected { expected: [Number(None, None), Array(None, None), String(None)], found: [String(Some(String("A", 270..273, DoubleQuote)))], span: 270..273 } }, InvalidArgs { command: "[B:+]", span: 306..307, variant: TypeNotExpected { expected: [Number(None, None), Array(None, None), String(None)], found: [Number(None, None)], span: 303..305 } }, InvalidArgs { command: "[B:+]", span: 306..307, variant: TypeNotExpected { expected: [Number(None, None), Array(None, None), String(None)], found: [String(Some(String("B", 308..311, DoubleQuote)))], span: 308..311 } }, Undefined("_forEachIndex", 532..545, false), Undefined("_y", 570..572, false), InvalidArgs { command: "[B:forEachReversed]", span: 759..774, variant: TypeNotExpected { expected: [Array(None, None)], found: [HashMap], span: 775..778 } }]) diff --git a/libs/sqf/tests/snapshots/inspector__tests__main.snap b/libs/sqf/tests/snapshots/inspector__tests__main.snap index ea1d7ab12..e59f4fcbe 100644 --- a/libs/sqf/tests/snapshots/inspector__tests__main.snap +++ b/libs/sqf/tests/snapshots/inspector__tests__main.snap @@ -2,4 +2,4 @@ source: libs/sqf/tests/inspector.rs expression: "(issues.len(), issues)" --- -(22, [InvalidArgs { command: "[B:setFuel]", span: 31..38, variant: TypeNotExpected { expected: [Number(None)], found: [Boolean(Some(Boolean(true, 39..43)))], span: 39..43 } }, Undefined("_test2", 46..52, false), NotPrivate("_test3", 113..119), Unused("_test5", Params(248..256), true), InvalidArgs { command: "[B:addPublicVariableEventHandler]", span: 319..348, variant: TypeNotExpected { expected: [String(None)], found: [Array(Some([]), None)], span: 316..318 } }, InvalidArgs { command: "[B:addPublicVariableEventHandler]", span: 319..348, variant: TypeNotExpected { expected: [Anything, Array(None, None)], found: [Code(Some(Code(Statements { content: [], source: "}", span: 350..351, issues: [] })))], span: 350..351 } }, Undefined("_test8", 887..893, false), InvalidArgs { command: "[B:ctrlSetText]", span: 1098..1109, variant: TypeNotExpected { expected: [String(None)], found: [Object], span: 1110..1117 } }, Undefined("_test9", 1498..1504, false), Unused("_test10", ForLoop(1752..1761), false), InvalidArgs { command: "[B:drawIcon]", span: 1992..2000, variant: TypeNotExpected { expected: [Array(Some([[(String(None), 0..0)], [(Array(None, None), 0..0)], [(Anything, 0..0)], [(Number(None), 0..0)], [(Number(None), 0..0)], [(Number(None), 0..0)], [(String(None), 0..0)]]), None)], found: [Array(Some([[(String(Some(String("#(rgb,1,1,1)color(1,1,1,1)", 2008..2036, DoubleQuote))), 2008..2036)], [(Array(Some([[(Number(Some(Number(FloatOrd(0.0), 2043..2044))), 2043..2044)], [(Number(Some(Number(FloatOrd(1.0), 2045..2046))), 2045..2046)], [(Number(Some(Number(FloatOrd(0.0), 2047..2048))), 2047..2048)], [(Number(Some(Number(FloatOrd(1.0), 2049..2050))), 2049..2050)]]), None), 2043..2050)], [(Object, 2057..2063)], [(Number(Some(Number(FloatOrd(0.0), 2069..2070))), 2069..2070)], [(Number(Some(Number(FloatOrd(0.0), 2076..2077))), 2076..2077)], [(Number(Some(Number(FloatOrd(0.0), 2083..2084))), 2083..2084)], [(Number(Some(Number(FloatOrd(5555.0), 2090..2094))), 2090..2094)]]), None)], span: 2007..2095 } }, InvalidArgs { command: "[B:setGusts]", span: 2434..2442, variant: TypeNotExpected { expected: [Number(None)], found: [String(None), String(Some(String("abc", 2401..2406, DoubleQuote)))], span: 2443..2454 } }, Undefined("_test12", 2537..2544, false), CountArrayComparison(true, 2724..2742, "_test14"), InvalidArgs { command: "[U:case]", span: 3448..3452, variant: NilResultUsed { found: [Nothing(CommandReturn)], span: 3453..3460 } }, InvalidArgs { command: "[B:forEach]", span: 3512..3519, variant: TypeNotExpected { expected: [Array(None, None), HashMap], found: [Number(Some(Number(FloatOrd(5.0), 3504..3505)))], span: 3520..3527 } }, InvalidArgs { command: "=", span: 3599..3635, variant: NilResultUsed { found: [Assignment], span: 3620..3624 } }, InvalidArgs { command: "[U:hashValue]", span: 3638..3647, variant: NilResultUsed { found: [Assignment], span: 3648..3655 } }, InvalidArgs { command: "[U:sin]", span: 3775..3778, variant: TypeNotExpected { expected: [Number(None)], found: [Object, Display], span: 3775..3778 } }, Unused("_test4", Assignment(223..229, 232..237), false), Unused("_test11", Params(1802..1811), false), Undefined("_test13", 2610..2617, true)]) +(23, [InvalidArgs { command: "[B:setFuel]", span: 31..38, variant: TypeNotExpected { expected: [Number(None, Some(0..=1))], found: [Boolean(Some(Boolean(true, 39..43)))], span: 39..43 } }, Undefined("_test2", 46..52, false), NotPrivate("_test3", 113..119), Unused("_test5", Params(248..256), true), InvalidArgs { command: "[B:addPublicVariableEventHandler]", span: 319..348, variant: TypeNotExpected { expected: [String(None)], found: [Array(Some([]), None)], span: 316..318 } }, InvalidArgs { command: "[B:addPublicVariableEventHandler]", span: 319..348, variant: TypeNotExpected { expected: [Code(None), String(None), Group, Array(None, None)], found: [Code(Some(Code(Statements { content: [], source: "}", span: 350..351, issues: [] })))], span: 350..351 } }, Undefined("_test8", 887..893, false), InvalidArgs { command: "[B:ctrlSetText]", span: 1098..1109, variant: TypeNotExpected { expected: [String(None)], found: [Object], span: 1110..1117 } }, Undefined("_test9", 1498..1504, false), Unused("_test10", ForLoop(1752..1761), false), InvalidArgs { command: "[B:drawIcon]", span: 1992..2000, variant: TypeNotExpected { expected: [Array(Some([[(String(None), 0..0)], [(Array(None, None), 0..0)], [(Object, 0..0), (Anything, 0..0)], [(Number(None, None), 0..0)], [(Number(None, None), 0..0)], [(Number(None, None), 0..0)], [(String(None), 0..0)]]), None)], found: [Array(Some([[(String(Some(String("#(rgb,1,1,1)color(1,1,1,1)", 2008..2036, DoubleQuote))), 2008..2036)], [(Array(Some([[(Number(Some(Number(FloatOrd(0.0), 2043..2044)), None), 2043..2044)], [(Number(Some(Number(FloatOrd(1.0), 2045..2046)), None), 2045..2046)], [(Number(Some(Number(FloatOrd(0.0), 2047..2048)), None), 2047..2048)], [(Number(Some(Number(FloatOrd(1.0), 2049..2050)), None), 2049..2050)]]), None), 2043..2050)], [(Object, 2057..2063)], [(Number(Some(Number(FloatOrd(0.0), 2069..2070)), None), 2069..2070)], [(Number(Some(Number(FloatOrd(0.0), 2076..2077)), None), 2076..2077)], [(Number(Some(Number(FloatOrd(0.0), 2083..2084)), None), 2083..2084)], [(Number(Some(Number(FloatOrd(5555.0), 2090..2094)), None), 2090..2094)]]), None)], span: 2007..2095 } }, InvalidArgs { command: "[B:setGusts]", span: 2434..2442, variant: TypeNotExpected { expected: [Number(None, None)], found: [String(None), String(Some(String("abc", 2401..2406, DoubleQuote)))], span: 2443..2454 } }, Undefined("_test12", 2537..2544, false), CountArrayComparison(true, 2724..2742, "_test14"), InvalidArgs { command: "[U:case]", span: 3448..3452, variant: NilResultUsed { found: [Nothing(CommandReturn)], span: 3453..3460 } }, InvalidArgs { command: "[B:forEach]", span: 3512..3519, variant: TypeNotExpected { expected: [Array(None, None), HashMap], found: [Number(Some(Number(FloatOrd(5.0), 3504..3505)), None)], span: 3520..3527 } }, InvalidArgs { command: "=", span: 3599..3635, variant: NilResultUsed { found: [Assignment], span: 3620..3624 } }, InvalidArgs { command: "[U:hashValue]", span: 3638..3647, variant: TypeNotExpected { expected: [Array(None, None), Boolean(None), Code(None), Config, Group, Namespace, Number(None, None), Object, Side, String(None)], found: [Assignment], span: 3638..3647 } }, InvalidArgs { command: "[U:hashValue]", span: 3658..3667, variant: TypeNotExpected { expected: [Array(None, None), Boolean(None), Code(None), Config, Group, Namespace, Number(None, None), Object, Side, String(None)], found: [Nothing(ExplicitNil)], span: 3658..3667 } }, InvalidArgs { command: "[U:sin]", span: 3775..3778, variant: TypeNotExpected { expected: [Number(None, None)], found: [Object, Display], span: 3775..3778 } }, Unused("_test4", Assignment(223..229, 232..237), false), Unused("_test11", Params(1802..1811), false), Undefined("_test13", 2610..2617, true)]) diff --git a/libs/sqf/tests/snapshots/inspector__tests__variable_usage.snap b/libs/sqf/tests/snapshots/inspector__tests__variable_usage.snap index 03ef2217b..3a71b6332 100644 --- a/libs/sqf/tests/snapshots/inspector__tests__variable_usage.snap +++ b/libs/sqf/tests/snapshots/inspector__tests__variable_usage.snap @@ -2,4 +2,4 @@ source: libs/sqf/tests/inspector.rs expression: "(issues.len(), issues)" --- -(5, [InvalidArgs { command: "[U:systemChat]", span: 51..61, variant: TypeNotExpected { expected: [String(None)], found: [Number(None)], span: 51..61 } }, Unused("_testC", Assignment(171..177, 180..183), true), InvalidArgs { command: "=", span: 483..517, variant: NilResultUsed { found: [Number(Some(Number(FloatOrd(5.0), 514..515))), Nothing(IfWithoutElse)], span: 507..511 } }, InvalidArgs { command: "[U:str]", span: 530..533, variant: NilResultUsed { found: [Number(Some(Number(FloatOrd(5.0), 514..515))), Nothing(IfWithoutElse)], span: 534..540 } }, InvalidArgs { command: "[B:setVariable]", span: 557..568, variant: NilResultUsed { found: [Array(Some([[(String(Some(String("why", 570..575, DoubleQuote))), 570..575)], [(Nothing(CommandReturn), 577..587)]]), None)], span: 569..597 } }]) +(5, [InvalidArgs { command: "[U:systemChat]", span: 51..61, variant: TypeNotExpected { expected: [String(None)], found: [Number(None, None)], span: 51..61 } }, Unused("_testC", Assignment(171..177, 180..183), true), InvalidArgs { command: "=", span: 483..517, variant: NilResultUsed { found: [Number(Some(Number(FloatOrd(5.0), 514..515)), None), Nothing(IfWithoutElse)], span: 507..511 } }, InvalidArgs { command: "[U:str]", span: 530..533, variant: NilResultUsed { found: [Number(Some(Number(FloatOrd(5.0), 514..515)), None), Nothing(IfWithoutElse)], span: 534..540 } }, InvalidArgs { command: "[B:setVariable]", span: 557..568, variant: NilResultUsed { found: [Array(Some([[(String(Some(String("why", 570..575, DoubleQuote))), 570..575)], [(Nothing(CommandReturn), 577..587)]]), None)], span: 569..597 } }]) diff --git a/libs/sqf/tests/snapshots/lints__simple_s12_invalid_args.snap b/libs/sqf/tests/snapshots/lints__simple_s12_invalid_args.snap index f489d5ed9..d8e02159b 100644 --- a/libs/sqf/tests/snapshots/lints__simple_s12_invalid_args.snap +++ b/libs/sqf/tests/snapshots/lints__simple_s12_invalid_args.snap @@ -20,7 +20,7 @@ expression: "lint(stringify! (s12_invalid_args), false).0" │ ^^^^ type not expected │ = note: found Bool - expected Number + expected Number<0..1> warning[L-S12]: Invalid argument type for `[B:setVariable]`