Skip to content

Commit

Permalink
Merge branch 'development' into out_of_curiosity
Browse files Browse the repository at this point in the history
# Conflicts:
#	src-json/meta.json
#	src/codegen/gencommon/normalize.ml
#	src/typing/typeloadModule.ml
  • Loading branch information
Simn committed Feb 5, 2024
2 parents f439aeb + 1242fb4 commit b5875ba
Show file tree
Hide file tree
Showing 45 changed files with 773 additions and 677 deletions.
7 changes: 0 additions & 7 deletions src-json/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,6 @@
"targets": ["TAbstract"],
"links": ["https://haxe.org/manual/types-abstract-enum.html"]
},
{
"name": "EnumConstructorParam",
"metadata": ":enumConstructorParam",
"doc": "Used internally to annotate GADT type parameters.",
"targets": ["TClass"],
"internal": true
},
{
"name": "Exhaustive",
"metadata": ":exhaustive",
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/compilationCache.ml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@ class cache = object(self)
val native_libs : (string,cached_native_lib) Hashtbl.t = Hashtbl.create 0
val mutable tasks : (server_task PriorityQueue.t) = PriorityQueue.Empty

method clear =
Hashtbl.clear contexts;
context_list <- [];
Hashtbl.clear haxelib;
Hashtbl.clear directories;
Hashtbl.clear native_libs;
tasks <- PriorityQueue.Empty

(* contexts *)

method get_context sign =
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/displayProcessing.ml
Original file line number Diff line number Diff line change
Expand Up @@ -239,15 +239,15 @@ let load_display_file_standalone (ctx : Typecore.typer) file =
let dir = ExtString.String.join (if path.backslash then "\\" else "/") parts in
com.class_paths#add (new ClassPath.directory_class_path dir User)
end;
ignore(TypeloadModule.type_module ctx (pack,name) file ~dont_check_path:true decls null_pos)
ignore(TypeloadModule.type_module ctx.com ctx.g (pack,name) file ~dont_check_path:true decls null_pos)

let load_display_content_standalone (ctx : Typecore.typer) input =
let com = ctx.com in
let file = file_input_marker in
let p = {pfile = file; pmin = 0; pmax = 0} in
let parsed = TypeloadParse.parse_file_from_string com file p input in
let pack,decls = TypeloadParse.handle_parser_result com p parsed in
ignore(TypeloadModule.type_module ctx (pack,"?DISPLAY") file ~dont_check_path:true decls p)
ignore(TypeloadModule.type_module ctx.com ctx.g (pack,"?DISPLAY") file ~dont_check_path:true decls p)

(* 4. Display processing before typing *)

Expand Down
80 changes: 35 additions & 45 deletions src/compiler/server.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ open Common
open CompilationCache
open Timer
open Type
open Typecore
open DisplayProcessingGlobals
open Ipaddr
open Json
open CompilationContext
open MessageReporting
open HxbData
open TypeloadCacheHook

exception Dirty of module_skip_reason
exception ServerError of string
Expand Down Expand Up @@ -162,10 +162,9 @@ let stat dir =
(Unix.stat (Path.remove_trailing_slash dir)).Unix.st_mtime

(* Gets a list of changed directories for the current compilation. *)
let get_changed_directories sctx (ctx : Typecore.typer) =
let get_changed_directories sctx com =
let t = Timer.timer ["server";"module cache";"changed dirs"] in
let cs = sctx.cs in
let com = ctx.Typecore.com in
let sign = Define.get_signature com.defines in
let dirs = try
(* First, check if we already have determined changed directories for current compilation. *)
Expand Down Expand Up @@ -229,16 +228,15 @@ let get_changed_directories sctx (ctx : Typecore.typer) =

(* Checks if module [m] can be reused from the cache and returns None in that case. Otherwise, returns
[Some m'] where [m'] is the module responsible for [m] not being reusable. *)
let check_module sctx ctx m_path m_extra p =
let com = ctx.Typecore.com in
let check_module sctx com m_path m_extra p =
let cc = CommonCache.get_cache com in
let content_changed m_path file =
let fkey = ctx.com.file_keys#get file in
let fkey = com.file_keys#get file in
try
let cfile = cc#find_file fkey in
(* We must use the module path here because the file path is absolute and would cause
positions in the parsed declarations to differ. *)
let new_data = TypeloadParse.parse_module ctx m_path p in
let new_data = TypeloadParse.parse_module com m_path p in
cfile.c_decls <> snd new_data
with Not_found ->
true
Expand All @@ -259,7 +257,7 @@ let check_module sctx ctx m_path m_extra p =
let unknown_state_modules = ref [] in
let rec check m_path m_extra =
let check_module_path () =
let directories = get_changed_directories sctx ctx in
let directories = get_changed_directories sctx com in
match m_extra.m_kind with
| MFake | MImport -> () (* don't get classpath *)
| MExtern ->
Expand All @@ -285,18 +283,12 @@ let check_module sctx ctx m_path m_extra p =
| MMacro when com.is_macro_context ->
check_module_shadowing directories m_path m_extra
| MMacro ->
(*
Creating another context while the previous one is incomplete means we have an infinite loop in the compiler.
Most likely because of circular dependencies in base modules (e.g. `StdTypes` or `String`)
Prevents spending another 5 hours for debugging.
@see https://github.com/HaxeFoundation/haxe/issues/8174
*)
if not ctx.g.complete && ctx.com.is_macro_context then
raise (ServerError ("Infinite loop in Haxe server detected. "
^ "Probably caused by shadowing a module of the standard library. "
^ "Make sure shadowed module does not pull macro context."));
let mctx = MacroContext.get_macro_context ctx in
check_module_shadowing (get_changed_directories sctx mctx) m_path m_extra
begin match com.get_macros() with
| None ->
()
| Some mcom ->
check_module_shadowing (get_changed_directories sctx mcom) m_path m_extra
end
in
let has_policy policy = List.mem policy m_extra.m_check_policy || match policy with
| NoCheckShadowing | NoCheckFileTimeModification when !ServerConfig.do_not_check_modules && !Parser.display_mode <> DMNone -> true
Expand All @@ -309,7 +301,7 @@ let check_module sctx ctx m_path m_extra p =
ServerMessage.unchanged_content com "" file;
end else begin
ServerMessage.not_cached com "" m_path;
if m_extra.m_kind = MFake then Hashtbl.remove Typecore.fake_modules (Path.UniqueKey.lazy_key m_extra.m_file);
if m_extra.m_kind = MFake then Hashtbl.remove com.fake_modules (Path.UniqueKey.lazy_key m_extra.m_file);
raise (Dirty (FileChanged file))
end
end
Expand Down Expand Up @@ -395,7 +387,7 @@ let check_module sctx ctx m_path m_extra p =
state

class hxb_reader_api_server
(ctx : Typecore.typer)
(com : Common.context)
(cc : context_cache)
= object(self)

Expand All @@ -410,7 +402,7 @@ class hxb_reader_api_server
}

method add_module (m : module_def) =
ctx.com.module_lut#add m.m_path m
com.module_lut#add m.m_path m

method resolve_type (pack : string list) (mname : string) (tname : string) =
let path = (pack,mname) in
Expand All @@ -422,7 +414,7 @@ class hxb_reader_api_server
| GoodModule m ->
m
| BinaryModule mc ->
let reader = new HxbReader.hxb_reader path ctx.com.hxb_reader_stats in
let reader = new HxbReader.hxb_reader path com.hxb_reader_stats in
let f_next chunks until =
let t_hxb = Timer.timer ["server";"module cache";"hxb read"] in
let r = reader#read_chunks_until (self :> HxbReaderApi.hxb_reader_api) chunks until in
Expand All @@ -434,7 +426,7 @@ class hxb_reader_api_server
(* We try to avoid reading expressions as much as possible, so we only do this for
our current display file if we're in display mode. *)
let is_display_file = DisplayPosition.display_position#is_in_file (Path.UniqueKey.lazy_key m.m_extra.m_file) in
if is_display_file || ctx.com.display.dms_full_typing then ignore(f_next chunks EOM);
if is_display_file || com.display.dms_full_typing then ignore(f_next chunks EOM);
m
| BadModule reason ->
die (Printf.sprintf "Unexpected BadModule %s" (s_type_path path)) __LOC__
Expand All @@ -443,7 +435,7 @@ class hxb_reader_api_server

method find_module (m_path : path) =
try
GoodModule (ctx.com.module_lut#find m_path)
GoodModule (com.module_lut#find m_path)
with Not_found -> try
let mc = cc#get_hxb_module m_path in
begin match mc.mc_extra.m_cache_state with
Expand All @@ -454,13 +446,13 @@ class hxb_reader_api_server
NoModule

method basic_types =
ctx.com.basic
com.basic

method get_var_id (i : int) =
i

method read_expression_eagerly (cf : tclass_field) =
ctx.com.display.dms_full_typing
com.display.dms_full_typing
end

let handle_cache_bound_objects com cbol =
Expand All @@ -475,12 +467,11 @@ let handle_cache_bound_objects com cbol =

(* Adds module [m] and all its dependencies (recursively) from the cache to the current compilation
context. *)
let rec add_modules sctx ctx (m : module_def) (from_binary : bool) (p : pos) =
let com = ctx.Typecore.com in
let rec add_modules sctx com (m : module_def) (from_binary : bool) (p : pos) =
let own_sign = CommonCache.get_cache_sign com in
let rec add_modules tabs m0 m =
if m.m_extra.m_added < ctx.com.compilation_step then begin
m.m_extra.m_added <- ctx.com.compilation_step;
if m.m_extra.m_added < com.compilation_step then begin
m.m_extra.m_added <- com.compilation_step;
(match m0.m_extra.m_kind, m.m_extra.m_kind with
| MCode, MMacro | MMacro, MCode ->
(* this was just a dependency to check : do not add to the context *)
Expand All @@ -501,7 +492,7 @@ let rec add_modules sctx ctx (m : module_def) (from_binary : bool) (p : pos) =
let m2 = try
com.module_lut#find mpath
with Not_found ->
match type_module sctx ctx mpath p with
match type_module sctx com mpath p with
| GoodModule m ->
m
| BinaryModule mc ->
Expand All @@ -521,27 +512,26 @@ let rec add_modules sctx ctx (m : module_def) (from_binary : bool) (p : pos) =

(* Looks up the module referred to by [mpath] in the cache. If it exists, a check is made to
determine if it's still valid. If this function returns None, the module is re-typed. *)
and type_module sctx (ctx:Typecore.typer) mpath p =
and type_module sctx com mpath p =
let t = Timer.timer ["server";"module cache"] in
let com = ctx.Typecore.com in
let cc = CommonCache.get_cache com in
let skip m_path reason =
ServerMessage.skipping_dep com "" (m_path,(Printer.s_module_skip_reason reason));
BadModule reason
in
let add_modules from_binary m =
let tadd = Timer.timer ["server";"module cache";"add modules"] in
add_modules sctx ctx m from_binary p;
add_modules sctx com m from_binary p;
tadd();
GoodModule m
in
let check_module sctx ctx m_path m_extra p =
let check_module sctx m_path m_extra p =
let tcheck = Timer.timer ["server";"module cache";"check"] in
let r = check_module sctx ctx mpath m_extra p in
let r = check_module sctx com mpath m_extra p in
tcheck();
r
in
let find_module_in_cache ctx cc m_path p =
let find_module_in_cache cc m_path p =
try
let m = cc#find_module m_path in
begin match m.m_extra.m_cache_state with
Expand All @@ -558,11 +548,11 @@ and type_module sctx (ctx:Typecore.typer) mpath p =
NoModule
in
(* Should not raise anything! *)
let m = match find_module_in_cache ctx cc mpath p with
let m = match find_module_in_cache cc mpath p with
| GoodModule m ->
(* "Good" here is an assumption, it only means that the module wasn't explicitly invalidated
in the cache. The true cache state will be known after check_module. *)
begin match check_module sctx ctx mpath m.m_extra p with
begin match check_module sctx mpath m.m_extra p with
| None ->
add_modules false m;
| Some reason ->
Expand All @@ -571,10 +561,10 @@ and type_module sctx (ctx:Typecore.typer) mpath p =
| BinaryModule mc ->
(* Similarly, we only know that a binary module wasn't explicitly tainted. Decode it only after
checking dependencies. This means that the actual decoding never has any reason to fail. *)
begin match check_module sctx ctx mpath mc.mc_extra p with
begin match check_module sctx mpath mc.mc_extra p with
| None ->
let reader = new HxbReader.hxb_reader mpath com.hxb_reader_stats in
let api = (new hxb_reader_api_server ctx cc :> HxbReaderApi.hxb_reader_api) in
let api = (new hxb_reader_api_server com cc :> HxbReaderApi.hxb_reader_api) in
let f_next chunks until =
let t_hxb = Timer.timer ["server";"module cache";"hxb read"] in
let r = reader#read_chunks_until api chunks until in
Expand All @@ -585,7 +575,7 @@ and type_module sctx (ctx:Typecore.typer) mpath p =
(* We try to avoid reading expressions as much as possible, so we only do this for
our current display file if we're in display mode. *)
let is_display_file = DisplayPosition.display_position#is_in_file (Path.UniqueKey.lazy_key m.m_extra.m_file) in
if is_display_file || ctx.com.display.dms_full_typing then ignore(f_next chunks EOM);
if is_display_file || com.display.dms_full_typing then ignore(f_next chunks EOM);
add_modules true m;
| Some reason ->
skip mpath reason
Expand Down Expand Up @@ -759,7 +749,7 @@ let do_connect ip port args =
if !has_error then exit 1

let enable_cache_mode sctx =
TypeloadModule.type_module_hook := type_module sctx;
type_module_hook := type_module sctx;
ServerCompilationContext.ensure_macro_setup sctx;
TypeloadParse.parse_hook := parse_file sctx.cs

Expand Down
1 change: 1 addition & 0 deletions src/compiler/serverCompilationContext.ml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ let reset sctx =
Hashtbl.clear sctx.changed_directories;
sctx.was_compilation <- false;
Parser.reset_state();
Lexer.cur := Lexer.make_file "";
measure_times := false;
Hashtbl.clear DeprecationCheck.warned_positions;
close_times();
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/serverConfig.ml
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
let do_not_check_modules = ref false
let populate_cache_from_display = ref true
let legacy_completion = ref false

let max_completion_items = ref 0

let reset () =
do_not_check_modules := false;
populate_cache_from_display := true;
legacy_completion := false;
max_completion_items := 0
3 changes: 3 additions & 0 deletions src/context/common.ml
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ type context = {
overload_cache : ((path * string),(Type.t * tclass_field) list) lookup;
module_lut : module_lut;
module_nonexistent_lut : (path,bool) lookup;
fake_modules : (Path.UniqueKey.t,module_def) Hashtbl.t;
mutable has_error : bool;
pass_debug_messages : string DynArray.t;
(* output *)
Expand Down Expand Up @@ -795,6 +796,7 @@ let create compilation_step cs version args display_mode =
modules = [];
module_lut = new module_lut;
module_nonexistent_lut = new hashtbl_lookup;
fake_modules = Hashtbl.create 0;
flash_version = 10.;
resources = Hashtbl.create 0;
net_std = [];
Expand Down Expand Up @@ -893,6 +895,7 @@ let clone com is_macro_context =
module_to_file = new hashtbl_lookup;
overload_cache = new hashtbl_lookup;
module_lut = new module_lut;
fake_modules = Hashtbl.create 0;
hxb_reader_stats = HxbReader.create_hxb_reader_stats ();
std = null_class;
empty_class_path = new ClassPath.directory_class_path "" User;
Expand Down
2 changes: 1 addition & 1 deletion src/context/display/displayEmitter.ml
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ let check_display_metadata ctx meta =
List.iter (fun e ->
if display_position#enclosed_in (pos e) then begin
let e = preprocess_expr ctx.com e in
delay ctx PTypeField (fun _ -> ignore(type_expr ctx e WithType.value));
delay ctx.g PTypeField (fun _ -> ignore(type_expr ctx e WithType.value));
end
) args
) meta
Expand Down
11 changes: 7 additions & 4 deletions src/context/display/displayException.ml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ let raise_package sl = raise (DisplayException(DisplayPackage sl))
(* global state *)
let last_completion_result = ref (Array.make 0 (CompletionItem.make (ITModule ([],"")) None))
let last_completion_pos = ref None
let max_completion_items = ref 0

let reset () =
last_completion_result := (Array.make 0 (CompletionItem.make (ITModule ([],"")) None));
last_completion_pos := None

let filter_somehow ctx items kind subj =
let subject = match subj.s_name with
Expand Down Expand Up @@ -88,7 +91,7 @@ let filter_somehow ctx items kind subj =
in
let ret = DynArray.create () in
let rec loop acc_types = match acc_types with
| (item,index,_) :: acc_types when DynArray.length ret < !max_completion_items ->
| (item,index,_) :: acc_types when DynArray.length ret < !ServerConfig.max_completion_items ->
DynArray.add ret (CompletionItem.to_json ctx (Some index) item);
loop acc_types
| _ ->
Expand All @@ -113,15 +116,15 @@ let patch_completion_subject subj =

let fields_to_json ctx fields kind subj =
last_completion_result := Array.of_list fields;
let needs_filtering = !max_completion_items > 0 && Array.length !last_completion_result > !max_completion_items in
let needs_filtering = !ServerConfig.max_completion_items > 0 && Array.length !last_completion_result > !ServerConfig.max_completion_items in
(* let p_before = subj.s_insert_pos in *)
let subj = patch_completion_subject subj in
let ja,num_items = if needs_filtering then
filter_somehow ctx fields kind subj
else
List.mapi (fun i item -> CompletionItem.to_json ctx (Some i) item) fields,Array.length !last_completion_result
in
let did_filter = num_items = !max_completion_items in
let did_filter = num_items = !ServerConfig.max_completion_items in
last_completion_pos := if did_filter then Some subj.s_start_pos else None;
let filter_string = (match subj.s_name with None -> "" | Some name -> name) in
(* print_endline (Printf.sprintf "FIELDS OUTPUT:\n\tfilter_string: %s\n\t num items: %i\n\t start: %s\n\t position: %s\n\t before cut: %s"
Expand Down
Loading

0 comments on commit b5875ba

Please sign in to comment.