mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
feat(lsp): quick fix for @deno-types="npm:@types/*" (#25954)
This commit is contained in:
parent
f930000415
commit
3881b71734
16 changed files with 545 additions and 25 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
@ -1492,9 +1492,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_doc"
|
name = "deno_doc"
|
||||||
version = "0.150.0"
|
version = "0.150.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c762829006b555837691b7016828eb1f93acf0a4ff344357b946898ea5b5610d"
|
checksum = "0841188bc852535b76e53be6c3d13c61cfc6751a731969b8959fe31fa696c73f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ammonia",
|
"ammonia",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
@ -1588,9 +1588,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_graph"
|
name = "deno_graph"
|
||||||
version = "0.82.3"
|
version = "0.83.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "938ed2efa1dd9fdcceeebc169b2b7910506b8dacc992cfdcffd84aa6a3eb8db0"
|
checksum = "20088a4497b1a212482883dc7b0365e99f703d575fb512d4a793531cdc92ea76"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -2832,9 +2832,9 @@ checksum = "31ae425815400e5ed474178a7a22e275a9687086a12ca63ec793ff292d8fdae8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "eszip"
|
name = "eszip"
|
||||||
version = "0.78.0"
|
version = "0.79.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d0546f00d41dbc6e90b50e922759c02559a897e59b683369c3a13519cd5108b6"
|
checksum = "8eb55c89bdde75a3826a79d49c9d847623ae7fbdb2695b542982982da990d33e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
|
|
@ -67,8 +67,8 @@ deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "proposa
|
||||||
deno_cache_dir = { workspace = true }
|
deno_cache_dir = { workspace = true }
|
||||||
deno_config = { version = "=0.35.0", features = ["workspace", "sync"] }
|
deno_config = { version = "=0.35.0", features = ["workspace", "sync"] }
|
||||||
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
||||||
deno_doc = { version = "0.150.0", features = ["html", "syntect"] }
|
deno_doc = { version = "0.150.1", features = ["html", "syntect"] }
|
||||||
deno_graph = { version = "=0.82.3" }
|
deno_graph = { version = "=0.83.0" }
|
||||||
deno_lint = { version = "=0.67.0", features = ["docs"] }
|
deno_lint = { version = "=0.67.0", features = ["docs"] }
|
||||||
deno_lockfile.workspace = true
|
deno_lockfile.workspace = true
|
||||||
deno_npm.workspace = true
|
deno_npm.workspace = true
|
||||||
|
@ -79,7 +79,7 @@ deno_runtime = { workspace = true, features = ["include_js_files_for_snapshottin
|
||||||
deno_semver.workspace = true
|
deno_semver.workspace = true
|
||||||
deno_task_shell = "=0.17.0"
|
deno_task_shell = "=0.17.0"
|
||||||
deno_terminal.workspace = true
|
deno_terminal.workspace = true
|
||||||
eszip = "=0.78.0"
|
eszip = "=0.79.1"
|
||||||
libsui = "0.4.0"
|
libsui = "0.4.0"
|
||||||
napi_sym.workspace = true
|
napi_sym.workspace = true
|
||||||
node_resolver.workspace = true
|
node_resolver.workspace = true
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use super::diagnostics::DenoDiagnostic;
|
use super::diagnostics::DenoDiagnostic;
|
||||||
use super::diagnostics::DiagnosticSource;
|
use super::diagnostics::DiagnosticSource;
|
||||||
|
use super::documents::Document;
|
||||||
use super::documents::Documents;
|
use super::documents::Documents;
|
||||||
use super::language_server;
|
use super::language_server;
|
||||||
use super::resolver::LspResolver;
|
use super::resolver::LspResolver;
|
||||||
|
@ -9,7 +10,9 @@ use super::tsc;
|
||||||
use super::urls::url_to_uri;
|
use super::urls::url_to_uri;
|
||||||
|
|
||||||
use crate::args::jsr_url;
|
use crate::args::jsr_url;
|
||||||
|
use crate::lsp::search::PackageSearchApi;
|
||||||
use crate::tools::lint::CliLinter;
|
use crate::tools::lint::CliLinter;
|
||||||
|
use deno_config::workspace::MappedResolution;
|
||||||
use deno_lint::diagnostic::LintDiagnosticRange;
|
use deno_lint::diagnostic::LintDiagnosticRange;
|
||||||
|
|
||||||
use deno_ast::SourceRange;
|
use deno_ast::SourceRange;
|
||||||
|
@ -1151,6 +1154,162 @@ impl CodeActionCollection {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn add_source_actions(
|
||||||
|
&mut self,
|
||||||
|
document: &Document,
|
||||||
|
range: &lsp::Range,
|
||||||
|
language_server: &language_server::Inner,
|
||||||
|
) {
|
||||||
|
async fn deno_types_for_npm_action(
|
||||||
|
document: &Document,
|
||||||
|
range: &lsp::Range,
|
||||||
|
language_server: &language_server::Inner,
|
||||||
|
) -> Option<lsp::CodeAction> {
|
||||||
|
let (dep_key, dependency, _) =
|
||||||
|
document.get_maybe_dependency(&range.end)?;
|
||||||
|
if dependency.maybe_deno_types_specifier.is_some() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if dependency.maybe_code.maybe_specifier().is_none()
|
||||||
|
&& dependency.maybe_type.maybe_specifier().is_none()
|
||||||
|
{
|
||||||
|
// We're using byonm and the package is not cached.
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let position = deno_graph::Position::new(
|
||||||
|
range.end.line as usize,
|
||||||
|
range.end.character as usize,
|
||||||
|
);
|
||||||
|
let import_range = dependency.imports.iter().find_map(|i| {
|
||||||
|
if json!(i.kind) != json!("es") && json!(i.kind) != json!("tsType") {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if !i.specifier_range.includes(&position) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
i.full_range.as_ref()
|
||||||
|
})?;
|
||||||
|
let referrer = document.specifier();
|
||||||
|
let file_referrer = document.file_referrer();
|
||||||
|
let config_data = language_server
|
||||||
|
.config
|
||||||
|
.tree
|
||||||
|
.data_for_specifier(file_referrer?)?;
|
||||||
|
let workspace_resolver = config_data.resolver.clone();
|
||||||
|
let npm_ref = if let Ok(resolution) =
|
||||||
|
workspace_resolver.resolve(&dep_key, document.specifier())
|
||||||
|
{
|
||||||
|
let specifier = match resolution {
|
||||||
|
MappedResolution::Normal { specifier, .. }
|
||||||
|
| MappedResolution::ImportMap { specifier, .. } => specifier,
|
||||||
|
_ => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
NpmPackageReqReference::from_specifier(&specifier).ok()?
|
||||||
|
} else {
|
||||||
|
// Only resolve bare package.json deps for byonm.
|
||||||
|
if !config_data.byonm {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if !language_server
|
||||||
|
.resolver
|
||||||
|
.is_bare_package_json_dep(&dep_key, referrer)
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
NpmPackageReqReference::from_str(&format!("npm:{}", &dep_key)).ok()?
|
||||||
|
};
|
||||||
|
let package_name = &npm_ref.req().name;
|
||||||
|
if package_name.starts_with("@types/") {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let managed_npm_resolver = language_server
|
||||||
|
.resolver
|
||||||
|
.maybe_managed_npm_resolver(file_referrer);
|
||||||
|
if let Some(npm_resolver) = managed_npm_resolver {
|
||||||
|
if !npm_resolver.is_pkg_req_folder_cached(npm_ref.req()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if language_server
|
||||||
|
.resolver
|
||||||
|
.npm_to_file_url(&npm_ref, document.specifier(), file_referrer)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
// The package import has types.
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let types_package_name = format!("@types/{package_name}");
|
||||||
|
let types_package_version = language_server
|
||||||
|
.npm_search_api
|
||||||
|
.versions(&types_package_name)
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
|
.and_then(|versions| versions.first().cloned())?;
|
||||||
|
let types_specifier_text =
|
||||||
|
if let Some(npm_resolver) = managed_npm_resolver {
|
||||||
|
let mut specifier_text = if let Some(req) =
|
||||||
|
npm_resolver.top_package_req_for_name(&types_package_name)
|
||||||
|
{
|
||||||
|
format!("npm:{req}")
|
||||||
|
} else {
|
||||||
|
format!("npm:{}@^{}", &types_package_name, types_package_version)
|
||||||
|
};
|
||||||
|
let specifier = ModuleSpecifier::parse(&specifier_text).ok()?;
|
||||||
|
if let Some(file_referrer) = file_referrer {
|
||||||
|
if let Some(text) = language_server
|
||||||
|
.get_ts_response_import_mapper(file_referrer)
|
||||||
|
.check_specifier(&specifier, referrer)
|
||||||
|
{
|
||||||
|
specifier_text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
specifier_text
|
||||||
|
} else {
|
||||||
|
types_package_name.clone()
|
||||||
|
};
|
||||||
|
let uri = language_server
|
||||||
|
.url_map
|
||||||
|
.specifier_to_uri(referrer, file_referrer)
|
||||||
|
.ok()?;
|
||||||
|
let position = lsp::Position {
|
||||||
|
line: import_range.start.line as u32,
|
||||||
|
character: import_range.start.character as u32,
|
||||||
|
};
|
||||||
|
let new_text = format!(
|
||||||
|
"{}// @deno-types=\"{}\"\n",
|
||||||
|
if position.character == 0 { "" } else { "\n" },
|
||||||
|
&types_specifier_text
|
||||||
|
);
|
||||||
|
let text_edit = lsp::TextEdit {
|
||||||
|
range: lsp::Range {
|
||||||
|
start: position,
|
||||||
|
end: position,
|
||||||
|
},
|
||||||
|
new_text,
|
||||||
|
};
|
||||||
|
Some(lsp::CodeAction {
|
||||||
|
title: format!(
|
||||||
|
"Add @deno-types directive for \"{}\"",
|
||||||
|
&types_specifier_text
|
||||||
|
),
|
||||||
|
kind: Some(lsp::CodeActionKind::QUICKFIX),
|
||||||
|
diagnostics: None,
|
||||||
|
edit: Some(lsp::WorkspaceEdit {
|
||||||
|
changes: Some([(uri, vec![text_edit])].into_iter().collect()),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if let Some(action) =
|
||||||
|
deno_types_for_npm_action(document, range, language_server).await
|
||||||
|
{
|
||||||
|
self.actions.push(CodeActionKind::Deno(action));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prepend the whitespace characters found at the start of line_content to content.
|
/// Prepend the whitespace characters found at the start of line_content to content.
|
||||||
|
|
|
@ -1517,17 +1517,19 @@ fn diagnose_dependency(
|
||||||
let import_ranges: Vec<_> = dependency
|
let import_ranges: Vec<_> = dependency
|
||||||
.imports
|
.imports
|
||||||
.iter()
|
.iter()
|
||||||
.map(|i| documents::to_lsp_range(&i.range))
|
.map(|i| documents::to_lsp_range(&i.specifier_range))
|
||||||
.collect();
|
.collect();
|
||||||
// TODO(nayeemrmn): This is a crude way of detecting `@deno-types` which has
|
// TODO(nayeemrmn): This is a crude way of detecting `@deno-types` which has
|
||||||
// a different specifier and therefore needs a separate call to
|
// a different specifier and therefore needs a separate call to
|
||||||
// `diagnose_resolution()`. It would be much cleaner if that were modelled as
|
// `diagnose_resolution()`. It would be much cleaner if that were modelled as
|
||||||
// a separate dependency: https://github.com/denoland/deno_graph/issues/247.
|
// a separate dependency: https://github.com/denoland/deno_graph/issues/247.
|
||||||
let is_types_deno_types = !dependency.maybe_type.is_none()
|
let is_types_deno_types = !dependency.maybe_type.is_none()
|
||||||
&& !dependency
|
&& !dependency.imports.iter().any(|i| {
|
||||||
.imports
|
dependency
|
||||||
.iter()
|
.maybe_type
|
||||||
.any(|i| dependency.maybe_type.includes(&i.range.start).is_some());
|
.includes(&i.specifier_range.start)
|
||||||
|
.is_some()
|
||||||
|
});
|
||||||
|
|
||||||
diagnostics.extend(
|
diagnostics.extend(
|
||||||
diagnose_resolution(
|
diagnose_resolution(
|
||||||
|
|
|
@ -207,11 +207,11 @@ pub struct Inner {
|
||||||
module_registry: ModuleRegistry,
|
module_registry: ModuleRegistry,
|
||||||
/// A lazily create "server" for handling test run requests.
|
/// A lazily create "server" for handling test run requests.
|
||||||
maybe_testing_server: Option<testing::TestServer>,
|
maybe_testing_server: Option<testing::TestServer>,
|
||||||
npm_search_api: CliNpmSearchApi,
|
pub npm_search_api: CliNpmSearchApi,
|
||||||
project_version: usize,
|
project_version: usize,
|
||||||
/// A collection of measurements which instrument that performance of the LSP.
|
/// A collection of measurements which instrument that performance of the LSP.
|
||||||
performance: Arc<Performance>,
|
performance: Arc<Performance>,
|
||||||
resolver: Arc<LspResolver>,
|
pub resolver: Arc<LspResolver>,
|
||||||
task_queue: LanguageServerTaskQueue,
|
task_queue: LanguageServerTaskQueue,
|
||||||
/// A memoized version of fixable diagnostic codes retrieved from TypeScript.
|
/// A memoized version of fixable diagnostic codes retrieved from TypeScript.
|
||||||
ts_fixable_diagnostics: Vec<String>,
|
ts_fixable_diagnostics: Vec<String>,
|
||||||
|
@ -1612,8 +1612,8 @@ impl Inner {
|
||||||
None => false,
|
None => false,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
if !fixable_diagnostics.is_empty() {
|
|
||||||
let mut code_actions = CodeActionCollection::default();
|
let mut code_actions = CodeActionCollection::default();
|
||||||
|
if !fixable_diagnostics.is_empty() {
|
||||||
let file_diagnostics = self
|
let file_diagnostics = self
|
||||||
.diagnostics_server
|
.diagnostics_server
|
||||||
.get_ts_diagnostics(&specifier, asset_or_doc.document_lsp_version());
|
.get_ts_diagnostics(&specifier, asset_or_doc.document_lsp_version());
|
||||||
|
@ -1721,9 +1721,14 @@ impl Inner {
|
||||||
.add_cache_all_action(&specifier, no_cache_diagnostics.to_owned());
|
.add_cache_all_action(&specifier, no_cache_diagnostics.to_owned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if let Some(document) = asset_or_doc.document() {
|
||||||
|
code_actions
|
||||||
|
.add_source_actions(document, ¶ms.range, self)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
code_actions.set_preferred_fixes();
|
code_actions.set_preferred_fixes();
|
||||||
all_actions.extend(code_actions.get_response());
|
all_actions.extend(code_actions.get_response());
|
||||||
}
|
|
||||||
|
|
||||||
// Refactor
|
// Refactor
|
||||||
let only = params
|
let only = params
|
||||||
|
|
|
@ -328,11 +328,11 @@ impl LspResolver {
|
||||||
) -> Option<(ModuleSpecifier, MediaType)> {
|
) -> Option<(ModuleSpecifier, MediaType)> {
|
||||||
let resolver = self.get_scope_resolver(file_referrer);
|
let resolver = self.get_scope_resolver(file_referrer);
|
||||||
let node_resolver = resolver.node_resolver.as_ref()?;
|
let node_resolver = resolver.node_resolver.as_ref()?;
|
||||||
Some(NodeResolution::into_specifier_and_media_type(
|
Some(NodeResolution::into_specifier_and_media_type(Some(
|
||||||
node_resolver
|
node_resolver
|
||||||
.resolve_req_reference(req_ref, referrer, NodeResolutionMode::Types)
|
.resolve_req_reference(req_ref, referrer, NodeResolutionMode::Types)
|
||||||
.ok(),
|
.ok()?,
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn in_node_modules(&self, specifier: &ModuleSpecifier) -> bool {
|
pub fn in_node_modules(&self, specifier: &ModuleSpecifier) -> bool {
|
||||||
|
@ -373,6 +373,26 @@ impl LspResolver {
|
||||||
Some(NodeResolution::into_specifier_and_media_type(Some(resolution)).1)
|
Some(NodeResolution::into_specifier_and_media_type(Some(resolution)).1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_bare_package_json_dep(
|
||||||
|
&self,
|
||||||
|
specifier_text: &str,
|
||||||
|
referrer: &ModuleSpecifier,
|
||||||
|
) -> bool {
|
||||||
|
let resolver = self.get_scope_resolver(Some(referrer));
|
||||||
|
let Some(node_resolver) = resolver.node_resolver.as_ref() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
node_resolver
|
||||||
|
.resolve_if_for_npm_pkg(
|
||||||
|
specifier_text,
|
||||||
|
referrer,
|
||||||
|
NodeResolutionMode::Types,
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
.flatten()
|
||||||
|
.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_closest_package_json(
|
pub fn get_closest_package_json(
|
||||||
&self,
|
&self,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
|
|
|
@ -428,6 +428,16 @@ impl ManagedCliNpmResolver {
|
||||||
self.resolution.snapshot()
|
self.resolution.snapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn top_package_req_for_name(&self, name: &str) -> Option<PackageReq> {
|
||||||
|
let package_reqs = self.resolution.package_reqs();
|
||||||
|
let mut entries = package_reqs
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, nv)| nv.name == name)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
entries.sort_by_key(|(_, nv)| &nv.version);
|
||||||
|
Some(entries.last()?.0.clone())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn serialized_valid_snapshot_for_system(
|
pub fn serialized_valid_snapshot_for_system(
|
||||||
&self,
|
&self,
|
||||||
system_info: &NpmSystemInfo,
|
system_info: &NpmSystemInfo,
|
||||||
|
|
|
@ -5906,6 +5906,135 @@ fn lsp_code_actions_deno_cache_all() {
|
||||||
client.shutdown();
|
client.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lsp_code_actions_deno_types_for_npm() {
|
||||||
|
let context = TestContextBuilder::new()
|
||||||
|
.use_http_server()
|
||||||
|
.use_temp_cwd()
|
||||||
|
.add_npm_env_vars()
|
||||||
|
.build();
|
||||||
|
let temp_dir = context.temp_dir();
|
||||||
|
temp_dir.write("deno.json", json!({}).to_string());
|
||||||
|
temp_dir.write(
|
||||||
|
"package.json",
|
||||||
|
json!({
|
||||||
|
"dependencies": {
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"@types/react": "^18.3.10",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
temp_dir.create_dir_all("managed_node_modules");
|
||||||
|
temp_dir.write(
|
||||||
|
"managed_node_modules/deno.json",
|
||||||
|
json!({
|
||||||
|
"nodeModulesDir": false,
|
||||||
|
})
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
context.run_npm("install");
|
||||||
|
let mut client = context.new_lsp_command().build();
|
||||||
|
client.initialize_default();
|
||||||
|
client.did_open(json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": temp_dir.url().join("file.ts").unwrap(),
|
||||||
|
"languageId": "typescript",
|
||||||
|
"version": 1,
|
||||||
|
"text": "import \"react\";\n",
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
let res = client.write_request(
|
||||||
|
"textDocument/codeAction",
|
||||||
|
json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": temp_dir.url().join("file.ts").unwrap(),
|
||||||
|
},
|
||||||
|
"range": {
|
||||||
|
"start": { "line": 0, "character": 7 },
|
||||||
|
"end": { "line": 0, "character": 7 },
|
||||||
|
},
|
||||||
|
"context": { "diagnostics": [], "only": ["quickfix"] },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
res,
|
||||||
|
json!([
|
||||||
|
{
|
||||||
|
"title": "Add @deno-types directive for \"@types/react\"",
|
||||||
|
"kind": "quickfix",
|
||||||
|
"edit": {
|
||||||
|
"changes": {
|
||||||
|
temp_dir.url().join("file.ts").unwrap(): [
|
||||||
|
{
|
||||||
|
"range": {
|
||||||
|
"start": { "line": 0, "character": 0 },
|
||||||
|
"end": { "line": 0, "character": 0 },
|
||||||
|
},
|
||||||
|
"newText": "// @deno-types=\"@types/react\"\n",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
client.did_open(json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": temp_dir.url().join("managed_node_modules/file.ts").unwrap(),
|
||||||
|
"languageId": "typescript",
|
||||||
|
"version": 1,
|
||||||
|
"text": "import \"npm:react\";\n",
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
client.write_request(
|
||||||
|
"workspace/executeCommand",
|
||||||
|
json!({
|
||||||
|
"command": "deno.cache",
|
||||||
|
"arguments": [
|
||||||
|
[],
|
||||||
|
temp_dir.url().join("managed_node_modules/file.ts").unwrap(),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
let res = client.write_request(
|
||||||
|
"textDocument/codeAction",
|
||||||
|
json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": temp_dir.url().join("managed_node_modules/file.ts").unwrap(),
|
||||||
|
},
|
||||||
|
"range": {
|
||||||
|
"start": { "line": 0, "character": 7 },
|
||||||
|
"end": { "line": 0, "character": 7 },
|
||||||
|
},
|
||||||
|
"context": { "diagnostics": [], "only": ["quickfix"] },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
res,
|
||||||
|
json!([
|
||||||
|
{
|
||||||
|
"title": "Add @deno-types directive for \"npm:@types/react@^18.3.10\"",
|
||||||
|
"kind": "quickfix",
|
||||||
|
"edit": {
|
||||||
|
"changes": {
|
||||||
|
temp_dir.url().join("managed_node_modules/file.ts").unwrap(): [
|
||||||
|
{
|
||||||
|
"range": {
|
||||||
|
"start": { "line": 0, "character": 0 },
|
||||||
|
"end": { "line": 0, "character": 0 },
|
||||||
|
},
|
||||||
|
"newText": "// @deno-types=\"npm:@types/react@^18.3.10\"\n",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
client.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn lsp_cache_on_save() {
|
fn lsp_cache_on_save() {
|
||||||
let context = TestContextBuilder::new()
|
let context = TestContextBuilder::new()
|
||||||
|
|
BIN
tests/registry/npm/@types/prop-types/prop-types-15.7.13.tgz
Normal file
BIN
tests/registry/npm/@types/prop-types/prop-types-15.7.13.tgz
Normal file
Binary file not shown.
48
tests/registry/npm/@types/prop-types/registry.json
Normal file
48
tests/registry/npm/@types/prop-types/registry.json
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
{
|
||||||
|
"name": "@types/prop-types",
|
||||||
|
"dist-tags": { "latest": "15.7.13" },
|
||||||
|
"versions": {
|
||||||
|
"15.7.13": {
|
||||||
|
"name": "@types/prop-types",
|
||||||
|
"version": "15.7.13",
|
||||||
|
"license": "MIT",
|
||||||
|
"_id": "@types/prop-types@15.7.13",
|
||||||
|
"dist": {
|
||||||
|
"shasum": "2af91918ee12d9d32914feb13f5326658461b451",
|
||||||
|
"tarball": "http://localhost:4260/@types/prop-types/prop-types-15.7.13.tgz",
|
||||||
|
"fileCount": 5,
|
||||||
|
"integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==",
|
||||||
|
"signatures": [
|
||||||
|
{
|
||||||
|
"sig": "MEUCIQCz+S+fZxW5ahdAmLsMoCnFlj4QvsEH0h70sXmSVc1EDgIgBDq1TH20PzRBFVHHY3gRc7JeNsAOozAmrQqCy+v1syk=",
|
||||||
|
"keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"unpackedSize": 6965
|
||||||
|
},
|
||||||
|
"main": "",
|
||||||
|
"types": "index.d.ts",
|
||||||
|
"scripts": {},
|
||||||
|
"repository": {
|
||||||
|
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||||
|
"type": "git",
|
||||||
|
"directory": "types/prop-types"
|
||||||
|
},
|
||||||
|
"description": "TypeScript definitions for prop-types",
|
||||||
|
"directories": {},
|
||||||
|
"dependencies": {},
|
||||||
|
"_hasShrinkwrap": false,
|
||||||
|
"typeScriptVersion": "4.8",
|
||||||
|
"typesPublisherContentHash": "463997a2d1b4bb7e18554d9d12146cc74169e8bda6a4b9008306c38797ae14d3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/prop-types",
|
||||||
|
"repository": {
|
||||||
|
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||||
|
"type": "git",
|
||||||
|
"directory": "types/prop-types"
|
||||||
|
},
|
||||||
|
"description": "TypeScript definitions for prop-types",
|
||||||
|
"readmeFilename": ""
|
||||||
|
}
|
BIN
tests/registry/npm/@types/react/react-18.3.10.tgz
Normal file
BIN
tests/registry/npm/@types/react/react-18.3.10.tgz
Normal file
Binary file not shown.
71
tests/registry/npm/@types/react/registry.json
Normal file
71
tests/registry/npm/@types/react/registry.json
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
{
|
||||||
|
"name": "@types/react",
|
||||||
|
"dist-tags": { "latest": "18.3.10" },
|
||||||
|
"versions": {
|
||||||
|
"18.3.10": {
|
||||||
|
"name": "@types/react",
|
||||||
|
"version": "18.3.10",
|
||||||
|
"license": "MIT",
|
||||||
|
"_id": "@types/react@18.3.10",
|
||||||
|
"dist": {
|
||||||
|
"shasum": "6edc26dc22ff8c9c226d3c7bf8357b013c842219",
|
||||||
|
"tarball": "http://localhost:4260/@types/react/react-18.3.10.tgz",
|
||||||
|
"fileCount": 17,
|
||||||
|
"integrity": "sha512-02sAAlBnP39JgXwkAq3PeU9DVaaGpZyF3MGcC0MKgQVkZor5IiiDAipVaxQHtDJAmO4GIy/rVBy/LzVj76Cyqg==",
|
||||||
|
"signatures": [
|
||||||
|
{
|
||||||
|
"sig": "MEUCIF6O9Y11lCvdqbD+e81mjGbAGN3pZa2cxxwi5Z+3bQr6AiEA0tDSc8Y9i7TjXbsZ2SnO/taFI6v99xnkZRDv5m6to7k=",
|
||||||
|
"keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"unpackedSize": 438614
|
||||||
|
},
|
||||||
|
"main": "",
|
||||||
|
"types": "index.d.ts",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": { "default": "./index.d.ts" },
|
||||||
|
"types@<=5.0": { "default": "./ts5.0/index.d.ts" }
|
||||||
|
},
|
||||||
|
"./canary": {
|
||||||
|
"types": { "default": "./canary.d.ts" },
|
||||||
|
"types@<=5.0": { "default": "./ts5.0/canary.d.ts" }
|
||||||
|
},
|
||||||
|
"./jsx-runtime": {
|
||||||
|
"types": { "default": "./jsx-runtime.d.ts" },
|
||||||
|
"types@<=5.0": { "default": "./ts5.0/jsx-runtime.d.ts" }
|
||||||
|
},
|
||||||
|
"./experimental": {
|
||||||
|
"types": { "default": "./experimental.d.ts" },
|
||||||
|
"types@<=5.0": { "default": "./ts5.0/experimental.d.ts" }
|
||||||
|
},
|
||||||
|
"./package.json": "./package.json",
|
||||||
|
"./jsx-dev-runtime": {
|
||||||
|
"types": { "default": "./jsx-dev-runtime.d.ts" },
|
||||||
|
"types@<=5.0": { "default": "./ts5.0/jsx-dev-runtime.d.ts" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scripts": {},
|
||||||
|
"repository": {
|
||||||
|
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||||
|
"type": "git",
|
||||||
|
"directory": "types/react"
|
||||||
|
},
|
||||||
|
"description": "TypeScript definitions for react",
|
||||||
|
"directories": {},
|
||||||
|
"dependencies": { "csstype": "^3.0.2", "@types/prop-types": "*" },
|
||||||
|
"_hasShrinkwrap": false,
|
||||||
|
"typeScriptVersion": "4.8",
|
||||||
|
"typesPublisherContentHash": "3fbf914f5052668104237c78a8f67cca37176346a3caed94eea6d5c504795f08"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react",
|
||||||
|
"repository": {
|
||||||
|
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||||
|
"type": "git",
|
||||||
|
"directory": "types/react"
|
||||||
|
},
|
||||||
|
"description": "TypeScript definitions for react",
|
||||||
|
"readmeFilename": ""
|
||||||
|
}
|
BIN
tests/registry/npm/csstype/csstype-3.1.3.tgz
Normal file
BIN
tests/registry/npm/csstype/csstype-3.1.3.tgz
Normal file
Binary file not shown.
|
@ -2,7 +2,7 @@
|
||||||
"name": "csstype",
|
"name": "csstype",
|
||||||
"description": "Strict TypeScript and Flow types for style based on MDN data",
|
"description": "Strict TypeScript and Flow types for style based on MDN data",
|
||||||
"dist-tags": {
|
"dist-tags": {
|
||||||
"latest": "2.6.20",
|
"latest": "3.1.3",
|
||||||
"version-2": "2.6.20"
|
"version-2": "2.6.20"
|
||||||
},
|
},
|
||||||
"versions": {
|
"versions": {
|
||||||
|
@ -73,6 +73,82 @@
|
||||||
},
|
},
|
||||||
"directories": {},
|
"directories": {},
|
||||||
"_hasShrinkwrap": false
|
"_hasShrinkwrap": false
|
||||||
|
},
|
||||||
|
"3.1.3": {
|
||||||
|
"name": "csstype",
|
||||||
|
"version": "3.1.3",
|
||||||
|
"main": "",
|
||||||
|
"types": "index.d.ts",
|
||||||
|
"description": "Strict TypeScript and Flow types for style based on MDN data",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/frenic/csstype.git"
|
||||||
|
},
|
||||||
|
"author": { "name": "Fredrik Nicol", "email": "fredrik.nicol@gmail.com" },
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/chokidar": "^2.1.3",
|
||||||
|
"@types/css-tree": "^2.3.1",
|
||||||
|
"@types/jest": "^29.5.0",
|
||||||
|
"@types/jsdom": "^21.1.1",
|
||||||
|
"@types/node": "^16.18.23",
|
||||||
|
"@types/prettier": "^2.7.2",
|
||||||
|
"@types/request": "^2.48.8",
|
||||||
|
"@types/turndown": "^5.0.1",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.57.0",
|
||||||
|
"@typescript-eslint/parser": "^5.57.0",
|
||||||
|
"chalk": "^4.1.2",
|
||||||
|
"chokidar": "^3.5.3",
|
||||||
|
"eslint": "^8.37.0",
|
||||||
|
"css-tree": "^2.3.1",
|
||||||
|
"eslint-config-prettier": "^8.8.0",
|
||||||
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
|
"fast-glob": "^3.2.12",
|
||||||
|
"flow-bin": "^0.203.1",
|
||||||
|
"jest": "^29.5.0",
|
||||||
|
"jsdom": "^21.1.1",
|
||||||
|
"mdn-browser-compat-data": "git+https://github.com/mdn/browser-compat-data.git#1bf44517bd08de735e9ec20dbfe8e86c96341054",
|
||||||
|
"mdn-data": "git+https://github.com/mdn/data.git#7f0c865a3c4b5d891285c93308ee5c25cb5cfee8",
|
||||||
|
"prettier": "^2.8.7",
|
||||||
|
"request": "^2.88.2",
|
||||||
|
"ts-jest": "^29.0.5",
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
|
"turndown": "^7.1.2",
|
||||||
|
"typescript": "~5.0.3"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"prepublish": "npm install --prefix __tests__ && npm install --prefix __tests__/__fixtures__",
|
||||||
|
"prepublishOnly": "tsc && npm run test:src && npm run build && ts-node --files prepublish.ts",
|
||||||
|
"update": "ts-node --files update.ts",
|
||||||
|
"build": "ts-node --files build.ts --start",
|
||||||
|
"watch": "ts-node --files build.ts --watch",
|
||||||
|
"lint": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
|
||||||
|
"pretty": "prettier --write build.ts **/*.{ts,js,json,md}",
|
||||||
|
"lazy": "tsc && npm run lint",
|
||||||
|
"test": "jest --runInBand",
|
||||||
|
"test:src": "jest src.*.ts",
|
||||||
|
"test:dist": "jest dist.*.ts --runInBand"
|
||||||
|
},
|
||||||
|
"gitHead": "fb448e21733ac5cb52523d3b678fdbbe1f9b42f2",
|
||||||
|
"bugs": { "url": "https://github.com/frenic/csstype/issues" },
|
||||||
|
"_id": "csstype@3.1.3",
|
||||||
|
"_nodeVersion": "18.16.0",
|
||||||
|
"_npmVersion": "9.5.1",
|
||||||
|
"dist": {
|
||||||
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||||
|
"shasum": "d80ff294d114fb0e6ac500fbf85b60137d7eff81",
|
||||||
|
"tarball": "http://localhost:4260/csstype/csstype-3.1.3.tgz",
|
||||||
|
"fileCount": 5,
|
||||||
|
"unpackedSize": 1246074,
|
||||||
|
"signatures": [
|
||||||
|
{
|
||||||
|
"keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA",
|
||||||
|
"sig": "MEQCIF2zTnkc6R7cr7euidncjKp9gnQSpUmoKPzB/pvL4rsQAiB4E1mDQEtpvu9cjct0kaUbtTAQc+rBLAO65gAk+ykfig=="
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"directories": {},
|
||||||
|
"_hasShrinkwrap": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"author": {
|
"author": {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[WILDCARD]Caching module info for http://127.0.0.1:4250/@denotest/module-graph/1.4.0/mod.ts
|
[WILDCARD]Caching module info for http://127.0.0.1:4250/@denotest/module-graph/1.4.0/other.ts
|
||||||
[WILDCARD]
|
[WILDCARD]
|
||||||
Test { other: Other {} }
|
Test { other: Other {} }
|
||||||
[WILDCARD]
|
[WILDCARD]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[WILDCARD]Caching module info for http://127.0.0.1:4250/@denotest/module-graph2/1.4.0/mod.ts
|
[WILDCARD]Caching module info for http://127.0.0.1:4250/@denotest/module-graph2/1.4.0/other.ts
|
||||||
[WILDCARD]
|
[WILDCARD]
|
||||||
Test { other: Other {} }
|
Test { other: Other {} }
|
||||||
[WILDCARD]
|
[WILDCARD]
|
||||||
|
|
Loading…
Reference in a new issue