mirror of
https://github.com/denoland/deno.git
synced 2025-09-26 12:19:12 +00:00
feat: Add Deno.formatDiagnostics (#4032)
This commit is contained in:
parent
5da7c7df1d
commit
2b7e28b591
8 changed files with 83 additions and 7 deletions
|
@ -1,6 +1,10 @@
|
||||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||||
//! This module encodes TypeScript errors (diagnostics) into Rust structs and
|
//! This module encodes TypeScript errors (diagnostics) into Rust structs and
|
||||||
//! contains code for printing them to the console.
|
//! contains code for printing them to the console.
|
||||||
|
|
||||||
|
// TODO(ry) This module does a lot of JSON parsing manually. It should use
|
||||||
|
// serde_json.
|
||||||
|
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
use crate::fmt_errors::format_maybe_source_line;
|
use crate::fmt_errors::format_maybe_source_line;
|
||||||
use crate::fmt_errors::format_maybe_source_name;
|
use crate::fmt_errors::format_maybe_source_name;
|
||||||
|
@ -29,7 +33,7 @@ impl Diagnostic {
|
||||||
let items_values = items_v.as_array().unwrap();
|
let items_values = items_v.as_array().unwrap();
|
||||||
|
|
||||||
for item_v in items_values {
|
for item_v in items_values {
|
||||||
items.push(DiagnosticItem::from_json_value(item_v));
|
items.push(DiagnosticItem::from_json_value(item_v)?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,14 +118,13 @@ pub struct DiagnosticItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiagnosticItem {
|
impl DiagnosticItem {
|
||||||
pub fn from_json_value(v: &serde_json::Value) -> Self {
|
pub fn from_json_value(v: &serde_json::Value) -> Option<Self> {
|
||||||
let obj = v.as_object().unwrap();
|
let obj = v.as_object().unwrap();
|
||||||
|
|
||||||
// required attributes
|
// required attributes
|
||||||
let message = obj
|
let message = obj
|
||||||
.get("message")
|
.get("message")
|
||||||
.and_then(|v| v.as_str().map(String::from))
|
.and_then(|v| v.as_str().map(String::from))?;
|
||||||
.unwrap();
|
|
||||||
let category = DiagnosticCategory::from(
|
let category = DiagnosticCategory::from(
|
||||||
obj.get("category").and_then(Value::as_i64).unwrap(),
|
obj.get("category").and_then(Value::as_i64).unwrap(),
|
||||||
);
|
);
|
||||||
|
@ -154,7 +157,7 @@ impl DiagnosticItem {
|
||||||
|
|
||||||
for related_info_v in related_info_values {
|
for related_info_v in related_info_values {
|
||||||
related_information
|
related_information
|
||||||
.push(DiagnosticItem::from_json_value(related_info_v));
|
.push(DiagnosticItem::from_json_value(related_info_v)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(related_information)
|
Some(related_information)
|
||||||
|
@ -162,7 +165,7 @@ impl DiagnosticItem {
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Some(Self {
|
||||||
message,
|
message,
|
||||||
message_chain,
|
message_chain,
|
||||||
related_information,
|
related_information,
|
||||||
|
@ -175,7 +178,7 @@ impl DiagnosticItem {
|
||||||
category,
|
category,
|
||||||
start_column,
|
start_column,
|
||||||
end_column,
|
end_column,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ export {
|
||||||
OpenOptions,
|
OpenOptions,
|
||||||
OpenMode
|
OpenMode
|
||||||
} from "./files.ts";
|
} from "./files.ts";
|
||||||
|
export { formatDiagnostics } from "./format_error.ts";
|
||||||
export { FsEvent, fsEvents } from "./fs_events.ts";
|
export { FsEvent, fsEvents } from "./fs_events.ts";
|
||||||
export {
|
export {
|
||||||
EOF,
|
EOF,
|
||||||
|
|
|
@ -17,6 +17,7 @@ export let OP_GET_DIR: number;
|
||||||
export let OP_START: number;
|
export let OP_START: number;
|
||||||
export let OP_APPLY_SOURCE_MAP: number;
|
export let OP_APPLY_SOURCE_MAP: number;
|
||||||
export let OP_FORMAT_ERROR: number;
|
export let OP_FORMAT_ERROR: number;
|
||||||
|
export let OP_FORMAT_DIAGNOSTIC: number;
|
||||||
export let OP_CACHE: number;
|
export let OP_CACHE: number;
|
||||||
export let OP_RESOLVE_MODULES: number;
|
export let OP_RESOLVE_MODULES: number;
|
||||||
export let OP_FETCH_ASSET: number;
|
export let OP_FETCH_ASSET: number;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||||
|
import { DiagnosticItem } from "./diagnostics.ts";
|
||||||
import * as dispatch from "./dispatch.ts";
|
import * as dispatch from "./dispatch.ts";
|
||||||
import { sendSync } from "./dispatch_json.ts";
|
import { sendSync } from "./dispatch_json.ts";
|
||||||
|
|
||||||
|
@ -7,3 +8,11 @@ export function formatError(errString: string): string {
|
||||||
const res = sendSync(dispatch.OP_FORMAT_ERROR, { error: errString });
|
const res = sendSync(dispatch.OP_FORMAT_ERROR, { error: errString });
|
||||||
return res.error;
|
return res.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format an array of diagnostic items and return them as a single string.
|
||||||
|
* @param items An array of diagnostic items to format
|
||||||
|
*/
|
||||||
|
export function formatDiagnostics(items: DiagnosticItem[]): string {
|
||||||
|
return sendSync(dispatch.OP_FORMAT_DIAGNOSTIC, { items });
|
||||||
|
}
|
||||||
|
|
37
cli/js/format_error_test.ts
Normal file
37
cli/js/format_error_test.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||||
|
import { assert, test } from "./test_util.ts";
|
||||||
|
|
||||||
|
test(function formatDiagnosticBasic() {
|
||||||
|
const fixture: Deno.DiagnosticItem[] = [
|
||||||
|
{
|
||||||
|
message: "Example error",
|
||||||
|
category: Deno.DiagnosticCategory.Error,
|
||||||
|
sourceLine: "abcdefghijklmnopqrstuv",
|
||||||
|
lineNumber: 1000,
|
||||||
|
scriptResourceName: "foo.ts",
|
||||||
|
startColumn: 1,
|
||||||
|
endColumn: 2,
|
||||||
|
code: 4000
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const out = Deno.formatDiagnostics(fixture);
|
||||||
|
assert(out.includes("Example error"));
|
||||||
|
assert(out.includes("foo.ts"));
|
||||||
|
});
|
||||||
|
|
||||||
|
test(function formatDiagnosticError() {
|
||||||
|
let thrown = false;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const bad = ([{ hello: 123 }] as any) as Deno.DiagnosticItem[];
|
||||||
|
try {
|
||||||
|
Deno.formatDiagnostics(bad);
|
||||||
|
} catch (e) {
|
||||||
|
assert(e instanceof TypeError);
|
||||||
|
thrown = true;
|
||||||
|
}
|
||||||
|
assert(thrown);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (import.meta.main) {
|
||||||
|
Deno.runTests();
|
||||||
|
}
|
7
cli/js/lib.deno.ns.d.ts
vendored
7
cli/js/lib.deno.ns.d.ts
vendored
|
@ -1901,6 +1901,13 @@ declare namespace Deno {
|
||||||
items: DiagnosticItem[];
|
items: DiagnosticItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** UNSTABLE: new API, yet to be vetted.
|
||||||
|
*
|
||||||
|
* Format an array of diagnostic items and return them as a single string.
|
||||||
|
* @param items An array of diagnostic items to format
|
||||||
|
*/
|
||||||
|
export function formatDiagnostics(items: DiagnosticItem[]): string;
|
||||||
|
|
||||||
/** UNSTABLE: new API, yet to be vetted.
|
/** UNSTABLE: new API, yet to be vetted.
|
||||||
*
|
*
|
||||||
* A specific subset TypeScript compiler options that can be supported by
|
* A specific subset TypeScript compiler options that can be supported by
|
||||||
|
|
|
@ -23,6 +23,7 @@ import "./fetch_test.ts";
|
||||||
import "./file_test.ts";
|
import "./file_test.ts";
|
||||||
import "./files_test.ts";
|
import "./files_test.ts";
|
||||||
import "./form_data_test.ts";
|
import "./form_data_test.ts";
|
||||||
|
import "./format_error_test.ts";
|
||||||
import "./fs_events_test.ts";
|
import "./fs_events_test.ts";
|
||||||
import "./get_random_values_test.ts";
|
import "./get_random_values_test.ts";
|
||||||
import "./globals_test.ts";
|
import "./globals_test.ts";
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||||
use super::dispatch_json::{Deserialize, JsonOp, Value};
|
use super::dispatch_json::{Deserialize, JsonOp, Value};
|
||||||
|
use crate::diagnostics::Diagnostic;
|
||||||
use crate::fmt_errors::JSError;
|
use crate::fmt_errors::JSError;
|
||||||
use crate::op_error::OpError;
|
use crate::op_error::OpError;
|
||||||
use crate::ops::json_op;
|
use crate::ops::json_op;
|
||||||
|
@ -18,6 +19,10 @@ pub fn init(i: &mut Isolate, s: &State) {
|
||||||
"format_error",
|
"format_error",
|
||||||
s.core_op(json_op(s.stateful_op(op_format_error))),
|
s.core_op(json_op(s.stateful_op(op_format_error))),
|
||||||
);
|
);
|
||||||
|
i.register_op(
|
||||||
|
"format_diagnostic",
|
||||||
|
s.core_op(json_op(s.stateful_op(op_format_diagnostic))),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
@ -68,3 +73,15 @@ fn op_apply_source_map(
|
||||||
"column": orig_column as u32,
|
"column": orig_column as u32,
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn op_format_diagnostic(
|
||||||
|
_state: &State,
|
||||||
|
args: Value,
|
||||||
|
_zero_copy: Option<ZeroCopyBuf>,
|
||||||
|
) -> Result<JsonOp, OpError> {
|
||||||
|
if let Some(diagnostic) = Diagnostic::from_json_value(&args) {
|
||||||
|
Ok(JsonOp::Sync(json!(diagnostic.to_string())))
|
||||||
|
} else {
|
||||||
|
Err(OpError::type_error("bad diagnostic".to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue