Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/compiler/args.ml
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,9 @@ let parse_args com =
let pack, target = (try ExtString.String.split s ":" with _ -> raise (Arg.Bad "Invalid remap format, expected source:target")) in
com.package_rules <- PMap.add pack (Remap target) com.package_rules;
),"<package:target>","remap a package to another one");
("Compilation",["--custom-extension"],[],Arg.String (fun ext ->
com.custom_ext <- Some ext;
),"<extension>","custom extension used to shadow modules with Module.custom.hx files");
("Compilation",["--macro"],[], Arg.String (fun e ->
actx.force_typing <- true;
actx.config_macros <- e :: actx.config_macros
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/compiler.ml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ let run_command ctx cmd =
module Setup = struct
let initialize_target ctx com actx =
init_platform com;
com.class_paths#lock_context (platform_name com.platform) false;
com.class_paths#lock_context com.custom_ext (platform_name com.platform) false;
let add_std dir =
com.class_paths#modify_inplace (fun cp -> match cp#scope with
| Std ->
Expand Down
3 changes: 3 additions & 0 deletions src/context/common.ml
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ type context = {
mutable doinline : bool;
mutable platform : platform;
mutable config : PlatformConfig.platform_config;
mutable custom_ext : string option;
empty_class_path : ClassPath.class_path;
class_paths : ClassPaths.class_paths;
main : Gctx.context_main;
Expand Down Expand Up @@ -746,6 +747,7 @@ let create timer_ctx compilation_step cs version args display_mode =
features = Hashtbl.create 0;
platform = Cross;
config = default_config;
custom_ext = None;
print = (fun s -> print_string s; flush stdout);
run_command = Sys.command;
run_command_args = (fun s args -> com.run_command (Printf.sprintf "%s %s" s (String.concat " " args)));
Expand Down Expand Up @@ -854,6 +856,7 @@ let clone com is_macro_context =
doinline = com.doinline;
platform = com.platform;
config = com.config;
custom_ext = com.custom_ext;
print = com.print;
run_command = com.run_command;
run_command_args = com.run_command_args;
Expand Down
3 changes: 2 additions & 1 deletion src/context/display/displayToplevel.ml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ class explore_class_path_task com checked recursive f_pack f_module dir pack = o
let name = String.sub file 0 (l - 3) in
try
let dot_pos = String.rindex name '.' in
if platform_str = String.sub file dot_pos (String.length name - dot_pos) then
let second_ext = String.sub file dot_pos (String.length name - dot_pos) in
if (Option.map_default (fun custom_ext -> custom_ext = second_ext) false com.custom_ext) || platform_str = second_ext then
String.sub file 0 dot_pos
else
raise Exit
Expand Down
7 changes: 7 additions & 0 deletions src/context/lookup.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ class virtual ['key,'value] lookup = object(self)
method virtual add : 'key -> 'value -> unit
method virtual remove : 'key -> unit
method virtual find : 'key -> 'value
method virtual find_opt : 'key -> 'value option
method virtual iter : ('key -> 'value -> unit) -> unit
method virtual fold : 'acc . ('key -> 'value -> 'acc -> 'acc) -> 'acc -> 'acc
method virtual mem : 'key -> bool
Expand All @@ -22,6 +23,9 @@ class ['key,'value] pmap_lookup = object(self)
method find (key : 'key) : 'value =
PMap.find key lut

method find_opt (key : 'key) : 'value option =
try Some (PMap.find key lut) with Not_found -> None

method iter (f : 'key -> 'value -> unit) =
PMap.iter f lut

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

method find_opt (key : 'key) : 'value option =
Hashtbl.find_opt lut key

method iter (f : 'key -> 'value -> unit) =
Hashtbl.iter f lut

Expand Down
78 changes: 44 additions & 34 deletions src/core/classPaths.ml
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,25 @@ let create_resolved_file file class_path = {
class_path;
}

type file_resolution_specificity =
| SpecificityNormal (* Standard Module.hx file *)
| SpecificityPlatformSpecific (* Module.[platform].hx file matching current platform *)
| SpecificityCustomExtension (* Module.[custom].hx file matching --custom-extension config *)
| SpecificityMacroSpecific (* Module.macro.hx file while in macro context *)
| SpecificityCoreApi (* Module.hx takes priority when loading @:coreApi types *)

(* We need to clean-up absolute ("") vs. cwd ("."). *)
let absolute_class_path = new directory_class_path "" User

class class_paths = object(self)
val mutable l = []
val file_lookup_cache = new Lookup.hashtbl_lookup;
val mutable custom_ext = None
val mutable platform_ext = ""
val mutable is_loading_core_api = false

method lock_context (platform_name : string) (core_api : bool) : unit =
method lock_context (custom_extension : string option) (platform_name : string) (core_api : bool) : unit =
custom_ext <- Option.map (fun ext -> "." ^ ext) custom_extension;
platform_ext <- "." ^ platform_name;
is_loading_core_api <- core_api;
self#clear_cache
Expand Down Expand Up @@ -76,59 +85,60 @@ class class_paths = object(self)
(*
This function is invoked for each file in the `dir`.
Each file is checked if it's specific for current platform
(e.g. ends with `.js.hx` while compiling for JS).
If it's not platform-specific:
Check the lookup cache and if the file is not there store full file path in the cache.
If the file is platform-specific:
Store the full file path in the lookup cache probably replacing the cached path to a
non-platform-specific file.
(e.g. ends with `.js.hx` while compiling for JS) or current
custom extension (e.g. ends with `.custom.hx` while compiling
with `--custom-extension custom`)

The lookup cache will store the full file path which is the more
specific in current context (see `file_resolution_specificity` type)
*)
let found = ref None in
let f_dir = Filename.dirname f_search in
let prepare_file file_own_name =
let relative_to_classpath = if f_dir = "." then file_own_name else f_dir ^ "/" ^ file_own_name in
(* `representation` is how the file is referenced to. E.g. when it's deduced from a module path. *)
let is_platform_specific,representation =
(* Platform specific file extensions are not allowed for loading @:coreApi types. *)
let specificity,representation =
if is_loading_core_api then
false,relative_to_classpath
SpecificityCoreApi,relative_to_classpath
else begin
let ext = extension relative_to_classpath in
let second_ext = extension (remove_extension relative_to_classpath) in
(* The file contains double extension and the secondary one matches current custom extension *)
if (Option.map_default (fun custom_ext -> custom_ext = second_ext) false custom_ext) then
SpecificityCustomExtension,(remove_extension (remove_extension relative_to_classpath)) ^ ext
(* The file contains ".macro.hx" double extension and we are in macro context *)
else if platform_ext = second_ext && second_ext = ".macro" then
SpecificityMacroSpecific,(remove_extension (remove_extension relative_to_classpath)) ^ ext
(* The file contains double extension and the secondary one matches current platform *)
if platform_ext = second_ext then
true,(remove_extension (remove_extension relative_to_classpath)) ^ ext
else if platform_ext = second_ext then
SpecificityPlatformSpecific,(remove_extension (remove_extension relative_to_classpath)) ^ ext
else
false,relative_to_classpath
SpecificityNormal,relative_to_classpath
end
in
(*
Store current full path for `representation` if
- we're loading @:coreApi
- or this is a platform-specific file for `representation`
- this `representation` was never found before
*)
if is_loading_core_api || is_platform_specific || not (file_lookup_cache#mem representation) then begin
let full_path = if dir = "." then file_own_name else dir ^ "/" ^ file_own_name in
let full_path = Some(create_resolved_file full_path cp) in
file_lookup_cache#add representation full_path;
if representation = f_search then found := full_path
end

let full_path = if dir = "." then file_own_name else dir ^ "/" ^ file_own_name in
let full_path = Some(create_resolved_file full_path cp, specificity) in

match file_lookup_cache#find_opt representation with
| Some (Some (_, old_specificity)) when (old_specificity >= specificity)-> ()
| _ -> file_lookup_cache#add representation full_path;

if representation = f_search then
match !found with
| Some (_, old_specificity) when (old_specificity >= specificity) -> ()
| _ -> found := full_path;
in
Array.iter prepare_file dir_listing;
!found

method find_file_noraise (f : string) =
try
match file_lookup_cache#find f with
| None ->
None
| Some f ->
Some f
file_lookup_cache#find f
with
| Not_found when Path.is_absolute_path f ->
let r = if Sys.file_exists f then
Some (create_resolved_file f absolute_class_path)
Some (create_resolved_file f absolute_class_path, SpecificityNormal)
else
None
in
Expand All @@ -144,8 +154,8 @@ class class_paths = object(self)
loop l
| Some(dir,dir_listing) ->
match self#cache_directory cp dir f dir_listing with
| Some f ->
Some f
| Some (f, specificity) ->
Some (f, specificity)
| None ->
loop l
end
Expand All @@ -157,7 +167,7 @@ class class_paths = object(self)
method find_file (f : string) =
match self#find_file_noraise f with
| None -> raise Not_found
| Some f -> f
| Some (f, _) -> f

method relative_path file =
let slashes path = String.concat "/" (ExtString.String.nsplit path "\\") in
Expand Down
2 changes: 1 addition & 1 deletion src/typing/macroContext.ml
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ let create_macro_context com =
com2.package_rules <- PMap.empty;
(* Inherit most display settings, but require normal typing. *)
com2.display <- {com.display with dms_kind = DMNone; dms_full_typing = true; dms_force_macro_typing = true; dms_inline = true; };
com2.class_paths#lock_context "macro" false;
com2.class_paths#lock_context com2.custom_ext "macro" false;
let name = platform_name Eval in
let eval_std = ref None in
com2.class_paths#modify (fun cp -> match cp#scope with
Expand Down
2 changes: 1 addition & 1 deletion src/typing/typeload.ml
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,7 @@ let load_core_class ctx c =
allow_package com2 "sys";
Define.raw_define_value com2.defines "target.threaded" "true"; (* hack because we check this in sys.thread classes *)
if ctx.com.is_macro_context then Common.define com2 Define.Macro;
com2.class_paths#lock_context (platform_name_macro ctx.com) true;
com2.class_paths#lock_context ctx.com.custom_ext (platform_name_macro ctx.com) true;
com2.class_paths#modify (fun cp -> match cp#scope with
| Std ->
[cp#clone]
Expand Down
8 changes: 8 additions & 0 deletions tests/misc/customExt/Bar.api.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class Bar {
public static function bar() {
trace("Hello from Bar.hx");
test();
}

static macro function test() return macro trace("Hello from Bar.hx macro");
}
5 changes: 5 additions & 0 deletions tests/misc/customExt/Bar.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Bar {
public static function bar() {
trace("Hello from Bar.hx");
}
}
9 changes: 9 additions & 0 deletions tests/misc/customExt/Foo.api.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Foo {
public static function bar() {
trace("Hello from Foo.hx");
var foo:Bool = true;
test();
}

static macro function test();
}
9 changes: 9 additions & 0 deletions tests/misc/customExt/Foo.eval.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Foo {
public static function bar() {
trace("Hello from Foo.hx");
var foo:Bool = true;
test();
}

static macro function test();
}
1 change: 1 addition & 0 deletions tests/misc/customExt/Foo.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#error "Foo.hx should not be used"
5 changes: 5 additions & 0 deletions tests/misc/customExt/Foo.macro.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Foo {
public static macro function test() {
return macro trace("Hello from macro");
}
}
7 changes: 7 additions & 0 deletions tests/misc/customExt/Main.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Main {
static public function main() {
Foo.bar();
Bar.bar();
}
}

1 change: 1 addition & 0 deletions tests/misc/customExt/compile1.hxml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--run Main
3 changes: 3 additions & 0 deletions tests/misc/customExt/compile1.hxml.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Foo.eval.hx:3: Hello from Foo.hx
Foo.macro.hx:3: Hello from macro
Bar.hx:3: Hello from Bar.hx
2 changes: 2 additions & 0 deletions tests/misc/customExt/compile2.hxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--custom-extension api
--run Main
4 changes: 4 additions & 0 deletions tests/misc/customExt/compile2.hxml.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Foo.api.hx:3: Hello from Foo.hx
Foo.macro.hx:3: Hello from macro
Bar.api.hx:3: Hello from Bar.hx
Bar.api.hx:7: Hello from Bar.hx macro
Loading