diff options
Diffstat (limited to 'cli/lsp/documents.rs')
-rw-r--r-- | cli/lsp/documents.rs | 58 |
1 files changed, 30 insertions, 28 deletions
diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs index 936d225ec..308e987bd 100644 --- a/cli/lsp/documents.rs +++ b/cli/lsp/documents.rs @@ -244,16 +244,18 @@ type MaybeModuleResult = type MaybeParsedSourceResult = Option<Result<ParsedSource, deno_ast::Diagnostic>>; -#[derive(Debug, Clone)] +#[derive(Debug)] struct DocumentInner { - /// contains the last-known-good set of dependencies from parsing the module + /// Contains the last-known-good set of dependencies from parsing the module. dependencies: Arc<DocumentDependencies>, fs_version: String, line_index: Arc<LineIndex>, maybe_language_id: Option<LanguageId>, maybe_lsp_version: Option<i32>, maybe_module: MaybeModuleResult, - maybe_navigation_tree: Option<Arc<tsc::NavigationTree>>, + // this is a lazily constructed value based on the state of the document, + // so having a mutex to hold it is ok + maybe_navigation_tree: Mutex<Option<Arc<tsc::NavigationTree>>>, maybe_parsed_source: MaybeParsedSourceResult, specifier: ModuleSpecifier, text_info: SourceTextInfo, @@ -291,7 +293,7 @@ impl Document { maybe_language_id: None, maybe_lsp_version: None, maybe_module, - maybe_navigation_tree: None, + maybe_navigation_tree: Mutex::new(None), maybe_parsed_source, text_info, specifier, @@ -327,7 +329,7 @@ impl Document { maybe_language_id: Some(language_id), maybe_lsp_version: Some(version), maybe_module, - maybe_navigation_tree: None, + maybe_navigation_tree: Mutex::new(None), maybe_parsed_source, text_info: source, specifier, @@ -390,27 +392,19 @@ impl Document { Arc::new(LineIndex::new(text_info.text_str())) }; Ok(Document(Arc::new(DocumentInner { + specifier: self.0.specifier.clone(), + fs_version: self.0.fs_version.clone(), + maybe_language_id: self.0.maybe_language_id.clone(), dependencies, text_info, line_index, maybe_module, maybe_parsed_source, maybe_lsp_version: Some(version), - maybe_navigation_tree: None, - ..(*self.0).clone() + maybe_navigation_tree: Mutex::new(None), }))) } - fn with_navigation_tree( - &self, - navigation_tree: Arc<tsc::NavigationTree>, - ) -> Document { - Document(Arc::new(DocumentInner { - maybe_navigation_tree: Some(navigation_tree), - ..(*self.0).clone() - })) - } - pub fn specifier(&self) -> &ModuleSpecifier { &self.0.specifier } @@ -494,7 +488,21 @@ impl Document { } pub fn maybe_navigation_tree(&self) -> Option<Arc<tsc::NavigationTree>> { - self.0.maybe_navigation_tree.clone() + self.0.maybe_navigation_tree.lock().clone() + } + + pub fn update_navigation_tree_if_version( + &self, + tree: Arc<tsc::NavigationTree>, + script_version: &str, + ) { + // Ensure we are updating the same document that the navigation tree was + // created for. Note: this should not be racy between the version check + // and setting the navigation tree, because the document is immutable + // and this is enforced by it being wrapped in an Arc. + if self.script_version() == script_version { + *self.0.maybe_navigation_tree.lock() = Some(tree); + } } pub fn dependencies(&self) -> &BTreeMap<String, deno_graph::Dependency> { @@ -1018,23 +1026,17 @@ impl Documents { /// Tries to cache a navigation tree that is associated with the provided specifier /// if the document stored has the same script version. pub fn try_cache_navigation_tree( - &mut self, + &self, specifier: &ModuleSpecifier, script_version: &str, navigation_tree: Arc<tsc::NavigationTree>, ) -> Result<(), AnyError> { - if let Some(doc) = self.open_docs.get_mut(specifier) { - if doc.script_version() == script_version { - *doc = doc.with_navigation_tree(navigation_tree); - } + if let Some(doc) = self.open_docs.get(specifier) { + doc.update_navigation_tree_if_version(navigation_tree, script_version) } else { let mut file_system_docs = self.file_system_docs.lock(); if let Some(doc) = file_system_docs.docs.get_mut(specifier) { - // ensure we are updating the same document - // that the navigation tree was created for - if doc.script_version() == script_version { - *doc = doc.with_navigation_tree(navigation_tree); - } + doc.update_navigation_tree_if_version(navigation_tree, script_version); } else { return Err(custom_error( "NotFound", |