@@ -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 ("."). *)
1522let absolute_class_path = new directory_class_path " " User
1623
1724class 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
0 commit comments