@@ -234,7 +234,7 @@ pub const Handle = struct {
234234 /// `true` if the document has been directly opened by the client i.e. with `textDocument/didOpen`
235235 /// `false` indicates the document only exists because it is a dependency of another document
236236 /// or has been closed with `textDocument/didClose` and is awaiting cleanup through `garbageCollection`
237- open : bool = false ,
237+ lsp_synced : bool = false ,
238238 /// true if a thread has acquired the permission to compute the `DocumentScope`
239239 /// all other threads will wait until the given thread has computed the `DocumentScope` before reading it.
240240 has_document_scope_lock : bool = false ,
@@ -520,16 +520,16 @@ pub const Handle = struct {
520520 return @bitCast (self .impl .status .load (.acquire ));
521521 }
522522
523- pub fn isOpen (self : * const Handle ) bool {
524- return self .getStatus ().open ;
523+ pub fn isLspSynced (self : * const Handle ) bool {
524+ return self .getStatus ().lsp_synced ;
525525 }
526526
527527 /// returns the previous value
528- fn setOpen (self : * Handle , open : bool ) bool {
529- if (open ) {
530- return self .impl .status .bitSet (@offsetOf (Handle .Status , "open " ), .release ) == 1 ;
528+ fn setLspSynced (self : * Handle , lsp_synced : bool ) bool {
529+ if (lsp_synced ) {
530+ return self .impl .status .bitSet (@offsetOf (Handle .Status , "lsp_synced " ), .release ) == 1 ;
531531 } else {
532- return self .impl .status .bitReset (@offsetOf (Handle .Status , "open " ), .release ) == 1 ;
532+ return self .impl .status .bitReset (@offsetOf (Handle .Status , "lsp_synced " ), .release ) == 1 ;
533533 }
534534 }
535535
@@ -558,7 +558,7 @@ pub const Handle = struct {
558558 defer tracy_zone .end ();
559559
560560 const new_status : Handle.Status = .{
561- .open = self .getStatus (). open ,
561+ .lsp_synced = self .isLspSynced () ,
562562 };
563563
564564 const new_tree = try parseTree (self .impl .allocator , new_text , self .tree .mode );
@@ -759,7 +759,7 @@ pub fn getOrLoadHandle(store: *DocumentStore, uri: Uri) ?*Handle {
759759 }
760760
761761 const file_contents = store .readUri (uri ) orelse return null ;
762- return store .createAndStoreDocument (uri , file_contents ) catch | err | {
762+ return store .createAndStoreDocument (uri , file_contents , false ) catch | err | {
763763 log .err ("failed to store document '{s}': {}" , .{ uri , err });
764764 return null ;
765765 };
@@ -839,40 +839,17 @@ fn getOrLoadBuildFile(self: *DocumentStore, uri: Uri) ?*BuildFile {
839839
840840/// **Not thread safe**
841841/// Assumes that no other thread is currently accessing the given document
842- pub fn openDocument (self : * DocumentStore , uri : Uri , text : []const u8 ) error {OutOfMemory }! void {
842+ pub fn openLspSyncedDocument (self : * DocumentStore , uri : Uri , text : []const u8 ) error {OutOfMemory }! void {
843843 const tracy_zone = tracy .trace (@src ());
844844 defer tracy_zone .end ();
845845
846- const handle_ptr : * Handle = try self .allocator .create (Handle );
847- errdefer self .allocator .destroy (handle_ptr );
848-
849846 const duped_text = try self .allocator .dupeZ (u8 , text );
850- handle_ptr .* = try self .createDocument (uri , duped_text , true );
851- errdefer handle_ptr .deinit ();
852-
853- const gop = try self .handles .getOrPut (self .allocator , handle_ptr .uri );
854- if (gop .found_existing ) {
855- if (gop .value_ptr .* .isOpen ()) {
856- log .warn ("Document already open: {s}" , .{uri });
857- }
858- std .mem .swap ([]const u8 , & gop .value_ptr .* .uri , & handle_ptr .uri );
859- gop .value_ptr .* .deinit ();
860- self .allocator .destroy (gop .value_ptr .* );
861- }
862- gop .value_ptr .* = handle_ptr ;
863-
864- try self .loadDependencies (handle_ptr .import_uris .items );
865-
866- if (isBuildFile (uri )) {
867- log .debug ("Opened document '{s}' (build file)" , .{uri });
868- } else {
869- log .debug ("Opened document '{s}'" , .{uri });
870- }
847+ _ = try self .createAndStoreDocument (uri , duped_text , true );
871848}
872849
873850/// **Thread safe** takes a shared lock, takes an exclusive lock (with `tryLock`)
874851/// Assumes that no other thread is currently accessing the given document
875- pub fn closeDocument (self : * DocumentStore , uri : Uri ) void {
852+ pub fn closeLspSyncedDocument (self : * DocumentStore , uri : Uri ) void {
876853 const tracy_zone = tracy .trace (@src ());
877854 defer tracy_zone .end ();
878855
@@ -886,7 +863,7 @@ pub fn closeDocument(self: *DocumentStore, uri: Uri) void {
886863 };
887864 // instead of destroying the handle here we just mark it not open
888865 // and let it be destroy by the garbage collection code
889- if (! handle .setOpen (false )) {
866+ if (! handle .setLspSynced (false )) {
890867 log .warn ("Document already closed: {s}" , .{uri });
891868 }
892869 }
@@ -906,12 +883,12 @@ pub fn closeDocument(self: *DocumentStore, uri: Uri) void {
906883///
907884/// **Thread safe** takes a shared lock when called on different documents
908885/// **Not thread safe** when called on the same document
909- pub fn refreshDocument (self : * DocumentStore , uri : Uri , new_text : [:0 ]const u8 ) ! void {
886+ pub fn refreshLspSyncedDocument (self : * DocumentStore , uri : Uri , new_text : [:0 ]const u8 ) ! void {
910887 const tracy_zone = tracy .trace (@src ());
911888 defer tracy_zone .end ();
912889
913890 const handle = self .getHandle (uri ).? ;
914- if (! handle .getStatus (). open ) {
891+ if (! handle .isLspSynced () ) {
915892 log .warn ("Document modified without being opened: {s}" , .{uri });
916893 }
917894 try handle .setSource (new_text );
@@ -920,26 +897,20 @@ pub fn refreshDocument(self: *DocumentStore, uri: Uri, new_text: [:0]const u8) !
920897 try self .loadDependencies (handle .import_uris .items );
921898}
922899
923- /// Removes a document from the store , unless said document is currently open and
900+ /// Refreshes a document from the file system , unless said document is currently open and
924901/// has been synchronized via `textDocument/didOpen`.
925902/// **Thread safe** takes an exclusive lock when called on different documents
926903/// **Not thread safe** when called on the same document
927904pub fn refreshDocumentFromFileSystem (self : * DocumentStore , uri : Uri ) ! bool {
928- {
929- const handle = self .getHandle (uri ) orelse return false ;
930- if (handle .getStatus ().open ) return false ;
905+ if (self .getHandle (uri )) | handle | {
906+ if (handle .isLspSynced ()) {
907+ return false ;
908+ }
931909 }
932910
933- {
934- self .lock .lock ();
935- defer self .lock .unlock ();
936-
937- const kv = self .handles .fetchSwapRemove (uri ) orelse return false ;
938- log .debug ("Closing document {s}" , .{kv .key });
939- kv .value .deinit ();
940- self .allocator .destroy (kv .value );
941- return true ;
942- }
911+ const file_contents = self .readUri (uri ) orelse return false ;
912+ _ = try self .createAndStoreDocument (uri , file_contents , false );
913+ return true ;
943914}
944915
945916/// Invalidates a build files.
@@ -1122,7 +1093,7 @@ fn garbageCollectionImports(self: *DocumentStore) error{OutOfMemory}!void {
11221093 var queue : std .ArrayListUnmanaged (Uri ) = .empty ;
11231094
11241095 for (self .handles .values (), 0.. ) | handle , handle_index | {
1125- if (! handle .getStatus ().open ) continue ;
1096+ if (! handle .getStatus ().lsp_synced ) continue ;
11261097 reachable .set (handle_index );
11271098
11281099 try self .collectDependenciesInternal (arena .allocator (), handle , & queue , false );
@@ -1536,14 +1507,14 @@ fn uriInImports(
15361507/// invalidates any pointers into `DocumentStore.build_files`
15371508/// takes ownership of the `text` passed in.
15381509/// **Thread safe** takes an exclusive lock
1539- fn createDocument (self : * DocumentStore , uri : Uri , text : [:0 ]const u8 , open : bool ) error {OutOfMemory }! Handle {
1510+ fn createDocument (self : * DocumentStore , uri : Uri , text : [:0 ]const u8 , lsp_synced : bool ) error {OutOfMemory }! Handle {
15401511 const tracy_zone = tracy .trace (@src ());
15411512 defer tracy_zone .end ();
15421513
15431514 var handle : Handle = try .init (self .allocator , uri , text );
15441515 errdefer handle .deinit ();
15451516
1546- _ = handle .setOpen ( open );
1517+ _ = handle .setLspSynced ( lsp_synced );
15471518
15481519 if (! supports_build_system ) {
15491520 // nothing to do
@@ -1574,35 +1545,61 @@ fn createDocument(self: *DocumentStore, uri: Uri, text: [:0]const u8, open: bool
15741545/// takes ownership of the `text` passed in.
15751546/// invalidates any pointers into `DocumentStore.build_files`
15761547/// **Thread safe** takes an exclusive lock
1577- fn createAndStoreDocument (self : * DocumentStore , uri : Uri , text : [:0 ]const u8 ) error {OutOfMemory }! * Handle {
1578- const handle_ptr : * Handle = try self .allocator .create (Handle );
1579- errdefer self .allocator .destroy (handle_ptr );
1548+ fn createAndStoreDocument (
1549+ self : * DocumentStore ,
1550+ uri : Uri ,
1551+ text : [:0 ]const u8 ,
1552+ lsp_synced : bool ,
1553+ ) error {OutOfMemory }! * Handle {
1554+ const handle = handle : {
1555+ errdefer self .allocator .free (text );
15801556
1581- handle_ptr .* = try self .createDocument ( uri , text , false );
1582- errdefer handle_ptr . deinit ( );
1557+ const handle : * Handle = try self .allocator . create ( Handle );
1558+ errdefer self . allocator . destroy ( handle );
15831559
1584- const gop = blk : {
1560+ handle .* = try self .createDocument (uri , text , lsp_synced );
1561+ break :handle handle ;
1562+ };
1563+ errdefer {
1564+ handle .deinit ();
1565+ self .allocator .destroy (handle );
1566+ }
1567+
1568+ const old_handle_optional = blk : {
15851569 self .lock .lock ();
15861570 defer self .lock .unlock ();
15871571
1588- const gop = try self .handles .getOrPutValue (self .allocator , handle_ptr .uri , handle_ptr );
1589- std .debug .assert (! gop .found_existing );
1572+ const gop = try self .handles .getOrPut (self .allocator , handle .uri );
1573+ const old_handle_optional = if (gop .found_existing ) old_handle_optional : {
1574+ gop .key_ptr .* = handle .uri ;
1575+ break :old_handle_optional gop .value_ptr .* ;
1576+ } else null ;
1577+ gop .value_ptr .* = handle ;
15901578
1591- std .debug .assert (self .currently_loading_uris .swapRemove (uri ));
1592- self .wait_for_currently_loading_uri .broadcast ();
1579+ if (self .currently_loading_uris .swapRemove (uri )) {
1580+ self .wait_for_currently_loading_uri .broadcast ();
1581+ }
15931582
1594- break :blk gop ;
1583+ break :blk old_handle_optional ;
15951584 };
15961585
1597- try self .loadDependencies (handle_ptr .import_uris .items );
1586+ if (old_handle_optional ) | old_handle | {
1587+ if (old_handle .isLspSynced ()) {
1588+ log .warn ("Document already open: {s}" , .{uri });
1589+ }
1590+ old_handle .deinit ();
1591+ self .allocator .destroy (old_handle );
1592+ }
1593+
1594+ try self .loadDependencies (handle .import_uris .items );
15981595
1599- if (isBuildFile (gop . value_ptr .* .uri )) {
1600- log .debug ("Opened document '{s}' (build file)" , .{gop . value_ptr .* .uri });
1596+ if (isBuildFile (handle .uri )) {
1597+ log .debug ("Opened document '{s}' (build file)" , .{handle .uri });
16011598 } else {
1602- log .debug ("Opened document '{s}'" , .{gop . value_ptr .* .uri });
1599+ log .debug ("Opened document '{s}'" , .{handle .uri });
16031600 }
16041601
1605- return gop . value_ptr .* ;
1602+ return handle ;
16061603}
16071604
16081605fn loadDependencies (store : * DocumentStore , import_uris : []const []const u8 ) ! void {
0 commit comments