Fix to never have undefined iteration order and lint against it (#4665)

This commit is contained in:
Jonathan Tran
2024-12-05 12:09:35 -05:00
committed by GitHub
parent 1495cc6d18
commit 2bf20988ef
12 changed files with 43 additions and 20 deletions

View File

@ -77,6 +77,9 @@ http = "1"
kittycad = { version = "0.3.28", default-features = false, features = ["js", "requests"] } kittycad = { version = "0.3.28", default-features = false, features = ["js", "requests"] }
kittycad-modeling-cmds = { version = "0.2.77", features = ["websocket"] } kittycad-modeling-cmds = { version = "0.2.77", features = ["websocket"] }
[workspace.lints.clippy]
iter_over_hash_type = "warn"
[[test]] [[test]]
name = "executor" name = "executor"
path = "tests/executor/main.rs" path = "tests/executor/main.rs"

View File

@ -27,3 +27,6 @@ anyhow = "1.0.93"
expectorate = "1.1.0" expectorate = "1.1.0"
pretty_assertions = "1.4.1" pretty_assertions = "1.4.1"
rustfmt-wrapper = "0.2.1" rustfmt-wrapper = "0.2.1"
[lints]
workspace = true

View File

@ -13,3 +13,6 @@ pico-args = "0.5.0"
serde = { version = "1.0.214", features = ["derive"] } serde = { version = "1.0.214", features = ["derive"] }
serde_json = "1.0.128" serde_json = "1.0.128"
tokio = { version = "1.41.1", features = ["macros", "rt-multi-thread"] } tokio = { version = "1.41.1", features = ["macros", "rt-multi-thread"] }
[lints]
workspace = true

View File

@ -21,3 +21,6 @@ kittycad = { workspace = true, features = ["clap"] }
kittycad-modeling-cmds = { workspace = true } kittycad-modeling-cmds = { workspace = true }
tokio = { version = "1.41", features = ["full", "time", "rt", "tracing"] } tokio = { version = "1.41", features = ["full", "time", "rt", "tracing"] }
uuid = { version = "1.11.0", features = ["v4", "js", "serde"] } uuid = { version = "1.11.0", features = ["v4", "js", "serde"] }
[lints]
workspace = true

View File

@ -121,6 +121,9 @@ pretty_assertions = "1.4.1"
tokio = { version = "1.41.1", features = ["rt-multi-thread", "macros", "time"] } tokio = { version = "1.41.1", features = ["rt-multi-thread", "macros", "time"] }
twenty-twenty = "0.8.0" twenty-twenty = "0.8.0"
[lints]
workspace = true
[[bench]] [[bench]]
name = "compiler_benchmark_criterion" name = "compiler_benchmark_criterion"
harness = false harness = false

View File

@ -22,6 +22,9 @@ members = ["."]
[profile.release] [profile.release]
debug = 1 debug = 1
[lints]
workspace = true
[[bin]] [[bin]]
name = "parser" name = "parser"
path = "fuzz_targets/parser.rs" path = "fuzz_targets/parser.rs"

View File

@ -1,9 +1,10 @@
use std::collections::{BTreeMap, HashMap}; use std::collections::BTreeMap;
use anyhow::Result; use anyhow::Result;
use base64::Engine; use base64::Engine;
use convert_case::Casing; use convert_case::Casing;
use handlebars::Renderable; use handlebars::Renderable;
use indexmap::IndexMap;
use itertools::Itertools; use itertools::Itertools;
use serde_json::json; use serde_json::json;
@ -271,7 +272,7 @@ fn init_handlebars() -> Result<handlebars::Handlebars<'static>> {
Ok(hbs) Ok(hbs)
} }
fn generate_index(combined: &HashMap<String, Box<dyn StdLibFn>>) -> Result<()> { fn generate_index(combined: &IndexMap<String, Box<dyn StdLibFn>>) -> Result<()> {
let hbs = init_handlebars()?; let hbs = init_handlebars()?;
let mut functions = Vec::new(); let mut functions = Vec::new();

View File

@ -213,7 +213,12 @@ impl EngineConnection {
WebSocketResponse::Success(SuccessWebSocketResponse { WebSocketResponse::Success(SuccessWebSocketResponse {
resp: OkWebSocketResponseData::ModelingBatch { responses }, resp: OkWebSocketResponseData::ModelingBatch { responses },
.. ..
}) => { }) =>
{
#[expect(
clippy::iter_over_hash_type,
reason = "modeling command uses a HashMap and keys are random, so we don't really have a choice"
)]
for (resp_id, batch_response) in responses { for (resp_id, batch_response) in responses {
let id: uuid::Uuid = (*resp_id).into(); let id: uuid::Uuid = (*resp_id).into();
match batch_response { match batch_response {

View File

@ -463,6 +463,10 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
responses: HashMap<uuid::Uuid, BatchResponse>, responses: HashMap<uuid::Uuid, BatchResponse>,
) -> Result<OkWebSocketResponseData, crate::errors::KclError> { ) -> Result<OkWebSocketResponseData, crate::errors::KclError> {
// Iterate over the responses and check for errors. // Iterate over the responses and check for errors.
#[expect(
clippy::iter_over_hash_type,
reason = "modeling command uses a HashMap and keys are random, so we don't really have a choice"
)]
for (cmd_id, resp) in responses.iter() { for (cmd_id, resp) in responses.iter() {
match resp { match resp {
BatchResponse::Success { response } => { BatchResponse::Success { response } => {

View File

@ -1,9 +1,6 @@
//! The executor for the AST. //! The executor for the AST.
use std::{ use std::{collections::HashSet, sync::Arc};
collections::{HashMap, HashSet},
sync::Arc,
};
use anyhow::Result; use anyhow::Result;
use async_recursion::async_recursion; use async_recursion::async_recursion;
@ -193,7 +190,7 @@ impl EnvironmentRef {
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
pub struct Environment { pub struct Environment {
bindings: HashMap<String, KclValue>, bindings: IndexMap<String, KclValue>,
parent: Option<EnvironmentRef>, parent: Option<EnvironmentRef>,
} }
@ -203,7 +200,7 @@ impl Environment {
pub fn root() -> Self { pub fn root() -> Self {
Self { Self {
// Prelude // Prelude
bindings: HashMap::from([ bindings: IndexMap::from([
("ZERO".to_string(), KclValue::from_number(0.0, NO_META)), ("ZERO".to_string(), KclValue::from_number(0.0, NO_META)),
("QUARTER_TURN".to_string(), KclValue::from_number(90.0, NO_META)), ("QUARTER_TURN".to_string(), KclValue::from_number(90.0, NO_META)),
("HALF_TURN".to_string(), KclValue::from_number(180.0, NO_META)), ("HALF_TURN".to_string(), KclValue::from_number(180.0, NO_META)),
@ -215,7 +212,7 @@ impl Environment {
pub fn new(parent: EnvironmentRef) -> Self { pub fn new(parent: EnvironmentRef) -> Self {
Self { Self {
bindings: HashMap::new(), bindings: IndexMap::new(),
parent: Some(parent), parent: Some(parent),
} }
} }
@ -770,8 +767,8 @@ pub struct Sketch {
/// The starting path. /// The starting path.
pub start: BasePath, pub start: BasePath,
/// Tag identifiers that have been declared in this sketch. /// Tag identifiers that have been declared in this sketch.
#[serde(default, skip_serializing_if = "HashMap::is_empty")] #[serde(default, skip_serializing_if = "IndexMap::is_empty")]
pub tags: HashMap<String, TagIdentifier>, pub tags: IndexMap<String, TagIdentifier>,
/// The original id of the sketch. This stays the same even if the sketch is /// The original id of the sketch. This stays the same even if the sketch is
/// is sketched on face etc. /// is sketched on face etc.
#[serde(skip)] #[serde(skip)]

View File

@ -25,11 +25,10 @@ pub mod types;
pub mod units; pub mod units;
pub mod utils; pub mod utils;
use std::collections::HashMap;
use anyhow::Result; use anyhow::Result;
pub use args::Args; pub use args::Args;
use derive_docs::stdlib; use derive_docs::stdlib;
use indexmap::IndexMap;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use parse_display::{Display, FromStr}; use parse_display::{Display, FromStr};
use schemars::JsonSchema; use schemars::JsonSchema;
@ -167,8 +166,8 @@ pub fn get_stdlib_fn(name: &str) -> Option<Box<dyn StdLibFn>> {
} }
pub struct StdLib { pub struct StdLib {
pub fns: HashMap<String, Box<dyn StdLibFn>>, pub fns: IndexMap<String, Box<dyn StdLibFn>>,
pub kcl_fns: HashMap<String, Box<dyn KclStdLibFn>>, pub kcl_fns: IndexMap<String, Box<dyn KclStdLibFn>>,
} }
impl std::fmt::Debug for StdLib { impl std::fmt::Debug for StdLib {
@ -198,7 +197,7 @@ impl StdLib {
} }
// Get the combined hashmaps. // Get the combined hashmaps.
pub fn combined(&self) -> HashMap<String, Box<dyn StdLibFn>> { pub fn combined(&self) -> IndexMap<String, Box<dyn StdLibFn>> {
let mut combined = self.fns.clone(); let mut combined = self.fns.clone();
for (k, v) in self.kcl_fns.clone() { for (k, v) in self.kcl_fns.clone() {
combined.insert(k, v.std_lib()); combined.insert(k, v.std_lib());

View File

@ -1,9 +1,8 @@
//! Functions related to sketching. //! Functions related to sketching.
use std::collections::HashMap;
use anyhow::Result; use anyhow::Result;
use derive_docs::stdlib; use derive_docs::stdlib;
use indexmap::IndexMap;
use kcmc::shared::Point2d as KPoint2d; // Point2d is already defined in this pkg, to impl ts_rs traits. use kcmc::shared::Point2d as KPoint2d; // Point2d is already defined in this pkg, to impl ts_rs traits.
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, ModelingCmd}; use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, ModelingCmd};
use kittycad_modeling_cmds as kcmc; use kittycad_modeling_cmds as kcmc;
@ -1301,7 +1300,7 @@ pub(crate) async fn inner_start_profile_at(
}), }),
surface: None, surface: None,
}); });
HashMap::from([(tag.name.to_string(), tag_identifier)]) IndexMap::from([(tag.name.to_string(), tag_identifier)])
} else { } else {
Default::default() Default::default()
}, },