From d95623570632bb669aa3a560dbacf1399bce402d Mon Sep 17 00:00:00 2001 From: George Zahariev Date: Mon, 9 Dec 2024 08:09:46 -0800 Subject: [PATCH] [flow][numeric-keys] Fix various places in env_builder to properly handle numeric keys Summary: This code in env builder was written before we supported numeric literal keys. Either it was not supporting numeric keys, or was not correctly handling them by using `raw` as the name. Changelog: [internal] Reviewed By: SamChou19815 Differential Revision: D66911505 fbshipit-source-id: af20857506e87426743ae4d7e46600b7375a800a --- src/analysis/env_builder/name_def.ml | 32 ++++++++++++++++++++++ src/analysis/env_builder/name_resolver.ml | 8 ++++-- src/analysis/env_builder/refinement_key.ml | 10 +++++-- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/analysis/env_builder/name_def.ml b/src/analysis/env_builder/name_def.ml index 92e53836c5a..58bddb696ee 100644 --- a/src/analysis/env_builder/name_def.ml +++ b/src/analysis/env_builder/name_def.ml @@ -612,6 +612,13 @@ let expression_is_definitely_synthesizable ~autocomplete_hooks = (* Autocompletion in LTI will use hints to find the expected type of the object we are completing. There are similar case for identifiers and literals below. *) false + | Property.NumberLiteral (loc, { Ast.NumberLiteral.value = key_value; _ }) + when Js_number.is_float_safe_integer key_value -> + let name = Dtoa.ecma_string_of_float key_value in + if autocomplete_hooks.Env_api.With_ALoc.obj_prop_decl_hook name loc then + false + else + synthesizable value | _ -> synthesizable value) | (_, Get { key = _; value = (_, fn); comments = _ }) | (_, Set { key = _; value = (_, fn); comments = _ }) @@ -1985,6 +1992,12 @@ class def_finder ~autocomplete_hooks ~react_jsx env_info toplevel_scope = Some h ) -> Base.Continue_or_stop.Continue (ObjectPropPatternHint (name, l, h) :: acc) + | ( Ast.Pattern.Object.Property.NumberLiteral (l, { Ast.NumberLiteral.value; _ }), + Some h + ) + when Js_number.is_float_safe_integer value -> + let name = Dtoa.ecma_string_of_float value in + Base.Continue_or_stop.Continue (ObjectPropPatternHint (name, l, h) :: acc) | _ -> Base.Continue_or_stop.Stop None) | Ast.Pattern.Object.RestElement (_, { Ast.Pattern.RestElement.argument; _ }) -> other_pattern_hint_opt argument @@ -3031,6 +3044,21 @@ class def_finder ~autocomplete_hooks ~react_jsx env_info toplevel_scope = ) when autocomplete_hooks.Env_api.With_ALoc.obj_prop_decl_hook name loc -> true + | ( _, + Init + { + key = + Property.NumberLiteral (loc, { Ast.NumberLiteral.value = key_value; _ }); + value; + _; + } + ) + when Js_number.is_float_safe_integer key_value -> + let name = Dtoa.ecma_string_of_float key_value in + if autocomplete_hooks.Env_api.With_ALoc.obj_prop_decl_hook name loc then + true + else + expression_has_autocomplete ~autocomplete_hooks value | (_, Init { value; _ }) -> expression_has_autocomplete ~autocomplete_hooks value | _ -> false) | SpreadProperty _ -> false @@ -3048,6 +3076,10 @@ class def_finder ~autocomplete_hooks ~react_jsx env_info toplevel_scope = let visit_object_key_and_compute_hint = function | Ast.Expression.Object.Property.StringLiteral (_, { Ast.StringLiteral.value = name; _ }) -> decompose_hints (Decomp_ObjProp name) object_hints + | Ast.Expression.Object.Property.NumberLiteral (_, { Ast.NumberLiteral.value; _ }) + when Js_number.is_float_safe_integer value -> + let name = Dtoa.ecma_string_of_float value in + decompose_hints (Decomp_ObjProp name) object_hints | Ast.Expression.Object.Property.NumberLiteral _ | Ast.Expression.Object.Property.BigIntLiteral _ -> [] diff --git a/src/analysis/env_builder/name_resolver.ml b/src/analysis/env_builder/name_resolver.ml index 838fc3aaff9..cff4de9ef57 100644 --- a/src/analysis/env_builder/name_resolver.ml +++ b/src/analysis/env_builder/name_resolver.ml @@ -5578,9 +5578,11 @@ module Make (Context : C) (FlowAPIUtils : F with type cx = Context.t) : let propname = match property with | PropertyIdentifier (_, { Flow_ast.Identifier.name; _ }) - | PropertyExpression (_, StringLiteral { Flow_ast.StringLiteral.value = name; _ }) - | PropertyExpression - (_, NumberLiteral { Flow_ast.NumberLiteral.value = _; raw = name; _ }) -> + | PropertyExpression (_, StringLiteral { Flow_ast.StringLiteral.value = name; _ }) -> + Some name + | PropertyExpression (_, NumberLiteral { Flow_ast.NumberLiteral.value; _ }) + when Js_number.is_float_safe_integer value -> + let name = Dtoa.ecma_string_of_float value in Some name | _ -> None in diff --git a/src/analysis/env_builder/refinement_key.ml b/src/analysis/env_builder/refinement_key.ml index 80ec30bc63e..cc68d182209 100644 --- a/src/analysis/env_builder/refinement_key.ml +++ b/src/analysis/env_builder/refinement_key.ml @@ -122,10 +122,14 @@ module Make (L : Loc_sig.S) : REFINEMENT_KEY with module L = L = struct let open Ast.Expression.Member in match property with | PropertyIdentifier (_, { Ast.Identifier.name; comments = _ }) - | PropertyExpression (_, Ast.Expression.StringLiteral { Ast.StringLiteral.value = name; _ }) + | PropertyExpression (_, Ast.Expression.StringLiteral { Ast.StringLiteral.value = name; _ }) -> + (match lookup_of_expression ~allow_optional _object with + | Some { base; projections } -> Some { base; projections = Prop name :: projections } + | None -> None) | PropertyExpression - (_, Ast.Expression.NumberLiteral { Ast.NumberLiteral.value = _; raw = name; comments = _ }) - -> + (_, Ast.Expression.NumberLiteral { Ast.NumberLiteral.value; raw = _; comments = _ }) + when Js_number.is_float_safe_integer value -> + let name = Dtoa.ecma_string_of_float value in (match lookup_of_expression ~allow_optional _object with | Some { base; projections } -> Some { base; projections = Prop name :: projections } | None -> None)