Skip to content
Open
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
10 changes: 9 additions & 1 deletion src/compiler/compilationCache.ml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class context_cache (index : int) (sign : Digest.t) = object(self)
val modules : (path,module_def) Hashtbl.t = Hashtbl.create 0
val binary_cache : (path,HxbData.module_cache) Hashtbl.t = Hashtbl.create 0
val tmp_binary_cache : (path,HxbData.module_cache) Hashtbl.t = Hashtbl.create 0
val tmp_parse_cache : (Path.UniqueKey.t,(string list * type_decl list) Parser.parse_result) Hashtbl.t = Hashtbl.create 0
val get_hxb_module_mutex = Mutex.create ()
val removed_files = Hashtbl.create 0
val mutable json = JNull
Expand Down Expand Up @@ -110,7 +111,14 @@ class context_cache (index : int) (sign : Digest.t) = object(self)
Hashtbl.replace modules path m

method clear_temp_cache =
Hashtbl.clear tmp_binary_cache
Hashtbl.clear tmp_binary_cache;
Hashtbl.clear tmp_parse_cache

method find_tmp_parse key =
Hashtbl.find tmp_parse_cache key

method cache_tmp_parse key r =
Hashtbl.replace tmp_parse_cache key r

method clear_cache =
Hashtbl.clear modules;
Expand Down
20 changes: 20 additions & 0 deletions src/compiler/server/serverCache.ml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,19 @@ let parse_file sctx com (rfile : ClassPaths.resolved_file) p =
let ffile = Path.get_full_path rfile.file
and fkey = com.part_scope.file_keys#get file in
let is_display_file = DisplayPosition.display_position#is_in_file (com.part_scope.file_keys#get ffile) in
let has_request_contents =
com.file_contents <> [] && (try List.assoc fkey com.file_contents <> None with Not_found -> false)
in
match is_display_file, sctx.ServerCompilationContext.current_stdin with
| true, Some stdin when (com.file_contents <> [] || Common.defined com Define.DisplayStdin) ->
TypeloadParse.parse_file_from_string com file p stdin
| _ when has_request_contents ->
(try
cc#find_tmp_parse fkey
with Not_found ->
let r = TypeloadParse.parse_file com rfile p in
cc#cache_tmp_parse fkey r;
r)
| _ ->
let ftime = file_time ffile in
let data = Std.finally (Timer.start_timer com.timer_ctx ["server";"parser cache"]) (fun () ->
Expand Down Expand Up @@ -213,6 +223,15 @@ let check_module sctx com m_path m_extra p =
end
end
in
let check_request_contents () =
let file = Path.UniqueKey.lazy_path m_extra.m_file in
let fkey = Path.UniqueKey.lazy_key m_extra.m_file in
let has_contents = (try List.assoc fkey com.file_contents <> None with Not_found -> false) in
if has_contents && content_changed m_path file then begin
ServerMessage.not_cached com "" m_path;
raise (Dirty (FileChanged file))
end
in
let find_module_extra sign mpath =
(com.cs#get_context sign)#find_module_extra mpath
in
Expand All @@ -234,6 +253,7 @@ let check_module sctx com m_path m_extra p =
try
check_module_path();
if not (has_policy NoFileSystemCheck) || Path.file_extension (Path.UniqueKey.lazy_path m_extra.m_file) <> "hx" then check_file();
if com.file_contents <> [] then check_request_contents();
if (get_typing_mode com m_extra) = FullTyping then check_dependencies();
None
with
Expand Down
8 changes: 8 additions & 0 deletions src/context/display/displayJson.ml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ class display_handler (jsonrpc : jsonrpc_handler) com (cs : CompilationCache.t)
pmax = pos;
};

let contents = match contents with
| Some s when (try Std.input_file ~bin:true file = s with _ -> false) -> None
| c -> c
in
com.file_contents <- [file_unique, contents];
end else begin
let file_contents = jsonrpc#get_opt_param (fun () ->
Expand All @@ -103,6 +107,10 @@ class display_handler (jsonrpc : jsonrpc_handler) com (cs : CompilationCache.t)
let s = jsonrpc#get_string_field "fileContents" "contents" fl in
Some s
) None in
let contents = match contents with
| Some s when (try Std.input_file ~bin:true file = s with _ -> false) -> None
| c -> c
in
(file_unique, contents)
| _ -> invalid_arg "fileContents"
) file_contents in
Expand Down
7 changes: 6 additions & 1 deletion src/context/display/displayTexpr.ml
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,13 @@ let check_display_file ctx cs =
| Some cc ->
begin try
let p = DisplayPosition.display_position#get in
let cfile = cc#find_file (ctx.com.part_scope.file_keys#get p.pfile) in
let fkey = ctx.com.part_scope.file_keys#get p.pfile in
let cfile = cc#find_file fkey in
let path = (cfile.c_package,get_module_name_of_cfile p.pfile cfile) in
if (try List.assoc fkey ctx.com.file_contents <> None with Not_found -> false) then begin
let _,_,_,decls,_ = TypeloadParse.parse_module' ctx.com path null_pos in
if decls <> cfile.c_decls then raise Not_found
end;
TypeloadParse.PdiHandler.handle_pdi ctx.com cfile.c_pdi;
(* We have to go through type_module_hook because one of the module's dependencies could be
invalid (issue #8991). *)
Expand Down
28 changes: 28 additions & 0 deletions tests/server/src/cases/UnsavedContentsStale.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package cases;

import haxe.display.FsPath;
import haxe.display.Server;
import TestCase;
import utest.Assert;

// A hover carrying unsaved buffer contents must be answered against THOSE contents even when the
// server has a cached parse of the file whose disk mtime still matches (file not saved). Models
// vshaxe: edit -> (invalidate deduplicated away / compile re-cached the disk parse) -> hover.
class UnsavedContentsStale extends TestCase {
static inline var V1 = "class A {\n\tstatic function main() {\n\t\tvar aaa = 42;\n\t\ttrace(aaa);\n\t}\n}";
static inline var V2 = "class A {\n\tstatic function main() {\n\t\tvar bbb = \"s\";\n\t\tvar aaa = 42;\n\t\ttrace(aaa);\n\t}\n}";

function test(_) {
vfs.putContent("A.hx", V1);
var args = ["-main", "A", "-js", "no.js", "--no-output"];
runHaxe(args);
assertSuccess();

var offset = V1.indexOf("aaa") + 1; // == V2.indexOf("bbb") + 1

// NO invalidate: the compile above cached A's disk parse; hover sends newer unsaved contents.
var res = runHaxeJson(args, DisplayMethods.Hover, {file: new FsPath("A.hx"), offset: offset, contents: V2});
var t = if (res == null || res.item == null) "<null>" else try res.item.type.args.path.typeName catch (_) "<untyped>";
Assert.equals("String", t, "got " + t);
}
}
Loading