From 726a642af58ac7bd70c9b37c4c3784e74051f755 Mon Sep 17 00:00:00 2001 From: Sam Zhou Date: Tue, 3 Dec 2024 17:09:36 -0800 Subject: [PATCH] [flow] Slight haste_namespace config tweak and add tests Summary: Previously, I reversed the list here because I think the lines in flowconfig are processed in order but they are prepended to the list in reverse order. However, that's my misunderstanding and flowconfig processing will reverse the lines first. This diff removes the reverse here to be consitent with other flowconfig options. In addition, I also added the compatibility mode that allow common code to import 1-namespace only code (choosing the first namespace). I also added test to test the namespace resolution behavior and the precedence rule change. Changelog: [internal] Reviewed By: panagosg7 Differential Revision: D66710892 fbshipit-source-id: 728f804ddb40032cce62401e8a93a8fb35948fcc --- src/common/haste_namespaces.ml | 16 ++++- tests/haste_namespaces/.flowconfig | 9 +++ tests/haste_namespaces/common/Common.js | 5 ++ tests/haste_namespaces/common/CommonLib.js | 1 + .../common/web/WebInCommon.js | 0 tests/haste_namespaces/haste_namespaces.exp | 69 +++++++++++++++++++ tests/haste_namespaces/native/Forked.js | 0 tests/haste_namespaces/native/NativeOnly.js | 8 +++ tests/haste_namespaces/web/Native.js | 0 tests/haste_namespaces/web/WebOnly.js | 6 ++ 10 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 tests/haste_namespaces/.flowconfig create mode 100644 tests/haste_namespaces/common/Common.js create mode 100644 tests/haste_namespaces/common/CommonLib.js create mode 100644 tests/haste_namespaces/common/web/WebInCommon.js create mode 100644 tests/haste_namespaces/haste_namespaces.exp create mode 100644 tests/haste_namespaces/native/Forked.js create mode 100644 tests/haste_namespaces/native/NativeOnly.js create mode 100644 tests/haste_namespaces/web/Native.js create mode 100644 tests/haste_namespaces/web/WebOnly.js diff --git a/src/common/haste_namespaces.ml b/src/common/haste_namespaces.ml index aeb3ada3af1..4b429675e91 100644 --- a/src/common/haste_namespaces.ml +++ b/src/common/haste_namespaces.ml @@ -37,7 +37,7 @@ let mk_options = IMap.empty in let namespaces_path_mapping = - Base.List.rev_map haste_namespaces_path_mapping ~f:(fun (path, ns) -> + Base.List.map haste_namespaces_path_mapping ~f:(fun (path, ns) -> (map_path path, list_to_bitset ~haste_namespaces ns) ) in @@ -69,6 +69,20 @@ let reachable_namespace_bitsets_from_namespace_bitset ~opts ns = None ) in + let additional = + match additional with + | Some _ -> additional + | None -> + if IMap.exists (fun _ b -> Bitset.equal b ns) opts.overlapping_namespaces_mapping then + Base.List.find_mapi (Nel.to_list opts.namespaces) ~f:(fun i _ -> + if Bitset.mem i ns then + Some (Bitset.all_zero size |> Bitset.set i) + else + None + ) + else + None + in match additional with | Some ns' -> [ns; ns'] | None -> [ns] diff --git a/tests/haste_namespaces/.flowconfig b/tests/haste_namespaces/.flowconfig new file mode 100644 index 00000000000..676db01980b --- /dev/null +++ b/tests/haste_namespaces/.flowconfig @@ -0,0 +1,9 @@ +[options] +all=true +module.system=haste +module.system.haste.experimental.namespaces=web +module.system.haste.experimental.namespaces=native +module.system.haste.experimental.namespace_path_mapping='/common/web' -> 'web' +module.system.haste.experimental.namespace_path_mapping='/common/' -> 'web,native' +module.system.haste.experimental.namespace_path_mapping='/web/' -> 'web' +module.system.haste.experimental.namespace_path_mapping='/native/' -> 'native' diff --git a/tests/haste_namespaces/common/Common.js b/tests/haste_namespaces/common/Common.js new file mode 100644 index 00000000000..b2102194cb4 --- /dev/null +++ b/tests/haste_namespaces/common/Common.js @@ -0,0 +1,5 @@ +import { native } from "NativeOnly"; // error: common code cannot import native-only code +import { web } from "WebOnly"; // ok: common code can import web-only code, because web-only code is treated as implicit common interface. TODO: common interface validation is missing for now + +web as empty; // error: string ~> empty +native as empty; diff --git a/tests/haste_namespaces/common/CommonLib.js b/tests/haste_namespaces/common/CommonLib.js new file mode 100644 index 00000000000..38260971ad6 --- /dev/null +++ b/tests/haste_namespaces/common/CommonLib.js @@ -0,0 +1 @@ +declare export const foo: string; diff --git a/tests/haste_namespaces/common/web/WebInCommon.js b/tests/haste_namespaces/common/web/WebInCommon.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/haste_namespaces/haste_namespaces.exp b/tests/haste_namespaces/haste_namespaces.exp new file mode 100644 index 00000000000..91f444f1b96 --- /dev/null +++ b/tests/haste_namespaces/haste_namespaces.exp @@ -0,0 +1,69 @@ +Error -------------------------------------------------------------------------------------------- common/Common.js:1:24 + +Cannot resolve module `NativeOnly`. [cannot-resolve-module] + + 1| import { native } from "NativeOnly"; // error: common code cannot import native-only code + ^^^^^^^^^^^^ + + +Error --------------------------------------------------------------------------------------------- common/Common.js:4:1 + +Cannot cast `web` to empty because string [1] is incompatible with empty [2]. [incompatible-cast] + + common/Common.js:4:1 + 4| web as empty; // error: string ~> empty + ^^^ + +References: + web/WebOnly.js:6:27 + 6| declare export const web: string; + ^^^^^^ [1] + common/Common.js:4:8 + 4| web as empty; // error: string ~> empty + ^^^^^ [2] + + +Error ----------------------------------------------------------------------------------------- native/NativeOnly.js:4:1 + +Cannot cast `foo` to empty because string [1] is incompatible with empty [2]. [incompatible-cast] + + native/NativeOnly.js:4:1 + 4| foo as empty; // error: string ~> empty + ^^^ + +References: + common/CommonLib.js:1:27 + 1| declare export const foo: string; + ^^^^^^ [1] + native/NativeOnly.js:4:8 + 4| foo as empty; // error: string ~> empty + ^^^^^ [2] + + +Error ----------------------------------------------------------------------------------------- native/NativeOnly.js:8:8 + +Cannot resolve module `WebInCommon`. [cannot-resolve-module] + + 8| import 'WebInCommon' // error: native code cannot import web code. This one tests the precedence rule in flowconfig + ^^^^^^^^^^^^^ + + +Error ----------------------------------------------------------------------------------------------- web/WebOnly.js:4:1 + +Cannot cast `foo` to empty because string [1] is incompatible with empty [2]. [incompatible-cast] + + web/WebOnly.js:4:1 + 4| foo as empty; // error: string ~> empty + ^^^ + +References: + common/CommonLib.js:1:27 + 1| declare export const foo: string; + ^^^^^^ [1] + web/WebOnly.js:4:8 + 4| foo as empty; // error: string ~> empty + ^^^^^ [2] + + + +Found 5 errors diff --git a/tests/haste_namespaces/native/Forked.js b/tests/haste_namespaces/native/Forked.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/haste_namespaces/native/NativeOnly.js b/tests/haste_namespaces/native/NativeOnly.js new file mode 100644 index 00000000000..08e0afd5474 --- /dev/null +++ b/tests/haste_namespaces/native/NativeOnly.js @@ -0,0 +1,8 @@ +import { foo } from "CommonLib"; + +foo as string; +foo as empty; // error: string ~> empty + +declare export const native: string; + +import 'WebInCommon' // error: native code cannot import web code. This one tests the precedence rule in flowconfig diff --git a/tests/haste_namespaces/web/Native.js b/tests/haste_namespaces/web/Native.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/haste_namespaces/web/WebOnly.js b/tests/haste_namespaces/web/WebOnly.js new file mode 100644 index 00000000000..04bb2ba501a --- /dev/null +++ b/tests/haste_namespaces/web/WebOnly.js @@ -0,0 +1,6 @@ +import { foo } from "CommonLib"; + +foo as string; +foo as empty; // error: string ~> empty + +declare export const web: string;