@ -52,16 +52,20 @@ let read_package_declaration source_file =
Utils . with_file_in path ~ f : loop | > Option . value ~ default : " "
let add_source_file path map =
let add_source_file =
let cwd = lazy ( Sys . getcwd () ) in
let convert_to_absolute p =
if Filename . is_relative p then Filename . concat ( Sys. getcwd () ) p else p
if Filename . is_relative p then Filename . concat ( Lazy. force cwd ) p else p
in
let basename = Filename . basename path in
let entry =
let current_source_file = SourceFile . from_abs_path ( convert_to_absolute path ) in
try
match String . Map . find_exn map basename with
| Singleton previous_source_file ->
fun path map ->
let basename = Filename . basename path in
let entry =
let current_source_file = SourceFile . from_abs_path ( convert_to_absolute path ) in
match String . Map . find map basename with
| None ->
(* Most common case: there is no conflict with the base name of the source file *)
Singleton current_source_file
| Some ( Singleton previous_source_file ) ->
(* Another source file with the same base name has been found.
Reading the package from the source file to resolve the ambiguity
only happens in this case * )
@ -71,73 +75,70 @@ let add_source_file path map =
[ ( current_package , current_source_file ) ; ( previous_package , previous_source_file ) ]
in
Duplicate source_list
| Duplicate previous_source_files ->
| Some ( Duplicate previous_source_files ) ->
(* Two or more source file with the same base name have been found *)
let current_package = read_package_declaration current_source_file in
Duplicate ( ( current_package , current_source_file ) :: previous_source_files )
with Not_found_s _ | Caml . Not_found ->
(* Most common case: there is no conflict with the base name of the source file *)
Singleton current_source_file
in
String . Map . set ~ key : basename ~ data : entry map
in
String . Map . set ~ key : basename ~ data : entry map
let add_root_path path roots = String . Set . add roots path
let load_from_verbose_output javac_verbose_out =
let file_in = In_channel . create javac_verbose_out in
let load_from_verbose_output =
let class_filename_re =
Str. regexp
( Printf . sprintf
(* the unreadable regexp below captures 3 possible forms:
1 . [ wrote DirectoryFileObject [ / path / to / classes_out : path / to / File . java ] ] , leaves ` path / to / File . java ` in match group 2
2 . [ wrote Regular FileObject[ path / to / File . java ] ] , leaves ` path / to / File . java ` in match group 5
3 . [ wrote SimpleFileObject [ path / to / File . java ] ] , also leaves ` path / to / File . java ` in match group 5
4 . [ wrote path / to / File . java ] leaves ` path / to / File . java ` in match group 6 ( from java 11 ) * )
" \\ [wrote \
\ \ ( DirectoryFileObject \ \ [ % s : \ \ ( . * \ \ ) \ \ | \ \ ( \ \ ( Regular \ \ | Simple \ \ ) FileObject \ \ [ \ \ ( . * \ \ ) \ \ ) \ \ ] \ \ | \ \ ( . * \ \ ) \ \ ) \ \ ] "
Config . javac_classes_out )
Printf. sprintf
(* the unreadable regexp below captures 3 possible forms:
1 . [ wrote DirectoryFileObject [ / path / to / classes_out : path / to / File . java ] ] , leaves ` path / to / File . java ` in match group 2
2 . [ wrote RegularFileObject [ path / to / File . java ] ] , leaves ` path / to / File . java ` in match group 5
3 . [ wrote Simple FileObject[ path / to / File . java ] ] , also leaves ` path / to / File . java ` in match group 5
4 . [ wrote path / to / File . java ] leaves ` path / to / File . java ` in match group 6 ( from java 11 ) * )
" \\ [wrote \
\ \ ( DirectoryFileObject \ \ [ % s : \ \ ( . * \ \ ) \ \ | \ \ ( \ \ ( Regular \ \ | Simple \ \ ) FileObject \ \ [ \ \ ( . * \ \ ) \ \ ) \ \ ] \ \ | \ \ ( . * \ \ ) \ \ ) \ \ ] "
Config . javac_classes_out
| > Str . regexp
in
let source_filename_re =
Str . regexp " \\ [parsing started \\ (Regular \\ |Simple \\ )FileObject \\ [ \\ (.* \\ ) \\ ] \\ ] "
in
let classpath_re = Str . regexp " \\ [search path for class files: \\ (.* \\ ) \\ ] " in
let rec loop paths roots sources classes =
match In_channel . input_line_exn file_in with
| exception End_of_file ->
In_channel . close file_in ;
let rec loop paths roots sources classes file_in =
match In_channel . input_line file_in with
| None ->
let classpath = classpath_of_paths ( String . Set . elements roots @ paths ) in
{ classpath ; sources ; classes }
| line ->
if Str . string_match class_filename_re line 0 then
let path =
try Str . matched_group 5 line
with Caml . Not_found -> (
try Config . javac_classes_out ^/ Str . matched_group 2 line
with Caml . Not_found ->
(* either matched group 5, 6, or 2 is found, see doc for [class_filename_re] above * )
Str . matched_group 6 line )
in
match Javalib . extract_class_name_from_file path with
| exception ( JBasics . Class_structure_error _ | Invalid_argument _ ) ->
( loop [ @ tailcall ] ) paths roots sources classes
| cn , root_info ->
let root_dir =
i f Stri ng. equal root_info " " then Filename . current_dir_name else root_info
in
( loop [ @ tailcall ] ) paths ( add_root_path root_dir roots ) sources
( JBasics . ClassSet . add cn classes )
else if Str . string_match source_filename_re line 0 the n
let path = Str . matched_group 2 line in
( loop [ @ tailcall ] ) paths roots ( add_source_file path sources ) classes
else if Str . string_match classpath_re line 0 the n
let classpath = Str . matched_group 1 line in
let parsed_paths = String . split ~ on : ',' classpath in
( loop [ @ tailcall ] ) parsed_paths roots sources classes
else (* skip this line *)
( loop [ @ tailcall ] ) paths roots sources classes
| Some line when Str . string_match class_filename_re line 0 -> (
let path =
try Str . matched_group 5 line
with Caml . Not_found -> (
try Config . javac_classes_out ^/ Str . matched_group 2 line
with Caml . Not_found ->
(* either matched group 5, 6, or 2 is found, see doc for [class_filename_re] above *)
Str . matched_group 6 line )
in
match Javalib . extract_class_name_from_file path with
| exception ( JBasics . Class_structure_error _ | Invalid_argument _ ) ->
loop paths roots sources classes file_in
| cn , root_info ->
let root_dir =
if String . equal root_info " " then Filename . current_dir_name else root_info
i n
loop paths ( add_root_path root_dir roots ) sources ( JBasics . ClassSet . add cn classes )
file_in )
| Some line when Str . string_match source_filename_re line 0 ->
let path = Str . matched_group 2 line i n
loop paths roots ( add_source_file path sources ) classes file_ in
| Some line when Str . string_match classpath_re line 0 ->
let classpath = Str . matched_group 1 line i n
let parsed_paths = String . split ~ on : ',' classpath in
loop parsed_paths roots sources classes file_ in
| _ ->
(* skip this line *)
loop paths roots sources classes file_in
in
loop [] String . Set . empty String . Map . empty JBasics . ClassSet . empty
fun javac_verbose_out ->
Utils . with_file_in javac_verbose_out
~ f : ( loop [] String . Set . empty String . Map . empty JBasics . ClassSet . empty )
let collect_classnames init jar_filename =
@ -187,6 +188,7 @@ let load_from_arguments classes_out_path =
let roots , classes = search_classes classes_out_path in
let split cp_option = Option . value_map ~ f : split_classpath ~ default : [] cp_option in
let classpath =
(* order follows https://docs.oracle.com/javase/7/docs/technotes/tools/windows/classpath.html *)
split Config . bootclasspath @ split Config . classpath @ String . Set . elements roots
| > classpath_of_paths
in