Skip to content

Commit bcfe279

Browse files
authored
feat(unstable/npm): initial type checking of npm specifiers (#16332)
1 parent 0e1a71f commit bcfe279

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+2134
-279
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/build.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,11 @@ fn create_compiler_snapshot(
201201
false
202202
}
203203

204+
#[op]
205+
fn op_is_node_file() -> bool {
206+
false
207+
}
208+
204209
#[op]
205210
fn op_script_version(
206211
_state: &mut OpState,
@@ -266,6 +271,7 @@ fn create_compiler_snapshot(
266271
op_build_info::decl(),
267272
op_cwd::decl(),
268273
op_exists::decl(),
274+
op_is_node_file::decl(),
269275
op_load::decl(),
270276
op_script_version::decl(),
271277
])

cli/dts/README.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,26 @@ The files in this directory are mostly from the TypeScript repository. We
44
currently (unfortunately) have a rather manual process for upgrading TypeScript.
55
It works like this currently:
66

7-
1. Checkout typescript repo in a separate directory.
8-
2. Copy typescript.js into Deno repo.
9-
3. Copy d.ts files into dts directory.
7+
1. Checkout denoland/TypeScript repo in a separate directory.
8+
1. Add Microsoft/TypeScript as a remote and fetch its latest tags
9+
1. Checkout a new branch based on this tag.
10+
1. Cherry pick the custom commit we made in a previous release to the new one.
11+
1. This commit has a "deno.ts" file in it. Read the instructions in it.
12+
1. Copy typescript.js into Deno repo.
13+
1. Copy d.ts files into dts directory.
1014

1115
So that might look something like this:
1216

1317
```
14-
git clone https://github.com/microsoft/TypeScript.git
18+
git clone https://github.com/denoland/TypeScript.git
1519
cd typescript
20+
git remote add upstream https://github.com/Microsoft/TypeScript
21+
git fetch upstream
1622
git checkout v3.9.7
23+
git checkout -b branch_v3.9.7
24+
git cherry pick <previous-release-branch-commit-we-did>
25+
npm install
26+
gulp local
1727
rsync lib/typescript.js ~/src/deno/cli/tsc/00_typescript.js
1828
rsync --exclude=protocol.d.ts --exclude=tsserverlibrary.d.ts --exclude=typescriptServices.d.ts lib/*.d.ts ~/src/deno/cli/dts/
1929
```

cli/lsp/diagnostics.rs

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,13 @@ async fn generate_lint_diagnostics(
458458
break;
459459
}
460460

461+
// ignore any npm package files
462+
if let Some(npm_resolver) = &snapshot.maybe_npm_resolver {
463+
if npm_resolver.in_npm_package(document.specifier()) {
464+
continue;
465+
}
466+
}
467+
461468
let version = document.maybe_lsp_version();
462469
diagnostics_vec.push((
463470
document.specifier().clone(),
@@ -597,6 +604,8 @@ pub enum DenoDiagnostic {
597604
NoCacheBlob,
598605
/// A data module was not found in the cache.
599606
NoCacheData(ModuleSpecifier),
607+
/// A remote npm package reference was not found in the cache.
608+
NoCacheNpm(NpmPackageReference, ModuleSpecifier),
600609
/// A local module was not found on the local file system.
601610
NoLocal(ModuleSpecifier),
602611
/// The specifier resolved to a remote specifier that was redirected to
@@ -622,6 +631,7 @@ impl DenoDiagnostic {
622631
Self::NoCache(_) => "no-cache",
623632
Self::NoCacheBlob => "no-cache-blob",
624633
Self::NoCacheData(_) => "no-cache-data",
634+
Self::NoCacheNpm(_, _) => "no-cache-npm",
625635
Self::NoLocal(_) => "no-local",
626636
Self::Redirect { .. } => "redirect",
627637
Self::ResolutionError(err) => match err {
@@ -690,16 +700,17 @@ impl DenoDiagnostic {
690700
}),
691701
..Default::default()
692702
},
693-
"no-cache" | "no-cache-data" => {
703+
"no-cache" | "no-cache-data" | "no-cache-npm" => {
694704
let data = diagnostic
695705
.data
696706
.clone()
697707
.ok_or_else(|| anyhow!("Diagnostic is missing data"))?;
698708
let data: DiagnosticDataSpecifier = serde_json::from_value(data)?;
699-
let title = if code == "no-cache" {
700-
format!("Cache \"{}\" and its dependencies.", data.specifier)
701-
} else {
702-
"Cache the data URL and its dependencies.".to_string()
709+
let title = match code.as_str() {
710+
"no-cache" | "no-cache-npm" => {
711+
format!("Cache \"{}\" and its dependencies.", data.specifier)
712+
}
713+
_ => "Cache the data URL and its dependencies.".to_string(),
703714
};
704715
lsp::CodeAction {
705716
title,
@@ -757,6 +768,7 @@ impl DenoDiagnostic {
757768
code.as_str(),
758769
"import-map-remap"
759770
| "no-cache"
771+
| "no-cache-npm"
760772
| "no-cache-data"
761773
| "no-assert-type"
762774
| "redirect"
@@ -777,6 +789,7 @@ impl DenoDiagnostic {
777789
Self::NoCache(specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Uncached or missing remote URL: \"{}\".", specifier), Some(json!({ "specifier": specifier }))),
778790
Self::NoCacheBlob => (lsp::DiagnosticSeverity::ERROR, "Uncached blob URL.".to_string(), None),
779791
Self::NoCacheData(specifier) => (lsp::DiagnosticSeverity::ERROR, "Uncached data URL.".to_string(), Some(json!({ "specifier": specifier }))),
792+
Self::NoCacheNpm(pkg_ref, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Uncached or missing npm package: \"{}\".", pkg_ref.req), Some(json!({ "specifier": specifier }))),
780793
Self::NoLocal(specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Unable to load a local module: \"{}\".\n Please check the file path.", specifier), None),
781794
Self::Redirect { from, to} => (lsp::DiagnosticSeverity::INFORMATION, format!("The import of \"{}\" was redirected to \"{}\".", from, to), Some(json!({ "specifier": from, "redirect": to }))),
782795
Self::ResolutionError(err) => (lsp::DiagnosticSeverity::ERROR, err.to_string(), None),
@@ -847,8 +860,20 @@ fn diagnose_resolved(
847860
.push(DenoDiagnostic::NoAssertType.to_lsp_diagnostic(&range)),
848861
}
849862
}
850-
} else if NpmPackageReference::from_specifier(specifier).is_ok() {
851-
// ignore npm specifiers for now
863+
} else if let Ok(pkg_ref) = NpmPackageReference::from_specifier(specifier)
864+
{
865+
if let Some(npm_resolver) = &snapshot.maybe_npm_resolver {
866+
// show diagnostics for npm package references that aren't cached
867+
if npm_resolver
868+
.resolve_package_folder_from_deno_module(&pkg_ref.req)
869+
.is_err()
870+
{
871+
diagnostics.push(
872+
DenoDiagnostic::NoCacheNpm(pkg_ref, specifier.clone())
873+
.to_lsp_diagnostic(&range),
874+
);
875+
}
876+
}
852877
} else {
853878
// When the document is not available, it means that it cannot be found
854879
// in the cache or locally on the disk, so we want to issue a diagnostic
@@ -882,6 +907,12 @@ fn diagnose_dependency(
882907
dependency_key: &str,
883908
dependency: &deno_graph::Dependency,
884909
) {
910+
if let Some(npm_resolver) = &snapshot.maybe_npm_resolver {
911+
if npm_resolver.in_npm_package(referrer) {
912+
return; // ignore, surface typescript errors instead
913+
}
914+
}
915+
885916
if let Some(import_map) = &snapshot.maybe_import_map {
886917
if let Resolved::Ok {
887918
specifier, range, ..
@@ -938,8 +969,8 @@ async fn generate_deno_diagnostics(
938969
&mut diagnostics,
939970
snapshot,
940971
specifier,
941-
&dependency_key,
942-
&dependency,
972+
dependency_key,
973+
dependency,
943974
);
944975
}
945976
}

0 commit comments

Comments
 (0)