mirror of
https://github.com/denoland/deno.git
synced 2025-02-12 16:59:32 -05:00
feat(lsp): provide X-Deno-Warning as a diagnostic (#10680)
Closes #9932
This commit is contained in:
parent
6966c4e916
commit
d987ca5b07
3 changed files with 121 additions and 8 deletions
|
@ -444,13 +444,21 @@ async fn generate_deps_diagnostics(
|
||||||
range,
|
range,
|
||||||
severity: Some(lsp::DiagnosticSeverity::Error),
|
severity: Some(lsp::DiagnosticSeverity::Error),
|
||||||
code,
|
code,
|
||||||
code_description: None,
|
|
||||||
source: Some("deno".to_string()),
|
source: Some("deno".to_string()),
|
||||||
message,
|
message,
|
||||||
related_information: None,
|
..Default::default()
|
||||||
tags: None,
|
|
||||||
data: None,
|
|
||||||
});
|
});
|
||||||
|
} else if sources.contains_key(&specifier) {
|
||||||
|
if let Some(message) = sources.get_maybe_warning(&specifier) {
|
||||||
|
diagnostics.push(lsp::Diagnostic {
|
||||||
|
range,
|
||||||
|
severity: Some(lsp::DiagnosticSeverity::Warning),
|
||||||
|
code: Some(lsp::NumberOrString::String("deno-warn".to_string())),
|
||||||
|
source: Some("deno".to_string()),
|
||||||
|
message,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,11 @@ use crate::module_graph::GraphBuilder;
|
||||||
use crate::program_state::ProgramState;
|
use crate::program_state::ProgramState;
|
||||||
use crate::specifier_handler::FetchHandler;
|
use crate::specifier_handler::FetchHandler;
|
||||||
use crate::text_encoding;
|
use crate::text_encoding;
|
||||||
use deno_runtime::permissions::Permissions;
|
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
|
use deno_runtime::permissions::Permissions;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
@ -105,6 +105,7 @@ struct Metadata {
|
||||||
length_utf16: usize,
|
length_utf16: usize,
|
||||||
line_index: LineIndex,
|
line_index: LineIndex,
|
||||||
maybe_types: Option<analysis::ResolvedDependency>,
|
maybe_types: Option<analysis::ResolvedDependency>,
|
||||||
|
maybe_warning: Option<String>,
|
||||||
media_type: MediaType,
|
media_type: MediaType,
|
||||||
source: String,
|
source: String,
|
||||||
version: String,
|
version: String,
|
||||||
|
@ -116,6 +117,7 @@ impl Metadata {
|
||||||
source: &str,
|
source: &str,
|
||||||
version: &str,
|
version: &str,
|
||||||
media_type: &MediaType,
|
media_type: &MediaType,
|
||||||
|
maybe_warning: Option<String>,
|
||||||
maybe_import_map: &Option<ImportMap>,
|
maybe_import_map: &Option<ImportMap>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let (dependencies, maybe_types) = if let Ok(parsed_module) =
|
let (dependencies, maybe_types) = if let Ok(parsed_module) =
|
||||||
|
@ -138,6 +140,7 @@ impl Metadata {
|
||||||
length_utf16: source.encode_utf16().count(),
|
length_utf16: source.encode_utf16().count(),
|
||||||
line_index,
|
line_index,
|
||||||
maybe_types,
|
maybe_types,
|
||||||
|
maybe_warning,
|
||||||
media_type: media_type.to_owned(),
|
media_type: media_type.to_owned(),
|
||||||
source: source.to_string(),
|
source: source.to_string(),
|
||||||
version: version.to_string(),
|
version: version.to_string(),
|
||||||
|
@ -180,6 +183,13 @@ impl Sources {
|
||||||
self.0.lock().unwrap().get_maybe_types(specifier)
|
self.0.lock().unwrap().get_maybe_types(specifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_maybe_warning(
|
||||||
|
&self,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
) -> Option<String> {
|
||||||
|
self.0.lock().unwrap().get_maybe_warning(specifier)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_media_type(
|
pub fn get_media_type(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
|
@ -271,6 +281,14 @@ impl Inner {
|
||||||
metadata.maybe_types
|
metadata.maybe_types
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_maybe_warning(
|
||||||
|
&mut self,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
) -> Option<String> {
|
||||||
|
let metadata = self.get_metadata(&specifier)?;
|
||||||
|
metadata.maybe_warning
|
||||||
|
}
|
||||||
|
|
||||||
fn get_media_type(
|
fn get_media_type(
|
||||||
&mut self,
|
&mut self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
|
@ -292,11 +310,11 @@ impl Inner {
|
||||||
let path = self.get_path(specifier)?;
|
let path = self.get_path(specifier)?;
|
||||||
let bytes = fs::read(path).ok()?;
|
let bytes = fs::read(path).ok()?;
|
||||||
let scheme = specifier.scheme();
|
let scheme = specifier.scheme();
|
||||||
let (source, media_type, maybe_types) = if scheme == "file" {
|
let (source, media_type, maybe_types, maybe_warning) = if scheme == "file" {
|
||||||
let maybe_charset =
|
let maybe_charset =
|
||||||
Some(text_encoding::detect_charset(&bytes).to_string());
|
Some(text_encoding::detect_charset(&bytes).to_string());
|
||||||
let source = get_source_from_bytes(bytes, maybe_charset).ok()?;
|
let source = get_source_from_bytes(bytes, maybe_charset).ok()?;
|
||||||
(source, MediaType::from(specifier), None)
|
(source, MediaType::from(specifier), None, None)
|
||||||
} else {
|
} else {
|
||||||
let cache_filename = self.http_cache.get_cache_filename(specifier)?;
|
let cache_filename = self.http_cache.get_cache_filename(specifier)?;
|
||||||
let headers = get_remote_headers(&cache_filename)?;
|
let headers = get_remote_headers(&cache_filename)?;
|
||||||
|
@ -307,13 +325,15 @@ impl Inner {
|
||||||
let maybe_types = headers.get("x-typescript-types").map(|s| {
|
let maybe_types = headers.get("x-typescript-types").map(|s| {
|
||||||
analysis::resolve_import(s, &specifier, &self.maybe_import_map)
|
analysis::resolve_import(s, &specifier, &self.maybe_import_map)
|
||||||
});
|
});
|
||||||
(source, media_type, maybe_types)
|
let maybe_warning = headers.get("x-deno-warning").cloned();
|
||||||
|
(source, media_type, maybe_types, maybe_warning)
|
||||||
};
|
};
|
||||||
let mut metadata = Metadata::new(
|
let mut metadata = Metadata::new(
|
||||||
specifier,
|
specifier,
|
||||||
&source,
|
&source,
|
||||||
&version,
|
&version,
|
||||||
&media_type,
|
&media_type,
|
||||||
|
maybe_warning,
|
||||||
&self.maybe_import_map,
|
&self.maybe_import_map,
|
||||||
);
|
);
|
||||||
if maybe_types.is_some() {
|
if maybe_types.is_some() {
|
||||||
|
@ -547,6 +567,23 @@ mod tests {
|
||||||
assert_eq!(actual, Some((specifier_type, MediaType::Dts)))
|
assert_eq!(actual, Some((specifier_type, MediaType::Dts)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_warning_header() {
|
||||||
|
let (sources, location) = setup();
|
||||||
|
let cache = HttpCache::new(&location);
|
||||||
|
let specifier = resolve_url("https://deno.land/x/lib.js").unwrap();
|
||||||
|
let mut headers = HashMap::new();
|
||||||
|
headers.insert(
|
||||||
|
"x-deno-warning".to_string(),
|
||||||
|
"this is a warning".to_string(),
|
||||||
|
);
|
||||||
|
cache
|
||||||
|
.set(&specifier, headers, b"export const a = 1;")
|
||||||
|
.unwrap();
|
||||||
|
let actual = sources.get_maybe_warning(&specifier);
|
||||||
|
assert_eq!(actual, Some("this is a warning".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_resolve_dependency_evil_redirect() {
|
fn test_resolve_dependency_evil_redirect() {
|
||||||
let (sources, location) = setup();
|
let (sources, location) = setup();
|
||||||
|
|
|
@ -1604,6 +1604,74 @@ fn lsp_completions_registry_empty() {
|
||||||
shutdown(&mut client);
|
shutdown(&mut client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lsp_diagnostics_warn() {
|
||||||
|
let _g = http_server();
|
||||||
|
let mut client = init("initialize_params.json");
|
||||||
|
did_open(
|
||||||
|
&mut client,
|
||||||
|
json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts",
|
||||||
|
"languageId": "typescript",
|
||||||
|
"version": 1,
|
||||||
|
"text": "import * as a from \"http://127.0.0.1:4545/cli/tests/x_deno_warning.js\";\n\nconsole.log(a)\n",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
let (maybe_res, maybe_err) = client
|
||||||
|
.write_request::<_, _, Value>(
|
||||||
|
"deno/cache",
|
||||||
|
json!({
|
||||||
|
"referrer": {
|
||||||
|
"uri": "file:///a/file.ts",
|
||||||
|
},
|
||||||
|
"uris": [
|
||||||
|
{
|
||||||
|
"uri": "http://127.0.0.1:4545/cli/tests/x_deno_warning.js",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert!(maybe_err.is_none());
|
||||||
|
assert!(maybe_res.is_some());
|
||||||
|
|
||||||
|
let (method, _) = client.read_notification::<Value>().unwrap();
|
||||||
|
assert_eq!(method, "textDocument/publishDiagnostics");
|
||||||
|
let (method, _) = client.read_notification::<Value>().unwrap();
|
||||||
|
assert_eq!(method, "textDocument/publishDiagnostics");
|
||||||
|
let (method, maybe_params) = client
|
||||||
|
.read_notification::<lsp::PublishDiagnosticsParams>()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(method, "textDocument/publishDiagnostics");
|
||||||
|
assert_eq!(
|
||||||
|
maybe_params,
|
||||||
|
Some(lsp::PublishDiagnosticsParams {
|
||||||
|
uri: Url::parse("file:///a/file.ts").unwrap(),
|
||||||
|
diagnostics: vec![lsp::Diagnostic {
|
||||||
|
range: lsp::Range {
|
||||||
|
start: lsp::Position {
|
||||||
|
line: 0,
|
||||||
|
character: 19
|
||||||
|
},
|
||||||
|
end: lsp::Position {
|
||||||
|
line: 0,
|
||||||
|
character: 70
|
||||||
|
}
|
||||||
|
},
|
||||||
|
severity: Some(lsp::DiagnosticSeverity::Warning),
|
||||||
|
code: Some(lsp::NumberOrString::String("deno-warn".to_string())),
|
||||||
|
source: Some("deno".to_string()),
|
||||||
|
message: "foobar".to_string(),
|
||||||
|
..Default::default()
|
||||||
|
}],
|
||||||
|
version: Some(1),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
shutdown(&mut client);
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct PerformanceAverage {
|
pub struct PerformanceAverage {
|
||||||
|
|
Loading…
Add table
Reference in a new issue