mirror of
https://github.com/denoland/deno.git
synced 2024-12-25 00:29:09 -05:00
fix(lsp): respect DENO_FUTURE for BYONM config (#23207)
This commit is contained in:
parent
049e703331
commit
61f1b8e8dc
5 changed files with 111 additions and 29 deletions
|
@ -1145,6 +1145,7 @@ pub struct ConfigData {
|
||||||
pub lint_options: Arc<LintOptions>,
|
pub lint_options: Arc<LintOptions>,
|
||||||
pub lint_rules: Arc<ConfiguredRules>,
|
pub lint_rules: Arc<ConfiguredRules>,
|
||||||
pub ts_config: Arc<LspTsConfig>,
|
pub ts_config: Arc<LspTsConfig>,
|
||||||
|
pub byonm: bool,
|
||||||
pub node_modules_dir: Option<PathBuf>,
|
pub node_modules_dir: Option<PathBuf>,
|
||||||
pub vendor_dir: Option<PathBuf>,
|
pub vendor_dir: Option<PathBuf>,
|
||||||
pub lockfile: Option<Arc<Mutex<Lockfile>>>,
|
pub lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||||
|
@ -1267,8 +1268,6 @@ impl ConfigData {
|
||||||
let lint_rules =
|
let lint_rules =
|
||||||
get_configured_rules(lint_options.rules.clone(), config_file.as_ref());
|
get_configured_rules(lint_options.rules.clone(), config_file.as_ref());
|
||||||
let ts_config = LspTsConfig::new(config_file.as_ref());
|
let ts_config = LspTsConfig::new(config_file.as_ref());
|
||||||
let node_modules_dir =
|
|
||||||
config_file.as_ref().and_then(resolve_node_modules_dir);
|
|
||||||
let vendor_dir = config_file.as_ref().and_then(|c| c.vendor_dir_path());
|
let vendor_dir = config_file.as_ref().and_then(|c| c.vendor_dir_path());
|
||||||
|
|
||||||
// Load lockfile
|
// Load lockfile
|
||||||
|
@ -1327,6 +1326,23 @@ impl ConfigData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let byonm = std::env::var("DENO_UNSTABLE_BYONM").is_ok()
|
||||||
|
|| config_file
|
||||||
|
.as_ref()
|
||||||
|
.map(|c| c.has_unstable("byonm"))
|
||||||
|
.unwrap_or(false)
|
||||||
|
|| (std::env::var("DENO_FUTURE").is_ok()
|
||||||
|
&& package_json.is_some()
|
||||||
|
&& config_file
|
||||||
|
.as_ref()
|
||||||
|
.map(|c| c.json.node_modules_dir.is_none())
|
||||||
|
.unwrap_or(true));
|
||||||
|
if byonm {
|
||||||
|
lsp_log!(" Enabled 'bring your own node_modules'.");
|
||||||
|
}
|
||||||
|
let node_modules_dir = config_file
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|c| resolve_node_modules_dir(c, byonm));
|
||||||
|
|
||||||
// Load import map
|
// Load import map
|
||||||
let mut import_map = None;
|
let mut import_map = None;
|
||||||
|
@ -1427,6 +1443,7 @@ impl ConfigData {
|
||||||
lint_options: Arc::new(lint_options),
|
lint_options: Arc::new(lint_options),
|
||||||
lint_rules: Arc::new(lint_rules),
|
lint_rules: Arc::new(lint_rules),
|
||||||
ts_config: Arc::new(ts_config),
|
ts_config: Arc::new(ts_config),
|
||||||
|
byonm,
|
||||||
node_modules_dir,
|
node_modules_dir,
|
||||||
vendor_dir,
|
vendor_dir,
|
||||||
lockfile: lockfile.map(Mutex::new).map(Arc::new),
|
lockfile: lockfile.map(Mutex::new).map(Arc::new),
|
||||||
|
@ -1648,7 +1665,10 @@ fn resolve_lockfile_from_config(config_file: &ConfigFile) -> Option<Lockfile> {
|
||||||
resolve_lockfile_from_path(lockfile_path)
|
resolve_lockfile_from_path(lockfile_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_node_modules_dir(config_file: &ConfigFile) -> Option<PathBuf> {
|
fn resolve_node_modules_dir(
|
||||||
|
config_file: &ConfigFile,
|
||||||
|
byonm: bool,
|
||||||
|
) -> Option<PathBuf> {
|
||||||
// For the language server, require an explicit opt-in via the
|
// For the language server, require an explicit opt-in via the
|
||||||
// `nodeModulesDir: true` setting in the deno.json file. This is to
|
// `nodeModulesDir: true` setting in the deno.json file. This is to
|
||||||
// reduce the chance of modifying someone's node_modules directory
|
// reduce the chance of modifying someone's node_modules directory
|
||||||
|
@ -1657,7 +1677,8 @@ fn resolve_node_modules_dir(config_file: &ConfigFile) -> Option<PathBuf> {
|
||||||
if explicitly_disabled {
|
if explicitly_disabled {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let enabled = config_file.json.node_modules_dir == Some(true)
|
let enabled = byonm
|
||||||
|
|| config_file.json.node_modules_dir == Some(true)
|
||||||
|| config_file.json.vendor == Some(true);
|
|| config_file.json.vendor == Some(true);
|
||||||
if !enabled {
|
if !enabled {
|
||||||
return None;
|
return None;
|
||||||
|
|
|
@ -4,7 +4,6 @@ use base64::Engine;
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::parking_lot::Mutex;
|
|
||||||
use deno_core::resolve_url;
|
use deno_core::resolve_url;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::serde_json::json;
|
use deno_core::serde_json::json;
|
||||||
|
@ -14,7 +13,6 @@ use deno_core::url;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_graph::GraphKind;
|
use deno_graph::GraphKind;
|
||||||
use deno_graph::Resolution;
|
use deno_graph::Resolution;
|
||||||
use deno_lockfile::Lockfile;
|
|
||||||
use deno_npm::NpmSystemInfo;
|
use deno_npm::NpmSystemInfo;
|
||||||
use deno_runtime::deno_fs;
|
use deno_runtime::deno_fs;
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
use deno_runtime::deno_node::NodeResolver;
|
||||||
|
@ -54,6 +52,7 @@ use super::client::Client;
|
||||||
use super::code_lens;
|
use super::code_lens;
|
||||||
use super::completions;
|
use super::completions;
|
||||||
use super::config::Config;
|
use super::config::Config;
|
||||||
|
use super::config::ConfigData;
|
||||||
use super::config::ConfigSnapshot;
|
use super::config::ConfigSnapshot;
|
||||||
use super::config::UpdateImportsOnFileMoveEnabled;
|
use super::config::UpdateImportsOnFileMoveEnabled;
|
||||||
use super::config::WorkspaceSettings;
|
use super::config::WorkspaceSettings;
|
||||||
|
@ -92,7 +91,6 @@ use crate::args::get_root_cert_store;
|
||||||
use crate::args::CaData;
|
use crate::args::CaData;
|
||||||
use crate::args::CacheSetting;
|
use crate::args::CacheSetting;
|
||||||
use crate::args::CliOptions;
|
use crate::args::CliOptions;
|
||||||
use crate::args::ConfigFile;
|
|
||||||
use crate::args::Flags;
|
use crate::args::Flags;
|
||||||
use crate::cache::DenoDir;
|
use crate::cache::DenoDir;
|
||||||
use crate::cache::FastInsecureHasher;
|
use crate::cache::FastInsecureHasher;
|
||||||
|
@ -152,10 +150,9 @@ struct LspNpmConfigHash(u64);
|
||||||
impl LspNpmConfigHash {
|
impl LspNpmConfigHash {
|
||||||
pub fn from_inner(inner: &Inner) -> Self {
|
pub fn from_inner(inner: &Inner) -> Self {
|
||||||
let config_data = inner.config.tree.root_data();
|
let config_data = inner.config.tree.root_data();
|
||||||
let node_modules_dir = config_data
|
let node_modules_dir =
|
||||||
.as_ref()
|
config_data.and_then(|d| d.node_modules_dir.as_ref());
|
||||||
.and_then(|d| d.node_modules_dir.as_ref());
|
let lockfile = config_data.and_then(|d| d.lockfile.as_ref());
|
||||||
let lockfile = config_data.as_ref().and_then(|d| d.lockfile.as_ref());
|
|
||||||
let mut hasher = FastInsecureHasher::new();
|
let mut hasher = FastInsecureHasher::new();
|
||||||
hasher.write_hashable(node_modules_dir);
|
hasher.write_hashable(node_modules_dir);
|
||||||
hasher.write_hashable(&inner.maybe_global_cache_path);
|
hasher.write_hashable(&inner.maybe_global_cache_path);
|
||||||
|
@ -792,11 +789,7 @@ impl Inner {
|
||||||
&deno_dir,
|
&deno_dir,
|
||||||
&self.initial_cwd,
|
&self.initial_cwd,
|
||||||
&self.http_client,
|
&self.http_client,
|
||||||
config_data.as_ref().and_then(|d| d.config_file.as_deref()),
|
config_data,
|
||||||
config_data.as_ref().and_then(|d| d.lockfile.as_ref()),
|
|
||||||
config_data
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|d| d.node_modules_dir.clone()),
|
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let node_resolver = Arc::new(NodeResolver::new(
|
let node_resolver = Arc::new(NodeResolver::new(
|
||||||
|
@ -854,16 +847,10 @@ async fn create_npm_resolver(
|
||||||
deno_dir: &DenoDir,
|
deno_dir: &DenoDir,
|
||||||
initial_cwd: &Path,
|
initial_cwd: &Path,
|
||||||
http_client: &Arc<HttpClient>,
|
http_client: &Arc<HttpClient>,
|
||||||
maybe_config_file: Option<&ConfigFile>,
|
config_data: Option<&ConfigData>,
|
||||||
maybe_lockfile: Option<&Arc<Mutex<Lockfile>>>,
|
|
||||||
maybe_node_modules_dir_path: Option<PathBuf>,
|
|
||||||
) -> Arc<dyn CliNpmResolver> {
|
) -> Arc<dyn CliNpmResolver> {
|
||||||
let is_byonm = std::env::var("DENO_UNSTABLE_BYONM").as_deref() == Ok("1")
|
let byonm = config_data.map(|d| d.byonm).unwrap_or(false);
|
||||||
|| maybe_config_file
|
create_cli_npm_resolver_for_lsp(if byonm {
|
||||||
.as_ref()
|
|
||||||
.map(|c| c.has_unstable("byonm"))
|
|
||||||
.unwrap_or(false);
|
|
||||||
create_cli_npm_resolver_for_lsp(if is_byonm {
|
|
||||||
CliNpmResolverCreateOptions::Byonm(CliNpmResolverByonmCreateOptions {
|
CliNpmResolverCreateOptions::Byonm(CliNpmResolverByonmCreateOptions {
|
||||||
fs: Arc::new(deno_fs::RealFs),
|
fs: Arc::new(deno_fs::RealFs),
|
||||||
root_node_modules_dir: initial_cwd.join("node_modules"),
|
root_node_modules_dir: initial_cwd.join("node_modules"),
|
||||||
|
@ -871,7 +858,7 @@ async fn create_npm_resolver(
|
||||||
} else {
|
} else {
|
||||||
CliNpmResolverCreateOptions::Managed(CliNpmResolverManagedCreateOptions {
|
CliNpmResolverCreateOptions::Managed(CliNpmResolverManagedCreateOptions {
|
||||||
http_client: http_client.clone(),
|
http_client: http_client.clone(),
|
||||||
snapshot: match maybe_lockfile {
|
snapshot: match config_data.and_then(|d| d.lockfile.as_ref()) {
|
||||||
Some(lockfile) => {
|
Some(lockfile) => {
|
||||||
CliNpmResolverManagedSnapshotOption::ResolveFromLockfile(
|
CliNpmResolverManagedSnapshotOption::ResolveFromLockfile(
|
||||||
lockfile.clone(),
|
lockfile.clone(),
|
||||||
|
@ -890,7 +877,8 @@ async fn create_npm_resolver(
|
||||||
// the user is typing.
|
// the user is typing.
|
||||||
cache_setting: CacheSetting::Only,
|
cache_setting: CacheSetting::Only,
|
||||||
text_only_progress_bar: ProgressBar::new(ProgressBarStyle::TextOnly),
|
text_only_progress_bar: ProgressBar::new(ProgressBarStyle::TextOnly),
|
||||||
maybe_node_modules_path: maybe_node_modules_dir_path,
|
maybe_node_modules_path: config_data
|
||||||
|
.and_then(|d| d.node_modules_dir.clone()),
|
||||||
// do not install while resolving in the lsp—leave that to the cache command
|
// do not install while resolving in the lsp—leave that to the cache command
|
||||||
package_json_installer:
|
package_json_installer:
|
||||||
CliNpmResolverManagedPackageJsonInstallerOption::NoInstall,
|
CliNpmResolverManagedPackageJsonInstallerOption::NoInstall,
|
||||||
|
|
|
@ -11786,6 +11786,56 @@ fn lsp_jupyter_byonm_diagnostics() {
|
||||||
client.shutdown();
|
client.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lsp_deno_future_env_byonm() {
|
||||||
|
let context = TestContextBuilder::for_npm()
|
||||||
|
.env("DENO_FUTURE", "1")
|
||||||
|
.use_temp_cwd()
|
||||||
|
.build();
|
||||||
|
let temp_dir = context.temp_dir();
|
||||||
|
temp_dir.path().join("package.json").write_json(&json!({
|
||||||
|
"dependencies": {
|
||||||
|
"@denotest/esm-basic": "*",
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
context.run_npm("install");
|
||||||
|
let mut client = context.new_lsp_command().build();
|
||||||
|
client.initialize_default();
|
||||||
|
let diagnostics = client.did_open(json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": temp_dir.uri().join("file.ts").unwrap(),
|
||||||
|
"languageId": "typescript",
|
||||||
|
"version": 1,
|
||||||
|
"text": r#"
|
||||||
|
import "npm:chalk";
|
||||||
|
import "@denotest/esm-basic";
|
||||||
|
"#,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
assert_eq!(
|
||||||
|
json!(diagnostics.all()),
|
||||||
|
json!([
|
||||||
|
{
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"character": 15,
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"character": 26,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"severity": 1,
|
||||||
|
"code": "resolver-error",
|
||||||
|
"source": "deno",
|
||||||
|
"message": format!("Could not find a matching package for 'npm:chalk' in '{}'. You must specify this as a package.json dependency when the node_modules folder is not managed by Deno.", temp_dir.path().join("package.json")),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
);
|
||||||
|
client.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn lsp_sloppy_imports_warn() {
|
fn lsp_sloppy_imports_warn() {
|
||||||
let context = TestContextBuilder::new().use_temp_cwd().build();
|
let context = TestContextBuilder::new().use_temp_cwd().build();
|
||||||
|
|
|
@ -292,9 +292,13 @@ impl TestContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_lsp_command(&self) -> LspClientBuilder {
|
pub fn new_lsp_command(&self) -> LspClientBuilder {
|
||||||
LspClientBuilder::new_with_dir(self.deno_dir.clone())
|
let mut builder = LspClientBuilder::new_with_dir(self.deno_dir.clone())
|
||||||
.deno_exe(&self.deno_exe)
|
.deno_exe(&self.deno_exe)
|
||||||
.set_root_dir(self.temp_dir.path().clone())
|
.set_root_dir(self.temp_dir.path().clone());
|
||||||
|
for (key, value) in &self.envs {
|
||||||
|
builder = builder.env(key, value);
|
||||||
|
}
|
||||||
|
builder
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_npm(&self, args: impl AsRef<str>) {
|
pub fn run_npm(&self, args: impl AsRef<str>) {
|
||||||
|
|
|
@ -33,7 +33,10 @@ use serde::Serialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use serde_json::to_value;
|
use serde_json::to_value;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::ffi::OsString;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::BufRead;
|
use std::io::BufRead;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
|
@ -465,6 +468,7 @@ pub struct LspClientBuilder {
|
||||||
root_dir: PathRef,
|
root_dir: PathRef,
|
||||||
use_diagnostic_sync: bool,
|
use_diagnostic_sync: bool,
|
||||||
deno_dir: TempDir,
|
deno_dir: TempDir,
|
||||||
|
envs: HashMap<OsString, OsString>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LspClientBuilder {
|
impl LspClientBuilder {
|
||||||
|
@ -481,6 +485,7 @@ impl LspClientBuilder {
|
||||||
root_dir: deno_dir.path().clone(),
|
root_dir: deno_dir.path().clone(),
|
||||||
use_diagnostic_sync: true,
|
use_diagnostic_sync: true,
|
||||||
deno_dir,
|
deno_dir,
|
||||||
|
envs: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,6 +519,17 @@ impl LspClientBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn env(
|
||||||
|
mut self,
|
||||||
|
key: impl AsRef<OsStr>,
|
||||||
|
value: impl AsRef<OsStr>,
|
||||||
|
) -> Self {
|
||||||
|
self
|
||||||
|
.envs
|
||||||
|
.insert(key.as_ref().to_owned(), value.as_ref().to_owned());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build(&self) -> LspClient {
|
pub fn build(&self) -> LspClient {
|
||||||
self.build_result().unwrap()
|
self.build_result().unwrap()
|
||||||
}
|
}
|
||||||
|
@ -534,6 +550,9 @@ impl LspClientBuilder {
|
||||||
.arg("lsp")
|
.arg("lsp")
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.stdout(Stdio::piped());
|
.stdout(Stdio::piped());
|
||||||
|
for (key, value) in &self.envs {
|
||||||
|
command.env(key, value);
|
||||||
|
}
|
||||||
if self.capture_stderr {
|
if self.capture_stderr {
|
||||||
command.stderr(Stdio::piped());
|
command.stderr(Stdio::piped());
|
||||||
} else if !self.print_stderr {
|
} else if !self.print_stderr {
|
||||||
|
|
Loading…
Reference in a new issue