From 7475a0a02d34b2dcae46d18e146e414df7637ad6 Mon Sep 17 00:00:00 2001 From: "Arend van Beelen jr." Date: Tue, 19 Aug 2025 11:38:18 +0200 Subject: [PATCH 1/2] fix(core): resolve issue with rest params in type inference --- .changeset/resting-rhinos-reverberate.md | 5 + crates/biome_js_analyze/src/services/typed.rs | 2 +- .../biome_js_type_info/src/local_inference.rs | 59 +++- crates/biome_js_type_info/src/type_data.rs | 3 + crates/biome_js_type_info/src/type_store.rs | 6 +- .../benches/module_graph.rs | 9 +- .../biome_module_graph/src/js_module_info.rs | 12 +- .../src/js_module_info/collector.rs | 36 ++- .../src/js_module_info/module_resolver.rs | 1 - .../fixtures/RedisCommander_stripped.d.ts | 197 ++++++++++++ ...export_type_referencing_imported_type.snap | 10 +- ...ction_returning_imported_promise_type.snap | 10 +- ...ion_returning_reexported_promise_type.snap | 10 +- .../test_resolve_recursive_looking_vfile.snap | 302 ++++++++---------- ...d_field_of_intersection_of_interfaces.snap | 120 ++++--- ..._resolve_type_of_this_in_class_assign.snap | 54 ++-- ..._resolve_type_of_this_in_class_export.snap | 42 +-- ...t_resolve_type_of_this_in_class_plain.snap | 42 +-- .../test_resolve_type_of_this_in_object.snap | 50 +-- crates/biome_module_graph/tests/spec_tests.rs | 47 ++- 20 files changed, 633 insertions(+), 384 deletions(-) create mode 100644 .changeset/resting-rhinos-reverberate.md create mode 100644 crates/biome_module_graph/tests/fixtures/RedisCommander_stripped.d.ts diff --git a/.changeset/resting-rhinos-reverberate.md b/.changeset/resting-rhinos-reverberate.md new file mode 100644 index 000000000000..83e2b67c246c --- /dev/null +++ b/.changeset/resting-rhinos-reverberate.md @@ -0,0 +1,5 @@ +--- +"@biomejs/biome": patch +--- + +Fixed [#6172](https://github.com/biomejs/biome/issues/6172): Resolved an issue with infering types for rest arguments. This issue caused the types of rest arguments to be incorrect and also caused sometimes extreme performance regressions in files that contained many methods with rest argument definitions. diff --git a/crates/biome_js_analyze/src/services/typed.rs b/crates/biome_js_analyze/src/services/typed.rs index 2205ec83f7b7..b1415327152d 100644 --- a/crates/biome_js_analyze/src/services/typed.rs +++ b/crates/biome_js_analyze/src/services/typed.rs @@ -14,7 +14,7 @@ use std::sync::Arc; /// /// This service is used for retrieving [`Type`] instances for arbitrary /// expressions or function definitions from the module graph. -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct TypedService { resolver: Option>, } diff --git a/crates/biome_js_type_info/src/local_inference.rs b/crates/biome_js_type_info/src/local_inference.rs index 9f4f0b7ac814..b031c21686ba 100644 --- a/crates/biome_js_type_info/src/local_inference.rs +++ b/crates/biome_js_type_info/src/local_inference.rs @@ -15,12 +15,12 @@ use biome_js_syntax::{ JsFunctionDeclaration, JsFunctionExpression, JsGetterObjectMember, JsInitializerClause, JsLogicalExpression, JsLogicalOperator, JsMethodObjectMember, JsNewExpression, JsObjectBindingPattern, JsObjectExpression, JsParameters, JsPropertyClassMember, - JsPropertyObjectMember, JsReferenceIdentifier, JsReturnStatement, JsSetterObjectMember, - JsSyntaxNode, JsSyntaxToken, JsUnaryExpression, JsUnaryOperator, JsVariableDeclaration, - JsVariableDeclarator, TsDeclareFunctionDeclaration, TsExternalModuleDeclaration, - TsInterfaceDeclaration, TsModuleDeclaration, TsReferenceType, TsReturnTypeAnnotation, - TsTypeAliasDeclaration, TsTypeAnnotation, TsTypeArguments, TsTypeList, TsTypeParameter, - TsTypeParameters, TsTypeofType, inner_string_text, unescape_js_string, + JsPropertyObjectMember, JsReferenceIdentifier, JsRestParameter, JsReturnStatement, + JsSetterObjectMember, JsSyntaxNode, JsSyntaxToken, JsUnaryExpression, JsUnaryOperator, + JsVariableDeclaration, JsVariableDeclarator, TsDeclareFunctionDeclaration, + TsExternalModuleDeclaration, TsInterfaceDeclaration, TsModuleDeclaration, TsReferenceType, + TsReturnTypeAnnotation, TsTypeAliasDeclaration, TsTypeAnnotation, TsTypeArguments, TsTypeList, + TsTypeParameter, TsTypeParameters, TsTypeofType, inner_string_text, unescape_js_string, }; use biome_rowan::{AstNode, SyntaxResult, Text, TokenText}; @@ -833,6 +833,7 @@ impl TypeData { name, ty: TypeReference::unknown(), is_optional: false, + is_rest: false, })]) } Ok(AnyJsArrowFunctionParameters::JsParameters(params)) => { @@ -1507,6 +1508,7 @@ impl FunctionParameter { .map(|ty| TypeReference::from_any_ts_type(resolver, scope_id, &ty)) .unwrap_or_default(), is_optional: false, + is_rest: false, }), } } @@ -1534,6 +1536,7 @@ impl FunctionParameter { name, ty: resolver.reference_to_owned_data(ty), is_optional: param.question_mark_token().is_some(), + is_rest: false, }) } else { let bindings = param @@ -1554,6 +1557,50 @@ impl FunctionParameter { } } + pub fn from_js_rest_parameter( + resolver: &mut dyn TypeResolver, + scope_id: ScopeId, + param: &JsRestParameter, + ) -> Self { + let name = param + .binding() + .ok() + .as_ref() + .and_then(|binding| binding.as_any_js_binding()) + .and_then(|binding| binding.as_js_identifier_binding()) + .and_then(|identifier| identifier.name_token().ok()) + .map(|token| token.token_text_trimmed().into()); + let ty = param + .type_annotation() + .and_then(|annotation| annotation.ty().ok()) + .map(|ty| TypeData::from_any_ts_type(resolver, scope_id, &ty)) + .unwrap_or_default(); + if let Some(name) = name { + Self::Named(NamedFunctionParameter { + name, + ty: resolver.reference_to_owned_data(ty), + is_optional: false, + is_rest: true, + }) + } else { + let bindings = param + .binding() + .ok() + .and_then(|binding| { + FunctionParameterBinding::bindings_from_any_js_binding_pattern_of_type( + resolver, scope_id, &binding, &ty, + ) + }) + .unwrap_or_default(); + Self::Pattern(PatternFunctionParameter { + bindings, + ty: resolver.reference_to_owned_data(ty), + is_optional: false, + is_rest: true, + }) + } + } + pub fn params_from_js_parameters( resolver: &mut dyn TypeResolver, scope_id: ScopeId, diff --git a/crates/biome_js_type_info/src/type_data.rs b/crates/biome_js_type_info/src/type_data.rs index 8515d2f3584d..010e24487366 100644 --- a/crates/biome_js_type_info/src/type_data.rs +++ b/crates/biome_js_type_info/src/type_data.rs @@ -556,6 +556,9 @@ pub struct NamedFunctionParameter { /// Whether the parameter is optional or not. pub is_optional: bool, + + /// Whether this is a rest parameter (`...`) or not. + pub is_rest: bool, } /// A function parameter that is bound to either one or more positional diff --git a/crates/biome_js_type_info/src/type_store.rs b/crates/biome_js_type_info/src/type_store.rs index 4b452dbfcbdb..43355895577d 100644 --- a/crates/biome_js_type_info/src/type_store.rs +++ b/crates/biome_js_type_info/src/type_store.rs @@ -25,7 +25,7 @@ use crate::{Resolvable, ResolvedTypeId, TypeData, TypeId, TypeReference, TypeRes /// some amount of deduplication is preferred. The reason for this is that type /// flattening can reduce disjoint types to the same type, at which point we /// store both to preserve their indices. -#[derive(Debug, Default)] +#[derive(Default)] pub struct TypeStore { types: Vec>, table: HashTable, @@ -254,9 +254,9 @@ impl TypeStore { } } -impl From for Box<[Arc]> { +impl From for Vec> { fn from(store: TypeStore) -> Self { - store.types.into() + store.types } } diff --git a/crates/biome_module_graph/benches/module_graph.rs b/crates/biome_module_graph/benches/module_graph.rs index f8c596d6d67b..4e4f03acdadf 100644 --- a/crates/biome_module_graph/benches/module_graph.rs +++ b/crates/biome_module_graph/benches/module_graph.rs @@ -37,11 +37,10 @@ const INDEX_D_TS_CASES: &[(&str, &[u8])] = &[ "@next/font/google/index.d.ts", include_bytes!("./next_font_google.d.ts") as &[u8], ), - // FIXME: enable it once the perf reaches a decent number - // ( - // "RedisCommander.d.ts", - // include_bytes!("./RedisCommander.d.ts") as &[u8], - // ) + ( + "RedisCommander.d.ts", + include_bytes!("./RedisCommander.d.ts") as &[u8], + ), ]; fn index_d_ts_cases() -> impl Iterator { diff --git a/crates/biome_module_graph/src/js_module_info.rs b/crates/biome_module_graph/src/js_module_info.rs index 3112d555a4d2..4723465f96e9 100644 --- a/crates/biome_module_graph/src/js_module_info.rs +++ b/crates/biome_module_graph/src/js_module_info.rs @@ -174,10 +174,10 @@ pub struct JsModuleInfoInner { /// Re-exports that apply to all symbols from another module, without /// assigning a name to them. - pub blanket_reexports: Box<[JsReexport]>, + pub blanket_reexports: Vec, /// Collection of all the declarations in the module. - pub(crate) bindings: Box<[JsBindingData]>, + pub(crate) bindings: Vec, /// Parsed expressions, mapped from their range to their type ID. pub(crate) expressions: FxHashMap, @@ -185,13 +185,17 @@ pub struct JsModuleInfoInner { /// All scopes in this module. /// /// The first entry is expected to be the global scope. - pub(crate) scopes: Box<[JsScopeData]>, + pub(crate) scopes: Vec, /// Lookup tree to find scopes by text range. pub(crate) scope_by_range: Lapper, /// Collection of all types in the module. - pub(crate) types: Box<[Arc]>, + /// + /// We do not store these using our `TypeStore`, because once the module + /// info is constructed, no new types can be registered in it, and we have + /// no use for a hash table anymore. + pub(crate) types: Vec>, } #[derive(Debug, Default)] diff --git a/crates/biome_module_graph/src/js_module_info/collector.rs b/crates/biome_module_graph/src/js_module_info/collector.rs index 2fa4693960f4..dcf769da7c9f 100644 --- a/crates/biome_module_graph/src/js_module_info/collector.rs +++ b/crates/biome_module_graph/src/js_module_info/collector.rs @@ -4,8 +4,8 @@ use biome_js_semantic::{SemanticEvent, SemanticEventExtractor}; use biome_js_syntax::{ AnyJsCombinedSpecifier, AnyJsDeclaration, AnyJsExportDefaultDeclaration, AnyJsExpression, AnyJsImportClause, JsForVariableDeclaration, JsFormalParameter, JsIdentifierBinding, - JsSyntaxKind, JsSyntaxNode, JsSyntaxToken, JsVariableDeclaration, TsIdentifierBinding, - TsTypeParameter, TsTypeParameterName, inner_string_text, + JsRestParameter, JsSyntaxKind, JsSyntaxNode, JsSyntaxToken, JsVariableDeclaration, + TsIdentifierBinding, TsTypeParameter, TsTypeParameterName, inner_string_text, }; use biome_js_type_info::{ BindingId, FunctionParameter, GLOBAL_RESOLVER, GLOBAL_UNKNOWN_ID, GenericTypeParameter, @@ -52,8 +52,8 @@ pub(super) struct JsModuleInfoCollector { /// Re-used from the semantic model in `biome_js_semantic`. extractor: SemanticEventExtractor, - /// Formal parameters. - formal_parameters: FxHashMap, + /// Function parameters, both formal parameters as well as rest parameters. + function_parameters: FxHashMap, /// Variable declarations. variable_declarations: FxHashMap>, @@ -174,7 +174,12 @@ impl JsModuleInfoCollector { } else if let Some(param) = JsFormalParameter::cast_ref(node) { let scope_id = *self.scope_stack.last().expect("there must be a scope"); let parsed_param = FunctionParameter::from_js_formal_parameter(self, scope_id, ¶m); - self.formal_parameters + self.function_parameters + .insert(param.syntax().clone(), parsed_param); + } else if let Some(param) = JsRestParameter::cast_ref(node) { + let scope_id = *self.scope_stack.last().expect("there must be a scope"); + let parsed_param = FunctionParameter::from_js_rest_parameter(self, scope_id, ¶m); + self.function_parameters .insert(param.syntax().clone(), parsed_param); } else if let Some(decl) = JsVariableDeclaration::cast_ref(node) { let scope_id = *self.scope_stack.last().expect("there must be a scope"); @@ -543,6 +548,10 @@ impl JsModuleInfoCollector { self.infer_all_types(&scope_by_range); self.resolve_all_and_downgrade_project_references(); + + // Purging before flattening will save us from duplicate work during + // flattening. We'll purge again after for a final cleanup. + self.purge_redundant_types(); self.flatten_all(); self.purge_redundant_types(); @@ -553,13 +562,12 @@ impl JsModuleInfoCollector { fn infer_all_types(&mut self, scope_by_range: &Lapper) { for index in 0..self.bindings.len() { - let binding_id = BindingId::new(index); - let binding = &self.bindings[binding_id.index()]; + let binding = &self.bindings[index]; if let Some(node) = self.binding_node_by_start.get(&binding.range.start()) { let name = binding.name.clone(); let scope_id = scope_id_for_range(scope_by_range, binding.range); let ty = self.infer_type(&node.clone(), &name, scope_id); - self.bindings[binding_id.index()].ty = ty; + self.bindings[index].ty = ty; } } } @@ -596,7 +604,11 @@ impl JsModuleInfoCollector { .find_map(|(name, ty)| (name == binding_name).then(|| ty.clone())) .unwrap_or_default(); } else if let Some(param) = JsFormalParameter::cast_ref(&ancestor) - .and_then(|param| self.formal_parameters.get(param.syntax())) + .and_then(|param| self.function_parameters.get(param.syntax())) + .or_else(|| { + JsRestParameter::cast_ref(&ancestor) + .and_then(|param| self.function_parameters.get(param.syntax())) + }) { return match param { FunctionParameter::Named(named) => named.ty.clone(), @@ -1031,10 +1043,10 @@ impl JsModuleInfo { static_import_paths: collector.static_import_paths, dynamic_import_paths: collector.dynamic_import_paths, exports: Exports(exports), - blanket_reexports: collector.blanket_reexports.into(), - bindings: collector.bindings.into(), + blanket_reexports: collector.blanket_reexports, + bindings: collector.bindings, expressions: collector.parsed_expressions, - scopes: collector.scopes.into(), + scopes: collector.scopes, scope_by_range, types: collector.types.into(), })) diff --git a/crates/biome_module_graph/src/js_module_info/module_resolver.rs b/crates/biome_module_graph/src/js_module_info/module_resolver.rs index 41ce23528250..b3b6ddcff10c 100644 --- a/crates/biome_module_graph/src/js_module_info/module_resolver.rs +++ b/crates/biome_module_graph/src/js_module_info/module_resolver.rs @@ -42,7 +42,6 @@ const MODULE_0_ID: ResolverId = ResolverId::from_level(TypeResolverLevel::Thin); /// statements. /// /// The module resolver is typically consumed through the `Typed` service. -#[derive(Debug)] pub struct ModuleResolver { module_graph: Arc, diff --git a/crates/biome_module_graph/tests/fixtures/RedisCommander_stripped.d.ts b/crates/biome_module_graph/tests/fixtures/RedisCommander_stripped.d.ts new file mode 100644 index 000000000000..07bc32bdb805 --- /dev/null +++ b/crates/biome_module_graph/tests/fixtures/RedisCommander_stripped.d.ts @@ -0,0 +1,197 @@ +/** + * This file is generated by @ioredis/interface-generator. + * Don't edit it manually. Instead, run `npm run generate` to update + * this file. + */ +/// +import { Callback } from "../types"; +export declare type RedisKey = string | Buffer; +export declare type RedisValue = string | Buffer | number; +export interface ResultTypes { + default: Promise; + pipeline: ChainableCommander; +} +export interface ChainableCommander extends RedisCommander<{ + type: "pipeline"; +}> { + length: number; +} +export declare type ClientContext = { + type: keyof ResultTypes; +}; +export declare type Result = ResultTypes[Context["type"]]; +interface RedisCommander { + /** + * Add multiple sorted sets and store the resulting sorted set in a new key + * - _group_: sorted-set + * - _complexity_: O(N)+O(M log(M)) with N being the sum of the sizes of the input sorted sets, and M being the number of elements in the resulting sorted set. + * - _since_: 2.0.0 + */ + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[] + ]): Result; + zunionstore(...args: [destination: RedisKey, numkeys: number | string, keys: RedisKey[]]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[] + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; +} +export default RedisCommander; diff --git a/crates/biome_module_graph/tests/snapshots/test_resolve_export_type_referencing_imported_type.snap b/crates/biome_module_graph/tests/snapshots/test_resolve_export_type_referencing_imported_type.snap index 445975fe574f..638215f6b0c3 100644 --- a/crates/biome_module_graph/tests/snapshots/test_resolve_export_type_referencing_imported_type.snap +++ b/crates/biome_module_graph/tests/snapshots/test_resolve_export_type_referencing_imported_type.snap @@ -48,7 +48,7 @@ BindingId(1) => JsBindingData { ``` Module TypeId(0) => Promise -Module TypeId(1) => Module(0) TypeId(8) +Module TypeId(1) => Module(0) TypeId(7) Module TypeId(2) => value: true @@ -78,14 +78,6 @@ Module TypeId(7) => sync Function "returnPromiseResult" { } returns: Module(0) TypeId(4) } - -Module TypeId(8) => sync Function "returnPromiseResult" { - accepts: { - params: [] - type_args: [] - } - returns: Module(0) TypeId(4) -} ``` # `/src/promisedResult.ts` diff --git a/crates/biome_module_graph/tests/snapshots/test_resolve_promise_from_imported_function_returning_imported_promise_type.snap b/crates/biome_module_graph/tests/snapshots/test_resolve_promise_from_imported_function_returning_imported_promise_type.snap index 45ddd8181f13..f3d868de4a3b 100644 --- a/crates/biome_module_graph/tests/snapshots/test_resolve_promise_from_imported_function_returning_imported_promise_type.snap +++ b/crates/biome_module_graph/tests/snapshots/test_resolve_promise_from_imported_function_returning_imported_promise_type.snap @@ -129,7 +129,7 @@ BindingId(1) => JsBindingData { ``` Module TypeId(0) => Promise -Module TypeId(1) => Module(0) TypeId(8) +Module TypeId(1) => Module(0) TypeId(7) Module TypeId(2) => value: true @@ -159,14 +159,6 @@ Module TypeId(7) => sync Function "returnPromiseResult" { } returns: Module(0) TypeId(4) } - -Module TypeId(8) => sync Function "returnPromiseResult" { - accepts: { - params: [] - type_args: [] - } - returns: Module(0) TypeId(4) -} ``` # Module Resolver diff --git a/crates/biome_module_graph/tests/snapshots/test_resolve_promise_from_imported_function_returning_reexported_promise_type.snap b/crates/biome_module_graph/tests/snapshots/test_resolve_promise_from_imported_function_returning_reexported_promise_type.snap index 2ac5263dcdaa..422594dfe971 100644 --- a/crates/biome_module_graph/tests/snapshots/test_resolve_promise_from_imported_function_returning_reexported_promise_type.snap +++ b/crates/biome_module_graph/tests/snapshots/test_resolve_promise_from_imported_function_returning_reexported_promise_type.snap @@ -155,7 +155,7 @@ BindingId(1) => JsBindingData { ``` Module TypeId(0) => Promise -Module TypeId(1) => Module(0) TypeId(8) +Module TypeId(1) => Module(0) TypeId(7) Module TypeId(2) => value: true @@ -185,14 +185,6 @@ Module TypeId(7) => sync Function "returnPromiseResult" { } returns: Module(0) TypeId(4) } - -Module TypeId(8) => sync Function "returnPromiseResult" { - accepts: { - params: [] - type_args: [] - } - returns: Module(0) TypeId(4) -} ``` # Module Resolver diff --git a/crates/biome_module_graph/tests/snapshots/test_resolve_recursive_looking_vfile.snap b/crates/biome_module_graph/tests/snapshots/test_resolve_recursive_looking_vfile.snap index a0b5275388ab..6615b4e643c4 100644 --- a/crates/biome_module_graph/tests/snapshots/test_resolve_recursive_looking_vfile.snap +++ b/crates/biome_module_graph/tests/snapshots/test_resolve_recursive_looking_vfile.snap @@ -175,49 +175,49 @@ export = vfile; ``` Exports { "history" => { - ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(49)) + ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(39)) } "data" => { - ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(34)) + ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(30)) } "messages" => { - ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(35)) + ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(40)) } "contents" => { - ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(44)) + ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(35)) } "path" => { - ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(26)) + ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(23)) } "dirname" => { - ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(26)) + ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(23)) } "basename" => { - ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(26)) + ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(23)) } "stem" => { - ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(26)) + ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(23)) } "extname" => { - ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(26)) + ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(23)) } "cwd" => { ExportOwnExport => JsOwnExport::Type(string) } "toString" => { - ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(36)) + ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(31)) } "message" => { - ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(38)) + ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(32)) } "fail" => { - ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(40)) + ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(34)) } "info" => { - ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(38)) + ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(32)) } "default" => { - ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(6)) + ExportOwnExport => JsOwnExport::Type(Module(0) TypeId(3)) } } Imports { @@ -237,21 +237,35 @@ Imports { ## Registered types ``` -Module TypeId(0) => instanceof Array - -Module TypeId(1) => instanceof Module(0) TypeId(41) - -Module TypeId(2) => Module(0) TypeId(44) | Module(0) TypeId(1) | Module(0) TypeId(46) +Module TypeId(0) => instanceof Module(0) TypeId(27) -Module TypeId(3) => Module(0) TypeId(53) | Module(0) TypeId(53) | Module(0) TypeId(53) +Module TypeId(1) => Module(0) TypeId(35) | Module(0) TypeId(0) | Module(0) TypeId(37) -Module TypeId(4) => Module(0) TypeId(53) | Module(0) TypeId(53) | Module(0) TypeId(53) +Module TypeId(2) => Module(0) TypeId(42) | Module(0) TypeId(42) | Module(0) TypeId(42) -Module TypeId(5) => Module(0) TypeId(53) | Module(0) TypeId(53) | Module(0) TypeId(53) - -Module TypeId(6) => Module(0) TypeId(42) +Module TypeId(3) => interface "VFile" { + extends: [] + type_args: [] + members: [ + (): Module(0) TypeId(29), + "history": Module(0) TypeId(39), + "data": Module(0) TypeId(30), + "messages": Module(0) TypeId(40), + "contents": Module(0) TypeId(35), + "path": Module(0) TypeId(23), + "dirname": Module(0) TypeId(23), + "basename": Module(0) TypeId(23), + "stem": Module(0) TypeId(23), + "extname": Module(0) TypeId(23), + "cwd": string, + "toString": Module(0) TypeId(31), + "message": Module(0) TypeId(32), + "fail": Module(0) TypeId(34), + "info": Module(0) TypeId(32) + ] +} -Module TypeId(7) => Namespace { +Module TypeId(4) => Namespace { path: Identifier( "vfile", ), @@ -261,7 +275,7 @@ Module TypeId(7) => Namespace { "BufferEncoding", ), ty: Resolved( - Module(0) TypeId(51), + Module(0) TypeId(41), ), }, TypeMember { @@ -269,7 +283,7 @@ Module TypeId(7) => Namespace { "VFileContents", ), ty: Resolved( - Module(0) TypeId(44), + Module(0) TypeId(35), ), }, TypeMember { @@ -277,7 +291,7 @@ Module TypeId(7) => Namespace { "VFileCompatible", ), ty: Resolved( - Module(0) TypeId(18), + Module(0) TypeId(15), ), }, TypeMember { @@ -285,7 +299,7 @@ Module TypeId(7) => Namespace { "Settings", ), ty: Resolved( - Module(0) TypeId(22), + Module(0) TypeId(19), ), }, TypeMember { @@ -293,7 +307,7 @@ Module TypeId(7) => Namespace { "VFileReporter", ), ty: Resolved( - Module(0) TypeId(24), + Module(0) TypeId(21), ), }, TypeMember { @@ -301,7 +315,7 @@ Module TypeId(7) => Namespace { "T", ), ty: Resolved( - Module(0) TypeId(23), + Module(0) TypeId(20), ), }, TypeMember { @@ -309,7 +323,7 @@ Module TypeId(7) => Namespace { "VFileOptions", ), ty: Resolved( - Module(0) TypeId(46), + Module(0) TypeId(37), ), }, TypeMember { @@ -317,260 +331,214 @@ Module TypeId(7) => Namespace { "VFile", ), ty: Resolved( - Module(0) TypeId(42), + Module(0) TypeId(3), ), }, ], } -Module TypeId(8) => value: ascii +Module TypeId(5) => value: ascii -Module TypeId(9) => value: utf8 +Module TypeId(6) => value: utf8 -Module TypeId(10) => value: utf-8 +Module TypeId(7) => value: utf-8 -Module TypeId(11) => value: utf16le +Module TypeId(8) => value: utf16le -Module TypeId(12) => value: ucs2 +Module TypeId(9) => value: ucs2 -Module TypeId(13) => value: ucs-2 +Module TypeId(10) => value: ucs-2 -Module TypeId(14) => value: base64 +Module TypeId(11) => value: base64 -Module TypeId(15) => value: latin1 +Module TypeId(12) => value: latin1 -Module TypeId(16) => value: binary +Module TypeId(13) => value: binary -Module TypeId(17) => value: hex +Module TypeId(14) => value: hex -Module TypeId(18) => Module(0) TypeId(42) | Module(0) TypeId(46) | Module(0) TypeId(44) +Module TypeId(15) => Module(0) TypeId(3) | Module(0) TypeId(37) | Module(0) TypeId(35) -Module TypeId(19) => instanceof Array +Module TypeId(16) => instanceof Array -Module TypeId(20) => instanceof Module(0) TypeId(23) +Module TypeId(17) => instanceof Module(0) TypeId(20) -Module TypeId(21) => sync Function { +Module TypeId(18) => sync Function { accepts: { params: [ - required files: Module(0) TypeId(19) - required options: Module(0) TypeId(20) + required files: Module(0) TypeId(16) + required options: Module(0) TypeId(17) ] type_args: [] } returns: string } -Module TypeId(22) => interface "Settings" { +Module TypeId(19) => interface "Settings" { extends: [] type_args: [] members: [] } -Module TypeId(23) => T = unknown +Module TypeId(20) => T = unknown -Module TypeId(24) => instanceof Module(0) TypeId(21) +Module TypeId(21) => instanceof Module(0) TypeId(18) -Module TypeId(25) => Module(0) TypeId(44) | undefined +Module TypeId(22) => Module(0) TypeId(35) | undefined -Module TypeId(26) => string | undefined +Module TypeId(23) => string | undefined -Module TypeId(27) => any +Module TypeId(24) => any -Module TypeId(28) => Module(0) TypeId(27) | undefined +Module TypeId(25) => Module(0) TypeId(24) | undefined -Module TypeId(29) => Module(0) TypeId(44) | undefined - -Module TypeId(30) => interface "VFileOptions" { +Module TypeId(26) => interface "VFileOptions" { extends: [] type_args: [] members: [ - "contents": Module(0) TypeId(29), - "path": Module(0) TypeId(26), - "basename": Module(0) TypeId(26), - "stem": Module(0) TypeId(26), - "extname": Module(0) TypeId(26), - "dirname": Module(0) TypeId(26), - "cwd": Module(0) TypeId(26), - "data": Module(0) TypeId(28) + "contents": Module(0) TypeId(22), + "path": Module(0) TypeId(23), + "basename": Module(0) TypeId(23), + "stem": Module(0) TypeId(23), + "extname": Module(0) TypeId(23), + "dirname": Module(0) TypeId(23), + "cwd": Module(0) TypeId(23), + "data": Module(0) TypeId(25) ] } -Module TypeId(31) => F extends Module(0) TypeId(42) +Module TypeId(27) => F extends Module(0) TypeId(3) -Module TypeId(32) => Module(0) TypeId(44) | Module(0) TypeId(45) | Module(0) TypeId(46) +Module TypeId(28) => Module(0) TypeId(35) | Module(0) TypeId(36) | Module(0) TypeId(37) -Module TypeId(33) => sync Function { +Module TypeId(29) => sync Function { accepts: { params: [ - optional input: Module(0) TypeId(32) + optional input: Module(0) TypeId(28) ] - type_args: [Module(0) TypeId(31)] + type_args: [Module(0) TypeId(27)] } - returns: Module(0) TypeId(45) + returns: Module(0) TypeId(36) } -Module TypeId(34) => unknown - -Module TypeId(35) => instanceof Array +Module TypeId(30) => unknown -Module TypeId(36) => sync Function { +Module TypeId(31) => sync Function { accepts: { params: [ - optional encoding: Module(0) TypeId(51) + optional encoding: Module(0) TypeId(41) ] type_args: [] } returns: string } -Module TypeId(37) => Module(0) TypeId(53) | Module(0) TypeId(53) | Module(0) TypeId(53) - -Module TypeId(38) => sync Function { +Module TypeId(32) => sync Function { accepts: { params: [ required reason: string - optional position: Module(0) TypeId(37) + optional position: Module(0) TypeId(2) optional ruleId: string ] type_args: [] } - returns: Module(0) TypeId(53) + returns: Module(0) TypeId(42) } -Module TypeId(39) => never +Module TypeId(33) => never -Module TypeId(40) => sync Function { +Module TypeId(34) => sync Function { accepts: { params: [ required reason: string - optional position: Module(0) TypeId(37) + optional position: Module(0) TypeId(2) optional ruleId: string ] type_args: [] } - returns: Module(0) TypeId(39) + returns: Module(0) TypeId(33) } -Module TypeId(41) => F extends Module(0) TypeId(42) +Module TypeId(35) => string | Module(0) TypeId(36) -Module TypeId(42) => interface "VFile" { - extends: [] - type_args: [] - members: [ - (): Module(0) TypeId(33), - "history": Module(0) TypeId(49), - "data": Module(0) TypeId(34), - "messages": Module(0) TypeId(35), - "contents": Module(0) TypeId(44), - "path": Module(0) TypeId(26), - "dirname": Module(0) TypeId(26), - "basename": Module(0) TypeId(26), - "stem": Module(0) TypeId(26), - "extname": Module(0) TypeId(26), - "cwd": string, - "toString": Module(0) TypeId(36), - "message": Module(0) TypeId(38), - "fail": Module(0) TypeId(40), - "info": Module(0) TypeId(38) - ] -} +Module TypeId(36) => unknown -Module TypeId(43) => F extends Module(0) TypeId(42) - -Module TypeId(44) => string | Module(0) TypeId(45) - -Module TypeId(45) => unknown - -Module TypeId(46) => interface "VFileOptions" { +Module TypeId(37) => interface "VFileOptions" { extends: [] type_args: [] members: [ - "contents": Module(0) TypeId(25), - "path": Module(0) TypeId(26), - "basename": Module(0) TypeId(26), - "stem": Module(0) TypeId(26), - "extname": Module(0) TypeId(26), - "dirname": Module(0) TypeId(26), - "cwd": Module(0) TypeId(26), - "data": Module(0) TypeId(28) + "contents": Module(0) TypeId(22), + "path": Module(0) TypeId(23), + "basename": Module(0) TypeId(23), + "stem": Module(0) TypeId(23), + "extname": Module(0) TypeId(23), + "dirname": Module(0) TypeId(23), + "cwd": Module(0) TypeId(23), + "data": Module(0) TypeId(25) ] } -Module TypeId(47) => Module(0) TypeId(44) | Module(0) TypeId(45) | Module(0) TypeId(46) - -Module TypeId(48) => sync Function { +Module TypeId(38) => sync Function { accepts: { params: [ - optional input: Module(0) TypeId(47) + optional input: Module(0) TypeId(28) ] - type_args: [Module(0) TypeId(43)] + type_args: [Module(0) TypeId(27)] } - returns: Module(0) TypeId(45) + returns: Module(0) TypeId(36) } -Module TypeId(49) => instanceof Array +Module TypeId(39) => instanceof Array -Module TypeId(50) => instanceof Array - -Module TypeId(51) => Module(0) TypeId(8) | Module(0) TypeId(9) | Module(0) TypeId(10) | Module(0) TypeId(11) | Module(0) TypeId(12) | Module(0) TypeId(13) | Module(0) TypeId(14) | Module(0) TypeId(15) | Module(0) TypeId(16) | Module(0) TypeId(17) - -Module TypeId(52) => sync Function { - accepts: { - params: [ - optional encoding: Module(0) TypeId(51) - ] - type_args: [] - } - returns: string -} +Module TypeId(40) => instanceof Array -Module TypeId(53) => instanceof Import Symbol: All from +Module TypeId(41) => Module(0) TypeId(5) | Module(0) TypeId(6) | Module(0) TypeId(7) | Module(0) TypeId(8) | Module(0) TypeId(9) | Module(0) TypeId(10) | Module(0) TypeId(11) | Module(0) TypeId(12) | Module(0) TypeId(13) | Module(0) TypeId(14) -Module TypeId(54) => Module(0) TypeId(53) | Module(0) TypeId(53) | Module(0) TypeId(53) +Module TypeId(42) => instanceof Import Symbol: All from -Module TypeId(55) => sync Function { +Module TypeId(43) => sync Function { accepts: { params: [ required reason: string - optional position: Module(0) TypeId(54) + optional position: Module(0) TypeId(2) optional ruleId: string ] type_args: [] } - returns: Module(0) TypeId(53) + returns: Module(0) TypeId(42) } -Module TypeId(56) => sync Function { +Module TypeId(44) => sync Function { accepts: { params: [ required reason: string - optional position: Module(0) TypeId(54) + optional position: Module(0) TypeId(2) optional ruleId: string ] type_args: [] } - returns: Module(0) TypeId(39) + returns: Module(0) TypeId(33) } -Module TypeId(57) => interface "VFile" { +Module TypeId(45) => interface "VFile" { extends: [] type_args: [] members: [ - (): Module(0) TypeId(48), - "history": Module(0) TypeId(49), - "data": Module(0) TypeId(34), - "messages": Module(0) TypeId(50), - "contents": Module(0) TypeId(44), - "path": Module(0) TypeId(26), - "dirname": Module(0) TypeId(26), - "basename": Module(0) TypeId(26), - "stem": Module(0) TypeId(26), - "extname": Module(0) TypeId(26), + (): Module(0) TypeId(38), + "history": Module(0) TypeId(39), + "data": Module(0) TypeId(30), + "messages": Module(0) TypeId(40), + "contents": Module(0) TypeId(35), + "path": Module(0) TypeId(23), + "dirname": Module(0) TypeId(23), + "basename": Module(0) TypeId(23), + "stem": Module(0) TypeId(23), + "extname": Module(0) TypeId(23), "cwd": string, - "toString": Module(0) TypeId(52), - "message": Module(0) TypeId(55), - "fail": Module(0) TypeId(56), - "info": Module(0) TypeId(55) + "toString": Module(0) TypeId(31), + "message": Module(0) TypeId(43), + "fail": Module(0) TypeId(44), + "info": Module(0) TypeId(43) ] } ``` diff --git a/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_destructured_field_of_intersection_of_interfaces.snap b/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_destructured_field_of_intersection_of_interfaces.snap index 24c40905213e..d156922d63cb 100644 --- a/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_destructured_field_of_intersection_of_interfaces.snap +++ b/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_destructured_field_of_intersection_of_interfaces.snap @@ -43,83 +43,79 @@ Imports { ## Registered types ``` -Module TypeId(0) => instanceof Promise +Module TypeId(0) => Module(0) TypeId(9) | Module(0) TypeId(10) | Module(0) TypeId(20) -Module TypeId(1) => Module(0) TypeId(10) | Module(0) TypeId(0) | Module(0) TypeId(22) +Module TypeId(1) => boolean -Module TypeId(2) => boolean +Module TypeId(2) => Module(0) TypeId(1) | Module(0) TypeId(20) -Module TypeId(3) => Module(0) TypeId(2) | Module(0) TypeId(22) - -Module TypeId(4) => sync Function { +Module TypeId(3) => sync Function { accepts: { params: [] type_args: [] } - returns: Module(0) TypeId(6) + returns: Module(0) TypeId(5) } -Module TypeId(5) => Module(0) TypeId(4) +Module TypeId(4) => Module(0) TypeId(3) -Module TypeId(6) => interface "(merged)" { +Module TypeId(5) => interface "(merged)" { extends: [] type_args: [] members: [ - "cache": Module(0) TypeId(22), - "mutate": Module(0) TypeId(7), + "cache": Module(0) TypeId(20), + "mutate": Module(0) TypeId(6), "errorRetryInterval": number ] } -Module TypeId(7) => instanceof Module(0) TypeId(18) +Module TypeId(6) => instanceof Module(0) TypeId(16) -Module TypeId(8) => interface "InternalConfiguration" { +Module TypeId(7) => interface "InternalConfiguration" { extends: [] type_args: [] - members: ["cache": Module(0) TypeId(22), "mutate": Module(0) TypeId(7)] + members: ["cache": Module(0) TypeId(20), "mutate": Module(0) TypeId(6)] } -Module TypeId(9) => interface "PublicConfiguration" { +Module TypeId(8) => interface "PublicConfiguration" { extends: [] type_args: [] members: ["errorRetryInterval": number] } -Module TypeId(10) => instanceof Module(0) TypeId(21) - -Module TypeId(11) => instanceof Promise +Module TypeId(9) => instanceof Module(0) TypeId(19) -Module TypeId(12) => Module(0) TypeId(10) | Module(0) TypeId(11) | Module(0) TypeId(22) +Module TypeId(10) => instanceof Promise -Module TypeId(13) => instanceof Module(0) TypeId(20) +Module TypeId(11) => Module(0) TypeId(9) | Module(0) TypeId(10) | Module(0) TypeId(20) -Module TypeId(14) => Module(0) TypeId(2) | Module(0) TypeId(22) +Module TypeId(12) => instanceof Module(0) TypeId(18) -Module TypeId(15) => undefined +Module TypeId(13) => undefined -Module TypeId(16) => Module(0) TypeId(10) | Module(0) TypeId(15) +Module TypeId(14) => Module(0) TypeId(9) | Module(0) TypeId(13) -Module TypeId(17) => instanceof Promise +Module TypeId(15) => instanceof Promise -Module TypeId(18) => sync Function { +Module TypeId(16) => sync Function { accepts: { params: [ - required key: Module(0) TypeId(22) - optional data: Module(0) TypeId(12) - optional opts: Module(0) TypeId(14) + required key: Module(0) TypeId(20) + optional data: Module(0) TypeId(11) + optional opts: Module(0) TypeId(2) ] type_args: [] } - returns: Module(0) TypeId(17) + returns: Module(0) TypeId(15) } -Module TypeId(19) => any +Module TypeId(17) => any -Module TypeId(20) => Data = unknown +Module TypeId(18) => Data = unknown -Module TypeId(21) => T = unknown +Module TypeId(19) => T = unknown -Module TypeId(22) => unknown +Module TypeId(20) => unknown ``` # Module Resolver @@ -127,77 +123,75 @@ Module TypeId(22) => unknown ## Registered types ``` -Full TypeId(0) => instanceof Promise - -Full TypeId(1) => Module(0) TypeId(10) | Module(0) TypeId(0) | Module(0) TypeId(22) +Full TypeId(0) => Module(0) TypeId(9) | Module(0) TypeId(10) | Module(0) TypeId(20) -Full TypeId(2) => boolean +Full TypeId(1) => boolean -Full TypeId(3) => Module(0) TypeId(2) | Module(0) TypeId(22) +Full TypeId(2) => Module(0) TypeId(1) | Module(0) TypeId(20) -Full TypeId(4) => sync Function { +Full TypeId(3) => sync Function { accepts: { params: [] type_args: [] } - returns: Module(0) TypeId(6) + returns: Module(0) TypeId(5) } -Full TypeId(5) => Module(0) TypeId(4) +Full TypeId(4) => Module(0) TypeId(3) -Full TypeId(6) => interface "(merged)" { +Full TypeId(5) => interface "(merged)" { extends: [] type_args: [] members: [ - "cache": Module(0) TypeId(22), - "mutate": Module(0) TypeId(7), + "cache": Module(0) TypeId(20), + "mutate": Module(0) TypeId(6), "errorRetryInterval": number ] } -Full TypeId(7) => instanceof Module(0) TypeId(18) +Full TypeId(6) => instanceof Module(0) TypeId(16) -Full TypeId(8) => interface "InternalConfiguration" { +Full TypeId(7) => interface "InternalConfiguration" { extends: [] type_args: [] - members: ["cache": Module(0) TypeId(22), "mutate": Module(0) TypeId(7)] + members: ["cache": Module(0) TypeId(20), "mutate": Module(0) TypeId(6)] } -Full TypeId(9) => interface "PublicConfiguration" { +Full TypeId(8) => interface "PublicConfiguration" { extends: [] type_args: [] members: ["errorRetryInterval": number] } -Full TypeId(10) => instanceof Module(0) TypeId(21) +Full TypeId(9) => instanceof Module(0) TypeId(19) -Full TypeId(11) => Module(0) TypeId(10) | Module(0) TypeId(11) | Module(0) TypeId(22) +Full TypeId(10) => instanceof Promise -Full TypeId(12) => instanceof Module(0) TypeId(20) +Full TypeId(11) => instanceof Module(0) TypeId(18) -Full TypeId(13) => undefined +Full TypeId(12) => undefined -Full TypeId(14) => Module(0) TypeId(10) | Module(0) TypeId(15) +Full TypeId(13) => Module(0) TypeId(9) | Module(0) TypeId(13) -Full TypeId(15) => instanceof Promise +Full TypeId(14) => instanceof Promise -Full TypeId(16) => sync Function { +Full TypeId(15) => sync Function { accepts: { params: [ - required key: Module(0) TypeId(22) - optional data: Module(0) TypeId(12) - optional opts: Module(0) TypeId(14) + required key: Module(0) TypeId(20) + optional data: Module(0) TypeId(11) + optional opts: Module(0) TypeId(2) ] type_args: [] } - returns: Module(0) TypeId(17) + returns: Module(0) TypeId(15) } -Full TypeId(17) => any +Full TypeId(16) => any -Full TypeId(18) => Data = unknown +Full TypeId(17) => Data = unknown -Full TypeId(19) => T = unknown +Full TypeId(18) => T = unknown -Full TypeId(20) => unknown +Full TypeId(19) => unknown ``` diff --git a/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_this_in_class_assign.snap b/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_this_in_class_assign.snap index 956e8d43fa28..30c86a12b6ec 100644 --- a/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_this_in_class_assign.snap +++ b/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_this_in_class_assign.snap @@ -68,7 +68,7 @@ Module TypeId(0) => sync Function { params: [] type_args: [] } - returns: Module(0) TypeId(5) + returns: Module(0) TypeId(21) } Module TypeId(1) => sync Function { @@ -76,7 +76,7 @@ Module TypeId(1) => sync Function { params: [] type_args: [] } - returns: Module(0) TypeId(5) + returns: Module(0) TypeId(21) } Module TypeId(2) => sync Function { @@ -84,79 +84,79 @@ Module TypeId(2) => sync Function { params: [] type_args: [] } - returns: Module(0) TypeId(5) + returns: Module(0) TypeId(21) } Module TypeId(3) => Module(0) TypeId(2) -Module TypeId(4) => instanceof Module(0) TypeId(13) +Module TypeId(4) => instanceof Module(0) TypeId(12) -Module TypeId(5) => Module(0) TypeId(23) - -Module TypeId(6) => Object { +Module TypeId(5) => Object { prototype: No prototype - members: ["x": Module(0) TypeId(5)] + members: ["x": Module(0) TypeId(21)] } -Module TypeId(7) => Module(0) TypeId(6) +Module TypeId(6) => Module(0) TypeId(5) -Module TypeId(8) => Module(0) TypeId(5) +Module TypeId(7) => Module(0) TypeId(21) -Module TypeId(9) => sync Function "fooGetter" { +Module TypeId(8) => sync Function "fooGetter" { accepts: { params: [] type_args: [] } - returns: Module(0) TypeId(5) + returns: Module(0) TypeId(21) } -Module TypeId(10) => sync Function "meth" { +Module TypeId(9) => sync Function "meth" { accepts: { params: [] type_args: [] } - returns: Module(0) TypeId(5) + returns: Module(0) TypeId(21) } -Module TypeId(11) => sync Function "nestedArrow" { +Module TypeId(10) => sync Function "nestedArrow" { accepts: { params: [] type_args: [] } - returns: Module(0) TypeId(23) + returns: Module(0) TypeId(21) } -Module TypeId(12) => sync Function "inObject" { +Module TypeId(11) => sync Function "inObject" { accepts: { params: [] type_args: [] } - returns: Module(0) TypeId(8) + returns: Module(0) TypeId(7) } -Module TypeId(13) => class { +Module TypeId(12) => class { extends: none implements: [] type_args: [] } -Module TypeId(14) => Module(0) TypeId(13) +Module TypeId(13) => Module(0) TypeId(12) + +Module TypeId(14) => instanceof Module(0) TypeId(13) -Module TypeId(15) => instanceof Module(0) TypeId(14) +Module TypeId(15) => Module(0) TypeId(21) -Module TypeId(16) => Module(0) TypeId(5) +Module TypeId(16) => Module(0) TypeId(21) -Module TypeId(17) => Module(0) TypeId(5) +Module TypeId(17) => Module(0) TypeId(0) -Module TypeId(18) => Module(0) TypeId(0) +Module TypeId(18) => Module(0) TypeId(1) -Module TypeId(19) => Module(0) TypeId(1) +Module TypeId(19) => Module(0) TypeId(9) Module TypeId(20) => Module(0) TypeId(10) -Module TypeId(21) => Module(0) TypeId(11) +Module TypeId(21) => Module(0) TypeId(23) -Module TypeId(22) => Module(0) TypeId(12) +Module TypeId(22) => Module(0) TypeId(11) Module TypeId(23) => value: foo ``` diff --git a/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_this_in_class_export.snap b/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_this_in_class_export.snap index fdce145f19db..4ca7aefe2f4b 100644 --- a/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_this_in_class_export.snap +++ b/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_this_in_class_export.snap @@ -80,7 +80,7 @@ Module TypeId(0) => sync Function { params: [] type_args: [] } - returns: Module(0) TypeId(5) + returns: Module(0) TypeId(16) } Module TypeId(1) => sync Function { @@ -88,7 +88,7 @@ Module TypeId(1) => sync Function { params: [] type_args: [] } - returns: Module(0) TypeId(5) + returns: Module(0) TypeId(16) } Module TypeId(2) => sync Function { @@ -96,39 +96,39 @@ Module TypeId(2) => sync Function { params: [] type_args: [] } - returns: Module(0) TypeId(5) + returns: Module(0) TypeId(16) } Module TypeId(3) => Module(0) TypeId(2) Module TypeId(4) => instanceof Module(0) TypeId(23) -Module TypeId(5) => Module(0) TypeId(18) - -Module TypeId(6) => Object { +Module TypeId(5) => Object { prototype: No prototype - members: ["x": Module(0) TypeId(5)] + members: ["x": Module(0) TypeId(16)] } -Module TypeId(7) => Module(0) TypeId(6) +Module TypeId(6) => Module(0) TypeId(5) + +Module TypeId(7) => Module(0) TypeId(16) -Module TypeId(8) => Module(0) TypeId(5) +Module TypeId(8) => Module(0) TypeId(23) -Module TypeId(9) => Module(0) TypeId(23) +Module TypeId(9) => instanceof Module(0) TypeId(8) -Module TypeId(10) => instanceof Module(0) TypeId(9) +Module TypeId(10) => Module(0) TypeId(16) -Module TypeId(11) => Module(0) TypeId(5) +Module TypeId(11) => Module(0) TypeId(16) -Module TypeId(12) => Module(0) TypeId(5) +Module TypeId(12) => Module(0) TypeId(0) -Module TypeId(13) => Module(0) TypeId(0) +Module TypeId(13) => Module(0) TypeId(1) -Module TypeId(14) => Module(0) TypeId(1) +Module TypeId(14) => Module(0) TypeId(20) -Module TypeId(15) => Module(0) TypeId(20) +Module TypeId(15) => Module(0) TypeId(21) -Module TypeId(16) => Module(0) TypeId(21) +Module TypeId(16) => Module(0) TypeId(18) Module TypeId(17) => Module(0) TypeId(22) @@ -139,7 +139,7 @@ Module TypeId(19) => sync Function "fooGetter" { params: [] type_args: [] } - returns: Module(0) TypeId(5) + returns: Module(0) TypeId(16) } Module TypeId(20) => sync Function "meth" { @@ -147,7 +147,7 @@ Module TypeId(20) => sync Function "meth" { params: [] type_args: [] } - returns: Module(0) TypeId(5) + returns: Module(0) TypeId(16) } Module TypeId(21) => sync Function "nestedArrow" { @@ -155,7 +155,7 @@ Module TypeId(21) => sync Function "nestedArrow" { params: [] type_args: [] } - returns: Module(0) TypeId(18) + returns: Module(0) TypeId(16) } Module TypeId(22) => sync Function "inObject" { @@ -163,7 +163,7 @@ Module TypeId(22) => sync Function "inObject" { params: [] type_args: [] } - returns: Module(0) TypeId(8) + returns: Module(0) TypeId(7) } Module TypeId(23) => class "Foo" { diff --git a/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_this_in_class_plain.snap b/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_this_in_class_plain.snap index f127be6cb4df..e7ef686d6a98 100644 --- a/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_this_in_class_plain.snap +++ b/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_this_in_class_plain.snap @@ -68,7 +68,7 @@ Module TypeId(0) => sync Function { params: [] type_args: [] } - returns: Module(0) TypeId(5) + returns: Module(0) TypeId(16) } Module TypeId(1) => sync Function { @@ -76,7 +76,7 @@ Module TypeId(1) => sync Function { params: [] type_args: [] } - returns: Module(0) TypeId(5) + returns: Module(0) TypeId(16) } Module TypeId(2) => sync Function { @@ -84,39 +84,39 @@ Module TypeId(2) => sync Function { params: [] type_args: [] } - returns: Module(0) TypeId(5) + returns: Module(0) TypeId(16) } Module TypeId(3) => Module(0) TypeId(2) Module TypeId(4) => instanceof Module(0) TypeId(23) -Module TypeId(5) => Module(0) TypeId(18) - -Module TypeId(6) => Object { +Module TypeId(5) => Object { prototype: No prototype - members: ["x": Module(0) TypeId(5)] + members: ["x": Module(0) TypeId(16)] } -Module TypeId(7) => Module(0) TypeId(6) +Module TypeId(6) => Module(0) TypeId(5) + +Module TypeId(7) => Module(0) TypeId(16) -Module TypeId(8) => Module(0) TypeId(5) +Module TypeId(8) => Module(0) TypeId(23) -Module TypeId(9) => Module(0) TypeId(23) +Module TypeId(9) => instanceof Module(0) TypeId(8) -Module TypeId(10) => instanceof Module(0) TypeId(9) +Module TypeId(10) => Module(0) TypeId(16) -Module TypeId(11) => Module(0) TypeId(5) +Module TypeId(11) => Module(0) TypeId(16) -Module TypeId(12) => Module(0) TypeId(5) +Module TypeId(12) => Module(0) TypeId(0) -Module TypeId(13) => Module(0) TypeId(0) +Module TypeId(13) => Module(0) TypeId(1) -Module TypeId(14) => Module(0) TypeId(1) +Module TypeId(14) => Module(0) TypeId(20) -Module TypeId(15) => Module(0) TypeId(20) +Module TypeId(15) => Module(0) TypeId(21) -Module TypeId(16) => Module(0) TypeId(21) +Module TypeId(16) => Module(0) TypeId(18) Module TypeId(17) => Module(0) TypeId(22) @@ -127,7 +127,7 @@ Module TypeId(19) => sync Function "fooGetter" { params: [] type_args: [] } - returns: Module(0) TypeId(5) + returns: Module(0) TypeId(16) } Module TypeId(20) => sync Function "meth" { @@ -135,7 +135,7 @@ Module TypeId(20) => sync Function "meth" { params: [] type_args: [] } - returns: Module(0) TypeId(5) + returns: Module(0) TypeId(16) } Module TypeId(21) => sync Function "nestedArrow" { @@ -143,7 +143,7 @@ Module TypeId(21) => sync Function "nestedArrow" { params: [] type_args: [] } - returns: Module(0) TypeId(18) + returns: Module(0) TypeId(16) } Module TypeId(22) => sync Function "inObject" { @@ -151,7 +151,7 @@ Module TypeId(22) => sync Function "inObject" { params: [] type_args: [] } - returns: Module(0) TypeId(8) + returns: Module(0) TypeId(7) } Module TypeId(23) => class "Foo" { diff --git a/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_this_in_object.snap b/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_this_in_object.snap index 9d0e5edad832..32f2f4ab3af7 100644 --- a/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_this_in_object.snap +++ b/crates/biome_module_graph/tests/snapshots/test_resolve_type_of_this_in_object.snap @@ -77,7 +77,7 @@ Module TypeId(2) => sync Function { params: [] type_args: [] } - returns: Module(0) TypeId(6) + returns: Module(0) TypeId(18) } Module TypeId(3) => sync Function { @@ -85,7 +85,7 @@ Module TypeId(3) => sync Function { params: [] type_args: [] } - returns: Module(0) TypeId(6) + returns: Module(0) TypeId(18) } Module TypeId(4) => Module(0) TypeId(3) @@ -95,69 +95,69 @@ Module TypeId(5) => Object { members: [ "x": Module(0) TypeId(20), "y": Module(0) TypeId(23), - get "fooGetter": Module(0) TypeId(10), + get "fooGetter": Module(0) TypeId(9), "arrow": Module(0) TypeId(1), "func": Module(0) TypeId(2), - "meth": Module(0) TypeId(11), - "nestedArrow": Module(0) TypeId(12), - "inObject": Module(0) TypeId(13) + "meth": Module(0) TypeId(10), + "nestedArrow": Module(0) TypeId(11), + "inObject": Module(0) TypeId(12) ] } -Module TypeId(6) => Module(0) TypeId(20) - -Module TypeId(7) => Object { +Module TypeId(6) => Object { prototype: No prototype - members: ["x": Module(0) TypeId(6)] + members: ["x": Module(0) TypeId(18)] } -Module TypeId(8) => Module(0) TypeId(7) +Module TypeId(7) => Module(0) TypeId(6) -Module TypeId(9) => Module(0) TypeId(6) +Module TypeId(8) => Module(0) TypeId(18) -Module TypeId(10) => sync Function "fooGetter" { +Module TypeId(9) => sync Function "fooGetter" { accepts: { params: [] type_args: [] } - returns: Module(0) TypeId(6) + returns: Module(0) TypeId(18) } -Module TypeId(11) => sync Function "meth" { +Module TypeId(10) => sync Function "meth" { accepts: { params: [] type_args: [] } - returns: Module(0) TypeId(6) + returns: Module(0) TypeId(18) } -Module TypeId(12) => sync Function "nestedArrow" { +Module TypeId(11) => sync Function "nestedArrow" { accepts: { params: [] type_args: [] } - returns: Module(0) TypeId(20) + returns: Module(0) TypeId(18) } -Module TypeId(13) => sync Function "inObject" { +Module TypeId(12) => sync Function "inObject" { accepts: { params: [] type_args: [] } - returns: Module(0) TypeId(9) + returns: Module(0) TypeId(8) } -Module TypeId(14) => Module(0) TypeId(5) +Module TypeId(13) => Module(0) TypeId(5) + +Module TypeId(14) => Module(0) TypeId(18) -Module TypeId(15) => Module(0) TypeId(6) +Module TypeId(15) => Module(0) TypeId(2) -Module TypeId(16) => Module(0) TypeId(2) +Module TypeId(16) => Module(0) TypeId(10) Module TypeId(17) => Module(0) TypeId(11) -Module TypeId(18) => Module(0) TypeId(12) +Module TypeId(18) => Module(0) TypeId(20) -Module TypeId(19) => Module(0) TypeId(13) +Module TypeId(19) => Module(0) TypeId(12) Module TypeId(20) => value: foo diff --git a/crates/biome_module_graph/tests/spec_tests.rs b/crates/biome_module_graph/tests/spec_tests.rs index 9c58e9c4a291..e9a63457ee63 100644 --- a/crates/biome_module_graph/tests/spec_tests.rs +++ b/crates/biome_module_graph/tests/spec_tests.rs @@ -480,7 +480,7 @@ fn test_resolve_exports() { ); assert_eq!( - data.blanket_reexports.as_ref(), + data.blanket_reexports, &[JsReexport { import: JsImport { specifier: "./reexports".into(), @@ -1526,6 +1526,51 @@ fn test_resolve_react_types() { assert!(promise_ty.is_promise_instance()); } +#[test] +fn test_resolve_redis_commander_types() { + let fs = MemoryFileSystem::default(); + fs.insert( + "/RedisCommander.d.ts".into(), + include_bytes!("./fixtures/RedisCommander_stripped.d.ts"), + ); + fs.insert( + "/index.ts".into(), + r#"import RedisCommander from "./RedisCommander.d.ts"; + "#, + ); + + let added_paths = [ + BiomePath::new("/RedisCommander.d.ts"), + BiomePath::new("/index.ts"), + ]; + let added_paths = get_added_paths(&fs, &added_paths); + + let module_graph = Arc::new(ModuleGraph::default()); + module_graph.update_graph_for_js_paths(&fs, &ProjectLayout::default(), &added_paths, &[]); + + // We previously had an issue with `RedisCommander.d.ts` that caused types + // to be duplicated. We should look out in this snapshot that method + // signatures are registered only once per signature. + let redis_commander_module = module_graph + .module_info_for_path(Utf8Path::new("/RedisCommander.d.ts")) + .expect("module must exist"); + let num_registered_signatures = redis_commander_module + .types() + .iter() + .filter(|ty| { + matches!( + ty, + TypeData::Function(function) + if function + .name + .as_ref() + .is_some_and(|name| *name == "zunionstore") + ) + }) + .count(); + assert_eq!(num_registered_signatures, 24); +} + #[test] fn test_resolve_single_reexport() { let fs = MemoryFileSystem::default(); From a46d5791d758b3a9cb196997ee72d69140c2a3c2 Mon Sep 17 00:00:00 2001 From: "Arend van Beelen jr." Date: Tue, 19 Aug 2025 11:57:55 +0200 Subject: [PATCH 2/2] Update .changeset/resting-rhinos-reverberate.md Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .changeset/resting-rhinos-reverberate.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/resting-rhinos-reverberate.md b/.changeset/resting-rhinos-reverberate.md index 83e2b67c246c..e0729807b93c 100644 --- a/.changeset/resting-rhinos-reverberate.md +++ b/.changeset/resting-rhinos-reverberate.md @@ -2,4 +2,4 @@ "@biomejs/biome": patch --- -Fixed [#6172](https://github.com/biomejs/biome/issues/6172): Resolved an issue with infering types for rest arguments. This issue caused the types of rest arguments to be incorrect and also caused sometimes extreme performance regressions in files that contained many methods with rest argument definitions. +Fixed [#6172](https://github.com/biomejs/biome/issues/6172): Resolved an issue with inferring types for rest parameters. This issue caused rest-parameter types to be incorrect, and in some cases caused extreme performance regressions in files that contained many methods with rest-parameter definitions.