Skip to content

Commit dc9c560

Browse files
authored
Add support for .custom.hx handling (#12397)
1 parent 2a81f68 commit dc9c560

File tree

19 files changed

+116
-38
lines changed

19 files changed

+116
-38
lines changed

src/compiler/args.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@ let parse_args com =
277277
let pack, target = (try ExtString.String.split s ":" with _ -> raise (Arg.Bad "Invalid remap format, expected source:target")) in
278278
com.package_rules <- PMap.add pack (Remap target) com.package_rules;
279279
),"<package:target>","remap a package to another one");
280+
("Compilation",["--custom-extension"],[],Arg.String (fun ext ->
281+
com.custom_ext <- Some ext;
282+
),"<extension>","custom extension used to shadow modules with Module.custom.hx files");
280283
("Compilation",["--macro"],[], Arg.String (fun e ->
281284
actx.force_typing <- true;
282285
actx.config_macros <- e :: actx.config_macros

src/compiler/compiler.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ let run_command ctx cmd =
7979
module Setup = struct
8080
let initialize_target ctx com actx =
8181
init_platform com;
82-
com.class_paths#lock_context (platform_name com.platform) false;
82+
com.class_paths#lock_context com.custom_ext (platform_name com.platform) false;
8383
let add_std dir =
8484
com.class_paths#modify_inplace (fun cp -> match cp#scope with
8585
| Std ->

src/context/common.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ type context = {
282282
mutable doinline : bool;
283283
mutable platform : platform;
284284
mutable config : PlatformConfig.platform_config;
285+
mutable custom_ext : string option;
285286
empty_class_path : ClassPath.class_path;
286287
class_paths : ClassPaths.class_paths;
287288
main : Gctx.context_main;
@@ -746,6 +747,7 @@ let create timer_ctx compilation_step cs version args display_mode =
746747
features = Hashtbl.create 0;
747748
platform = Cross;
748749
config = default_config;
750+
custom_ext = None;
749751
print = (fun s -> print_string s; flush stdout);
750752
run_command = Sys.command;
751753
run_command_args = (fun s args -> com.run_command (Printf.sprintf "%s %s" s (String.concat " " args)));
@@ -854,6 +856,7 @@ let clone com is_macro_context =
854856
doinline = com.doinline;
855857
platform = com.platform;
856858
config = com.config;
859+
custom_ext = com.custom_ext;
857860
print = com.print;
858861
run_command = com.run_command;
859862
run_command_args = com.run_command_args;

src/context/display/displayToplevel.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ class explore_class_path_task com checked recursive f_pack f_module dir pack = o
8989
let name = String.sub file 0 (l - 3) in
9090
try
9191
let dot_pos = String.rindex name '.' in
92-
if platform_str = String.sub file dot_pos (String.length name - dot_pos) then
92+
let second_ext = String.sub file dot_pos (String.length name - dot_pos) in
93+
if (Option.map_default (fun custom_ext -> custom_ext = second_ext) false com.custom_ext) || platform_str = second_ext then
9394
String.sub file 0 dot_pos
9495
else
9596
raise Exit

src/context/lookup.ml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ class virtual ['key,'value] lookup = object(self)
33
method virtual add : 'key -> 'value -> unit
44
method virtual remove : 'key -> unit
55
method virtual find : 'key -> 'value
6+
method virtual find_opt : 'key -> 'value option
67
method virtual iter : ('key -> 'value -> unit) -> unit
78
method virtual fold : 'acc . ('key -> 'value -> 'acc -> 'acc) -> 'acc -> 'acc
89
method virtual mem : 'key -> bool
@@ -22,6 +23,9 @@ class ['key,'value] pmap_lookup = object(self)
2223
method find (key : 'key) : 'value =
2324
PMap.find key lut
2425

26+
method find_opt (key : 'key) : 'value option =
27+
try Some (PMap.find key lut) with Not_found -> None
28+
2529
method iter (f : 'key -> 'value -> unit) =
2630
PMap.iter f lut
2731

@@ -48,6 +52,9 @@ class ['key,'value] hashtbl_lookup = object(self)
4852
method find (key : 'key) : 'value =
4953
Hashtbl.find lut key
5054

55+
method find_opt (key : 'key) : 'value option =
56+
Hashtbl.find_opt lut key
57+
5158
method iter (f : 'key -> 'value -> unit) =
5259
Hashtbl.iter f lut
5360

src/core/classPaths.ml

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,25 @@ let create_resolved_file file class_path = {
1111
class_path;
1212
}
1313

14+
type file_resolution_specificity =
15+
| SpecificityNormal (* Standard Module.hx file *)
16+
| SpecificityPlatformSpecific (* Module.[platform].hx file matching current platform *)
17+
| SpecificityCustomExtension (* Module.[custom].hx file matching --custom-extension config *)
18+
| SpecificityMacroSpecific (* Module.macro.hx file while in macro context *)
19+
| SpecificityCoreApi (* Module.hx takes priority when loading @:coreApi types *)
20+
1421
(* We need to clean-up absolute ("") vs. cwd ("."). *)
1522
let absolute_class_path = new directory_class_path "" User
1623

1724
class class_paths = object(self)
1825
val mutable l = []
1926
val file_lookup_cache = new Lookup.hashtbl_lookup;
27+
val mutable custom_ext = None
2028
val mutable platform_ext = ""
2129
val mutable is_loading_core_api = false
2230

23-
method lock_context (platform_name : string) (core_api : bool) : unit =
31+
method lock_context (custom_extension : string option) (platform_name : string) (core_api : bool) : unit =
32+
custom_ext <- Option.map (fun ext -> "." ^ ext) custom_extension;
2433
platform_ext <- "." ^ platform_name;
2534
is_loading_core_api <- core_api;
2635
self#clear_cache
@@ -76,59 +85,60 @@ class class_paths = object(self)
7685
(*
7786
This function is invoked for each file in the `dir`.
7887
Each file is checked if it's specific for current platform
79-
(e.g. ends with `.js.hx` while compiling for JS).
80-
If it's not platform-specific:
81-
Check the lookup cache and if the file is not there store full file path in the cache.
82-
If the file is platform-specific:
83-
Store the full file path in the lookup cache probably replacing the cached path to a
84-
non-platform-specific file.
88+
(e.g. ends with `.js.hx` while compiling for JS) or current
89+
custom extension (e.g. ends with `.custom.hx` while compiling
90+
with `--custom-extension custom`)
91+
92+
The lookup cache will store the full file path which is the more
93+
specific in current context (see `file_resolution_specificity` type)
8594
*)
8695
let found = ref None in
8796
let f_dir = Filename.dirname f_search in
8897
let prepare_file file_own_name =
8998
let relative_to_classpath = if f_dir = "." then file_own_name else f_dir ^ "/" ^ file_own_name in
9099
(* `representation` is how the file is referenced to. E.g. when it's deduced from a module path. *)
91-
let is_platform_specific,representation =
92-
(* Platform specific file extensions are not allowed for loading @:coreApi types. *)
100+
let specificity,representation =
93101
if is_loading_core_api then
94-
false,relative_to_classpath
102+
SpecificityCoreApi,relative_to_classpath
95103
else begin
96104
let ext = extension relative_to_classpath in
97105
let second_ext = extension (remove_extension relative_to_classpath) in
106+
(* The file contains double extension and the secondary one matches current custom extension *)
107+
if (Option.map_default (fun custom_ext -> custom_ext = second_ext) false custom_ext) then
108+
SpecificityCustomExtension,(remove_extension (remove_extension relative_to_classpath)) ^ ext
109+
(* The file contains ".macro.hx" double extension and we are in macro context *)
110+
else if platform_ext = second_ext && second_ext = ".macro" then
111+
SpecificityMacroSpecific,(remove_extension (remove_extension relative_to_classpath)) ^ ext
98112
(* The file contains double extension and the secondary one matches current platform *)
99-
if platform_ext = second_ext then
100-
true,(remove_extension (remove_extension relative_to_classpath)) ^ ext
113+
else if platform_ext = second_ext then
114+
SpecificityPlatformSpecific,(remove_extension (remove_extension relative_to_classpath)) ^ ext
101115
else
102-
false,relative_to_classpath
116+
SpecificityNormal,relative_to_classpath
103117
end
104118
in
105-
(*
106-
Store current full path for `representation` if
107-
- we're loading @:coreApi
108-
- or this is a platform-specific file for `representation`
109-
- this `representation` was never found before
110-
*)
111-
if is_loading_core_api || is_platform_specific || not (file_lookup_cache#mem representation) then begin
112-
let full_path = if dir = "." then file_own_name else dir ^ "/" ^ file_own_name in
113-
let full_path = Some(create_resolved_file full_path cp) in
114-
file_lookup_cache#add representation full_path;
115-
if representation = f_search then found := full_path
116-
end
119+
120+
let full_path = if dir = "." then file_own_name else dir ^ "/" ^ file_own_name in
121+
let full_path = Some(create_resolved_file full_path cp, specificity) in
122+
123+
match file_lookup_cache#find_opt representation with
124+
| Some (Some (_, old_specificity)) when (old_specificity >= specificity)-> ()
125+
| _ -> file_lookup_cache#add representation full_path;
126+
127+
if representation = f_search then
128+
match !found with
129+
| Some (_, old_specificity) when (old_specificity >= specificity) -> ()
130+
| _ -> found := full_path;
117131
in
118132
Array.iter prepare_file dir_listing;
119133
!found
120134

121135
method find_file_noraise (f : string) =
122136
try
123-
match file_lookup_cache#find f with
124-
| None ->
125-
None
126-
| Some f ->
127-
Some f
137+
file_lookup_cache#find f
128138
with
129139
| Not_found when Path.is_absolute_path f ->
130140
let r = if Sys.file_exists f then
131-
Some (create_resolved_file f absolute_class_path)
141+
Some (create_resolved_file f absolute_class_path, SpecificityNormal)
132142
else
133143
None
134144
in
@@ -144,8 +154,8 @@ class class_paths = object(self)
144154
loop l
145155
| Some(dir,dir_listing) ->
146156
match self#cache_directory cp dir f dir_listing with
147-
| Some f ->
148-
Some f
157+
| Some (f, specificity) ->
158+
Some (f, specificity)
149159
| None ->
150160
loop l
151161
end
@@ -157,7 +167,7 @@ class class_paths = object(self)
157167
method find_file (f : string) =
158168
match self#find_file_noraise f with
159169
| None -> raise Not_found
160-
| Some f -> f
170+
| Some (f, _) -> f
161171

162172
method relative_path file =
163173
let slashes path = String.concat "/" (ExtString.String.nsplit path "\\") in

src/typing/macroContext.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -716,7 +716,7 @@ let create_macro_context com =
716716
com2.package_rules <- PMap.empty;
717717
(* Inherit most display settings, but require normal typing. *)
718718
com2.display <- {com.display with dms_kind = DMNone; dms_full_typing = true; dms_force_macro_typing = true; dms_inline = true; };
719-
com2.class_paths#lock_context "macro" false;
719+
com2.class_paths#lock_context com2.custom_ext "macro" false;
720720
let name = platform_name Eval in
721721
let eval_std = ref None in
722722
com2.class_paths#modify (fun cp -> match cp#scope with

src/typing/typeload.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ let load_core_class ctx c =
799799
allow_package com2 "sys";
800800
Define.raw_define_value com2.defines "target.threaded" "true"; (* hack because we check this in sys.thread classes *)
801801
if ctx.com.is_macro_context then Common.define com2 Define.Macro;
802-
com2.class_paths#lock_context (platform_name_macro ctx.com) true;
802+
com2.class_paths#lock_context ctx.com.custom_ext (platform_name_macro ctx.com) true;
803803
com2.class_paths#modify (fun cp -> match cp#scope with
804804
| Std ->
805805
[cp#clone]

tests/misc/customExt/Bar.api.hx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class Bar {
2+
public static function bar() {
3+
trace("Hello from Bar.hx");
4+
test();
5+
}
6+
7+
static macro function test() return macro trace("Hello from Bar.hx macro");
8+
}

tests/misc/customExt/Bar.hx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class Bar {
2+
public static function bar() {
3+
trace("Hello from Bar.hx");
4+
}
5+
}

0 commit comments

Comments
 (0)