mirror of
https://github.com/denoland/deno.git
synced 2025-01-11 00:21:05 -05:00
refactor(lsp): determine file referrer for each document (#23867)
This commit is contained in:
parent
143ea4759f
commit
0a30897925
8 changed files with 320 additions and 117 deletions
|
@ -248,6 +248,8 @@ impl<'a> TsResponseImportMapper<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
let file_referrer = self.documents.get_file_referrer(referrer);
|
||||
|
||||
if let Some(jsr_path) = specifier.as_str().strip_prefix(jsr_url().as_str())
|
||||
{
|
||||
let mut segments = jsr_path.split('/');
|
||||
|
@ -259,7 +261,11 @@ impl<'a> TsResponseImportMapper<'a> {
|
|||
let version = Version::parse_standard(segments.next()?).ok()?;
|
||||
let nv = PackageNv { name, version };
|
||||
let path = segments.collect::<Vec<_>>().join("/");
|
||||
let export = self.resolver.jsr_lookup_export_for_path(&nv, &path)?;
|
||||
let export = self.resolver.jsr_lookup_export_for_path(
|
||||
&nv,
|
||||
&path,
|
||||
file_referrer.as_deref(),
|
||||
)?;
|
||||
let sub_path = (export != ".").then_some(export);
|
||||
let mut req = None;
|
||||
req = req.or_else(|| {
|
||||
|
@ -281,7 +287,11 @@ impl<'a> TsResponseImportMapper<'a> {
|
|||
}
|
||||
None
|
||||
});
|
||||
req = req.or_else(|| self.resolver.jsr_lookup_req_for_nv(&nv));
|
||||
req = req.or_else(|| {
|
||||
self
|
||||
.resolver
|
||||
.jsr_lookup_req_for_nv(&nv, file_referrer.as_deref())
|
||||
});
|
||||
let spec_str = if let Some(req) = req {
|
||||
let req_ref = PackageReqReference { req, sub_path };
|
||||
JsrPackageReqReference::new(req_ref).to_string()
|
||||
|
@ -298,7 +308,10 @@ impl<'a> TsResponseImportMapper<'a> {
|
|||
return Some(spec_str);
|
||||
}
|
||||
|
||||
if let Some(npm_resolver) = self.resolver.maybe_managed_npm_resolver() {
|
||||
if let Some(npm_resolver) = self
|
||||
.resolver
|
||||
.maybe_managed_npm_resolver(file_referrer.as_deref())
|
||||
{
|
||||
if npm_resolver.in_npm_package(specifier) {
|
||||
if let Ok(Some(pkg_id)) =
|
||||
npm_resolver.resolve_pkg_id_from_specifier(specifier)
|
||||
|
|
|
@ -157,6 +157,7 @@ pub async fn get_import_completions(
|
|||
maybe_import_map: Option<&ImportMap>,
|
||||
) -> Option<lsp::CompletionResponse> {
|
||||
let document = documents.get(specifier)?;
|
||||
let file_referrer = document.file_referrer();
|
||||
let (text, _, range) = document.get_maybe_dependency(position)?;
|
||||
let range = to_narrow_lsp_range(&document.text_info(), &range);
|
||||
if let Some(completion_list) = get_import_map_completions(
|
||||
|
@ -209,8 +210,8 @@ pub async fn get_import_completions(
|
|||
0
|
||||
};
|
||||
let maybe_list = module_registries
|
||||
.get_completions(&text, offset, &range, |specifier| {
|
||||
documents.exists(specifier)
|
||||
.get_completions(&text, offset, &range, |s| {
|
||||
documents.exists(s, file_referrer)
|
||||
})
|
||||
.await;
|
||||
let list = maybe_list.unwrap_or_else(|| lsp::CompletionList {
|
||||
|
@ -825,7 +826,7 @@ mod tests {
|
|||
for (specifier, source, version, language_id) in open_sources {
|
||||
let specifier =
|
||||
resolve_url(specifier).expect("failed to create specifier");
|
||||
documents.open(specifier, *version, *language_id, (*source).into());
|
||||
documents.open(specifier, *version, *language_id, (*source).into(), None);
|
||||
}
|
||||
for (specifier, source) in fs_sources {
|
||||
let specifier =
|
||||
|
@ -834,10 +835,9 @@ mod tests {
|
|||
.global()
|
||||
.set(&specifier, HashMap::default(), source.as_bytes())
|
||||
.expect("could not cache file");
|
||||
assert!(
|
||||
documents.get(&specifier).is_some(),
|
||||
"source could not be setup"
|
||||
);
|
||||
let document =
|
||||
documents.get_or_load(&specifier, &temp_dir.uri().join("$").unwrap());
|
||||
assert!(document.is_some(), "source could not be setup");
|
||||
}
|
||||
documents
|
||||
}
|
||||
|
|
|
@ -1294,6 +1294,7 @@ fn diagnose_resolution(
|
|||
resolution: &Resolution,
|
||||
is_dynamic: bool,
|
||||
maybe_assert_type: Option<&str>,
|
||||
referrer_doc: &Document,
|
||||
import_map: Option<&ImportMap>,
|
||||
) -> Vec<DenoDiagnostic> {
|
||||
fn check_redirect_diagnostic(
|
||||
|
@ -1327,13 +1328,21 @@ fn diagnose_resolution(
|
|||
match resolution {
|
||||
Resolution::Ok(resolved) => {
|
||||
let specifier = &resolved.specifier;
|
||||
let managed_npm_resolver = snapshot.resolver.maybe_managed_npm_resolver();
|
||||
for (_, headers) in snapshot.resolver.redirect_chain_headers(specifier) {
|
||||
let managed_npm_resolver = snapshot
|
||||
.resolver
|
||||
.maybe_managed_npm_resolver(referrer_doc.file_referrer());
|
||||
for (_, headers) in snapshot
|
||||
.resolver
|
||||
.redirect_chain_headers(specifier, referrer_doc.file_referrer())
|
||||
{
|
||||
if let Some(message) = headers.get("x-deno-warning") {
|
||||
diagnostics.push(DenoDiagnostic::DenoWarn(message.clone()));
|
||||
}
|
||||
}
|
||||
if let Some(doc) = snapshot.documents.get(specifier) {
|
||||
if let Some(doc) = snapshot
|
||||
.documents
|
||||
.get_or_load(specifier, referrer_doc.specifier())
|
||||
{
|
||||
if let Some(headers) = doc.maybe_headers() {
|
||||
if let Some(message) = headers.get("x-deno-warning") {
|
||||
diagnostics.push(DenoDiagnostic::DenoWarn(message.clone()));
|
||||
|
@ -1430,10 +1439,11 @@ fn diagnose_resolution(
|
|||
fn diagnose_dependency(
|
||||
diagnostics: &mut Vec<lsp::Diagnostic>,
|
||||
snapshot: &language_server::StateSnapshot,
|
||||
referrer: &ModuleSpecifier,
|
||||
referrer_doc: &Document,
|
||||
dependency_key: &str,
|
||||
dependency: &deno_graph::Dependency,
|
||||
) {
|
||||
let referrer = referrer_doc.specifier();
|
||||
if snapshot.resolver.in_node_modules(referrer) {
|
||||
return; // ignore, surface typescript errors instead
|
||||
}
|
||||
|
@ -1488,6 +1498,7 @@ fn diagnose_dependency(
|
|||
},
|
||||
dependency.is_dynamic,
|
||||
dependency.maybe_attribute_type.as_deref(),
|
||||
referrer_doc,
|
||||
import_map.map(|i| i.as_ref()),
|
||||
)
|
||||
.iter()
|
||||
|
@ -1511,6 +1522,7 @@ fn diagnose_dependency(
|
|||
&dependency.maybe_type,
|
||||
dependency.is_dynamic,
|
||||
dependency.maybe_attribute_type.as_deref(),
|
||||
referrer_doc,
|
||||
import_map.map(|i| i.as_ref()),
|
||||
)
|
||||
.iter()
|
||||
|
@ -1543,7 +1555,7 @@ fn generate_deno_diagnostics(
|
|||
diagnose_dependency(
|
||||
&mut diagnostics,
|
||||
snapshot,
|
||||
specifier,
|
||||
&document,
|
||||
dependency_key,
|
||||
dependency,
|
||||
);
|
||||
|
@ -1630,11 +1642,12 @@ mod tests {
|
|||
*version,
|
||||
*language_id,
|
||||
(*source).into(),
|
||||
None,
|
||||
);
|
||||
}
|
||||
StateSnapshot {
|
||||
project_version: 0,
|
||||
documents,
|
||||
documents: Arc::new(documents),
|
||||
assets: Default::default(),
|
||||
config: Arc::new(config),
|
||||
resolver,
|
||||
|
|
|
@ -266,6 +266,9 @@ pub struct Document {
|
|||
/// Contains the last-known-good set of dependencies from parsing the module.
|
||||
config: Arc<Config>,
|
||||
dependencies: Arc<IndexMap<String, deno_graph::Dependency>>,
|
||||
// TODO(nayeemrmn): This is unused, use it for scope attribution for remote
|
||||
// modules.
|
||||
file_referrer: Option<ModuleSpecifier>,
|
||||
maybe_types_dependency: Option<Arc<deno_graph::TypesDependency>>,
|
||||
maybe_fs_version: Option<String>,
|
||||
line_index: Arc<LineIndex>,
|
||||
|
@ -295,6 +298,7 @@ impl Document {
|
|||
resolver: Arc<LspResolver>,
|
||||
config: Arc<Config>,
|
||||
cache: &Arc<LspCache>,
|
||||
file_referrer: Option<ModuleSpecifier>,
|
||||
) -> Arc<Self> {
|
||||
let text_info = SourceTextInfo::new(content);
|
||||
let media_type = resolve_media_type(
|
||||
|
@ -310,6 +314,7 @@ impl Document {
|
|||
text_info.clone(),
|
||||
maybe_headers.as_ref(),
|
||||
media_type,
|
||||
file_referrer.as_ref(),
|
||||
&resolver,
|
||||
)
|
||||
} else {
|
||||
|
@ -329,6 +334,7 @@ impl Document {
|
|||
Arc::new(Self {
|
||||
config,
|
||||
dependencies,
|
||||
file_referrer: file_referrer.filter(|_| specifier.scheme() != "file"),
|
||||
maybe_types_dependency,
|
||||
maybe_fs_version: calculate_fs_version(cache, &specifier),
|
||||
line_index,
|
||||
|
@ -370,6 +376,7 @@ impl Document {
|
|||
&self.specifier,
|
||||
&parsed_source_result,
|
||||
self.maybe_headers.as_ref(),
|
||||
self.file_referrer.as_ref(),
|
||||
&resolver,
|
||||
)
|
||||
.ok();
|
||||
|
@ -384,8 +391,10 @@ impl Document {
|
|||
maybe_test_module_fut =
|
||||
get_maybe_test_module_fut(maybe_parsed_source.as_ref(), &config);
|
||||
} else {
|
||||
let graph_resolver = resolver.as_graph_resolver();
|
||||
let npm_resolver = resolver.as_graph_npm_resolver();
|
||||
let graph_resolver =
|
||||
resolver.as_graph_resolver(self.file_referrer.as_ref());
|
||||
let npm_resolver =
|
||||
resolver.as_graph_npm_resolver(self.file_referrer.as_ref());
|
||||
dependencies = Arc::new(
|
||||
self
|
||||
.dependencies
|
||||
|
@ -420,6 +429,7 @@ impl Document {
|
|||
config,
|
||||
// updated properties
|
||||
dependencies,
|
||||
file_referrer: self.file_referrer.clone(),
|
||||
maybe_types_dependency,
|
||||
maybe_navigation_tree: Mutex::new(None),
|
||||
// maintain - this should all be copies/clones
|
||||
|
@ -475,6 +485,7 @@ impl Document {
|
|||
text_info.clone(),
|
||||
self.maybe_headers.as_ref(),
|
||||
media_type,
|
||||
self.file_referrer.as_ref(),
|
||||
self.resolver.as_ref(),
|
||||
)
|
||||
} else {
|
||||
|
@ -499,6 +510,7 @@ impl Document {
|
|||
Ok(Arc::new(Self {
|
||||
config: self.config.clone(),
|
||||
specifier: self.specifier.clone(),
|
||||
file_referrer: self.file_referrer.clone(),
|
||||
maybe_fs_version: self.maybe_fs_version.clone(),
|
||||
maybe_language_id: self.maybe_language_id,
|
||||
dependencies,
|
||||
|
@ -522,6 +534,7 @@ impl Document {
|
|||
Arc::new(Self {
|
||||
config: self.config.clone(),
|
||||
specifier: self.specifier.clone(),
|
||||
file_referrer: self.file_referrer.clone(),
|
||||
maybe_fs_version: calculate_fs_version(cache, &self.specifier),
|
||||
maybe_language_id: self.maybe_language_id,
|
||||
dependencies: self.dependencies.clone(),
|
||||
|
@ -543,6 +556,7 @@ impl Document {
|
|||
Arc::new(Self {
|
||||
config: self.config.clone(),
|
||||
specifier: self.specifier.clone(),
|
||||
file_referrer: self.file_referrer.clone(),
|
||||
maybe_fs_version: calculate_fs_version(cache, &self.specifier),
|
||||
maybe_language_id: self.maybe_language_id,
|
||||
dependencies: self.dependencies.clone(),
|
||||
|
@ -564,6 +578,10 @@ impl Document {
|
|||
&self.specifier
|
||||
}
|
||||
|
||||
pub fn file_referrer(&self) -> Option<&ModuleSpecifier> {
|
||||
self.file_referrer.as_ref()
|
||||
}
|
||||
|
||||
pub fn content(&self) -> Arc<str> {
|
||||
self.text_info.text()
|
||||
}
|
||||
|
@ -729,6 +747,7 @@ impl FileSystemDocuments {
|
|||
resolver: &Arc<LspResolver>,
|
||||
config: &Arc<Config>,
|
||||
cache: &Arc<LspCache>,
|
||||
file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> Option<Arc<Document>> {
|
||||
let new_fs_version = calculate_fs_version(cache, specifier);
|
||||
let old_doc = self.docs.get(specifier).map(|v| v.value().clone());
|
||||
|
@ -745,7 +764,7 @@ impl FileSystemDocuments {
|
|||
};
|
||||
if dirty {
|
||||
// attempt to update the file on the file system
|
||||
self.refresh_document(specifier, resolver, config, cache)
|
||||
self.refresh_document(specifier, resolver, config, cache, file_referrer)
|
||||
} else {
|
||||
old_doc
|
||||
}
|
||||
|
@ -759,6 +778,7 @@ impl FileSystemDocuments {
|
|||
resolver: &Arc<LspResolver>,
|
||||
config: &Arc<Config>,
|
||||
cache: &Arc<LspCache>,
|
||||
file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> Option<Arc<Document>> {
|
||||
let doc = if specifier.scheme() == "file" {
|
||||
let path = specifier_to_file_path(specifier).ok()?;
|
||||
|
@ -774,6 +794,7 @@ impl FileSystemDocuments {
|
|||
resolver.clone(),
|
||||
config.clone(),
|
||||
cache,
|
||||
file_referrer.cloned(),
|
||||
)
|
||||
} else if specifier.scheme() == "data" {
|
||||
let source = deno_graph::source::RawDataUrl::parse(specifier)
|
||||
|
@ -789,6 +810,7 @@ impl FileSystemDocuments {
|
|||
resolver.clone(),
|
||||
config.clone(),
|
||||
cache,
|
||||
file_referrer.cloned(),
|
||||
)
|
||||
} else {
|
||||
let http_cache = cache.root_vendor_or_global();
|
||||
|
@ -818,6 +840,7 @@ impl FileSystemDocuments {
|
|||
resolver.clone(),
|
||||
config.clone(),
|
||||
cache,
|
||||
file_referrer.cloned(),
|
||||
)
|
||||
};
|
||||
self.docs.insert(specifier.clone(), doc.clone());
|
||||
|
@ -882,6 +905,7 @@ impl Documents {
|
|||
version: i32,
|
||||
language_id: LanguageId,
|
||||
content: Arc<str>,
|
||||
file_referrer: Option<ModuleSpecifier>,
|
||||
) -> Arc<Document> {
|
||||
let document = Document::new(
|
||||
specifier.clone(),
|
||||
|
@ -895,6 +919,7 @@ impl Documents {
|
|||
self.resolver.clone(),
|
||||
self.config.clone(),
|
||||
&self.cache,
|
||||
file_referrer,
|
||||
);
|
||||
|
||||
self.file_system_docs.remove_document(&specifier);
|
||||
|
@ -964,6 +989,19 @@ impl Documents {
|
|||
self.file_system_docs.set_dirty(true);
|
||||
}
|
||||
|
||||
pub fn get_file_referrer<'a>(
|
||||
&self,
|
||||
specifier: &'a ModuleSpecifier,
|
||||
) -> Option<Cow<'a, ModuleSpecifier>> {
|
||||
if specifier.scheme() == "file" {
|
||||
Some(Cow::Borrowed(specifier))
|
||||
} else {
|
||||
self
|
||||
.get(specifier)
|
||||
.and_then(|d| d.file_referrer().cloned().map(Cow::Owned))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return `true` if the provided specifier can be resolved to a document,
|
||||
/// otherwise `false`.
|
||||
pub fn contains_import(
|
||||
|
@ -971,9 +1009,10 @@ impl Documents {
|
|||
specifier: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
) -> bool {
|
||||
let file_referrer = self.get_file_referrer(referrer);
|
||||
let maybe_specifier = self
|
||||
.resolver
|
||||
.as_graph_resolver()
|
||||
.as_graph_resolver(file_referrer.as_deref())
|
||||
.resolve(
|
||||
specifier,
|
||||
&deno_graph::Range {
|
||||
|
@ -985,7 +1024,7 @@ impl Documents {
|
|||
)
|
||||
.ok();
|
||||
if let Some(import_specifier) = maybe_specifier {
|
||||
self.exists(&import_specifier)
|
||||
self.exists(&import_specifier, file_referrer.as_deref())
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -994,23 +1033,32 @@ impl Documents {
|
|||
pub fn resolve_document_specifier(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> Option<ModuleSpecifier> {
|
||||
let specifier = if let Ok(jsr_req_ref) =
|
||||
JsrPackageReqReference::from_specifier(specifier)
|
||||
{
|
||||
Cow::Owned(self.resolver.jsr_to_registry_url(&jsr_req_ref)?)
|
||||
Cow::Owned(
|
||||
self
|
||||
.resolver
|
||||
.jsr_to_registry_url(&jsr_req_ref, file_referrer)?,
|
||||
)
|
||||
} else {
|
||||
Cow::Borrowed(specifier)
|
||||
};
|
||||
if !DOCUMENT_SCHEMES.contains(&specifier.scheme()) {
|
||||
return None;
|
||||
}
|
||||
self.resolver.resolve_redirects(&specifier)
|
||||
self.resolver.resolve_redirects(&specifier, file_referrer)
|
||||
}
|
||||
|
||||
/// Return `true` if the specifier can be resolved to a document.
|
||||
pub fn exists(&self, specifier: &ModuleSpecifier) -> bool {
|
||||
let specifier = self.resolve_document_specifier(specifier);
|
||||
pub fn exists(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> bool {
|
||||
let specifier = self.resolve_document_specifier(specifier, file_referrer);
|
||||
if let Some(specifier) = specifier {
|
||||
if self.open_docs.contains_key(&specifier) {
|
||||
return true;
|
||||
|
@ -1043,11 +1091,38 @@ impl Documents {
|
|||
}
|
||||
|
||||
/// Return a document for the specifier.
|
||||
pub fn get(
|
||||
pub fn get(&self, specifier: &ModuleSpecifier) -> Option<Arc<Document>> {
|
||||
if let Some(document) = self.open_docs.get(specifier) {
|
||||
Some(document.clone())
|
||||
} else {
|
||||
let old_doc = self
|
||||
.file_system_docs
|
||||
.docs
|
||||
.get(specifier)
|
||||
.map(|d| d.value().clone());
|
||||
if let Some(old_doc) = old_doc {
|
||||
self.file_system_docs.get(
|
||||
specifier,
|
||||
&self.resolver,
|
||||
&self.config,
|
||||
&self.cache,
|
||||
old_doc.file_referrer(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a document for the specifier.
|
||||
pub fn get_or_load(
|
||||
&self,
|
||||
original_specifier: &ModuleSpecifier,
|
||||
specifier: &ModuleSpecifier,
|
||||
referrer: &ModuleSpecifier,
|
||||
) -> Option<Arc<Document>> {
|
||||
let specifier = self.resolve_document_specifier(original_specifier)?;
|
||||
let file_referrer = self.get_file_referrer(referrer);
|
||||
let specifier =
|
||||
self.resolve_document_specifier(specifier, file_referrer.as_deref())?;
|
||||
if let Some(document) = self.open_docs.get(&specifier) {
|
||||
Some(document.clone())
|
||||
} else {
|
||||
|
@ -1056,6 +1131,7 @@ impl Documents {
|
|||
&self.resolver,
|
||||
&self.config,
|
||||
&self.cache,
|
||||
file_referrer.as_deref(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1110,6 +1186,7 @@ impl Documents {
|
|||
referrer: &ModuleSpecifier,
|
||||
) -> Vec<Option<(ModuleSpecifier, MediaType)>> {
|
||||
let document = self.get(referrer);
|
||||
let file_referrer = document.as_ref().and_then(|d| d.file_referrer());
|
||||
let dependencies = document.as_ref().map(|d| d.dependencies());
|
||||
let mut results = Vec::new();
|
||||
for specifier in specifiers {
|
||||
|
@ -1124,22 +1201,36 @@ impl Documents {
|
|||
dependencies.as_ref().and_then(|d| d.get(specifier))
|
||||
{
|
||||
if let Some(specifier) = dep.maybe_type.maybe_specifier() {
|
||||
results.push(self.resolve_dependency(specifier, referrer));
|
||||
results.push(self.resolve_dependency(
|
||||
specifier,
|
||||
referrer,
|
||||
file_referrer,
|
||||
));
|
||||
} else if let Some(specifier) = dep.maybe_code.maybe_specifier() {
|
||||
results.push(self.resolve_dependency(specifier, referrer));
|
||||
results.push(self.resolve_dependency(
|
||||
specifier,
|
||||
referrer,
|
||||
file_referrer,
|
||||
));
|
||||
} else {
|
||||
results.push(None);
|
||||
}
|
||||
} else if let Ok(specifier) = self.resolver.as_graph_resolver().resolve(
|
||||
specifier,
|
||||
&deno_graph::Range {
|
||||
specifier: referrer.clone(),
|
||||
start: deno_graph::Position::zeroed(),
|
||||
end: deno_graph::Position::zeroed(),
|
||||
},
|
||||
ResolutionMode::Types,
|
||||
) {
|
||||
results.push(self.resolve_dependency(&specifier, referrer));
|
||||
} else if let Ok(specifier) =
|
||||
self.resolver.as_graph_resolver(file_referrer).resolve(
|
||||
specifier,
|
||||
&deno_graph::Range {
|
||||
specifier: referrer.clone(),
|
||||
start: deno_graph::Position::zeroed(),
|
||||
end: deno_graph::Position::zeroed(),
|
||||
},
|
||||
ResolutionMode::Types,
|
||||
)
|
||||
{
|
||||
results.push(self.resolve_dependency(
|
||||
&specifier,
|
||||
referrer,
|
||||
file_referrer,
|
||||
));
|
||||
} else {
|
||||
results.push(None);
|
||||
}
|
||||
|
@ -1203,6 +1294,7 @@ impl Documents {
|
|||
&self.resolver,
|
||||
&self.config,
|
||||
&self.cache,
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1283,6 +1375,7 @@ impl Documents {
|
|||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
referrer: &ModuleSpecifier,
|
||||
file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> Option<(ModuleSpecifier, MediaType)> {
|
||||
if let Some(module_name) = specifier.as_str().strip_prefix("node:") {
|
||||
if deno_node::is_builtin_node_module(module_name) {
|
||||
|
@ -1294,13 +1387,15 @@ impl Documents {
|
|||
}
|
||||
|
||||
if let Ok(npm_ref) = NpmPackageReqReference::from_specifier(specifier) {
|
||||
return self.resolver.npm_to_file_url(&npm_ref, referrer);
|
||||
return self
|
||||
.resolver
|
||||
.npm_to_file_url(&npm_ref, referrer, file_referrer);
|
||||
}
|
||||
let Some(doc) = self.get(specifier) else {
|
||||
let Some(doc) = self.get_or_load(specifier, referrer) else {
|
||||
return Some((specifier.clone(), MediaType::from_specifier(specifier)));
|
||||
};
|
||||
if let Some(specifier) = doc.maybe_types_dependency().maybe_specifier() {
|
||||
self.resolve_dependency(specifier, referrer)
|
||||
if let Some(types) = doc.maybe_types_dependency().maybe_specifier() {
|
||||
self.resolve_dependency(types, specifier, file_referrer)
|
||||
} else {
|
||||
let media_type = doc.media_type();
|
||||
Some((doc.specifier().clone(), media_type))
|
||||
|
@ -1364,11 +1459,17 @@ fn parse_and_analyze_module(
|
|||
text_info: SourceTextInfo,
|
||||
maybe_headers: Option<&HashMap<String, String>>,
|
||||
media_type: MediaType,
|
||||
file_referrer: Option<&ModuleSpecifier>,
|
||||
resolver: &LspResolver,
|
||||
) -> (Option<ParsedSourceResult>, Option<ModuleResult>) {
|
||||
let parsed_source_result = parse_source(specifier, text_info, media_type);
|
||||
let module_result =
|
||||
analyze_module(specifier, &parsed_source_result, maybe_headers, resolver);
|
||||
let module_result = analyze_module(
|
||||
specifier,
|
||||
&parsed_source_result,
|
||||
maybe_headers,
|
||||
file_referrer,
|
||||
resolver,
|
||||
);
|
||||
(Some(parsed_source_result), Some(module_result))
|
||||
}
|
||||
|
||||
|
@ -1391,6 +1492,7 @@ fn analyze_module(
|
|||
specifier: &ModuleSpecifier,
|
||||
parsed_source_result: &ParsedSourceResult,
|
||||
maybe_headers: Option<&HashMap<String, String>>,
|
||||
file_referrer: Option<&ModuleSpecifier>,
|
||||
resolver: &LspResolver,
|
||||
) -> ModuleResult {
|
||||
match parsed_source_result {
|
||||
|
@ -1404,8 +1506,8 @@ fn analyze_module(
|
|||
// dynamic imports like import(`./dir/${something}`) in the LSP
|
||||
file_system: &deno_graph::source::NullFileSystem,
|
||||
jsr_url_provider: &CliJsrUrlProvider,
|
||||
maybe_resolver: Some(resolver.as_graph_resolver()),
|
||||
maybe_npm_resolver: Some(resolver.as_graph_npm_resolver()),
|
||||
maybe_resolver: Some(resolver.as_graph_resolver(file_referrer)),
|
||||
maybe_npm_resolver: Some(resolver.as_graph_npm_resolver(file_referrer)),
|
||||
},
|
||||
)),
|
||||
Err(err) => Err(deno_graph::ModuleGraphError::ModuleError(
|
||||
|
@ -1448,6 +1550,7 @@ console.log(b);
|
|||
1,
|
||||
"javascript".parse().unwrap(),
|
||||
content.into(),
|
||||
None,
|
||||
);
|
||||
assert!(document.is_diagnosable());
|
||||
assert!(document.is_open());
|
||||
|
@ -1473,6 +1576,7 @@ console.log(b);
|
|||
1,
|
||||
"javascript".parse().unwrap(),
|
||||
content.into(),
|
||||
None,
|
||||
);
|
||||
documents
|
||||
.change(
|
||||
|
@ -1517,6 +1621,7 @@ console.log(b, "hello deno");
|
|||
1,
|
||||
LanguageId::TypeScript,
|
||||
"".into(),
|
||||
None,
|
||||
);
|
||||
|
||||
// make a clone of the document store and close the document in that one
|
||||
|
@ -1586,6 +1691,7 @@ console.log(b, "hello deno");
|
|||
1,
|
||||
LanguageId::TypeScript,
|
||||
"import {} from 'test';".into(),
|
||||
None,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
|
|
|
@ -114,7 +114,10 @@ impl RootCertStoreProvider for LspRootCertStoreProvider {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LanguageServer(Arc<tokio::sync::RwLock<Inner>>, CancellationToken);
|
||||
pub struct LanguageServer(
|
||||
pub Arc<tokio::sync::RwLock<Inner>>,
|
||||
CancellationToken,
|
||||
);
|
||||
|
||||
/// Snapshot of the state used by TSC.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
|
@ -122,7 +125,7 @@ pub struct StateSnapshot {
|
|||
pub project_version: usize,
|
||||
pub assets: AssetsSnapshot,
|
||||
pub config: Arc<Config>,
|
||||
pub documents: Documents,
|
||||
pub documents: Arc<Documents>,
|
||||
pub resolver: Arc<LspResolver>,
|
||||
}
|
||||
|
||||
|
@ -149,7 +152,7 @@ impl Default for LanguageServerTaskQueue {
|
|||
}
|
||||
|
||||
impl LanguageServerTaskQueue {
|
||||
fn queue_task(&self, task_fn: LanguageServerTaskFn) -> bool {
|
||||
pub fn queue_task(&self, task_fn: LanguageServerTaskFn) -> bool {
|
||||
self.task_tx.send(task_fn).is_ok()
|
||||
}
|
||||
|
||||
|
@ -578,7 +581,7 @@ impl Inner {
|
|||
project_version: self.project_version,
|
||||
assets: self.assets.snapshot(),
|
||||
config: Arc::new(self.config.clone()),
|
||||
documents: self.documents.clone(),
|
||||
documents: Arc::new(self.documents.clone()),
|
||||
resolver: self.resolver.snapshot(),
|
||||
})
|
||||
}
|
||||
|
@ -990,6 +993,8 @@ impl Inner {
|
|||
params.text_document.uri
|
||||
);
|
||||
}
|
||||
let file_referrer = (params.text_document.uri.scheme() == "file")
|
||||
.then(|| params.text_document.uri.clone());
|
||||
let specifier = self
|
||||
.url_map
|
||||
.normalize_url(¶ms.text_document.uri, LspUrlKind::File);
|
||||
|
@ -998,6 +1003,7 @@ impl Inner {
|
|||
params.text_document.version,
|
||||
params.text_document.language_id.parse().unwrap(),
|
||||
params.text_document.text.into(),
|
||||
file_referrer,
|
||||
);
|
||||
self.project_changed([(document.specifier(), ChangeKind::Opened)], false);
|
||||
if document.is_diagnosable() {
|
||||
|
@ -1228,6 +1234,8 @@ impl Inner {
|
|||
&self,
|
||||
params: DocumentFormattingParams,
|
||||
) -> LspResult<Option<Vec<TextEdit>>> {
|
||||
let file_referrer = (params.text_document.uri.scheme() == "file")
|
||||
.then(|| params.text_document.uri.clone());
|
||||
let mut specifier = self
|
||||
.url_map
|
||||
.normalize_url(¶ms.text_document.uri, LspUrlKind::File);
|
||||
|
@ -1241,7 +1249,9 @@ impl Inner {
|
|||
{
|
||||
return Ok(None);
|
||||
}
|
||||
let document = match self.documents.get(&specifier) {
|
||||
let document =
|
||||
file_referrer.and_then(|r| self.documents.get_or_load(&specifier, &r));
|
||||
let document = match document {
|
||||
Some(doc) if doc.is_open() => doc,
|
||||
_ => return Ok(None),
|
||||
};
|
||||
|
@ -1329,41 +1339,44 @@ impl Inner {
|
|||
|
||||
let mark = self.performance.mark_with_args("lsp.hover", ¶ms);
|
||||
let asset_or_doc = self.get_asset_or_document(&specifier)?;
|
||||
let file_referrer = asset_or_doc.document().and_then(|d| d.file_referrer());
|
||||
let hover = if let Some((_, dep, range)) = asset_or_doc
|
||||
.get_maybe_dependency(¶ms.text_document_position_params.position)
|
||||
{
|
||||
let dep_doc = dep.get_code().and_then(|s| self.documents.get(s));
|
||||
let dep_doc = dep
|
||||
.get_code()
|
||||
.and_then(|s| self.documents.get_or_load(s, &specifier));
|
||||
let dep_maybe_types_dependency =
|
||||
dep_doc.as_ref().map(|d| d.maybe_types_dependency());
|
||||
let value = match (dep.maybe_code.is_none(), dep.maybe_type.is_none(), &dep_maybe_types_dependency) {
|
||||
(false, false, None) => format!(
|
||||
"**Resolved Dependency**\n\n**Code**: {}\n\n**Types**: {}\n",
|
||||
self.resolution_to_hover_text(&dep.maybe_code),
|
||||
self.resolution_to_hover_text(&dep.maybe_type),
|
||||
self.resolution_to_hover_text(&dep.maybe_code, file_referrer),
|
||||
self.resolution_to_hover_text(&dep.maybe_type, file_referrer),
|
||||
),
|
||||
(false, false, Some(types_dep)) if !types_dep.is_none() => format!(
|
||||
"**Resolved Dependency**\n\n**Code**: {}\n**Types**: {}\n**Import Types**: {}\n",
|
||||
self.resolution_to_hover_text(&dep.maybe_code),
|
||||
self.resolution_to_hover_text(&dep.maybe_type),
|
||||
self.resolution_to_hover_text(types_dep),
|
||||
self.resolution_to_hover_text(&dep.maybe_code, file_referrer),
|
||||
self.resolution_to_hover_text(&dep.maybe_type, file_referrer),
|
||||
self.resolution_to_hover_text(types_dep, file_referrer),
|
||||
),
|
||||
(false, false, Some(_)) => format!(
|
||||
"**Resolved Dependency**\n\n**Code**: {}\n\n**Types**: {}\n",
|
||||
self.resolution_to_hover_text(&dep.maybe_code),
|
||||
self.resolution_to_hover_text(&dep.maybe_type),
|
||||
self.resolution_to_hover_text(&dep.maybe_code, file_referrer),
|
||||
self.resolution_to_hover_text(&dep.maybe_type, file_referrer),
|
||||
),
|
||||
(false, true, Some(types_dep)) if !types_dep.is_none() => format!(
|
||||
"**Resolved Dependency**\n\n**Code**: {}\n\n**Types**: {}\n",
|
||||
self.resolution_to_hover_text(&dep.maybe_code),
|
||||
self.resolution_to_hover_text(types_dep),
|
||||
self.resolution_to_hover_text(&dep.maybe_code, file_referrer),
|
||||
self.resolution_to_hover_text(types_dep, file_referrer),
|
||||
),
|
||||
(false, true, _) => format!(
|
||||
"**Resolved Dependency**\n\n**Code**: {}\n",
|
||||
self.resolution_to_hover_text(&dep.maybe_code),
|
||||
self.resolution_to_hover_text(&dep.maybe_code, file_referrer),
|
||||
),
|
||||
(true, false, _) => format!(
|
||||
"**Resolved Dependency**\n\n**Types**: {}\n",
|
||||
self.resolution_to_hover_text(&dep.maybe_type),
|
||||
self.resolution_to_hover_text(&dep.maybe_type, file_referrer),
|
||||
),
|
||||
(true, true, _) => unreachable!("{}", json!(params)),
|
||||
};
|
||||
|
@ -1394,7 +1407,11 @@ impl Inner {
|
|||
Ok(hover)
|
||||
}
|
||||
|
||||
fn resolution_to_hover_text(&self, resolution: &Resolution) -> String {
|
||||
fn resolution_to_hover_text(
|
||||
&self,
|
||||
resolution: &Resolution,
|
||||
file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> String {
|
||||
match resolution {
|
||||
Resolution::Ok(resolved) => {
|
||||
let specifier = &resolved.specifier;
|
||||
|
@ -1416,7 +1433,9 @@ impl Inner {
|
|||
if let Ok(jsr_req_ref) =
|
||||
JsrPackageReqReference::from_specifier(specifier)
|
||||
{
|
||||
if let Some(url) = self.resolver.jsr_to_registry_url(&jsr_req_ref)
|
||||
if let Some(url) = self
|
||||
.resolver
|
||||
.jsr_to_registry_url(&jsr_req_ref, file_referrer)
|
||||
{
|
||||
result = format!("{result} (<{url}>)");
|
||||
}
|
||||
|
|
|
@ -184,31 +184,49 @@ impl LspResolver {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn as_graph_resolver(&self) -> &dyn Resolver {
|
||||
pub fn as_graph_resolver(
|
||||
&self,
|
||||
_file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> &dyn Resolver {
|
||||
self.graph_resolver.as_ref()
|
||||
}
|
||||
|
||||
pub fn as_graph_npm_resolver(&self) -> &dyn NpmResolver {
|
||||
pub fn as_graph_npm_resolver(
|
||||
&self,
|
||||
_file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> &dyn NpmResolver {
|
||||
self.graph_resolver.as_ref()
|
||||
}
|
||||
|
||||
pub fn maybe_managed_npm_resolver(&self) -> Option<&ManagedCliNpmResolver> {
|
||||
pub fn maybe_managed_npm_resolver(
|
||||
&self,
|
||||
_file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> Option<&ManagedCliNpmResolver> {
|
||||
self.npm_resolver.as_ref().and_then(|r| r.as_managed())
|
||||
}
|
||||
|
||||
pub fn graph_import_specifiers(
|
||||
pub fn graph_imports_by_referrer(
|
||||
&self,
|
||||
) -> impl Iterator<Item = &ModuleSpecifier> {
|
||||
) -> IndexMap<&ModuleSpecifier, Vec<&ModuleSpecifier>> {
|
||||
self
|
||||
.graph_imports
|
||||
.values()
|
||||
.flat_map(|i| i.dependencies.values())
|
||||
.flat_map(|value| value.get_type().or_else(|| value.get_code()))
|
||||
.iter()
|
||||
.map(|(s, i)| {
|
||||
(
|
||||
s,
|
||||
i.dependencies
|
||||
.values()
|
||||
.flat_map(|d| d.get_type().or_else(|| d.get_code()))
|
||||
.collect(),
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn jsr_to_registry_url(
|
||||
&self,
|
||||
req_ref: &JsrPackageReqReference,
|
||||
_file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> Option<ModuleSpecifier> {
|
||||
self.jsr_resolver.as_ref()?.jsr_to_registry_url(req_ref)
|
||||
}
|
||||
|
@ -217,11 +235,16 @@ impl LspResolver {
|
|||
&self,
|
||||
nv: &PackageNv,
|
||||
path: &str,
|
||||
_file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> Option<String> {
|
||||
self.jsr_resolver.as_ref()?.lookup_export_for_path(nv, path)
|
||||
}
|
||||
|
||||
pub fn jsr_lookup_req_for_nv(&self, nv: &PackageNv) -> Option<PackageReq> {
|
||||
pub fn jsr_lookup_req_for_nv(
|
||||
&self,
|
||||
nv: &PackageNv,
|
||||
_file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> Option<PackageReq> {
|
||||
self.jsr_resolver.as_ref()?.lookup_req_for_nv(nv)
|
||||
}
|
||||
|
||||
|
@ -229,6 +252,7 @@ impl LspResolver {
|
|||
&self,
|
||||
req_ref: &NpmPackageReqReference,
|
||||
referrer: &ModuleSpecifier,
|
||||
_file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> Option<(ModuleSpecifier, MediaType)> {
|
||||
let node_resolver = self.node_resolver.as_ref()?;
|
||||
Some(NodeResolution::into_specifier_and_media_type(
|
||||
|
@ -275,6 +299,7 @@ impl LspResolver {
|
|||
pub fn resolve_redirects(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
_file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> Option<ModuleSpecifier> {
|
||||
let Some(redirect_resolver) = self.redirect_resolver.as_ref() else {
|
||||
return Some(specifier.clone());
|
||||
|
@ -285,6 +310,7 @@ impl LspResolver {
|
|||
pub fn redirect_chain_headers(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
_file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> Vec<(ModuleSpecifier, Arc<HashMap<String, String>>)> {
|
||||
let Some(redirect_resolver) = self.redirect_resolver.as_ref() else {
|
||||
return vec![];
|
||||
|
|
|
@ -4,6 +4,7 @@ use super::analysis::CodeActionData;
|
|||
use super::code_lens;
|
||||
use super::config;
|
||||
use super::documents::AssetOrDocument;
|
||||
use super::documents::Document;
|
||||
use super::documents::DocumentsFilter;
|
||||
use super::language_server;
|
||||
use super::language_server::StateSnapshot;
|
||||
|
@ -393,8 +394,8 @@ impl TsServer {
|
|||
let _join_handle = thread::spawn(move || {
|
||||
run_tsc_thread(
|
||||
receiver,
|
||||
performance.clone(),
|
||||
specifier_map.clone(),
|
||||
performance,
|
||||
specifier_map,
|
||||
maybe_inspector_server,
|
||||
)
|
||||
});
|
||||
|
@ -3990,6 +3991,8 @@ struct State {
|
|||
response_tx: Option<oneshot::Sender<Result<String, AnyError>>>,
|
||||
state_snapshot: Arc<StateSnapshot>,
|
||||
specifier_map: Arc<TscSpecifierMap>,
|
||||
root_referrers: HashMap<ModuleSpecifier, ModuleSpecifier>,
|
||||
last_referrer: Option<ModuleSpecifier>,
|
||||
token: CancellationToken,
|
||||
pending_requests: Option<UnboundedReceiver<Request>>,
|
||||
mark: Option<PerformanceMark>,
|
||||
|
@ -4008,12 +4011,30 @@ impl State {
|
|||
response_tx: None,
|
||||
state_snapshot,
|
||||
specifier_map,
|
||||
root_referrers: Default::default(),
|
||||
last_referrer: None,
|
||||
token: Default::default(),
|
||||
mark: None,
|
||||
pending_requests: Some(pending_requests),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_document(&self, specifier: &ModuleSpecifier) -> Option<Arc<Document>> {
|
||||
if let Some(referrer) = self.root_referrers.get(specifier) {
|
||||
self
|
||||
.state_snapshot
|
||||
.documents
|
||||
.get_or_load(specifier, referrer)
|
||||
} else if let Some(referrer) = &self.last_referrer {
|
||||
self
|
||||
.state_snapshot
|
||||
.documents
|
||||
.get_or_load(specifier, referrer)
|
||||
} else {
|
||||
self.state_snapshot.documents.get(specifier)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_asset_or_document(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
|
@ -4022,10 +4043,8 @@ impl State {
|
|||
if specifier.scheme() == "asset" {
|
||||
snapshot.assets.get(specifier).map(AssetOrDocument::Asset)
|
||||
} else {
|
||||
snapshot
|
||||
.documents
|
||||
.get(specifier)
|
||||
.map(AssetOrDocument::Document)
|
||||
let document = self.get_document(specifier);
|
||||
document.map(AssetOrDocument::Document)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4037,11 +4056,8 @@ impl State {
|
|||
None
|
||||
}
|
||||
} else {
|
||||
self
|
||||
.state_snapshot
|
||||
.documents
|
||||
.get(specifier)
|
||||
.map(|d| d.script_version())
|
||||
let document = self.get_document(specifier);
|
||||
document.map(|d| d.script_version())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4222,7 +4238,7 @@ fn op_resolve_inner(
|
|||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
state.last_referrer = Some(referrer);
|
||||
state.performance.measure(mark);
|
||||
Ok(specifiers)
|
||||
}
|
||||
|
@ -4235,6 +4251,7 @@ fn op_respond(
|
|||
) {
|
||||
let state = state.borrow_mut::<State>();
|
||||
state.performance.measure(state.mark.take().unwrap());
|
||||
state.last_referrer = None;
|
||||
let response = if !error.is_empty() {
|
||||
Err(anyhow!("tsc error: {error}"))
|
||||
} else {
|
||||
|
@ -4269,9 +4286,16 @@ fn op_script_names(state: &mut OpState) -> Vec<String> {
|
|||
}
|
||||
|
||||
// inject these next because they're global
|
||||
for specifier in state.state_snapshot.resolver.graph_import_specifiers() {
|
||||
if seen.insert(Cow::Borrowed(specifier.as_str())) {
|
||||
result.push(specifier.to_string());
|
||||
for (referrer, specifiers) in
|
||||
state.state_snapshot.resolver.graph_imports_by_referrer()
|
||||
{
|
||||
for specifier in specifiers {
|
||||
if seen.insert(Cow::Borrowed(specifier.as_str())) {
|
||||
result.push(specifier.to_string());
|
||||
}
|
||||
state
|
||||
.root_referrers
|
||||
.insert(specifier.clone(), referrer.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4289,8 +4313,12 @@ fn op_script_names(state: &mut OpState) -> Vec<String> {
|
|||
let types_specifier = (|| {
|
||||
let documents = &state.state_snapshot.documents;
|
||||
let types = doc.maybe_types_dependency().maybe_specifier()?;
|
||||
let (types, _) = documents.resolve_dependency(types, specifier)?;
|
||||
let types_doc = documents.get(&types)?;
|
||||
let (types, _) = documents.resolve_dependency(
|
||||
types,
|
||||
specifier,
|
||||
doc.file_referrer(),
|
||||
)?;
|
||||
let types_doc = documents.get_or_load(&types, specifier)?;
|
||||
Some(types_doc.specifier().clone())
|
||||
})();
|
||||
// If there is a types dep, use that as the root instead. But if the doc
|
||||
|
@ -5169,11 +5197,12 @@ mod tests {
|
|||
*version,
|
||||
*language_id,
|
||||
(*source).into(),
|
||||
None,
|
||||
);
|
||||
}
|
||||
let snapshot = Arc::new(StateSnapshot {
|
||||
project_version: 0,
|
||||
documents,
|
||||
documents: Arc::new(documents),
|
||||
assets: Default::default(),
|
||||
config: Arc::new(config),
|
||||
resolver,
|
||||
|
|
|
@ -98,7 +98,7 @@ fn lsp_tsconfig_types() {
|
|||
}
|
||||
}));
|
||||
|
||||
assert_eq!(diagnostics.all().len(), 0);
|
||||
assert_eq!(json!(diagnostics.all()), json!([]));
|
||||
|
||||
client.shutdown();
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ fn lsp_tsconfig_types_config_sub_dir() {
|
|||
}
|
||||
}));
|
||||
|
||||
assert_eq!(diagnostics.all().len(), 0);
|
||||
assert_eq!(json!(diagnostics.all()), json!([]));
|
||||
|
||||
client.shutdown();
|
||||
}
|
||||
|
@ -11730,27 +11730,24 @@ fn lsp_vendor_dir() {
|
|||
temp_dir.path().join("deno.json"),
|
||||
"{ \"vendor\": true, \"lock\": false }\n",
|
||||
);
|
||||
let refresh_config = |client: &mut LspClient| {
|
||||
client.change_configuration(json!({ "deno": {
|
||||
"enable": true,
|
||||
"config": "./deno.json",
|
||||
"codeLens": {
|
||||
"implementations": true,
|
||||
"references": true,
|
||||
},
|
||||
"importMap": null,
|
||||
"lint": false,
|
||||
"suggest": {
|
||||
"autoImports": true,
|
||||
"completeFunctionCalls": false,
|
||||
"names": true,
|
||||
"paths": true,
|
||||
"imports": {},
|
||||
},
|
||||
"unstable": false,
|
||||
} }));
|
||||
};
|
||||
refresh_config(&mut client);
|
||||
client.change_configuration(json!({ "deno": {
|
||||
"enable": true,
|
||||
"config": "./deno.json",
|
||||
"codeLens": {
|
||||
"implementations": true,
|
||||
"references": true,
|
||||
},
|
||||
"importMap": null,
|
||||
"lint": false,
|
||||
"suggest": {
|
||||
"autoImports": true,
|
||||
"completeFunctionCalls": false,
|
||||
"names": true,
|
||||
"paths": true,
|
||||
"imports": {},
|
||||
},
|
||||
"unstable": false,
|
||||
} }));
|
||||
|
||||
let diagnostics = client.read_diagnostics();
|
||||
// won't be cached until a manual cache occurs
|
||||
|
|
Loading…
Reference in a new issue