diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2024-08-07 09:43:05 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-07 07:43:05 +0000 |
commit | 04473c04ed59cc2a987af3405074591fbc1341a4 (patch) | |
tree | 50d56d1990328a6d32627e74ef73514525d78fde | |
parent | 4fa8869f2487749a9f190cb3047f4f3e6d571f27 (diff) |
fix(compile): support workspace members importing other members (#24909)
28 files changed, 171 insertions, 52 deletions
diff --git a/Cargo.lock b/Cargo.lock index e3f51056c..b962ef131 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1329,9 +1329,9 @@ dependencies = [ [[package]] name = "deno_config" -version = "0.26.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8188c39699541affc0c0f89bbba07d31212385fa0c4e1a5a9e530b0f3cbc776f" +checksum = "fc1f3c577bf7fdbb449cb99c2560309364c71cc3dcc7af94387ef8810b089173" dependencies = [ "anyhow", "deno_package_json", @@ -1552,9 +1552,9 @@ dependencies = [ [[package]] name = "deno_graph" -version = "0.81.0" +version = "0.81.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f1f965754dcdbaa5c9433a8c8da4a3cb7d93f29b58aa84b5617fe887f57415" +checksum = "d2cada0d9fd56536d3208cff2b130096e396ee2716466850cf0b7927249e40a0" dependencies = [ "anyhow", "async-trait", @@ -1955,9 +1955,9 @@ dependencies = [ [[package]] name = "deno_semver" -version = "0.5.7" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e23ce551a58eeefc05a48042a9c76d3409c96a1a6a522a82c4ced26930ece201" +checksum = "9fb7520ac21cb236c6f8cc81964e8bf22c72fc58c7b5f762f99b9a95abfe3212" dependencies = [ "monch", "once_cell", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 510c10ea9..6d9e1b7b2 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -65,17 +65,17 @@ winres.workspace = true [dependencies] deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "proposal", "react", "sourcemap", "transforms", "typescript", "view", "visit"] } deno_cache_dir = { workspace = true } -deno_config = { version = "=0.26.1", features = ["workspace", "sync"] } +deno_config = { version = "=0.28.0", features = ["workspace", "sync"] } deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] } deno_doc = { version = "0.145.0", features = ["html", "syntect"] } deno_emit = "=0.44.0" -deno_graph = { version = "=0.81.0" } +deno_graph = { version = "=0.81.1" } deno_lint = { version = "=0.62.0", features = ["docs"] } deno_lockfile.workspace = true deno_npm = "=0.21.4" deno_package_json.workspace = true deno_runtime = { workspace = true, features = ["include_js_files_for_snapshotting"] } -deno_semver = "=0.5.7" +deno_semver = "=0.5.9" deno_task_shell = "=0.17.0" deno_terminal.workspace = true eszip = "=0.73.0" diff --git a/cli/args/mod.rs b/cli/args/mod.rs index fcc1a8d7c..ddfdb95c4 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -1435,7 +1435,6 @@ impl CliOptions { self .workspace() .jsr_packages() - .into_iter() .map(|pkg| config_to_deno_graph_workspace_member(&pkg.config_file)) .collect::<Result<Vec<_>, _>>() } diff --git a/cli/errors.rs b/cli/errors.rs index a8fde6e76..25b3fc332 100644 --- a/cli/errors.rs +++ b/cli/errors.rs @@ -29,7 +29,6 @@ fn get_diagnostic_class(_: &ParseDiagnostic) -> &'static str { fn get_module_graph_error_class(err: &ModuleGraphError) -> &'static str { use deno_graph::JsrLoadError; use deno_graph::NpmLoadError; - use deno_graph::WorkspaceLoadError; match err { ModuleGraphError::ResolutionError(err) @@ -71,10 +70,6 @@ fn get_module_graph_error_class(err: &ModuleGraphError) -> &'static str { | JsrLoadError::PackageVersionNotFound(_) | JsrLoadError::UnknownExport { .. } => "NotFound", }, - ModuleLoadError::Workspace(err) => match err { - WorkspaceLoadError::MemberInvalidExportPath { .. } => "TypeError", - WorkspaceLoadError::MissingMemberExports { .. } => "NotFound", - }, }, }, } diff --git a/cli/graph_util.rs b/cli/graph_util.rs index 91549472e..77d086fa8 100644 --- a/cli/graph_util.rs +++ b/cli/graph_util.rs @@ -500,8 +500,6 @@ impl ModuleGraphBuilder { .maybe_file_watcher_reporter .as_ref() .map(|r| r.as_reporter()); - let workspace_members = - self.options.resolve_deno_graph_workspace_members()?; let mut locker = self .lockfile .as_ref() @@ -515,7 +513,6 @@ impl ModuleGraphBuilder { imports: maybe_imports, is_dynamic: options.is_dynamic, passthrough_jsr_specifiers: false, - workspace_members: &workspace_members, executor: Default::default(), file_system: &DenoGraphFsAdapter(self.fs.as_ref()), jsr_url_provider: &CliJsrUrlProvider, diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs index c48544a2d..bbfe3a6df 100644 --- a/cli/lsp/config.rs +++ b/cli/lsp/config.rs @@ -1518,6 +1518,7 @@ impl ConfigData { WorkspaceResolver::new_raw( scope.clone(), None, + member_dir.workspace.resolver_jsr_pkgs().collect(), member_dir.workspace.package_jsons().cloned().collect(), pkg_json_dep_resolution, ) diff --git a/cli/lsp/jsr.rs b/cli/lsp/jsr.rs index b02e01fb6..9ffcdf9e6 100644 --- a/cli/lsp/jsr.rs +++ b/cli/lsp/jsr.rs @@ -20,7 +20,6 @@ use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; use deno_semver::Version; use serde::Deserialize; -use std::borrow::Cow; use std::collections::HashMap; use std::sync::Arc; @@ -157,7 +156,7 @@ impl JsrCacheResolver { let maybe_nv = self.req_to_nv(&req); let nv = maybe_nv.as_ref()?; let info = self.package_version_info(nv)?; - let path = info.export(&normalize_export_name(req_ref.sub_path()))?; + let path = info.export(&req_ref.export_name())?; if let Some(workspace_scope) = self.workspace_scope_by_name.get(&nv.name) { workspace_scope.join(path).ok() } else { @@ -267,30 +266,6 @@ fn read_cached_url( .ok()? } -// TODO(nayeemrmn): This is duplicated from a private function in deno_graph -// 0.65.1. Make it public or cleanup otherwise. -fn normalize_export_name(sub_path: Option<&str>) -> Cow<str> { - let Some(sub_path) = sub_path else { - return Cow::Borrowed("."); - }; - if sub_path.is_empty() || matches!(sub_path, "/" | ".") { - Cow::Borrowed(".") - } else { - let sub_path = if sub_path.starts_with('/') { - Cow::Owned(format!(".{}", sub_path)) - } else if !sub_path.starts_with("./") { - Cow::Owned(format!("./{}", sub_path)) - } else { - Cow::Borrowed(sub_path) - }; - if let Some(prefix) = sub_path.strip_suffix('/') { - Cow::Owned(prefix.to_string()) - } else { - sub_path - } - } -} - #[derive(Debug)] pub struct CliJsrSearchApi { file_fetcher: Arc<FileFetcher>, diff --git a/cli/lsp/resolver.rs b/cli/lsp/resolver.rs index d6fc3096c..dec46566f 100644 --- a/cli/lsp/resolver.rs +++ b/cli/lsp/resolver.rs @@ -523,6 +523,7 @@ fn create_graph_resolver( Arc::new(ModuleSpecifier::parse("file:///").unwrap()), None, Vec::new(), + Vec::new(), PackageJsonDepResolution::Disabled, )) }, diff --git a/cli/resolver.rs b/cli/resolver.rs index 18804c025..b72fcd322 100644 --- a/cli/resolver.rs +++ b/cli/resolver.rs @@ -535,6 +535,9 @@ impl Resolver for CliGraphResolver { MappedResolutionError::ImportMap(err) => { ResolveError::Other(err.into()) } + MappedResolutionError::Workspace(err) => { + ResolveError::Other(err.into()) + } }); let result = match result { Ok(resolution) => match resolution { @@ -552,6 +555,9 @@ impl Resolver for CliGraphResolver { Ok(specifier) } } + MappedResolution::WorkspaceJsrPackage { specifier, .. } => { + Ok(specifier) + } MappedResolution::WorkspaceNpmPackage { target_pkg_json: pkg_json, sub_path, diff --git a/cli/standalone/binary.rs b/cli/standalone/binary.rs index 8fb640be3..ed38e164b 100644 --- a/cli/standalone/binary.rs +++ b/cli/standalone/binary.rs @@ -19,6 +19,7 @@ use std::process::Command; use deno_ast::ModuleSpecifier; use deno_config::workspace::PackageJsonDepResolution; +use deno_config::workspace::ResolverWorkspaceJsrPackage; use deno_config::workspace::Workspace; use deno_config::workspace::WorkspaceResolver; use deno_core::anyhow::bail; @@ -33,6 +34,7 @@ use deno_npm::NpmSystemInfo; use deno_runtime::deno_node::PackageJson; use deno_semver::npm::NpmVersionReqParseError; use deno_semver::package::PackageReq; +use deno_semver::Version; use deno_semver::VersionReqSpecifierParseError; use eszip::EszipRelativeFileBaseUrl; use indexmap::IndexMap; @@ -80,9 +82,18 @@ pub struct SerializedWorkspaceResolverImportMap { pub json: String, } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SerializedResolverWorkspaceJsrPackage { + pub relative_base: String, + pub name: String, + pub version: Option<Version>, + pub exports: IndexMap<String, String>, +} + #[derive(Deserialize, Serialize)] pub struct SerializedWorkspaceResolver { pub import_map: Option<SerializedWorkspaceResolverImportMap>, + pub jsr_pkgs: Vec<SerializedResolverWorkspaceJsrPackage>, pub package_jsons: BTreeMap<String, serde_json::Value>, pub pkg_json_resolution: PackageJsonDepResolution, } @@ -620,6 +631,16 @@ impl<'a> DenoCompileBinaryWriter<'a> { json: i.to_json(), } }), + jsr_pkgs: self + .workspace_resolver + .jsr_packages() + .map(|pkg| SerializedResolverWorkspaceJsrPackage { + relative_base: root_dir_url.specifier_key(&pkg.base).into_owned(), + name: pkg.name.clone(), + version: pkg.version.clone(), + exports: pkg.exports.clone(), + }) + .collect(), package_jsons: self .workspace_resolver .package_jsons() diff --git a/cli/standalone/mod.rs b/cli/standalone/mod.rs index e4661051a..635293cc9 100644 --- a/cli/standalone/mod.rs +++ b/cli/standalone/mod.rs @@ -8,6 +8,7 @@ use deno_ast::MediaType; use deno_config::workspace::MappedResolution; use deno_config::workspace::MappedResolutionError; +use deno_config::workspace::ResolverWorkspaceJsrPackage; use deno_config::workspace::WorkspaceResolver; use deno_core::anyhow::Context; use deno_core::error::generic_error; @@ -169,6 +170,9 @@ impl ModuleLoader for EmbeddedModuleLoader { self.shared.workspace_resolver.resolve(specifier, &referrer); match mapped_resolution { + Ok(MappedResolution::WorkspaceJsrPackage { specifier, .. }) => { + Ok(specifier) + } Ok(MappedResolution::WorkspaceNpmPackage { target_pkg_json: pkg_json, sub_path, @@ -613,6 +617,17 @@ pub async fn run( WorkspaceResolver::new_raw( root_dir_url.clone(), import_map, + metadata + .workspace_resolver + .jsr_pkgs + .iter() + .map(|pkg| ResolverWorkspaceJsrPackage { + base: root_dir_url.join(&pkg.relative_base).unwrap(), + name: pkg.name.clone(), + version: pkg.version.clone(), + exports: pkg.exports.clone(), + }) + .collect(), pkg_jsons, metadata.workspace_resolver.pkg_json_resolution, ) diff --git a/cli/tools/doc.rs b/cli/tools/doc.rs index bc0d81cc9..e7eab9b91 100644 --- a/cli/tools/doc.rs +++ b/cli/tools/doc.rs @@ -59,7 +59,6 @@ async fn generate_doc_nodes_for_builtin_types( imports: Vec::new(), is_dynamic: false, passthrough_jsr_specifiers: false, - workspace_members: &[], executor: Default::default(), file_system: &NullFileSystem, jsr_url_provider: Default::default(), diff --git a/cli/tools/lint/rules/no_sloppy_imports.rs b/cli/tools/lint/rules/no_sloppy_imports.rs index b5e057bfc..1ae792e08 100644 --- a/cli/tools/lint/rules/no_sloppy_imports.rs +++ b/cli/tools/lint/rules/no_sloppy_imports.rs @@ -203,10 +203,14 @@ impl<'a> deno_graph::source::Resolver for SloppyImportCaptureResolver<'a> { None => Ok(specifier), } } - deno_config::workspace::MappedResolution::WorkspaceNpmPackage { + deno_config::workspace::MappedResolution::WorkspaceJsrPackage { + .. + } + | deno_config::workspace::MappedResolution::WorkspaceNpmPackage { .. } | deno_config::workspace::MappedResolution::PackageJson { .. } => { + // this error is ignored Err(ResolveError::Other(anyhow!(""))) } } diff --git a/cli/tools/registry/unfurl.rs b/cli/tools/registry/unfurl.rs index a28ba445a..489c9a1be 100644 --- a/cli/tools/registry/unfurl.rs +++ b/cli/tools/registry/unfurl.rs @@ -75,6 +75,9 @@ impl SpecifierUnfurler { match resolved { MappedResolution::Normal(specifier) | MappedResolution::ImportMap(specifier) => Some(specifier), + MappedResolution::WorkspaceJsrPackage { pkg_req_ref, .. } => { + Some(ModuleSpecifier::parse(&pkg_req_ref.to_string()).unwrap()) + } MappedResolution::WorkspaceNpmPackage { target_pkg_json: pkg_json, pkg_name, @@ -388,11 +391,14 @@ mod tests { use super::*; use deno_ast::MediaType; use deno_ast::ModuleSpecifier; + use deno_config::workspace::ResolverWorkspaceJsrPackage; use deno_core::serde_json::json; use deno_core::url::Url; use deno_runtime::deno_fs::RealFs; use deno_runtime::deno_node::PackageJson; + use deno_semver::Version; use import_map::ImportMapWithDiagnostics; + use indexmap::IndexMap; use pretty_assertions::assert_eq; use test_util::testdata_path; @@ -436,6 +442,13 @@ mod tests { let workspace_resolver = WorkspaceResolver::new_raw( Arc::new(ModuleSpecifier::from_directory_path(&cwd).unwrap()), Some(import_map), + vec![ResolverWorkspaceJsrPackage { + base: ModuleSpecifier::from_directory_path(cwd.join("jsr-package")) + .unwrap(), + name: "@denotest/example".to_string(), + version: Some(Version::parse_standard("1.0.0").unwrap()), + exports: IndexMap::from([(".".to_string(), "mod.ts".to_string())]), + }], vec![Arc::new(package_json)], deno_config::workspace::PackageJsonDepResolution::Enabled, ); @@ -458,6 +471,7 @@ import b from "./b.js"; import b2 from "./b"; import "./mod.ts"; import url from "url"; +import "@denotest/example"; // TODO: unfurl these to jsr // import "npm:@jsr/std__fs@1/file"; // import "npm:@jsr/std__fs@1"; @@ -507,6 +521,7 @@ import b from "./b.ts"; import b2 from "./b.ts"; import "./mod.ts"; import url from "node:url"; +import "jsr:@denotest/example@^1.0.0"; // TODO: unfurl these to jsr // import "npm:@jsr/std__fs@1/file"; // import "npm:@jsr/std__fs@1"; diff --git a/cli/tools/vendor/test.rs b/cli/tools/vendor/test.rs index dc851858e..65f37efdc 100644 --- a/cli/tools/vendor/test.rs +++ b/cli/tools/vendor/test.rs @@ -300,6 +300,7 @@ fn build_resolver( Arc::new(ModuleSpecifier::from_directory_path(root_dir).unwrap()), maybe_original_import_map, Vec::new(), + Vec::new(), deno_config::workspace::PackageJsonDepResolution::Enabled, )), maybe_jsx_import_source_config, diff --git a/tests/integration/lsp_tests.rs b/tests/integration/lsp_tests.rs index d89061683..28c36cd20 100644 --- a/tests/integration/lsp_tests.rs +++ b/tests/integration/lsp_tests.rs @@ -14198,7 +14198,10 @@ fn lsp_deno_json_workspace_jsr_resolution() { json!({ "contents": { "kind": "markdown", - "value": format!("**Resolved Dependency**\n\n**Code**: jsr​:​@org/project1​@^1.0.0 (<{}project1/mod.ts>)\n", temp_dir.uri()), + "value": format!( + "**Resolved Dependency**\n\n**Code**: file​://{}\n", + temp_dir.uri().join("project1/mod.ts").unwrap().path(), + ), }, "range": { "start": { "line": 0, "character": 7 }, diff --git a/tests/specs/compile/workspace/__test__.jsonc b/tests/specs/compile/workspace/__test__.jsonc new file mode 100644 index 000000000..be2bbd1e4 --- /dev/null +++ b/tests/specs/compile/workspace/__test__.jsonc @@ -0,0 +1,22 @@ +{ + "tempDir": true, + "steps": [{ + "if": "unix", + "args": "compile --output main main.ts", + "output": "[WILDCARD]" + }, { + "if": "unix", + "commandName": "./main", + "args": [], + "output": "main.out" + }, { + "if": "windows", + "args": "compile --output main.exe main.ts", + "output": "[WILDCARD]" + }, { + "if": "windows", + "commandName": "./main.exe", + "args": [], + "output": "main.out" + }] +} diff --git a/tests/specs/compile/workspace/add/deno.json b/tests/specs/compile/workspace/add/deno.json new file mode 100644 index 000000000..ad6afb93e --- /dev/null +++ b/tests/specs/compile/workspace/add/deno.json @@ -0,0 +1,5 @@ +{ + "name": "@david/add", + "version": "0.0.1", + "exports": "./mod.ts" +} diff --git a/tests/specs/compile/workspace/add/mod.test.ts b/tests/specs/compile/workspace/add/mod.test.ts new file mode 100644 index 000000000..6de834e17 --- /dev/null +++ b/tests/specs/compile/workspace/add/mod.test.ts @@ -0,0 +1,6 @@ +import { add } from "./mod.ts"; +import { assertEquals } from "@std/assert"; + +Deno.test("add", () => { + assertEquals(add(1, 2), 3); +}); diff --git a/tests/specs/compile/workspace/add/mod.ts b/tests/specs/compile/workspace/add/mod.ts new file mode 100644 index 000000000..8d9b8a22a --- /dev/null +++ b/tests/specs/compile/workspace/add/mod.ts @@ -0,0 +1,3 @@ +export function add(a: number, b: number): number { + return a + b; +} diff --git a/tests/specs/compile/workspace/deno.json b/tests/specs/compile/workspace/deno.json new file mode 100644 index 000000000..4504c4276 --- /dev/null +++ b/tests/specs/compile/workspace/deno.json @@ -0,0 +1,9 @@ +{ + "workspace": [ + "./add", + "./subtract" + ], + "imports": { + "@std/assert": "jsr:@std/assert@^1.0.2" + } +} diff --git a/tests/specs/compile/workspace/deno.lock b/tests/specs/compile/workspace/deno.lock new file mode 100644 index 000000000..7ceb772c6 --- /dev/null +++ b/tests/specs/compile/workspace/deno.lock @@ -0,0 +1,26 @@ +{ + "version": "3", + "packages": { + "specifiers": { + "jsr:@std/assert@^1.0.2": "jsr:@std/assert@1.0.2", + "jsr:@std/internal@^1.0.1": "jsr:@std/internal@1.0.1" + }, + "jsr": { + "@std/assert@1.0.2": { + "integrity": "ccacec332958126deaceb5c63ff8b4eaf9f5ed0eac9feccf124110435e59e49c", + "dependencies": [ + "jsr:@std/internal@^1.0.1" + ] + }, + "@std/internal@1.0.1": { + "integrity": "6f8c7544d06a11dd256c8d6ba54b11ed870aac6c5aeafff499892662c57673e6" + } + } + }, + "remote": {}, + "workspace": { + "dependencies": [ + "jsr:@std/assert@^1.0.2" + ] + } +} diff --git a/tests/specs/compile/workspace/main.out b/tests/specs/compile/workspace/main.out new file mode 100644 index 000000000..a83d1d524 --- /dev/null +++ b/tests/specs/compile/workspace/main.out @@ -0,0 +1 @@ +-3 diff --git a/tests/specs/compile/workspace/main.ts b/tests/specs/compile/workspace/main.ts new file mode 100644 index 000000000..896f107ad --- /dev/null +++ b/tests/specs/compile/workspace/main.ts @@ -0,0 +1,3 @@ +import { subtract } from "@david/subtract"; + +console.log(subtract(2, 5)); diff --git a/tests/specs/compile/workspace/subtract/deno.json b/tests/specs/compile/workspace/subtract/deno.json new file mode 100644 index 000000000..d2bdfbec7 --- /dev/null +++ b/tests/specs/compile/workspace/subtract/deno.json @@ -0,0 +1,5 @@ +{ + "name": "@david/subtract", + "version": "0.0.1", + "exports": "./mod.ts" +} diff --git a/tests/specs/compile/workspace/subtract/mod.test.ts b/tests/specs/compile/workspace/subtract/mod.test.ts new file mode 100644 index 000000000..1bc00da1e --- /dev/null +++ b/tests/specs/compile/workspace/subtract/mod.test.ts @@ -0,0 +1,6 @@ +import { subtract } from "./mod.ts"; +import { assertEquals } from "@std/assert"; + +Deno.test("subtract", () => { + assertEquals(subtract(4, 2), 2); +}); diff --git a/tests/specs/compile/workspace/subtract/mod.ts b/tests/specs/compile/workspace/subtract/mod.ts new file mode 100644 index 000000000..3d8ba39af --- /dev/null +++ b/tests/specs/compile/workspace/subtract/mod.ts @@ -0,0 +1,5 @@ +import { add } from "@david/add"; + +export function subtract(a: number, b: number): number { + return add(a, -b); +} diff --git a/tests/specs/run/workspaces/basic/main.out b/tests/specs/run/workspaces/basic/main.out index 9806f7d63..256b380af 100644 --- a/tests/specs/run/workspaces/basic/main.out +++ b/tests/specs/run/workspaces/basic/main.out @@ -1,11 +1,7 @@ [WILDCARD]Workspace config generated this import map { "imports": { "chalk": "npm:chalk", - "chalk/": "npm:/chalk/", - "asdfasdfasdf": "jsr:asdfasdfasdf@^0.0.0", - "asdfasdfasdf/": "jsr:/asdfasdfasdf@^0.0.0/", - "qwerqwer": "jsr:qwerqwer@^0.0.0", - "qwerqwer/": "jsr:/qwerqwer@^0.0.0/" + "chalk/": "npm:/chalk/" }, "scopes": { "./bar/": { |