summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/lsp/config.rs63
-rw-r--r--tests/integration/lsp_tests.rs402
2 files changed, 442 insertions, 23 deletions
diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs
index 3fded336b..481273930 100644
--- a/cli/lsp/config.rs
+++ b/cli/lsp/config.rs
@@ -1299,16 +1299,27 @@ impl ConfigData {
}
};
- let vendor_dir = config_file.as_ref().and_then(|c| {
- if c.vendor() == Some(true) {
- Some(c.specifier.to_file_path().ok()?.parent()?.join("vendor"))
- } else {
- None
- }
- });
+ let vendor_dir = if let Some(workspace_root) = workspace_root {
+ workspace_root.vendor_dir.clone()
+ } else {
+ config_file.as_ref().and_then(|c| {
+ if c.vendor() == Some(true) {
+ Some(c.specifier.to_file_path().ok()?.parent()?.join("vendor"))
+ } else {
+ None
+ }
+ })
+ };
// Load lockfile
- let lockfile = config_file.as_ref().and_then(resolve_lockfile_from_config);
+ let lockfile = if let Some(workspace_root) = workspace_root {
+ workspace_root.lockfile.clone()
+ } else {
+ config_file
+ .as_ref()
+ .and_then(resolve_lockfile_from_config)
+ .map(Arc::new)
+ };
if let Some(lockfile) = &lockfile {
if let Ok(specifier) = ModuleSpecifier::from_file_path(&lockfile.filename)
{
@@ -1376,23 +1387,31 @@ impl ConfigData {
})
.map(|(r, _)| r)
.ok();
- let byonm = std::env::var("DENO_UNSTABLE_BYONM").is_ok()
- || config_file
- .as_ref()
- .map(|c| c.has_unstable("byonm"))
- .unwrap_or(false)
- || (*DENO_FUTURE
- && package_json.is_some()
- && config_file
+ let byonm = if let Some(workspace_root) = workspace_root {
+ workspace_root.byonm
+ } else {
+ std::env::var("DENO_UNSTABLE_BYONM").is_ok()
+ || config_file
.as_ref()
- .map(|c| c.json.node_modules_dir.is_none())
- .unwrap_or(true));
+ .map(|c| c.has_unstable("byonm"))
+ .unwrap_or(false)
+ || (*DENO_FUTURE
+ && 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));
+ let node_modules_dir = if let Some(workspace_root) = workspace_root {
+ workspace_root.node_modules_dir.clone()
+ } else {
+ config_file
+ .as_ref()
+ .and_then(|c| resolve_node_modules_dir(c, byonm))
+ };
// Load import map
let mut import_map = None;
@@ -1547,7 +1566,7 @@ impl ConfigData {
byonm,
node_modules_dir,
vendor_dir,
- lockfile: lockfile.map(Arc::new),
+ lockfile,
package_json: package_json.map(Arc::new),
npmrc,
import_map,
diff --git a/tests/integration/lsp_tests.rs b/tests/integration/lsp_tests.rs
index f66fc97be..2111c6f07 100644
--- a/tests/integration/lsp_tests.rs
+++ b/tests/integration/lsp_tests.rs
@@ -12366,7 +12366,7 @@ fn lsp_deno_json_scopes_import_map() {
}
#[test]
-fn lsp_deno_json_scopes_vendor_dirs() {
+fn lsp_deno_json_scopes_vendor_dir() {
let context = TestContextBuilder::new()
.use_http_server()
.use_temp_cwd()
@@ -12551,6 +12551,194 @@ fn lsp_deno_json_scopes_vendor_dirs() {
}
#[test]
+fn lsp_deno_json_scopes_node_modules_dir() {
+ let context = TestContextBuilder::new()
+ .use_http_server()
+ .use_temp_cwd()
+ .build();
+ let temp_dir = context.temp_dir();
+ temp_dir.create_dir_all("project1");
+ temp_dir.create_dir_all("project2/project3");
+ temp_dir.write(
+ "project1/deno.json",
+ json!({
+ "nodeModulesDir": true,
+ })
+ .to_string(),
+ );
+ temp_dir.write(
+ "project2/deno.json",
+ json!({
+ "nodeModulesDir": true,
+ })
+ .to_string(),
+ );
+ temp_dir.write(
+ "project2/project3/deno.json",
+ json!({
+ "nodeModulesDir": true,
+ })
+ .to_string(),
+ );
+ let mut client = context.new_lsp_command().build();
+ client.initialize_default();
+ client.did_open(json!({
+ "textDocument": {
+ "uri": temp_dir.uri().join("project1/file.ts").unwrap(),
+ "languageId": "typescript",
+ "version": 1,
+ "text": "import \"npm:@denotest/add@1\";\n",
+ },
+ }));
+ client.write_request(
+ "workspace/executeCommand",
+ json!({
+ "command": "deno.cache",
+ "arguments": [[], temp_dir.uri().join("project1/file.ts").unwrap()],
+ }),
+ );
+ let res = client.write_request(
+ "textDocument/definition",
+ json!({
+ "textDocument": {
+ "uri": temp_dir.uri().join("project1/file.ts").unwrap(),
+ },
+ "position": { "line": 0, "character": 7 },
+ }),
+ );
+ // The temp dir is symlinked in macos, and `node_modules` is canonicalized.
+ let canon_temp_dir =
+ Url::from_directory_path(temp_dir.path().canonicalize()).unwrap();
+ assert_eq!(
+ res,
+ json!([{
+ "targetUri": canon_temp_dir.join("project1/node_modules/.deno/@denotest+add@1.0.0/node_modules/@denotest/add/index.d.ts").unwrap(),
+ "targetRange": {
+ "start": {
+ "line": 0,
+ "character": 0,
+ },
+ "end": {
+ "line": 1,
+ "character": 0,
+ },
+ },
+ "targetSelectionRange": {
+ "start": {
+ "line": 0,
+ "character": 0,
+ },
+ "end": {
+ "line": 1,
+ "character": 0,
+ },
+ },
+ }]),
+ );
+ client.did_open(json!({
+ "textDocument": {
+ "uri": temp_dir.uri().join("project2/file.ts").unwrap(),
+ "languageId": "typescript",
+ "version": 1,
+ "text": "import \"npm:@denotest/add@1\";\n",
+ },
+ }));
+ client.write_request(
+ "workspace/executeCommand",
+ json!({
+ "command": "deno.cache",
+ "arguments": [[], temp_dir.uri().join("project2/file.ts").unwrap()],
+ }),
+ );
+ let res = client.write_request(
+ "textDocument/definition",
+ json!({
+ "textDocument": {
+ "uri": temp_dir.uri().join("project2/file.ts").unwrap(),
+ },
+ "position": { "line": 0, "character": 7 },
+ }),
+ );
+ assert_eq!(
+ res,
+ json!([{
+ "targetUri": canon_temp_dir.join("project2/node_modules/.deno/@denotest+add@1.0.0/node_modules/@denotest/add/index.d.ts").unwrap(),
+ "targetRange": {
+ "start": {
+ "line": 0,
+ "character": 0,
+ },
+ "end": {
+ "line": 1,
+ "character": 0,
+ },
+ },
+ "targetSelectionRange": {
+ "start": {
+ "line": 0,
+ "character": 0,
+ },
+ "end": {
+ "line": 1,
+ "character": 0,
+ },
+ },
+ }]),
+ );
+ client.did_open(json!({
+ "textDocument": {
+ "uri": temp_dir.uri().join("project2/project3/file.ts").unwrap(),
+ "languageId": "typescript",
+ "version": 1,
+ "text": "import \"npm:@denotest/add@1\";\n",
+ },
+ }));
+ client.write_request(
+ "workspace/executeCommand",
+ json!({
+ "command": "deno.cache",
+ "arguments": [[], temp_dir.uri().join("project2/project3/file.ts").unwrap()],
+ }),
+ );
+ let res = client.write_request(
+ "textDocument/definition",
+ json!({
+ "textDocument": {
+ "uri": temp_dir.uri().join("project2/project3/file.ts").unwrap(),
+ },
+ "position": { "line": 0, "character": 7 },
+ }),
+ );
+ assert_eq!(
+ res,
+ json!([{
+ "targetUri": canon_temp_dir.join("project2/project3/node_modules/.deno/@denotest+add@1.0.0/node_modules/@denotest/add/index.d.ts").unwrap(),
+ "targetRange": {
+ "start": {
+ "line": 0,
+ "character": 0,
+ },
+ "end": {
+ "line": 1,
+ "character": 0,
+ },
+ },
+ "targetSelectionRange": {
+ "start": {
+ "line": 0,
+ "character": 0,
+ },
+ "end": {
+ "line": 1,
+ "character": 0,
+ },
+ },
+ }]),
+ );
+ client.shutdown();
+}
+
+#[test]
fn lsp_deno_json_scopes_ts_config() {
let context = TestContextBuilder::new().use_temp_cwd().build();
let temp_dir = context.temp_dir();
@@ -13370,6 +13558,218 @@ fn lsp_deno_json_workspace_import_map() {
}
#[test]
+fn lsp_workspace_lockfile() {
+ let context = TestContextBuilder::new()
+ .use_http_server()
+ .use_temp_cwd()
+ .build();
+ let temp_dir = context.temp_dir();
+ temp_dir.create_dir_all("project1/project2");
+ temp_dir.write(
+ "project1/deno.json",
+ json!({
+ "workspace": ["project2"],
+ })
+ .to_string(),
+ );
+ temp_dir.write("project1/deno.lock", json!({
+ "version": "3",
+ "redirects": {
+ "http://localhost:4545/subdir/mod1.ts": "http://localhost:4545/subdir/mod2.ts",
+ },
+ "remote": {},
+ }).to_string());
+ temp_dir.write("project1/project2/deno.json", json!({}).to_string());
+ let mut client = context.new_lsp_command().build();
+ client.initialize_default();
+ client.did_open(json!({
+ "textDocument": {
+ "uri": temp_dir.uri().join("project1/project2/file.ts").unwrap(),
+ "languageId": "typescript",
+ "version": 1,
+ "text": "import \"http://localhost:4545/subdir/mod1.ts\";\n",
+ },
+ }));
+ client.write_request(
+ "workspace/executeCommand",
+ json!({
+ "command": "deno.cache",
+ "arguments": [[], temp_dir.uri().join("project1/project2/file.ts").unwrap()],
+ }),
+ );
+ client.read_diagnostics();
+ let res = client.write_request(
+ "textDocument/definition",
+ json!({
+ "textDocument": { "uri": temp_dir.uri().join("project1/project2/file.ts").unwrap() },
+ "position": { "line": 0, "character": 7 },
+ }),
+ );
+ assert_eq!(
+ res,
+ json!([{
+ "targetUri": "deno:/http/localhost%3A4545/subdir/mod2.ts",
+ "targetRange": {
+ "start": { "line": 0, "character": 0 },
+ "end": { "line": 1, "character": 0 },
+ },
+ "targetSelectionRange": {
+ "start": { "line": 0, "character": 0 },
+ "end": { "line": 1, "character": 0 },
+ },
+ }]),
+ );
+ client.shutdown();
+}
+
+#[test]
+fn lsp_deno_json_workspace_vendor_dir() {
+ let context = TestContextBuilder::new()
+ .use_http_server()
+ .use_temp_cwd()
+ .build();
+ let temp_dir = context.temp_dir();
+ temp_dir.create_dir_all("project1/project2");
+ temp_dir.write(
+ "project1/deno.json",
+ json!({
+ "workspace": ["project2"],
+ "vendor": true,
+ })
+ .to_string(),
+ );
+ temp_dir.write("project1/project2/deno.json", json!({}).to_string());
+ let mut client = context.new_lsp_command().build();
+ client.initialize_default();
+ client.did_open(json!({
+ "textDocument": {
+ "uri": temp_dir.uri().join("project1/project2/file.ts").unwrap(),
+ "languageId": "typescript",
+ "version": 1,
+ "text": "import \"http://localhost:4545/subdir/mod1.ts\";\n",
+ },
+ }));
+ client.write_request(
+ "workspace/executeCommand",
+ json!({
+ "command": "deno.cache",
+ "arguments": [[], temp_dir.uri().join("project1/project2/file.ts").unwrap()],
+ }),
+ );
+ let res = client.write_request(
+ "textDocument/definition",
+ json!({
+ "textDocument": {
+ "uri": temp_dir.uri().join("project1/project2/file.ts").unwrap(),
+ },
+ "position": { "line": 0, "character": 7 },
+ }),
+ );
+ assert_eq!(
+ res,
+ json!([{
+ "targetUri": temp_dir.uri().join("project1/vendor/http_localhost_4545/subdir/mod1.ts").unwrap(),
+ "targetRange": {
+ "start": {
+ "line": 0,
+ "character": 0,
+ },
+ "end": {
+ "line": 17,
+ "character": 0,
+ },
+ },
+ "targetSelectionRange": {
+ "start": {
+ "line": 0,
+ "character": 0,
+ },
+ "end": {
+ "line": 17,
+ "character": 0,
+ },
+ },
+ }]),
+ );
+ client.shutdown();
+}
+
+#[test]
+fn lsp_deno_json_workspace_node_modules_dir() {
+ let context = TestContextBuilder::new()
+ .use_http_server()
+ .use_temp_cwd()
+ .build();
+ let temp_dir = context.temp_dir();
+ temp_dir.create_dir_all("project1/project2");
+ temp_dir.write(
+ "project1/deno.json",
+ json!({
+ "workspace": ["project2"],
+ "nodeModulesDir": true,
+ })
+ .to_string(),
+ );
+ temp_dir.write("project1/project2/deno.json", json!({}).to_string());
+ let mut client = context.new_lsp_command().build();
+ client.initialize_default();
+ client.did_open(json!({
+ "textDocument": {
+ "uri": temp_dir.uri().join("project1/project2/file.ts").unwrap(),
+ "languageId": "typescript",
+ "version": 1,
+ "text": "import \"npm:@denotest/add@1\";\n",
+ },
+ }));
+ client.write_request(
+ "workspace/executeCommand",
+ json!({
+ "command": "deno.cache",
+ "arguments": [[], temp_dir.uri().join("project1/project2/file.ts").unwrap()],
+ }),
+ );
+ let res = client.write_request(
+ "textDocument/definition",
+ json!({
+ "textDocument": {
+ "uri": temp_dir.uri().join("project1/project2/file.ts").unwrap(),
+ },
+ "position": { "line": 0, "character": 7 },
+ }),
+ );
+ // The temp dir is symlinked in macos, and `node_modules` is canonicalized.
+ let canon_temp_dir =
+ Url::from_directory_path(temp_dir.path().canonicalize()).unwrap();
+ assert_eq!(
+ res,
+ json!([{
+ "targetUri": canon_temp_dir.join("project1/node_modules/.deno/@denotest+add@1.0.0/node_modules/@denotest/add/index.d.ts").unwrap(),
+ "targetRange": {
+ "start": {
+ "line": 0,
+ "character": 0,
+ },
+ "end": {
+ "line": 1,
+ "character": 0,
+ },
+ },
+ "targetSelectionRange": {
+ "start": {
+ "line": 0,
+ "character": 0,
+ },
+ "end": {
+ "line": 1,
+ "character": 0,
+ },
+ },
+ }]),
+ );
+ client.shutdown();
+}
+
+#[test]
fn lsp_deno_json_workspace_jsr_resolution() {
let context = TestContextBuilder::new().use_temp_cwd().build();
let temp_dir = context.temp_dir();