summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNayeem Rahman <nayeemrmn99@gmail.com>2024-05-30 04:16:15 +0100
committerGitHub <noreply@github.com>2024-05-30 03:16:15 +0000
commit556012320ecf546aaf5f7ac84d75c29593af758e (patch)
treea1cbb0becdd74d9e3aef11f7f6ef0237a13cfcbe
parentd67ee9a08be200dc1ce9a416c9cda82730e24b68 (diff)
feat(lsp): support .npmrc (#24042)
Closes #24040
-rw-r--r--cli/args/mod.rs14
-rw-r--r--cli/lsp/config.rs36
-rw-r--r--tests/integration/lsp_tests.rs77
3 files changed, 109 insertions, 18 deletions
diff --git a/cli/args/mod.rs b/cli/args/mod.rs
index 5bdecca9b..fe9c27928 100644
--- a/cli/args/mod.rs
+++ b/cli/args/mod.rs
@@ -554,12 +554,12 @@ fn discover_package_json(
///
/// In the future we will need to support it in user directory or global directory
/// as per https://docs.npmjs.com/cli/v10/configuring-npm/npmrc#files.
-fn discover_npmrc(
+pub fn discover_npmrc(
maybe_package_json_path: Option<PathBuf>,
maybe_deno_json_path: Option<PathBuf>,
-) -> Result<Arc<ResolvedNpmRc>, AnyError> {
+) -> Result<(Arc<ResolvedNpmRc>, Option<PathBuf>), AnyError> {
if !*DENO_FUTURE {
- return Ok(create_default_npmrc());
+ return Ok((create_default_npmrc(), None));
}
const NPMRC_NAME: &str = ".npmrc";
@@ -599,7 +599,7 @@ fn discover_npmrc(
if let Some(package_json_path) = maybe_package_json_path {
if let Some(package_json_dir) = package_json_path.parent() {
if let Some((source, path)) = try_to_read_npmrc(package_json_dir)? {
- return try_to_parse_npmrc(source, &path);
+ return try_to_parse_npmrc(source, &path).map(|r| (r, Some(path)));
}
}
}
@@ -607,13 +607,13 @@ fn discover_npmrc(
if let Some(deno_json_path) = maybe_deno_json_path {
if let Some(deno_json_dir) = deno_json_path.parent() {
if let Some((source, path)) = try_to_read_npmrc(deno_json_dir)? {
- return try_to_parse_npmrc(source, &path);
+ return try_to_parse_npmrc(source, &path).map(|r| (r, Some(path)));
}
}
}
log::debug!("No .npmrc file found");
- Ok(create_default_npmrc())
+ Ok((create_default_npmrc(), None))
}
pub fn create_default_npmrc() -> Arc<ResolvedNpmRc> {
@@ -938,7 +938,7 @@ impl CliOptions {
} else {
maybe_package_json = discover_package_json(&flags, None, &initial_cwd)?;
}
- let npmrc = discover_npmrc(
+ let (npmrc, _) = discover_npmrc(
maybe_package_json.as_ref().map(|p| p.path.clone()),
maybe_config_file.as_ref().and_then(|cf| {
if cf.specifier.scheme() == "file" {
diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs
index 02f3d5afb..d3cdd2a94 100644
--- a/cli/lsp/config.rs
+++ b/cli/lsp/config.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use super::logging::lsp_log;
+use crate::args::discover_npmrc;
use crate::args::read_lockfile_at_path;
use crate::args::ConfigFile;
use crate::args::FmtOptions;
@@ -1175,10 +1176,12 @@ impl ConfigData {
.entry(config_file.specifier.clone())
.or_insert(ConfigWatchedFileType::DenoJson);
}
- let config_file_canonicalized_specifier = config_file
+ let config_file_path = config_file
.as_ref()
- .and_then(|c| c.specifier.to_file_path().ok())
- .and_then(|p| canonicalize_path_maybe_not_exists(&p).ok())
+ .and_then(|c| specifier_to_file_path(&c.specifier).ok());
+ let config_file_canonicalized_specifier = config_file_path
+ .as_ref()
+ .and_then(|p| canonicalize_path_maybe_not_exists(p).ok())
.and_then(|p| ModuleSpecifier::from_file_path(p).ok());
if let Some(specifier) = config_file_canonicalized_specifier {
watched_files
@@ -1306,17 +1309,17 @@ impl ConfigData {
// Load package.json
let mut package_json = None;
- // TODO(bartlomieju): support discovering .npmrc
- let npmrc = None;
- if let Ok(path) = specifier_to_file_path(scope) {
- let path = path.join("package.json");
- if let Ok(specifier) = ModuleSpecifier::from_file_path(&path) {
+ let package_json_path = specifier_to_file_path(scope)
+ .ok()
+ .map(|p| p.join("package.json"));
+ if let Some(path) = &package_json_path {
+ if let Ok(specifier) = ModuleSpecifier::from_file_path(path) {
watched_files
.entry(specifier)
.or_insert(ConfigWatchedFileType::PackageJson);
}
let package_json_canonicalized_specifier =
- canonicalize_path_maybe_not_exists(&path)
+ canonicalize_path_maybe_not_exists(path)
.ok()
.and_then(|p| ModuleSpecifier::from_file_path(p).ok());
if let Some(specifier) = package_json_canonicalized_specifier {
@@ -1324,7 +1327,7 @@ impl ConfigData {
.entry(specifier)
.or_insert(ConfigWatchedFileType::PackageJson);
}
- if let Ok(source) = std::fs::read_to_string(&path) {
+ if let Ok(source) = std::fs::read_to_string(path) {
match PackageJson::load_from_string(path.clone(), source) {
Ok(result) => {
lsp_log!(" Resolved package.json: \"{}\"", path.display());
@@ -1340,6 +1343,17 @@ impl ConfigData {
}
}
}
+ let npmrc = discover_npmrc(package_json_path, config_file_path)
+ .inspect(|(_, path)| {
+ if let Some(path) = path {
+ lsp_log!(" Resolved .npmrc: \"{}\"", path.display());
+ }
+ })
+ .inspect_err(|err| {
+ lsp_warn!(" Couldn't read .npmrc for \"{scope}\": {err}");
+ })
+ .map(|(r, _)| r)
+ .ok();
let byonm = std::env::var("DENO_UNSTABLE_BYONM").is_ok()
|| config_file
.as_ref()
@@ -1464,7 +1478,7 @@ impl ConfigData {
vendor_dir,
lockfile: lockfile.map(Mutex::new).map(Arc::new),
package_json: package_json.map(Arc::new),
- npmrc: npmrc.map(Arc::new),
+ npmrc,
import_map: import_map.map(Arc::new),
import_map_from_settings,
watched_files,
diff --git a/tests/integration/lsp_tests.rs b/tests/integration/lsp_tests.rs
index 09882a666..51507b0a6 100644
--- a/tests/integration/lsp_tests.rs
+++ b/tests/integration/lsp_tests.rs
@@ -8861,6 +8861,83 @@ fn lsp_tls_cert() {
}
#[test]
+fn lsp_npmrc() {
+ let context = TestContextBuilder::new()
+ .use_http_server()
+ .use_temp_cwd()
+ .add_npm_env_vars()
+ .env("DENO_FUTURE", "1")
+ .build();
+ let temp_dir = context.temp_dir();
+ temp_dir.write(
+ temp_dir.path().join("deno.json"),
+ json!({
+ "nodeModulesDir": true,
+ })
+ .to_string(),
+ );
+ temp_dir.write(
+ temp_dir.path().join("package.json"),
+ json!({
+ "name": "npmrc_test",
+ "version": "0.0.1",
+ "dependencies": {
+ "@denotest/basic": "1.0.0",
+ },
+ })
+ .to_string(),
+ );
+ temp_dir.write(
+ temp_dir.path().join(".npmrc"),
+ "\
+@denotest:registry=http://127.0.0.1:4261/
+//127.0.0.1:4261/:_authToken=private-reg-token
+",
+ );
+ let file = source_file(
+ temp_dir.path().join("main.ts"),
+ r#"
+ import { getValue, setValue } from "@denotest/basic";
+ setValue(42);
+ const n: string = getValue();
+ console.log(n);
+ "#,
+ );
+ let mut client = context.new_lsp_command().build();
+ client.initialize_default();
+ client.write_request(
+ "workspace/executeCommand",
+ json!({
+ "command": "deno.cache",
+ "arguments": [[], file.uri()],
+ }),
+ );
+ let diagnostics = client.did_open_file(&file);
+ assert_eq!(
+ json!(diagnostics.all()),
+ json!([
+ {
+ "range": {
+ "start": {
+ "line": 3,
+ "character": 12,
+ },
+ "end": {
+ "line": 3,
+ "character": 13,
+ },
+ },
+ "severity": 1,
+ "code": 2322,
+ "source": "deno-ts",
+ "message": "Type 'number' is not assignable to type 'string'.",
+ },
+ ]),
+ );
+ client.shutdown();
+}
+
+#[test]
fn lsp_diagnostics_warn_redirect() {
let context = TestContextBuilder::new()
.use_http_server()