diff --git a/Cargo.lock b/Cargo.lock index 07ed7a93c77ab..d55ef8772ca00 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1572,6 +1572,7 @@ version = "0.30.0" dependencies = [ "miette", "owo-colors", + "rustc-hash", "textwrap", "unicode-width", ] @@ -1796,6 +1797,7 @@ dependencies = [ "oxc_span", "oxc_syntax", "pico-args", + "rustc-hash", ] [[package]] diff --git a/crates/oxc_diagnostics/Cargo.toml b/crates/oxc_diagnostics/Cargo.toml index 71b8032778847..e294b504d1ecc 100644 --- a/crates/oxc_diagnostics/Cargo.toml +++ b/crates/oxc_diagnostics/Cargo.toml @@ -22,5 +22,6 @@ doctest = false miette = { workspace = true } owo-colors = { workspace = true } +rustc-hash = { workspace = true } textwrap = { workspace = true } unicode-width = { workspace = true } diff --git a/crates/oxc_diagnostics/src/reporter/checkstyle.rs b/crates/oxc_diagnostics/src/reporter/checkstyle.rs index 957b16491a196..9ecbf4cc3e8bc 100644 --- a/crates/oxc_diagnostics/src/reporter/checkstyle.rs +++ b/crates/oxc_diagnostics/src/reporter/checkstyle.rs @@ -1,7 +1,8 @@ -use std::{borrow::Cow, collections::HashMap}; +use std::borrow::Cow; use super::{DiagnosticReporter, Info}; use crate::{Error, Severity}; +use rustc_hash::FxHashMap; #[derive(Default)] pub struct CheckstyleReporter { @@ -24,7 +25,7 @@ impl DiagnosticReporter for CheckstyleReporter { #[allow(clippy::print_stdout)] fn format_checkstyle(diagnostics: &[Error]) { let infos = diagnostics.iter().map(Info::new).collect::>(); - let mut grouped: HashMap> = HashMap::new(); + let mut grouped: FxHashMap> = FxHashMap::default(); for info in infos { grouped.entry(info.filename.clone()).or_default().push(info); } diff --git a/crates/oxc_linter/src/rules/eslint/no_this_before_super.rs b/crates/oxc_linter/src/rules/eslint/no_this_before_super.rs index c8c51f5ea8be4..519826ebb5a78 100644 --- a/crates/oxc_linter/src/rules/eslint/no_this_before_super.rs +++ b/crates/oxc_linter/src/rules/eslint/no_this_before_super.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use oxc_ast::{ ast::{Argument, Expression, MethodDefinitionKind}, @@ -12,6 +12,7 @@ use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::NodeId; use oxc_span::{GetSpan, Span}; +use rustc_hash::FxHashMap; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -62,7 +63,8 @@ impl Rule for NoThisBeforeSuper { // first pass -> find super calls and local violations let mut wanted_nodes = Vec::new(); let mut basic_blocks_with_super_called = HashSet::::new(); - let mut basic_blocks_with_local_violations = HashMap::>::new(); + let mut basic_blocks_with_local_violations = + FxHashMap::>::default(); for node in semantic.nodes() { match node.kind() { AstKind::Function(_) | AstKind::ArrowFunctionExpression(_) => { @@ -153,7 +155,7 @@ impl NoThisBeforeSuper { cfg: &ControlFlowGraph, id: BasicBlockId, basic_blocks_with_super_called: &HashSet, - basic_blocks_with_local_violations: &HashMap>, + basic_blocks_with_local_violations: &FxHashMap>, follow_join: bool, ) -> Vec { neighbors_filtered_by_edge_weight( @@ -212,7 +214,7 @@ impl NoThisBeforeSuper { cfg: &ControlFlowGraph, output: Vec, basic_blocks_with_super_called: &HashSet, - basic_blocks_with_local_violations: &HashMap>, + basic_blocks_with_local_violations: &FxHashMap>, ) -> bool { // Deciding whether we definitely call this before super in all // codepaths is as simple as seeing if any individual codepath diff --git a/crates/oxc_linter/src/rules/jest/no_confusing_set_timeout.rs b/crates/oxc_linter/src/rules/jest/no_confusing_set_timeout.rs index dad249f04d2a8..cd185ff0d8e22 100644 --- a/crates/oxc_linter/src/rules/jest/no_confusing_set_timeout.rs +++ b/crates/oxc_linter/src/rules/jest/no_confusing_set_timeout.rs @@ -1,11 +1,10 @@ -use std::collections::HashMap; - use cow_utils::CowUtils; use oxc_ast::{ast::MemberExpression, AstKind}; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::{AstNode, NodeId, ReferenceId}; use oxc_span::{GetSpan, Span}; +use rustc_hash::FxHashMap; use crate::{ context::LintContext, @@ -80,10 +79,11 @@ impl Rule for NoConfusingSetTimeout { let scopes = ctx.scopes(); let symbol_table = ctx.symbols(); let possible_nodes = collect_possible_jest_call_node(ctx); - let id_to_jest_node_map = possible_nodes.iter().fold(HashMap::new(), |mut acc, cur| { - acc.insert(cur.node.id(), cur); - acc - }); + let id_to_jest_node_map = + possible_nodes.iter().fold(FxHashMap::default(), |mut acc, cur| { + acc.insert(cur.node.id(), cur); + acc + }); let mut jest_reference_id_list: Vec<(ReferenceId, Span)> = vec![]; let mut seen_jest_set_timeout = false; @@ -151,7 +151,7 @@ fn handle_jest_set_time_out<'a>( reference_id_list: impl Iterator, jest_reference_id_list: &Vec<(ReferenceId, Span)>, seen_jest_set_timeout: &mut bool, - id_to_jest_node_map: &HashMap>, + id_to_jest_node_map: &FxHashMap>, ) { let nodes = ctx.nodes(); let scopes = ctx.scopes(); @@ -199,7 +199,7 @@ fn handle_jest_set_time_out<'a>( fn is_jest_fn_call<'a>( parent_node: &AstNode<'a>, - id_to_jest_node_map: &HashMap>, + id_to_jest_node_map: &FxHashMap>, ctx: &LintContext<'a>, ) -> bool { let mut id = parent_node.id(); diff --git a/crates/oxc_linter/src/rules/jest/no_duplicate_hooks.rs b/crates/oxc_linter/src/rules/jest/no_duplicate_hooks.rs index d39f5ca92b60c..927f9d2f280a0 100644 --- a/crates/oxc_linter/src/rules/jest/no_duplicate_hooks.rs +++ b/crates/oxc_linter/src/rules/jest/no_duplicate_hooks.rs @@ -1,10 +1,9 @@ -use std::collections::HashMap; - use oxc_ast::AstKind; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::NodeId; use oxc_span::Span; +use rustc_hash::FxHashMap; use crate::{ context::LintContext, @@ -104,7 +103,8 @@ impl Rule for NoDuplicateHooks { let Some(root_node) = ctx.nodes().root_node() else { return; }; - let mut hook_contexts: HashMap>> = HashMap::new(); + let mut hook_contexts: FxHashMap>> = + FxHashMap::default(); hook_contexts.insert(root_node.id(), Vec::new()); let mut possibles_jest_nodes = collect_possible_jest_call_node(ctx); @@ -120,7 +120,7 @@ impl NoDuplicateHooks { fn run<'a>( possible_jest_node: &PossibleJestNode<'a, '_>, root_node_id: NodeId, - hook_contexts: &mut HashMap>>, + hook_contexts: &mut FxHashMap>>, ctx: &LintContext<'a>, ) { let node = possible_jest_node.node; @@ -157,7 +157,7 @@ impl NoDuplicateHooks { let last_context = if let Some(val) = contexts.last_mut() { Some(val) } else { - let mut context = HashMap::new(); + let mut context = FxHashMap::default(); context.insert(hook_name.clone(), 0); contexts.push(context); contexts.last_mut() diff --git a/crates/oxc_linter/src/rules/jest/no_identical_title.rs b/crates/oxc_linter/src/rules/jest/no_identical_title.rs index 8a7a812502fb1..5a91f89d4d5c2 100644 --- a/crates/oxc_linter/src/rules/jest/no_identical_title.rs +++ b/crates/oxc_linter/src/rules/jest/no_identical_title.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use oxc_ast::{ ast::{Argument, CallExpression}, AstKind, @@ -8,6 +6,7 @@ use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::NodeId; use oxc_span::Span; +use rustc_hash::FxHashMap; use crate::{ context::LintContext, @@ -74,8 +73,8 @@ declare_oxc_lint!( impl Rule for NoIdenticalTitle { fn run_once(&self, ctx: &LintContext) { let possible_jest_nodes = collect_possible_jest_call_node(ctx); - let mut title_to_span_mapping = HashMap::new(); - let mut span_to_parent_mapping = HashMap::new(); + let mut title_to_span_mapping = FxHashMap::default(); + let mut span_to_parent_mapping = FxHashMap::default(); possible_jest_nodes .iter() diff --git a/crates/oxc_linter/src/rules/jest/no_standalone_expect.rs b/crates/oxc_linter/src/rules/jest/no_standalone_expect.rs index f189f1d99bfd1..01b682b744f54 100644 --- a/crates/oxc_linter/src/rules/jest/no_standalone_expect.rs +++ b/crates/oxc_linter/src/rules/jest/no_standalone_expect.rs @@ -1,10 +1,9 @@ -use std::collections::HashMap; - use oxc_ast::AstKind; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::NodeId; use oxc_span::Span; +use rustc_hash::FxHashMap; use crate::{ context::LintContext, @@ -76,10 +75,11 @@ impl Rule for NoStandaloneExpect { fn run_once(&self, ctx: &LintContext<'_>) { let possible_jest_nodes = collect_possible_jest_call_node(ctx); - let id_nodes_mapping = possible_jest_nodes.iter().fold(HashMap::new(), |mut acc, cur| { - acc.entry(cur.node.id()).or_insert(cur); - acc - }); + let id_nodes_mapping = + possible_jest_nodes.iter().fold(FxHashMap::default(), |mut acc, cur| { + acc.entry(cur.node.id()).or_insert(cur); + acc + }); for possible_jest_node in &possible_jest_nodes { self.run(possible_jest_node, &id_nodes_mapping, ctx); @@ -91,7 +91,7 @@ impl NoStandaloneExpect { fn run<'a>( &self, possible_jest_node: &PossibleJestNode<'a, '_>, - id_nodes_mapping: &HashMap>, + id_nodes_mapping: &FxHashMap>, ctx: &LintContext<'a>, ) { let node = possible_jest_node.node; @@ -129,7 +129,7 @@ impl NoStandaloneExpect { fn is_correct_place_to_call_expect<'a>( node: &AstNode<'a>, additional_test_block_functions: &[String], - id_nodes_mapping: &HashMap>, + id_nodes_mapping: &FxHashMap>, ctx: &LintContext<'a>, ) -> Option<()> { let mut parent = ctx.nodes().parent_node(node.id())?; @@ -197,7 +197,7 @@ fn is_correct_place_to_call_expect<'a>( fn is_var_declarator_or_test_block<'a>( node: &AstNode<'a>, additional_test_block_functions: &[String], - id_nodes_mapping: &HashMap>, + id_nodes_mapping: &FxHashMap>, ctx: &LintContext<'a>, ) -> bool { match node.kind() { diff --git a/crates/oxc_linter/src/rules/jest/prefer_hooks_on_top.rs b/crates/oxc_linter/src/rules/jest/prefer_hooks_on_top.rs index b236687d27ea6..894deb8dc7dfc 100644 --- a/crates/oxc_linter/src/rules/jest/prefer_hooks_on_top.rs +++ b/crates/oxc_linter/src/rules/jest/prefer_hooks_on_top.rs @@ -1,10 +1,9 @@ -use std::collections::HashMap; - use oxc_ast::AstKind; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::ScopeId; use oxc_span::Span; +use rustc_hash::FxHashMap; use crate::{ context::LintContext, @@ -141,7 +140,7 @@ declare_oxc_lint!( impl Rule for PreferHooksOnTop { fn run_once(&self, ctx: &LintContext) { - let mut hooks_contexts: HashMap = HashMap::default(); + let mut hooks_contexts: FxHashMap = FxHashMap::default(); let mut possibles_jest_nodes = collect_possible_jest_call_node(ctx); possibles_jest_nodes.sort_by_key(|n| n.node.id()); @@ -154,7 +153,7 @@ impl Rule for PreferHooksOnTop { impl PreferHooksOnTop { fn run<'a>( possible_jest_node: &PossibleJestNode<'a, '_>, - hooks_context: &mut HashMap, + hooks_context: &mut FxHashMap, ctx: &LintContext<'a>, ) { let node = possible_jest_node.node; diff --git a/crates/oxc_linter/src/rules/jest/require_top_level_describe.rs b/crates/oxc_linter/src/rules/jest/require_top_level_describe.rs index d3a1be13ea367..b2310ea8ef917 100644 --- a/crates/oxc_linter/src/rules/jest/require_top_level_describe.rs +++ b/crates/oxc_linter/src/rules/jest/require_top_level_describe.rs @@ -1,10 +1,9 @@ -use std::collections::HashMap; - use oxc_ast::AstKind; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::ScopeId; use oxc_span::Span; +use rustc_hash::FxHashMap; use crate::{ context::LintContext, @@ -123,7 +122,7 @@ impl Rule for RequireTopLevelDescribe { } fn run_once(&self, ctx: &LintContext) { - let mut describe_contexts: HashMap = HashMap::new(); + let mut describe_contexts: FxHashMap = FxHashMap::default(); let mut possibles_jest_nodes = collect_possible_jest_call_node(ctx); possibles_jest_nodes.sort_by_key(|n| n.node.id()); @@ -137,7 +136,7 @@ impl RequireTopLevelDescribe { fn run<'a>( &self, possible_jest_node: &PossibleJestNode<'a, '_>, - describe_contexts: &mut HashMap, + describe_contexts: &mut FxHashMap, ctx: &LintContext<'a>, ) { let node = possible_jest_node.node; diff --git a/crates/oxc_linter/src/rules/jest/valid_title.rs b/crates/oxc_linter/src/rules/jest/valid_title.rs index 3ae406d804d28..36fafee306807 100644 --- a/crates/oxc_linter/src/rules/jest/valid_title.rs +++ b/crates/oxc_linter/src/rules/jest/valid_title.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, hash::Hash}; +use std::hash::Hash; use cow_utils::CowUtils; use oxc_ast::{ @@ -9,6 +9,7 @@ use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_span::{GetSpan, Span}; use regex::Regex; +use rustc_hash::FxHashMap; use crate::{ context::LintContext, @@ -31,8 +32,8 @@ pub struct ValidTitleConfig { ignore_type_of_describe_name: bool, disallowed_words: Vec, ignore_space: bool, - must_not_match_patterns: HashMap, - must_match_patterns: HashMap, + must_not_match_patterns: FxHashMap, + must_match_patterns: FxHashMap, } impl std::ops::Deref for ValidTitle { @@ -206,14 +207,14 @@ impl MatchKind { fn compile_matcher_patterns( matcher_patterns: &serde_json::Value, -) -> Option> { +) -> Option> { matcher_patterns .as_array() .map_or_else( || { // for `{ "describe": "/pattern/" }` let obj = matcher_patterns.as_object()?; - let mut map: HashMap = HashMap::new(); + let mut map: FxHashMap = FxHashMap::default(); for (key, value) in obj { let Some(v) = compile_matcher_pattern(MatcherPattern::String(value)) else { continue; @@ -227,7 +228,7 @@ fn compile_matcher_patterns( }, |value| { // for `["/pattern/", "message"]` - let mut map: HashMap = HashMap::new(); + let mut map: FxHashMap = FxHashMap::default(); let v = &compile_matcher_pattern(MatcherPattern::Vec(value))?; map.insert(MatchKind::Describe, v.clone()); map.insert(MatchKind::Test, v.clone()); @@ -239,7 +240,7 @@ fn compile_matcher_patterns( || { // for `"/pattern/"` let string = matcher_patterns.as_str()?; - let mut map: HashMap = HashMap::new(); + let mut map: FxHashMap = FxHashMap::default(); let v = &compile_matcher_pattern(MatcherPattern::String( &serde_json::Value::String(string.to_string()), ))?; diff --git a/crates/oxc_linter/src/rules/react/no_unknown_property.rs b/crates/oxc_linter/src/rules/react/no_unknown_property.rs index e84a906493020..4d82851717935 100644 --- a/crates/oxc_linter/src/rules/react/no_unknown_property.rs +++ b/crates/oxc_linter/src/rules/react/no_unknown_property.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, collections::hash_map::HashMap}; +use std::borrow::Cow; use cow_utils::CowUtils; use itertools::Itertools; @@ -12,7 +12,7 @@ use oxc_macros::declare_oxc_lint; use oxc_span::{GetSpan, Span}; use phf::{phf_map, phf_set, Map, Set}; use regex::Regex; -use rustc_hash::FxHashSet; +use rustc_hash::{FxHashMap, FxHashSet}; use serde::Deserialize; use crate::{ @@ -426,11 +426,11 @@ const DOM_PROPERTIES_IGNORE_CASE: [&str; 5] = [ "webkitDirectory", ]; -static DOM_PROPERTIES_LOWER_MAP: Lazy> = Lazy::new(|| { +static DOM_PROPERTIES_LOWER_MAP: Lazy> = Lazy::new(|| { DOM_PROPERTIES_NAMES .iter() .map(|it| (it.cow_to_lowercase().into_owned(), *it)) - .collect::>() + .collect::>() }); /// diff --git a/crates/oxc_linter/src/rules/typescript/triple_slash_reference.rs b/crates/oxc_linter/src/rules/typescript/triple_slash_reference.rs index 4a358d59dbedf..509bd9217a75e 100644 --- a/crates/oxc_linter/src/rules/typescript/triple_slash_reference.rs +++ b/crates/oxc_linter/src/rules/typescript/triple_slash_reference.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use oxc_ast::{ ast::{Statement, TSModuleReference}, AstKind, @@ -7,6 +5,7 @@ use oxc_ast::{ use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_span::{GetSpan, Span}; +use rustc_hash::FxHashMap; use crate::{ context::{ContextHost, LintContext}, @@ -113,7 +112,7 @@ impl Rule for TripleSlashReference { // We don't need to iterate over all comments since Triple-slash directives are only valid at the top of their containing file. // We are trying to get the first statement start potioin, falling back to the program end if statement does not exist let comments_range_end = program.body.first().map_or(program.span.end, |v| v.span().start); - let mut refs_for_import = HashMap::new(); + let mut refs_for_import = FxHashMap::default(); for comment in ctx.semantic().trivias().comments_range(0..comments_range_end) { let raw = &ctx.semantic().source_text() diff --git a/crates/oxc_linter/src/service.rs b/crates/oxc_linter/src/service.rs index ef02958a467f2..297911c05762b 100644 --- a/crates/oxc_linter/src/service.rs +++ b/crates/oxc_linter/src/service.rs @@ -1,5 +1,4 @@ use std::{ - collections::HashMap, ffi::OsStr, fs, path::{Path, PathBuf}, @@ -15,7 +14,7 @@ use oxc_resolver::Resolver; use oxc_semantic::{ModuleRecord, SemanticBuilder}; use oxc_span::{SourceType, VALID_EXTENSIONS}; use rayon::{iter::ParallelBridge, prelude::ParallelIterator}; -use rustc_hash::FxHashSet; +use rustc_hash::{FxHashMap, FxHashSet}; use crate::{ partial_loader::{JavaScriptSource, PartialLoader, LINT_PARTIAL_LOADER_EXT}, @@ -145,7 +144,7 @@ impl LintService { /// /// See the "problem section" in /// and the solution is copied here to fix the issue. -type CacheState = Mutex, Arc<(Mutex, Condvar)>>>; +type CacheState = Mutex, Arc<(Mutex, Condvar)>>>; #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum CacheStateEntry { diff --git a/crates/oxc_prettier/Cargo.toml b/crates/oxc_prettier/Cargo.toml index abd88c72ef9c9..4c004f4020ff8 100644 --- a/crates/oxc_prettier/Cargo.toml +++ b/crates/oxc_prettier/Cargo.toml @@ -27,6 +27,7 @@ oxc_syntax = { workspace = true } bitflags = { workspace = true } cow-utils = { workspace = true } +rustc-hash = { workspace = true } [dev-dependencies] oxc_parser = { workspace = true } diff --git a/crates/oxc_prettier/src/printer/mod.rs b/crates/oxc_prettier/src/printer/mod.rs index 93ab90f740a9b..d3103cbfe1e10 100644 --- a/crates/oxc_prettier/src/printer/mod.rs +++ b/crates/oxc_prettier/src/printer/mod.rs @@ -5,9 +5,10 @@ mod command; -use std::collections::{HashMap, VecDeque}; +use std::collections::VecDeque; use oxc_allocator::Allocator; +use rustc_hash::FxHashMap; use self::command::{Command, Indent, Mode}; use crate::{ @@ -27,7 +28,7 @@ pub struct Printer<'a> { cmds: Vec>, line_suffix: Vec>, - group_mode_map: HashMap, + group_mode_map: FxHashMap, // states new_line: &'static str, @@ -59,7 +60,7 @@ impl<'a> Printer<'a> { pos: 0, cmds, line_suffix: vec![], - group_mode_map: HashMap::new(), + group_mode_map: FxHashMap::default(), new_line: options.end_of_line.as_str(), allocator, } diff --git a/crates/oxc_semantic/examples/cfg.rs b/crates/oxc_semantic/examples/cfg.rs index 4cfe951170319..2beeae7b3cdee 100644 --- a/crates/oxc_semantic/examples/cfg.rs +++ b/crates/oxc_semantic/examples/cfg.rs @@ -1,5 +1,5 @@ #![allow(clippy::print_stdout)] -use std::{collections::HashMap, env, path::Path, sync::Arc}; +use std::{env, path::Path, sync::Arc}; use itertools::Itertools; use oxc_allocator::Allocator; @@ -13,6 +13,7 @@ use oxc_cfg::{ use oxc_parser::Parser; use oxc_semantic::{dot::DebugDot, SemanticBuilder}; use oxc_span::SourceType; +use rustc_hash::FxHashMap; // Instruction: // 1. create a `test.js`, @@ -76,7 +77,7 @@ fn main() -> std::io::Result<()> { .cfg() .expect("we set semantic to build the control flow (`with_cfg`) for us so it should always be `Some`"); - let mut ast_nodes_by_block = HashMap::<_, Vec<_>>::new(); + let mut ast_nodes_by_block = FxHashMap::<_, Vec<_>>::default(); for node in semantic.semantic.nodes() { let block = node.cfg_id(); let block_ix = cfg.graph.node_weight(block).unwrap();