summaryrefslogtreecommitdiff
path: root/cli/lsp/language_server.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/lsp/language_server.rs')
-rw-r--r--cli/lsp/language_server.rs439
1 files changed, 268 insertions, 171 deletions
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index 2ccbb6284..21a229b47 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -18,7 +18,6 @@ use std::collections::HashMap;
use std::env;
use std::path::PathBuf;
use std::sync::Arc;
-use std::sync::Mutex;
use tokio::fs;
use crate::deno_dir;
@@ -42,35 +41,44 @@ use super::tsc::TsServer;
use super::utils;
#[derive(Debug, Clone)]
-pub struct LanguageServer {
- assets: Arc<Mutex<HashMap<ModuleSpecifier, Option<AssetDocument>>>>,
- client: Client,
- ts_server: TsServer,
- config: Arc<Mutex<Config>>,
- documents: Arc<Mutex<DocumentCache>>,
- sources: Arc<Mutex<Sources>>,
- diagnostics: Arc<Mutex<DiagnosticCollection>>,
- maybe_config_uri: Arc<Mutex<Option<Url>>>,
- maybe_import_map: Arc<Mutex<Option<ImportMap>>>,
- maybe_import_map_uri: Arc<Mutex<Option<Url>>>,
-}
+pub struct LanguageServer(Arc<tokio::sync::Mutex<Inner>>);
#[derive(Debug, Clone, Default)]
pub struct StateSnapshot {
- pub assets: Arc<Mutex<HashMap<ModuleSpecifier, Option<AssetDocument>>>>,
+ pub assets: HashMap<ModuleSpecifier, Option<AssetDocument>>,
pub documents: DocumentCache,
- pub sources: Arc<Mutex<Sources>>,
+ pub sources: Sources,
+}
+
+#[derive(Debug)]
+struct Inner {
+ assets: HashMap<ModuleSpecifier, Option<AssetDocument>>,
+ client: Client,
+ ts_server: TsServer,
+ config: Config,
+ documents: DocumentCache,
+ sources: Sources,
+ diagnostics: DiagnosticCollection,
+ maybe_config_uri: Option<Url>,
+ maybe_import_map: Option<ImportMap>,
+ maybe_import_map_uri: Option<Url>,
}
impl LanguageServer {
pub fn new(client: Client) -> Self {
+ Self(Arc::new(tokio::sync::Mutex::new(Inner::new(client))))
+ }
+}
+
+impl Inner {
+ fn new(client: Client) -> Self {
let maybe_custom_root = env::var("DENO_DIR").map(String::into).ok();
let dir = deno_dir::DenoDir::new(maybe_custom_root)
.expect("could not access DENO_DIR");
let location = dir.root.join("deps");
- let sources = Arc::new(Mutex::new(Sources::new(&location)));
+ let sources = Sources::new(&location);
- LanguageServer {
+ Self {
assets: Default::default(),
client,
ts_server: TsServer::new(),
@@ -85,20 +93,18 @@ impl LanguageServer {
}
fn enabled(&self) -> bool {
- let config = self.config.lock().unwrap();
- config.settings.enable
+ self.config.settings.enable
}
/// Searches assets, open documents and external sources for a line_index,
/// which might be performed asynchronously, hydrating in memory caches for
/// subsequent requests.
- pub async fn get_line_index(
+ async fn get_line_index(
&self,
specifier: ModuleSpecifier,
) -> Result<LineIndex, AnyError> {
if specifier.as_url().scheme() == "asset" {
- let maybe_asset =
- { self.assets.lock().unwrap().get(&specifier).cloned() };
+ let maybe_asset = self.assets.get(&specifier).cloned();
if let Some(maybe_asset) = maybe_asset {
if let Some(asset) = maybe_asset {
Ok(asset.line_index)
@@ -106,22 +112,19 @@ impl LanguageServer {
Err(anyhow!("asset is missing: {}", specifier))
}
} else {
- let state_snapshot = self.snapshot();
+ let mut state_snapshot = self.snapshot();
if let Some(asset) =
- tsc::get_asset(&specifier, &self.ts_server, &state_snapshot).await?
+ tsc::get_asset(&specifier, &self.ts_server, &mut state_snapshot)
+ .await?
{
Ok(asset.line_index)
} else {
Err(anyhow!("asset is missing: {}", specifier))
}
}
- } else if let Some(line_index) =
- self.documents.lock().unwrap().line_index(&specifier)
- {
+ } else if let Some(line_index) = self.documents.line_index(&specifier) {
Ok(line_index)
- } else if let Some(line_index) =
- self.sources.lock().unwrap().get_line_index(&specifier)
- {
+ } else if let Some(line_index) = self.sources.get_line_index(&specifier) {
Ok(line_index)
} else {
Err(anyhow!("Unable to find line index for: {}", specifier))
@@ -130,124 +133,129 @@ impl LanguageServer {
/// Only searches already cached assets and documents for a line index. If
/// the line index cannot be found, `None` is returned.
- pub fn get_line_index_sync(
+ fn get_line_index_sync(
&self,
specifier: &ModuleSpecifier,
) -> Option<LineIndex> {
if specifier.as_url().scheme() == "asset" {
- if let Some(Some(asset)) = self.assets.lock().unwrap().get(specifier) {
+ if let Some(Some(asset)) = self.assets.get(specifier) {
Some(asset.line_index.clone())
} else {
None
}
} else {
- let documents = self.documents.lock().unwrap();
+ let documents = &self.documents;
if documents.contains(specifier) {
documents.line_index(specifier)
} else {
- self.sources.lock().unwrap().get_line_index(specifier)
+ self.sources.get_line_index(specifier)
}
}
}
- async fn prepare_diagnostics(&self) -> Result<(), AnyError> {
+ async fn prepare_diagnostics(&mut self) -> Result<(), AnyError> {
let (enabled, lint_enabled) = {
- let config = self.config.lock().unwrap();
+ let config = &self.config;
(config.settings.enable, config.settings.lint)
};
let lint = async {
- let mut disturbed = false;
+ let mut diagnostics = None;
if lint_enabled {
- let diagnostic_collection = self.diagnostics.lock().unwrap().clone();
- let diagnostics = diagnostics::generate_lint_diagnostics(
- self.snapshot(),
- diagnostic_collection,
- )
- .await;
- disturbed = !diagnostics.is_empty();
- {
- let mut diagnostics_collection = self.diagnostics.lock().unwrap();
- for (specifier, version, diagnostics) in diagnostics {
- diagnostics_collection.set(
- specifier,
- DiagnosticSource::Lint,
- version,
- diagnostics,
- );
- }
- }
+ diagnostics = Some(
+ diagnostics::generate_lint_diagnostics(
+ self.snapshot(),
+ self.diagnostics.clone(),
+ )
+ .await,
+ );
};
- Ok::<bool, AnyError>(disturbed)
+ Ok::<_, AnyError>(diagnostics)
};
let ts = async {
- let mut disturbed = false;
+ let mut diagnostics = None;
if enabled {
- let diagnostics_collection = self.diagnostics.lock().unwrap().clone();
- let diagnostics = diagnostics::generate_ts_diagnostics(
- self.snapshot(),
- diagnostics_collection,
- &self.ts_server,
- )
- .await?;
- disturbed = !diagnostics.is_empty();
- {
- let mut diagnostics_collection = self.diagnostics.lock().unwrap();
- for (specifier, version, diagnostics) in diagnostics {
- diagnostics_collection.set(
- specifier,
- DiagnosticSource::TypeScript,
- version,
- diagnostics,
- );
- }
- }
+ diagnostics = Some(
+ diagnostics::generate_ts_diagnostics(
+ self.snapshot(),
+ self.diagnostics.clone(),
+ &self.ts_server,
+ )
+ .await?,
+ );
};
- Ok::<bool, AnyError>(disturbed)
+ Ok::<_, AnyError>(diagnostics)
};
let deps = async {
- let mut disturbed = false;
+ let mut diagnostics = None;
if enabled {
- let diagnostics_collection = self.diagnostics.lock().unwrap().clone();
- let diagnostics = diagnostics::generate_dependency_diagnostics(
- self.snapshot(),
- diagnostics_collection,
- )
- .await?;
- disturbed = !diagnostics.is_empty();
- {
- let mut diagnostics_collection = self.diagnostics.lock().unwrap();
- for (specifier, version, diagnostics) in diagnostics {
- diagnostics_collection.set(
- specifier,
- DiagnosticSource::Deno,
- version,
- diagnostics,
- );
- }
- }
+ diagnostics = Some(
+ diagnostics::generate_dependency_diagnostics(
+ self.snapshot(),
+ self.diagnostics.clone(),
+ )
+ .await?,
+ );
};
- Ok::<bool, AnyError>(disturbed)
+ Ok::<_, AnyError>(diagnostics)
};
let (lint_res, ts_res, deps_res) = tokio::join!(lint, ts, deps);
- if lint_res? || ts_res? || deps_res? {
+ let mut disturbed = false;
+
+ if let Some(diagnostics) = lint_res? {
+ for (specifier, version, diagnostics) in diagnostics {
+ self.diagnostics.set(
+ specifier,
+ DiagnosticSource::Lint,
+ version,
+ diagnostics,
+ );
+ disturbed = true;
+ }
+ }
+
+ if let Some(diagnostics) = ts_res? {
+ for (specifier, version, diagnostics) in diagnostics {
+ self.diagnostics.set(
+ specifier,
+ DiagnosticSource::TypeScript,
+ version,
+ diagnostics,
+ );
+ disturbed = true;
+ }
+ }
+
+ if let Some(diagnostics) = deps_res? {
+ for (specifier, version, diagnostics) in diagnostics {
+ self.diagnostics.set(
+ specifier,
+ DiagnosticSource::Deno,
+ version,
+ diagnostics,
+ );
+ disturbed = true;
+ }
+ }
+
+ if disturbed {
self.publish_diagnostics().await?;
}
Ok(())
}
- async fn publish_diagnostics(&self) -> Result<(), AnyError> {
+ async fn publish_diagnostics(&mut self) -> Result<(), AnyError> {
let (maybe_changes, diagnostics_collection) = {
- let mut diagnostics_collection = self.diagnostics.lock().unwrap();
+ let diagnostics_collection = &mut self.diagnostics;
let maybe_changes = diagnostics_collection.take_changes();
(maybe_changes, diagnostics_collection.clone())
};
if let Some(diagnostic_changes) = maybe_changes {
- let settings = self.config.lock().unwrap().settings.clone();
+ let settings = self.config.settings.clone();
for specifier in diagnostic_changes {
// TODO(@kitsonk) not totally happy with the way we collect and store
// different types of diagnostics and offer them up to the client, we
@@ -275,7 +283,7 @@ impl LanguageServer {
);
}
let uri = specifier.as_url().clone();
- let version = self.documents.lock().unwrap().version(&specifier);
+ let version = self.documents.version(&specifier);
self
.client
.publish_diagnostics(uri, diagnostics, version)
@@ -286,17 +294,17 @@ impl LanguageServer {
Ok(())
}
- pub fn snapshot(&self) -> StateSnapshot {
+ fn snapshot(&self) -> StateSnapshot {
StateSnapshot {
assets: self.assets.clone(),
- documents: self.documents.lock().unwrap().clone(),
+ documents: self.documents.clone(),
sources: self.sources.clone(),
}
}
- pub async fn update_import_map(&self) -> Result<(), AnyError> {
+ async fn update_import_map(&mut self) -> Result<(), AnyError> {
let (maybe_import_map, maybe_root_uri) = {
- let config = self.config.lock().unwrap();
+ let config = &self.config;
(config.settings.import_map.clone(), config.root_uri.clone())
};
if let Some(import_map_str) = &maybe_import_map {
@@ -331,15 +339,15 @@ impl LanguageServer {
})?;
let import_map =
ImportMap::from_json(&import_map_url.to_string(), &import_map_json)?;
- *self.maybe_import_map_uri.lock().unwrap() = Some(import_map_url);
- *self.maybe_import_map.lock().unwrap() = Some(import_map);
+ self.maybe_import_map_uri = Some(import_map_url);
+ self.maybe_import_map = Some(import_map);
} else {
- *self.maybe_import_map.lock().unwrap() = None;
+ self.maybe_import_map = None;
}
Ok(())
}
- async fn update_tsconfig(&self) -> Result<(), AnyError> {
+ async fn update_tsconfig(&mut self) -> Result<(), AnyError> {
let mut tsconfig = TsConfig::new(json!({
"allowJs": true,
"experimentalDecorators": true,
@@ -351,7 +359,7 @@ impl LanguageServer {
"target": "esnext",
}));
let (maybe_config, maybe_root_uri) = {
- let config = self.config.lock().unwrap();
+ let config = &self.config;
if config.settings.unstable {
let unstable_libs = json!({
"lib": ["deno.ns", "deno.window", "deno.unstable"]
@@ -394,7 +402,7 @@ impl LanguageServer {
let (value, maybe_ignored_options) =
parse_config(&config_text, &config_path)?;
tsconfig.merge(&value);
- *self.maybe_config_uri.lock().unwrap() = Some(config_url);
+ self.maybe_config_uri = Some(config_url);
if let Some(ignored_options) = maybe_ignored_options {
// TODO(@kitsonk) turn these into diagnostics that can be sent to the
// client
@@ -409,10 +417,10 @@ impl LanguageServer {
}
}
-#[lspower::async_trait]
-impl lspower::LanguageServer for LanguageServer {
+// lspower::LanguageServer methods. This file's LanguageServer delegates to us.
+impl Inner {
async fn initialize(
- &self,
+ &mut self,
params: InitializeParams,
) -> LspResult<InitializeResult> {
info!("Starting Deno language server...");
@@ -441,7 +449,7 @@ impl lspower::LanguageServer for LanguageServer {
}
{
- let mut config = self.config.lock().unwrap();
+ let config = &mut self.config;
config.root_uri = params.root_uri;
if let Some(value) = params.initialization_options {
config.update(value)?;
@@ -459,7 +467,7 @@ impl lspower::LanguageServer for LanguageServer {
})
}
- async fn initialized(&self, _: InitializedParams) {
+ async fn initialized(&mut self, _: InitializedParams) {
// Check to see if we need to setup the import map
if let Err(err) = self.update_import_map().await {
self
@@ -470,8 +478,6 @@ impl lspower::LanguageServer for LanguageServer {
if self
.config
- .lock()
- .unwrap()
.client_capabilities
.workspace_did_change_watched_files
{
@@ -506,7 +512,7 @@ impl lspower::LanguageServer for LanguageServer {
Ok(())
}
- async fn did_open(&self, params: DidOpenTextDocumentParams) {
+ async fn did_open(&mut self, params: DidOpenTextDocumentParams) {
if params.text_document.uri.scheme() == "deno" {
// we can ignore virtual text documents opening, as they don't need to
// be tracked in memory, as they are static assets that won't change
@@ -514,16 +520,14 @@ impl lspower::LanguageServer for LanguageServer {
return;
}
let specifier = utils::normalize_url(params.text_document.uri);
- self.documents.lock().unwrap().open(
+ self.documents.open(
specifier.clone(),
params.text_document.version,
params.text_document.text,
);
if let Err(err) = self
.documents
- .lock()
- .unwrap()
- .analyze_dependencies(&specifier, &self.maybe_import_map.lock().unwrap())
+ .analyze_dependencies(&specifier, &self.maybe_import_map)
{
error!("{}", err);
}
@@ -534,9 +538,9 @@ impl lspower::LanguageServer for LanguageServer {
}
}
- async fn did_change(&self, params: DidChangeTextDocumentParams) {
+ async fn did_change(&mut self, params: DidChangeTextDocumentParams) {
let specifier = utils::normalize_url(params.text_document.uri);
- if let Err(err) = self.documents.lock().unwrap().change(
+ if let Err(err) = self.documents.change(
&specifier,
params.text_document.version,
params.content_changes,
@@ -545,9 +549,7 @@ impl lspower::LanguageServer for LanguageServer {
}
if let Err(err) = self
.documents
- .lock()
- .unwrap()
- .analyze_dependencies(&specifier, &self.maybe_import_map.lock().unwrap())
+ .analyze_dependencies(&specifier, &self.maybe_import_map)
{
error!("{}", err);
}
@@ -558,7 +560,7 @@ impl lspower::LanguageServer for LanguageServer {
}
}
- async fn did_close(&self, params: DidCloseTextDocumentParams) {
+ async fn did_close(&mut self, params: DidCloseTextDocumentParams) {
if params.text_document.uri.scheme() == "deno" {
// we can ignore virtual text documents opening, as they don't need to
// be tracked in memory, as they are static assets that won't change
@@ -566,7 +568,7 @@ impl lspower::LanguageServer for LanguageServer {
return;
}
let specifier = utils::normalize_url(params.text_document.uri);
- self.documents.lock().unwrap().close(&specifier);
+ self.documents.close(&specifier);
// TODO(@kitsonk): how to better lazily do this?
if let Err(err) = self.prepare_diagnostics().await {
@@ -579,16 +581,10 @@ impl lspower::LanguageServer for LanguageServer {
}
async fn did_change_configuration(
- &self,
+ &mut self,
params: DidChangeConfigurationParams,
) {
- let config = if self
- .config
- .lock()
- .unwrap()
- .client_capabilities
- .workspace_configuration
- {
+ let config = if self.config.client_capabilities.workspace_configuration {
self
.client
.configuration(vec![ConfigurationItem {
@@ -611,7 +607,7 @@ impl lspower::LanguageServer for LanguageServer {
};
if let Some(config) = config {
- if let Err(err) = self.config.lock().unwrap().update(config) {
+ if let Err(err) = self.config.update(config) {
error!("failed to update settings: {}", err);
}
if let Err(err) = self.update_import_map().await {
@@ -632,14 +628,12 @@ impl lspower::LanguageServer for LanguageServer {
}
async fn did_change_watched_files(
- &self,
+ &mut self,
params: DidChangeWatchedFilesParams,
) {
// if the current import map has changed, we need to reload it
- let maybe_import_map_uri =
- self.maybe_import_map_uri.lock().unwrap().clone();
- if let Some(import_map_uri) = maybe_import_map_uri {
- if params.changes.iter().any(|fe| import_map_uri == fe.uri) {
+ if let Some(import_map_uri) = &self.maybe_import_map_uri {
+ if params.changes.iter().any(|fe| *import_map_uri == fe.uri) {
if let Err(err) = self.update_import_map().await {
self
.client
@@ -649,9 +643,8 @@ impl lspower::LanguageServer for LanguageServer {
}
}
// if the current tsconfig has changed, we need to reload it
- let maybe_config_uri = self.maybe_config_uri.lock().unwrap().clone();
- if let Some(config_uri) = maybe_config_uri {
- if params.changes.iter().any(|fe| config_uri == fe.uri) {
+ if let Some(config_uri) = &self.maybe_config_uri {
+ if params.changes.iter().any(|fe| *config_uri == fe.uri) {
if let Err(err) = self.update_tsconfig().await {
self
.client
@@ -669,8 +662,6 @@ impl lspower::LanguageServer for LanguageServer {
let specifier = utils::normalize_url(params.text_document.uri.clone());
let file_text = self
.documents
- .lock()
- .unwrap()
.content(&specifier)
.map_err(|_| {
LspError::invalid_params(
@@ -793,7 +784,7 @@ impl lspower::LanguageServer for LanguageServer {
}
async fn references(
- &self,
+ &mut self,
params: ReferenceParams,
) -> LspResult<Option<Vec<Location>>> {
if !self.enabled() {
@@ -842,7 +833,7 @@ impl lspower::LanguageServer for LanguageServer {
}
async fn goto_definition(
- &self,
+ &mut self,
params: GotoDefinitionParams,
) -> LspResult<Option<GotoDefinitionResponse>> {
if !self.enabled() {
@@ -1038,7 +1029,7 @@ impl lspower::LanguageServer for LanguageServer {
.into_workspace_edit(
&params.new_name,
|s| self.get_line_index(s),
- |s| self.documents.lock().unwrap().version(&s),
+ |s| self.documents.version(&s),
)
.await
.map_err(|err| {
@@ -1052,7 +1043,7 @@ impl lspower::LanguageServer for LanguageServer {
}
async fn request_else(
- &self,
+ &mut self,
method: &str,
params: Option<Value>,
) -> LspResult<Option<Value>> {
@@ -1089,30 +1080,139 @@ impl lspower::LanguageServer for LanguageServer {
}
}
+#[lspower::async_trait]
+impl lspower::LanguageServer for LanguageServer {
+ async fn initialize(
+ &self,
+ params: InitializeParams,
+ ) -> LspResult<InitializeResult> {
+ self.0.lock().await.initialize(params).await
+ }
+
+ async fn initialized(&self, params: InitializedParams) {
+ self.0.lock().await.initialized(params).await
+ }
+
+ async fn shutdown(&self) -> LspResult<()> {
+ self.0.lock().await.shutdown().await
+ }
+
+ async fn did_open(&self, params: DidOpenTextDocumentParams) {
+ self.0.lock().await.did_open(params).await
+ }
+
+ async fn did_change(&self, params: DidChangeTextDocumentParams) {
+ self.0.lock().await.did_change(params).await
+ }
+
+ async fn did_close(&self, params: DidCloseTextDocumentParams) {
+ self.0.lock().await.did_close(params).await
+ }
+
+ async fn did_save(&self, params: DidSaveTextDocumentParams) {
+ self.0.lock().await.did_save(params).await
+ }
+
+ async fn did_change_configuration(
+ &self,
+ params: DidChangeConfigurationParams,
+ ) {
+ self.0.lock().await.did_change_configuration(params).await
+ }
+
+ async fn did_change_watched_files(
+ &self,
+ params: DidChangeWatchedFilesParams,
+ ) {
+ self.0.lock().await.did_change_watched_files(params).await
+ }
+
+ async fn formatting(
+ &self,
+ params: DocumentFormattingParams,
+ ) -> LspResult<Option<Vec<TextEdit>>> {
+ self.0.lock().await.formatting(params).await
+ }
+
+ async fn hover(&self, params: HoverParams) -> LspResult<Option<Hover>> {
+ self.0.lock().await.hover(params).await
+ }
+
+ async fn document_highlight(
+ &self,
+ params: DocumentHighlightParams,
+ ) -> LspResult<Option<Vec<DocumentHighlight>>> {
+ self.0.lock().await.document_highlight(params).await
+ }
+
+ async fn references(
+ &self,
+ params: ReferenceParams,
+ ) -> LspResult<Option<Vec<Location>>> {
+ self.0.lock().await.references(params).await
+ }
+
+ async fn goto_definition(
+ &self,
+ params: GotoDefinitionParams,
+ ) -> LspResult<Option<GotoDefinitionResponse>> {
+ self.0.lock().await.goto_definition(params).await
+ }
+
+ async fn completion(
+ &self,
+ params: CompletionParams,
+ ) -> LspResult<Option<CompletionResponse>> {
+ self.0.lock().await.completion(params).await
+ }
+
+ async fn goto_implementation(
+ &self,
+ params: GotoImplementationParams,
+ ) -> LspResult<Option<GotoImplementationResponse>> {
+ self.0.lock().await.goto_implementation(params).await
+ }
+
+ async fn rename(
+ &self,
+ params: RenameParams,
+ ) -> LspResult<Option<WorkspaceEdit>> {
+ self.0.lock().await.rename(params).await
+ }
+
+ async fn request_else(
+ &self,
+ method: &str,
+ params: Option<Value>,
+ ) -> LspResult<Option<Value>> {
+ self.0.lock().await.request_else(method, params).await
+ }
+}
+
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
-pub struct CacheParams {
- pub text_document: TextDocumentIdentifier,
+struct CacheParams {
+ text_document: TextDocumentIdentifier,
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
-pub struct VirtualTextDocumentParams {
- pub text_document: TextDocumentIdentifier,
+struct VirtualTextDocumentParams {
+ text_document: TextDocumentIdentifier,
}
-impl LanguageServer {
- async fn cache(&self, params: CacheParams) -> LspResult<bool> {
+impl Inner {
+ async fn cache(&mut self, params: CacheParams) -> LspResult<bool> {
let specifier = utils::normalize_url(params.text_document.uri);
- let maybe_import_map = self.maybe_import_map.lock().unwrap().clone();
+ let maybe_import_map = self.maybe_import_map.clone();
sources::cache(specifier.clone(), maybe_import_map)
.await
.map_err(|err| {
error!("{}", err);
LspError::internal_error()
})?;
- if self.documents.lock().unwrap().contains(&specifier) {
- self.diagnostics.lock().unwrap().invalidate(&specifier);
+ if self.documents.contains(&specifier) {
+ self.diagnostics.invalidate(&specifier);
}
self.prepare_diagnostics().await.map_err(|err| {
error!("{}", err);
@@ -1128,20 +1228,18 @@ impl LanguageServer {
let specifier = utils::normalize_url(params.text_document.uri);
let url = specifier.as_url();
let contents = if url.as_str() == "deno:/status.md" {
- let documents = self.documents.lock().unwrap();
Some(format!(
r#"# Deno Language Server Status
- Documents in memory: {}
"#,
- documents.len()
+ self.documents.len()
))
} else {
match url.scheme() {
"asset" => {
- let maybe_asset =
- { self.assets.lock().unwrap().get(&specifier).cloned() };
+ let maybe_asset = self.assets.get(&specifier).cloned();
if let Some(maybe_asset) = maybe_asset {
if let Some(asset) = maybe_asset {
Some(asset.text)
@@ -1149,9 +1247,9 @@ impl LanguageServer {
None
}
} else {
- let state_snapshot = self.snapshot();
+ let mut state_snapshot = self.snapshot();
if let Some(asset) =
- tsc::get_asset(&specifier, &self.ts_server, &state_snapshot)
+ tsc::get_asset(&specifier, &self.ts_server, &mut state_snapshot)
.await
.map_err(|_| LspError::internal_error())?
{
@@ -1163,8 +1261,7 @@ impl LanguageServer {
}
}
_ => {
- let mut sources = self.sources.lock().unwrap();
- if let Some(text) = sources.get_text(&specifier) {
+ if let Some(text) = self.sources.get_text(&specifier) {
Some(text)
} else {
error!("The cached sources was not found: {}", specifier);