refactor(lsp): determine file referrer for each document (#23867)

This commit is contained in:
Nayeem Rahman 2024-05-23 17:31:56 +01:00 committed by GitHub
parent 143ea4759f
commit 0a30897925
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 320 additions and 117 deletions

View file

@ -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(&params.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(&params.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", &params);
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(&params.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}>)");
}