mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 15:24:46 -05:00
fix(lsp): support data urls in deno.importMap
option (#11397)
This commit is contained in:
parent
a442821d97
commit
84f8747157
5 changed files with 127 additions and 36 deletions
|
@ -143,6 +143,24 @@ fn fetch_local(specifier: &ModuleSpecifier) -> Result<File, AnyError> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Returns the decoded body and content-type of a provided
|
||||
/// data URL.
|
||||
pub fn get_source_from_data_url(
|
||||
specifier: &ModuleSpecifier,
|
||||
) -> Result<(String, String), AnyError> {
|
||||
let data_url = DataUrl::process(specifier.as_str())
|
||||
.map_err(|e| uri_error(format!("{:?}", e)))?;
|
||||
let mime = data_url.mime_type();
|
||||
let charset = mime.get_parameter("charset").map(|v| v.to_string());
|
||||
let (bytes, _) = data_url
|
||||
.decode_to_vec()
|
||||
.map_err(|e| uri_error(format!("{:?}", e)))?;
|
||||
Ok((
|
||||
strip_shebang(get_source_from_bytes(bytes, charset)?),
|
||||
format!("{}", mime),
|
||||
))
|
||||
}
|
||||
|
||||
/// Given a vector of bytes and optionally a charset, decode the bytes to a
|
||||
/// string.
|
||||
pub fn get_source_from_bytes(
|
||||
|
@ -340,15 +358,7 @@ impl FileFetcher {
|
|||
));
|
||||
}
|
||||
|
||||
let data_url = DataUrl::process(specifier.as_str())
|
||||
.map_err(|e| uri_error(format!("{:?}", e)))?;
|
||||
let mime = data_url.mime_type();
|
||||
let charset = mime.get_parameter("charset").map(|v| v.to_string());
|
||||
let (bytes, _) = data_url
|
||||
.decode_to_vec()
|
||||
.map_err(|e| uri_error(format!("{:?}", e)))?;
|
||||
let source = strip_shebang(get_source_from_bytes(bytes, charset)?);
|
||||
let content_type = format!("{}", mime);
|
||||
let (source, content_type) = get_source_from_data_url(specifier)?;
|
||||
let (media_type, _) =
|
||||
map_content_type(specifier, Some(content_type.clone()));
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ use super::urls;
|
|||
use crate::config_file::ConfigFile;
|
||||
use crate::config_file::TsConfig;
|
||||
use crate::deno_dir;
|
||||
use crate::file_fetcher::get_source_from_data_url;
|
||||
use crate::fs_util;
|
||||
use crate::logger;
|
||||
use crate::tools::fmt::format_file;
|
||||
|
@ -474,6 +475,10 @@ impl Inner {
|
|||
let import_map_url = if let Ok(url) = Url::from_file_path(import_map_str)
|
||||
{
|
||||
Ok(url)
|
||||
} else if import_map_str.starts_with("data:") {
|
||||
Url::parse(import_map_str).map_err(|_| {
|
||||
anyhow!("Bad data url for import map: {:?}", import_map_str)
|
||||
})
|
||||
} else if let Some(root_uri) = &maybe_root_uri {
|
||||
let root_path = root_uri
|
||||
.to_file_path()
|
||||
|
@ -488,6 +493,10 @@ impl Inner {
|
|||
import_map_str
|
||||
))
|
||||
}?;
|
||||
|
||||
let import_map_json = if import_map_url.scheme() == "data" {
|
||||
get_source_from_data_url(&import_map_url)?.0
|
||||
} else {
|
||||
let import_map_path = import_map_url.to_file_path().map_err(|_| {
|
||||
anyhow!("Cannot convert \"{}\" into a file path.", import_map_url)
|
||||
})?;
|
||||
|
@ -495,14 +504,14 @@ impl Inner {
|
|||
" Resolved import map: \"{}\"",
|
||||
import_map_path.to_string_lossy()
|
||||
);
|
||||
let import_map_json =
|
||||
fs::read_to_string(import_map_path).await.map_err(|err| {
|
||||
anyhow!(
|
||||
"Failed to load the import map at: {}. [{}]",
|
||||
import_map_url,
|
||||
err
|
||||
)
|
||||
})?;
|
||||
})?
|
||||
};
|
||||
let import_map =
|
||||
ImportMap::from_json(&import_map_url.to_string(), &import_map_json)?;
|
||||
self.maybe_import_map_uri = Some(import_map_url);
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::colors;
|
||||
use crate::file_fetcher::get_source_from_bytes;
|
||||
use crate::file_fetcher::strip_shebang;
|
||||
use crate::file_fetcher::get_source_from_data_url;
|
||||
use crate::flags::Flags;
|
||||
use crate::ops;
|
||||
use crate::program_state::ProgramState;
|
||||
use crate::version;
|
||||
use data_url::DataUrl;
|
||||
use deno_core::error::anyhow;
|
||||
use deno_core::error::type_error;
|
||||
use deno_core::error::uri_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::error::Context;
|
||||
use deno_core::futures::FutureExt;
|
||||
|
@ -123,19 +120,6 @@ fn read_string_slice(
|
|||
Ok(string)
|
||||
}
|
||||
|
||||
fn get_source_from_data_url(
|
||||
specifier: &ModuleSpecifier,
|
||||
) -> Result<String, AnyError> {
|
||||
let data_url = DataUrl::process(specifier.as_str())
|
||||
.map_err(|e| uri_error(format!("{:?}", e)))?;
|
||||
let mime = data_url.mime_type();
|
||||
let charset = mime.get_parameter("charset").map(|v| v.to_string());
|
||||
let (bytes, _) = data_url
|
||||
.decode_to_vec()
|
||||
.map_err(|e| uri_error(format!("{:?}", e)))?;
|
||||
Ok(strip_shebang(get_source_from_bytes(bytes, charset)?))
|
||||
}
|
||||
|
||||
const SPECIFIER: &str = "file://$deno$/bundle.js";
|
||||
|
||||
struct EmbeddedModuleLoader(String);
|
||||
|
@ -169,7 +153,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
) -> Pin<Box<deno_core::ModuleSourceFuture>> {
|
||||
let module_specifier = module_specifier.clone();
|
||||
let is_data_uri = get_source_from_data_url(&module_specifier).ok();
|
||||
let code = if let Some(ref source) = is_data_uri {
|
||||
let code = if let Some((ref source, _)) = is_data_uri {
|
||||
source.to_string()
|
||||
} else {
|
||||
self.0.to_string()
|
||||
|
|
|
@ -316,6 +316,32 @@ fn lsp_import_map() {
|
|||
shutdown(&mut client);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lsp_import_map_data_url() {
|
||||
let mut client = init("initialize_params_import_map.json");
|
||||
let diagnostics = did_open(
|
||||
&mut client,
|
||||
json!({
|
||||
"textDocument": {
|
||||
"uri": "file:///a/file.ts",
|
||||
"languageId": "typescript",
|
||||
"version": 1,
|
||||
"text": "import example from \"example\";\n"
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
let mut diagnostics = diagnostics.into_iter().flat_map(|x| x.diagnostics);
|
||||
// This indicates that the import map from initialize_params_import_map.json
|
||||
// is applied correctly.
|
||||
assert!(diagnostics.any(|diagnostic| diagnostic.code
|
||||
== Some(lsp::NumberOrString::String("no-cache".to_string()))
|
||||
&& diagnostic
|
||||
.message
|
||||
.contains("https://deno.land/x/example/mod.ts")));
|
||||
shutdown(&mut client);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lsp_hover() {
|
||||
let mut client = init("initialize_params.json");
|
||||
|
|
62
cli/tests/testdata/lsp/initialize_params_import_map.json
vendored
Normal file
62
cli/tests/testdata/lsp/initialize_params_import_map.json
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"processId": 0,
|
||||
"clientInfo": {
|
||||
"name": "test-harness",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"rootUri": null,
|
||||
"initializationOptions": {
|
||||
"enable": true,
|
||||
"codeLens": {
|
||||
"implementations": true,
|
||||
"references": true
|
||||
},
|
||||
"importMap": "data:application/json;utf8,{\"imports\": { \"example\": \"https://deno.land/x/example/mod.ts\" }}",
|
||||
"lint": true,
|
||||
"suggest": {
|
||||
"autoImports": true,
|
||||
"completeFunctionCalls": false,
|
||||
"names": true,
|
||||
"paths": true,
|
||||
"imports": {
|
||||
"hosts": {
|
||||
"http://localhost:4545/": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"unstable": false
|
||||
},
|
||||
"capabilities": {
|
||||
"textDocument": {
|
||||
"codeAction": {
|
||||
"codeActionLiteralSupport": {
|
||||
"codeActionKind": {
|
||||
"valueSet": [
|
||||
"quickfix"
|
||||
]
|
||||
}
|
||||
},
|
||||
"isPreferredSupport": true,
|
||||
"dataSupport": true,
|
||||
"resolveSupport": {
|
||||
"properties": [
|
||||
"edit"
|
||||
]
|
||||
}
|
||||
},
|
||||
"foldingRange": {
|
||||
"lineFoldingOnly": true
|
||||
},
|
||||
"synchronization": {
|
||||
"dynamicRegistration": true,
|
||||
"willSave": true,
|
||||
"willSaveWaitUntil": true,
|
||||
"didSave": true
|
||||
}
|
||||
},
|
||||
"workspace": {
|
||||
"configuration": true,
|
||||
"workspaceFolders": true
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue