summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKitson Kelly <me@kitsonkelly.com>2021-07-28 07:25:09 +1000
committerGitHub <noreply@github.com>2021-07-28 07:25:09 +1000
commit667b026798b5284e9ec8bf47baba80f343975d2e (patch)
tree3e2d85160925222b7052645ffb5fa0c8a4aa476e
parentfd0b24b246e3c6ed22e96f67361da654bbff8b48 (diff)
feat(lsp): ability to set DENO_DIR via settings (#11527)
Ref: denoland/vscode_deno#287
-rw-r--r--cli/flags.rs3
-rw-r--r--cli/lsp/README.md1
-rw-r--r--cli/lsp/config.rs5
-rw-r--r--cli/lsp/language_server.rs99
-rw-r--r--cli/lsp/registries.rs6
-rw-r--r--cli/lsp/sources.rs10
-rw-r--r--cli/program_state.rs7
-rw-r--r--cli/specifier_handler.rs8
-rw-r--r--cli/tests/integration/lsp_tests.rs90
-rw-r--r--cli/tests/lsp/initialize_params.json1
-rw-r--r--cli/tests/lsp/initialize_params_bad_config_option.json1
-rw-r--r--cli/tests/lsp/initialize_params_code_lens_test.json1
-rw-r--r--cli/tests/lsp/initialize_params_code_lens_test_disabled.json1
-rw-r--r--cli/tests/lsp/initialize_params_did_config_change.json1
-rw-r--r--cli/tests/lsp/initialize_params_disabled.json1
-rw-r--r--cli/tests/lsp/initialize_params_registry.json1
-rw-r--r--cli/tests/lsp/initialize_params_unstable.json1
-rw-r--r--cli/tools/standalone.rs1
18 files changed, 213 insertions, 25 deletions
diff --git a/cli/flags.rs b/cli/flags.rs
index b7e4e84db..086b20e10 100644
--- a/cli/flags.rs
+++ b/cli/flags.rs
@@ -139,6 +139,9 @@ pub struct Flags {
pub allow_write: Option<Vec<PathBuf>>,
pub ca_file: Option<String>,
pub cache_blocklist: Vec<String>,
+ /// This is not exposed as an option in the CLI, it is used internally when
+ /// the language server is configured with an explicit cache option.
+ pub cache_path: Option<PathBuf>,
pub cached_only: bool,
pub config_path: Option<String>,
pub coverage_dir: Option<String>,
diff --git a/cli/lsp/README.md b/cli/lsp/README.md
index 764998fb1..2256c4038 100644
--- a/cli/lsp/README.md
+++ b/cli/lsp/README.md
@@ -19,6 +19,7 @@ methods that the client calls via the Language Server RPC protocol.
There are several settings that the language server supports for a workspace:
- `deno.enable`
+- `deno.cache`
- `deno.config`
- `deno.importMap`
- `deno.codeLens.implementations`
diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs
index aeb0e29b9..a58a8d1ae 100644
--- a/cli/lsp/config.rs
+++ b/cli/lsp/config.rs
@@ -148,6 +148,10 @@ pub struct WorkspaceSettings {
#[serde(default)]
pub enable: bool,
+ /// An option that points to a path string of the path to utilise as the
+ /// cache/DENO_DIR for the language server.
+ pub cache: Option<String>,
+
/// An option that points to a path string of the config file to apply to
/// code within the workspace.
pub config: Option<String>,
@@ -475,6 +479,7 @@ mod tests {
config.get_workspace_settings(),
WorkspaceSettings {
enable: false,
+ cache: None,
config: None,
import_map: None,
code_lens: CodeLensSettings {
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index 27d6e4204..ab17d03fb 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -95,6 +95,9 @@ pub(crate) struct Inner {
module_registries: registries::ModuleRegistry,
/// The path to the module registries cache
module_registries_location: PathBuf,
+ /// An optional path to the DENO_DIR which has been specified in the client
+ /// options.
+ maybe_cache_path: Option<PathBuf>,
/// An optional configuration file which has been specified in the client
/// options.
maybe_config_file: Option<ConfigFile>,
@@ -144,10 +147,11 @@ impl Inner {
config,
diagnostics_server,
documents: Default::default(),
- maybe_config_file: Default::default(),
- maybe_config_uri: Default::default(),
- maybe_import_map: Default::default(),
- maybe_import_map_uri: Default::default(),
+ maybe_cache_path: None,
+ maybe_config_file: None,
+ maybe_config_uri: None,
+ maybe_import_map: None,
+ maybe_import_map_uri: None,
module_registries,
module_registries_location,
performance,
@@ -358,7 +362,7 @@ impl Inner {
self.maybe_config_uri = None;
if let Some(config_str) = maybe_config {
if !config_str.is_empty() {
- info!("Updating TypeScript configuration from: \"{}\"", config_str);
+ info!("Setting TypeScript configuration from: \"{}\"", config_str);
let config_url = if let Ok(url) = Url::from_file_path(config_str) {
Ok(url)
} else if let Some(root_uri) = maybe_root_uri {
@@ -417,6 +421,62 @@ impl Inner {
})
}
+ pub fn update_cache(&mut self) -> Result<(), AnyError> {
+ let mark = self.performance.mark("update_cache", None::<()>);
+ self.performance.measure(mark);
+ let (maybe_cache, maybe_root_uri) = {
+ let config = &self.config;
+ (
+ config.get_workspace_settings().cache,
+ config.root_uri.clone(),
+ )
+ };
+ let maybe_cache_path = if let Some(cache_str) = &maybe_cache {
+ info!("Setting cache path from: \"{}\"", cache_str);
+ let cache_url = if let Ok(url) = Url::from_file_path(cache_str) {
+ Ok(url)
+ } else if let Some(root_uri) = &maybe_root_uri {
+ let root_path = root_uri
+ .to_file_path()
+ .map_err(|_| anyhow!("Bad root_uri: {}", root_uri))?;
+ let cache_path = root_path.join(cache_str);
+ Url::from_file_path(cache_path).map_err(|_| {
+ anyhow!("Bad file path for import path: {:?}", cache_str)
+ })
+ } else {
+ Err(anyhow!(
+ "The path to the cache path (\"{}\") is not resolvable.",
+ cache_str
+ ))
+ }?;
+ let cache_path = cache_url.to_file_path().map_err(|_| {
+ anyhow!("Cannot convert \"{}\" into a file path.", cache_url)
+ })?;
+ info!(
+ " Resolved cache path: \"{}\"",
+ cache_path.to_string_lossy()
+ );
+ Some(cache_path)
+ } else {
+ None
+ };
+ if self.maybe_cache_path != maybe_cache_path {
+ let maybe_custom_root = maybe_cache_path
+ .clone()
+ .or_else(|| env::var("DENO_DIR").map(String::into).ok());
+ let dir = deno_dir::DenoDir::new(maybe_custom_root)
+ .expect("could not access DENO_DIR");
+ let module_registries_location = dir.root.join(REGISTRIES_PATH);
+ self.module_registries =
+ registries::ModuleRegistry::new(&module_registries_location);
+ self.module_registries_location = module_registries_location;
+ let sources_location = dir.root.join(SOURCES_PATH);
+ self.sources = Sources::new(&sources_location);
+ self.maybe_cache_path = maybe_cache_path;
+ }
+ Ok(())
+ }
+
pub async fn update_import_map(&mut self) -> Result<(), AnyError> {
let mark = self.performance.mark("update_import_map", None::<()>);
let (maybe_import_map, maybe_root_uri) = {
@@ -427,7 +487,7 @@ impl Inner {
)
};
if let Some(import_map_str) = &maybe_import_map {
- info!("Updating import map from: \"{}\"", import_map_str);
+ info!("Setting import map from: \"{}\"", import_map_str);
let import_map_url = if let Ok(url) = Url::from_file_path(import_map_str)
{
Ok(url)
@@ -620,8 +680,12 @@ impl Inner {
}
self.update_debug_flag();
+ // Check to see if we need to change the cache path
+ if let Err(err) = self.update_cache() {
+ self.client.show_message(MessageType::Warning, err).await;
+ }
if let Err(err) = self.update_tsconfig().await {
- warn!("Updating tsconfig has errored: {}", err);
+ self.client.show_message(MessageType::Warning, err).await;
}
if capabilities.code_action_provider.is_some() {
@@ -636,14 +700,6 @@ impl Inner {
self.ts_fixable_diagnostics = fixable_diagnostics;
}
- self.performance.measure(mark);
- Ok(InitializeResult {
- capabilities,
- server_info: Some(server_info),
- })
- }
-
- 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.client.show_message(MessageType::Warning, err).await;
@@ -653,6 +709,14 @@ impl Inner {
self.client.show_message(MessageType::Warning, err).await;
}
+ self.performance.measure(mark);
+ Ok(InitializeResult {
+ capabilities,
+ server_info: Some(server_info),
+ })
+ }
+
+ async fn initialized(&mut self, _: InitializedParams) {
if self
.config
.client_capabilities
@@ -836,6 +900,9 @@ impl Inner {
}
self.update_debug_flag();
+ if let Err(err) = self.update_cache() {
+ self.client.show_message(MessageType::Warning, err).await;
+ }
if let Err(err) = self.update_import_map().await {
self.client.show_message(MessageType::Warning, err).await;
}
@@ -2413,6 +2480,7 @@ impl Inner {
&specifier,
&self.maybe_import_map,
&self.maybe_config_file,
+ &self.maybe_cache_path,
)
.await
.map_err(|err| {
@@ -2425,6 +2493,7 @@ impl Inner {
&referrer,
&self.maybe_import_map,
&self.maybe_config_file,
+ &self.maybe_cache_path,
)
.await
.map_err(|err| {
diff --git a/cli/lsp/registries.rs b/cli/lsp/registries.rs
index 96c24b43f..d044927bc 100644
--- a/cli/lsp/registries.rs
+++ b/cli/lsp/registries.rs
@@ -254,8 +254,10 @@ pub struct ModuleRegistry {
impl Default for ModuleRegistry {
fn default() -> Self {
- let custom_root = std::env::var("DENO_DIR").map(String::into).ok();
- let dir = deno_dir::DenoDir::new(custom_root).unwrap();
+ // This only gets used when creating the tsc runtime and for testing, and so
+ // it shouldn't ever actually access the DenoDir, so it doesn't support a
+ // custom root.
+ let dir = deno_dir::DenoDir::new(None).unwrap();
let location = dir.root.join("registries");
let http_cache = HttpCache::new(&location);
let cache_setting = CacheSetting::Use;
diff --git a/cli/lsp/sources.rs b/cli/lsp/sources.rs
index 62c76260c..033a1e9d5 100644
--- a/cli/lsp/sources.rs
+++ b/cli/lsp/sources.rs
@@ -9,6 +9,7 @@ use crate::config_file::ConfigFile;
use crate::file_fetcher::get_source_from_bytes;
use crate::file_fetcher::map_content_type;
use crate::file_fetcher::SUPPORTED_SCHEMES;
+use crate::flags::Flags;
use crate::http_cache;
use crate::http_cache::HttpCache;
use crate::import_map::ImportMap;
@@ -36,8 +37,15 @@ pub async fn cache(
specifier: &ModuleSpecifier,
maybe_import_map: &Option<ImportMap>,
maybe_config_file: &Option<ConfigFile>,
+ maybe_cache_path: &Option<PathBuf>,
) -> Result<(), AnyError> {
- let program_state = Arc::new(ProgramState::build(Default::default()).await?);
+ let program_state = Arc::new(
+ ProgramState::build(Flags {
+ cache_path: maybe_cache_path.clone(),
+ ..Default::default()
+ })
+ .await?,
+ );
let handler = Arc::new(Mutex::new(FetchHandler::new(
&program_state,
Permissions::allow_all(),
diff --git a/cli/program_state.rs b/cli/program_state.rs
index 264b22729..6775b2276 100644
--- a/cli/program_state.rs
+++ b/cli/program_state.rs
@@ -61,8 +61,11 @@ pub struct ProgramState {
impl ProgramState {
pub async fn build(flags: flags::Flags) -> Result<Arc<Self>, AnyError> {
- let custom_root = env::var("DENO_DIR").map(String::into).ok();
- let dir = deno_dir::DenoDir::new(custom_root)?;
+ let maybe_custom_root = flags
+ .cache_path
+ .clone()
+ .or_else(|| env::var("DENO_DIR").map(String::into).ok());
+ let dir = deno_dir::DenoDir::new(maybe_custom_root)?;
let deps_cache_location = dir.root.join("deps");
let http_cache = http_cache::HttpCache::new(&deps_cache_location);
let ca_file = flags.ca_file.clone().or_else(|| env::var("DENO_CERT").ok());
diff --git a/cli/specifier_handler.rs b/cli/specifier_handler.rs
index 78687ba95..cec1049a3 100644
--- a/cli/specifier_handler.rs
+++ b/cli/specifier_handler.rs
@@ -1,7 +1,6 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use crate::ast::Location;
-use crate::deno_dir::DenoDir;
use crate::disk_cache::DiskCache;
use crate::file_fetcher::FileFetcher;
use crate::media_type::MediaType;
@@ -19,7 +18,6 @@ use deno_core::serde_json;
use deno_core::ModuleSpecifier;
use log::debug;
use std::collections::HashMap;
-use std::env;
use std::fmt;
use std::path::PathBuf;
use std::pin::Pin;
@@ -236,9 +234,7 @@ impl FetchHandler {
root_permissions: Permissions,
dynamic_permissions: Permissions,
) -> Result<Self, AnyError> {
- let custom_root = env::var("DENO_DIR").map(String::into).ok();
- let deno_dir = DenoDir::new(custom_root)?;
- let disk_cache = deno_dir.gen_cache;
+ let disk_cache = program_state.dir.gen_cache.clone();
let file_fetcher = program_state.file_fetcher.clone();
Ok(FetchHandler {
@@ -571,10 +567,12 @@ impl SpecifierHandler for MemoryHandler {
#[cfg(test)]
pub mod tests {
use super::*;
+ use crate::deno_dir::DenoDir;
use crate::file_fetcher::CacheSetting;
use crate::http_cache::HttpCache;
use deno_core::resolve_url_or_path;
use deno_runtime::deno_web::BlobStore;
+ use std::env;
use tempfile::TempDir;
macro_rules! map (
diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs
index 7f4f4e591..8bf019aa7 100644
--- a/cli/tests/integration/lsp_tests.rs
+++ b/cli/tests/integration/lsp_tests.rs
@@ -2526,6 +2526,96 @@ fn lsp_auto_discover_registry() {
}
#[test]
+fn lsp_cache_location() {
+ let _g = http_server();
+ let temp_dir = TempDir::new().expect("could not create temp dir");
+ let mut params: lsp::InitializeParams =
+ serde_json::from_value(load_fixture("initialize_params.json")).unwrap();
+
+ params.root_uri = Some(Url::from_file_path(temp_dir.path()).unwrap());
+ if let Some(Value::Object(mut map)) = params.initialization_options {
+ map.insert("cache".to_string(), json!(".cache"));
+ params.initialization_options = Some(Value::Object(map));
+ }
+
+ let deno_exe = deno_exe_path();
+ let mut client = LspClient::new(&deno_exe).unwrap();
+ client
+ .write_request::<_, _, Value>("initialize", params)
+ .unwrap();
+
+ client.write_notification("initialized", json!({})).unwrap();
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file_01.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "export const a = \"a\";\n",
+ }
+ }),
+ );
+ let diagnostics = did_open(
+ &mut client,
+ load_fixture("did_open_params_import_hover.json"),
+ );
+ let diagnostics = diagnostics.into_iter().flat_map(|x| x.diagnostics);
+ assert_eq!(diagnostics.count(), 12);
+ let (maybe_res, maybe_err) = client
+ .write_request::<_, _, Value>(
+ "deno/cache",
+ json!({
+ "referrer": {
+ "uri": "file:///a/file.ts",
+ },
+ "uris": [],
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert!(maybe_res.is_some());
+ let (maybe_res, maybe_err) = client
+ .write_request(
+ "textDocument/hover",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ },
+ "position": {
+ "line": 0,
+ "character": 28
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_err.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!({
+ "contents": {
+ "kind": "markdown",
+ "value": "**Resolved Dependency**\n\n**Code**: http&#8203;://127.0.0.1:4545/xTypeScriptTypes.js\n"
+ },
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 20
+ },
+ "end":{
+ "line": 0,
+ "character": 61
+ }
+ }
+ }))
+ );
+ let cache_path = temp_dir.path().join(".cache");
+ assert!(cache_path.is_dir());
+ assert!(cache_path.join("gen").is_dir());
+ shutdown(&mut client);
+}
+
+#[test]
fn lsp_diagnostics_warn() {
let _g = http_server();
let mut client = init("initialize_params.json");
diff --git a/cli/tests/lsp/initialize_params.json b/cli/tests/lsp/initialize_params.json
index f0b2d1dad..27711efd0 100644
--- a/cli/tests/lsp/initialize_params.json
+++ b/cli/tests/lsp/initialize_params.json
@@ -7,6 +7,7 @@
"rootUri": null,
"initializationOptions": {
"enable": true,
+ "cache": null,
"codeLens": {
"implementations": true,
"references": true,
diff --git a/cli/tests/lsp/initialize_params_bad_config_option.json b/cli/tests/lsp/initialize_params_bad_config_option.json
index fbff31566..cfe40acec 100644
--- a/cli/tests/lsp/initialize_params_bad_config_option.json
+++ b/cli/tests/lsp/initialize_params_bad_config_option.json
@@ -7,6 +7,7 @@
"rootUri": null,
"initializationOptions": {
"enable": true,
+ "cache": null,
"codeLens": {
"implementations": true,
"references": true,
diff --git a/cli/tests/lsp/initialize_params_code_lens_test.json b/cli/tests/lsp/initialize_params_code_lens_test.json
index 792928462..fb803c04f 100644
--- a/cli/tests/lsp/initialize_params_code_lens_test.json
+++ b/cli/tests/lsp/initialize_params_code_lens_test.json
@@ -7,6 +7,7 @@
"rootUri": null,
"initializationOptions": {
"enable": true,
+ "cache": null,
"importMap": null,
"lint": true,
"suggest": {
diff --git a/cli/tests/lsp/initialize_params_code_lens_test_disabled.json b/cli/tests/lsp/initialize_params_code_lens_test_disabled.json
index febec5695..c4d5e42f8 100644
--- a/cli/tests/lsp/initialize_params_code_lens_test_disabled.json
+++ b/cli/tests/lsp/initialize_params_code_lens_test_disabled.json
@@ -7,6 +7,7 @@
"rootUri": null,
"initializationOptions": {
"enable": true,
+ "cache": null,
"codeLens": {
"implementations": true,
"references": true,
diff --git a/cli/tests/lsp/initialize_params_did_config_change.json b/cli/tests/lsp/initialize_params_did_config_change.json
index 02237c788..b5cec8499 100644
--- a/cli/tests/lsp/initialize_params_did_config_change.json
+++ b/cli/tests/lsp/initialize_params_did_config_change.json
@@ -7,6 +7,7 @@
"rootUri": null,
"initializationOptions": {
"enable": true,
+ "cache": null,
"codeLens": {
"implementations": true,
"references": true
diff --git a/cli/tests/lsp/initialize_params_disabled.json b/cli/tests/lsp/initialize_params_disabled.json
index d5e59770a..349cc6ae3 100644
--- a/cli/tests/lsp/initialize_params_disabled.json
+++ b/cli/tests/lsp/initialize_params_disabled.json
@@ -7,6 +7,7 @@
"rootUri": null,
"initializationOptions": {
"enable": false,
+ "cache": null,
"codeLens": {
"implementations": true,
"references": true
diff --git a/cli/tests/lsp/initialize_params_registry.json b/cli/tests/lsp/initialize_params_registry.json
index 0a19c50ec..e98a62f7f 100644
--- a/cli/tests/lsp/initialize_params_registry.json
+++ b/cli/tests/lsp/initialize_params_registry.json
@@ -7,6 +7,7 @@
"rootUri": null,
"initializationOptions": {
"enable": true,
+ "cache": null,
"codeLens": {
"implementations": true,
"references": true
diff --git a/cli/tests/lsp/initialize_params_unstable.json b/cli/tests/lsp/initialize_params_unstable.json
index 153e3aef1..e18b6ba8b 100644
--- a/cli/tests/lsp/initialize_params_unstable.json
+++ b/cli/tests/lsp/initialize_params_unstable.json
@@ -7,6 +7,7 @@
"rootUri": null,
"initializationOptions": {
"enable": true,
+ "cache": null,
"codeLens": {
"implementations": true,
"references": true
diff --git a/cli/tools/standalone.rs b/cli/tools/standalone.rs
index 259c61222..dfec6c7dd 100644
--- a/cli/tools/standalone.rs
+++ b/cli/tools/standalone.rs
@@ -207,6 +207,7 @@ pub fn compile_to_runtime_flags(
allow_write: flags.allow_write,
ca_file: flags.ca_file,
cache_blocklist: vec![],
+ cache_path: None,
cached_only: false,
config_path: None,
coverage_dir: flags.coverage_dir,