fix(lsp): handle data URLs properly (#9522)

Fixes #9514

Co-authored-by: Ryan Dahl <ry@tinyclouds.org>
This commit is contained in:
Kitson Kelly 2021-02-18 15:37:05 +11:00 committed by GitHub
parent 78e34d4912
commit 2225e83da2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 374 additions and 125 deletions

View file

@ -53,7 +53,7 @@ use super::tsc;
use super::tsc::AssetDocument;
use super::tsc::Assets;
use super::tsc::TsServer;
use super::utils;
use super::urls;
lazy_static! {
static ref ABSTRACT_MODIFIER: Regex = Regex::new(r"\babstract\b").unwrap();
@ -101,6 +101,8 @@ pub(crate) struct Inner {
ts_fixable_diagnostics: Vec<String>,
/// An abstraction that handles interactions with TypeScript.
ts_server: TsServer,
/// A map of specifiers and URLs used to translate over the LSP.
pub url_map: urls::LspUrlMap,
}
impl LanguageServer {
@ -131,6 +133,7 @@ impl Inner {
sources,
ts_fixable_diagnostics: Default::default(),
ts_server: TsServer::new(),
url_map: Default::default(),
}
}
@ -661,7 +664,7 @@ impl Inner {
// already managed by the language service
return;
}
let specifier = utils::normalize_url(params.text_document.uri);
let specifier = self.url_map.normalize_url(&params.text_document.uri);
self.documents.open(
specifier.clone(),
params.text_document.version,
@ -678,7 +681,7 @@ impl Inner {
async fn did_change(&mut self, params: DidChangeTextDocumentParams) {
let mark = self.performance.mark("did_change");
let specifier = utils::normalize_url(params.text_document.uri);
let specifier = self.url_map.normalize_url(&params.text_document.uri);
match self.documents.change(
&specifier,
params.text_document.version,
@ -704,7 +707,7 @@ impl Inner {
// already managed by the language service
return;
}
let specifier = utils::normalize_url(params.text_document.uri);
let specifier = self.url_map.normalize_url(&params.text_document.uri);
self.documents.close(&specifier);
self.navigation_trees.remove(&specifier);
@ -802,7 +805,7 @@ impl Inner {
params: DocumentFormattingParams,
) -> LspResult<Option<Vec<TextEdit>>> {
let mark = self.performance.mark("formatting");
let specifier = utils::normalize_url(params.text_document.uri.clone());
let specifier = self.url_map.normalize_url(&params.text_document.uri);
let file_text = self
.documents
.content(&specifier)
@ -858,9 +861,9 @@ impl Inner {
return Ok(None);
}
let mark = self.performance.mark("hover");
let specifier = utils::normalize_url(
params.text_document_position_params.text_document.uri,
);
let specifier = self
.url_map
.normalize_url(&params.text_document_position_params.text_document.uri);
let line_index =
if let Some(line_index) = self.get_line_index_sync(&specifier) {
line_index
@ -898,7 +901,7 @@ impl Inner {
}
let mark = self.performance.mark("code_action");
let specifier = utils::normalize_url(params.text_document.uri);
let specifier = self.url_map.normalize_url(&params.text_document.uri);
let fixable_diagnostics: Vec<&Diagnostic> = params
.context
.diagnostics
@ -915,7 +918,9 @@ impl Inner {
_ => false,
},
"deno" => match &d.code {
Some(NumberOrString::String(code)) => code == "no-cache",
Some(NumberOrString::String(code)) => {
code == "no-cache" || code == "no-cache-data"
}
_ => false,
},
_ => false,
@ -1053,7 +1058,7 @@ impl Inner {
}
let mark = self.performance.mark("code_lens");
let specifier = utils::normalize_url(params.text_document.uri);
let specifier = self.url_map.normalize_url(&params.text_document.uri);
let line_index = self.get_line_index_sync(&specifier).unwrap();
let navigation_tree =
self.get_navigation_tree(&specifier).await.map_err(|err| {
@ -1209,7 +1214,7 @@ impl Inner {
LspError::internal_error()
})?;
let implementation_location =
implementation.to_location(&line_index);
implementation.to_location(&line_index, self);
if !(implementation_specifier == code_lens_data.specifier
&& implementation_location.range.start == params.range.start)
{
@ -1222,11 +1227,13 @@ impl Inner {
} else {
"1 implementation".to_string()
};
let url = utils::normalize_specifier(&code_lens_data.specifier)
let url = self
.url_map
.normalize_specifier(&code_lens_data.specifier)
.map_err(|err| {
error!("{}", err);
LspError::internal_error()
})?;
error!("{}", err);
LspError::internal_error()
})?;
Command {
title,
command: "deno.showReferences".to_string(),
@ -1300,7 +1307,7 @@ impl Inner {
error!("Unable to get line index: {}", err);
LspError::internal_error()
})?;
locations.push(reference.to_location(&line_index));
locations.push(reference.to_location(&line_index, self));
}
let command = if !locations.is_empty() {
let title = if locations.len() > 1 {
@ -1308,11 +1315,13 @@ impl Inner {
} else {
"1 reference".to_string()
};
let url = utils::normalize_specifier(&code_lens_data.specifier)
let url = self
.url_map
.normalize_specifier(&code_lens_data.specifier)
.map_err(|err| {
error!("{}", err);
LspError::internal_error()
})?;
error!("{}", err);
LspError::internal_error()
})?;
Command {
title,
command: "deno.showReferences".to_string(),
@ -1366,9 +1375,9 @@ impl Inner {
return Ok(None);
}
let mark = self.performance.mark("document_highlight");
let specifier = utils::normalize_url(
params.text_document_position_params.text_document.uri,
);
let specifier = self
.url_map
.normalize_url(&params.text_document_position_params.text_document.uri);
let line_index =
if let Some(line_index) = self.get_line_index_sync(&specifier) {
line_index
@ -1412,8 +1421,9 @@ impl Inner {
return Ok(None);
}
let mark = self.performance.mark("references");
let specifier =
utils::normalize_url(params.text_document_position.text_document.uri);
let specifier = self
.url_map
.normalize_url(&params.text_document_position.text_document.uri);
let line_index =
if let Some(line_index) = self.get_line_index_sync(&specifier) {
line_index
@ -1444,7 +1454,7 @@ impl Inner {
// TODO(lucacasonato): handle error correctly
let line_index =
self.get_line_index(reference_specifier).await.unwrap();
results.push(reference.to_location(&line_index));
results.push(reference.to_location(&line_index, self));
}
self.performance.measure(mark);
@ -1463,9 +1473,9 @@ impl Inner {
return Ok(None);
}
let mark = self.performance.mark("goto_definition");
let specifier = utils::normalize_url(
params.text_document_position_params.text_document.uri,
);
let specifier = self
.url_map
.normalize_url(&params.text_document_position_params.text_document.uri);
let line_index =
if let Some(line_index) = self.get_line_index_sync(&specifier) {
line_index
@ -1503,8 +1513,9 @@ impl Inner {
return Ok(None);
}
let mark = self.performance.mark("completion");
let specifier =
utils::normalize_url(params.text_document_position.text_document.uri);
let specifier = self
.url_map
.normalize_url(&params.text_document_position.text_document.uri);
// TODO(lucacasonato): handle error correctly
let line_index =
if let Some(line_index) = self.get_line_index_sync(&specifier) {
@ -1548,9 +1559,9 @@ impl Inner {
return Ok(None);
}
let mark = self.performance.mark("goto_implementation");
let specifier = utils::normalize_url(
params.text_document_position_params.text_document.uri,
);
let specifier = self
.url_map
.normalize_url(&params.text_document_position_params.text_document.uri);
let line_index =
if let Some(line_index) = self.get_line_index_sync(&specifier) {
line_index
@ -1605,8 +1616,9 @@ impl Inner {
return Ok(None);
}
let mark = self.performance.mark("rename");
let specifier =
utils::normalize_url(params.text_document_position.text_document.uri);
let specifier = self
.url_map
.normalize_url(&params.text_document_position.text_document.uri);
let line_index =
if let Some(line_index) = self.get_line_index_sync(&specifier) {
@ -1710,9 +1722,9 @@ impl Inner {
return Ok(None);
}
let mark = self.performance.mark("signature_help");
let specifier = utils::normalize_url(
params.text_document_position_params.text_document.uri,
);
let specifier = self
.url_map
.normalize_url(&params.text_document_position_params.text_document.uri);
let line_index =
if let Some(line_index) = self.get_line_index_sync(&specifier) {
line_index
@ -1930,10 +1942,10 @@ impl Inner {
/// in the Deno cache, including any of their dependencies.
async fn cache(&mut self, params: CacheParams) -> LspResult<bool> {
let mark = self.performance.mark("cache");
let referrer = utils::normalize_url(params.referrer.uri);
let referrer = self.url_map.normalize_url(&params.referrer.uri);
if !params.uris.is_empty() {
for identifier in &params.uris {
let specifier = utils::normalize_url(identifier.uri.clone());
let specifier = self.url_map.normalize_url(&identifier.uri);
sources::cache(&specifier, &self.maybe_import_map)
.await
.map_err(|err| {
@ -1976,7 +1988,7 @@ impl Inner {
params: VirtualTextDocumentParams,
) -> LspResult<Option<String>> {
let mark = self.performance.mark("virtual_text_document");
let specifier = utils::normalize_url(params.text_document.uri);
let specifier = self.url_map.normalize_url(&params.text_document.uri);
let contents = if specifier.as_str() == "deno:/status.md" {
let mut contents = String::new();
@ -2170,15 +2182,15 @@ mod tests {
("initialize_request.json", LspResponse::RequestAny),
("initialized_notification.json", LspResponse::None),
("did_open_notification_asset.json", LspResponse::None),
("hover_request_asset_01.json", LspResponse::RequestAny),
("definition_request_asset.json", LspResponse::RequestAny),
(
"virtual_text_document_request.json",
LspResponse::RequestAny,
),
(
"hover_request_asset_02.json",
"hover_request_asset.json",
LspResponse::Request(
4,
5,
json!({
"contents": [
{
@ -2807,6 +2819,7 @@ mod tests {
("initialize_request.json", LspResponse::RequestAny),
("initialized_notification.json", LspResponse::None),
("did_open_notification_asset.json", LspResponse::None),
("references_request_asset.json", LspResponse::RequestAny),
(
"virtual_text_document_request.json",
LspResponse::RequestAny,