summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKitson Kelly <me@kitsonkelly.com>2021-06-22 07:27:32 +1000
committerGitHub <noreply@github.com>2021-06-22 07:27:32 +1000
commita5eb2dfc93afc2899ed6e1ad2b3e029157889f7c (patch)
tree5fb4abf918304fa13e961cc791c7b43b26367d7c
parent281c4cd8fcf5fd54f558a6922736def2c7804529 (diff)
fix(#10761): graph errors reported as diagnostics for `Deno.emit()` (#10767)
Fixes #10761
-rw-r--r--cli/diagnostics.rs33
-rw-r--r--cli/module_graph.rs12
-rw-r--r--cli/ops/runtime_compiler.rs4
-rw-r--r--cli/tests/compiler_api_test.ts46
4 files changed, 88 insertions, 7 deletions
diff --git a/cli/diagnostics.rs b/cli/diagnostics.rs
index b7327d72c..695330af3 100644
--- a/cli/diagnostics.rs
+++ b/cli/diagnostics.rs
@@ -6,7 +6,9 @@ use deno_core::serde::Deserialize;
use deno_core::serde::Deserializer;
use deno_core::serde::Serialize;
use deno_core::serde::Serializer;
+use deno_core::ModuleSpecifier;
use regex::Regex;
+use std::collections::HashMap;
use std::error::Error;
use std::fmt;
@@ -233,13 +235,14 @@ impl Diagnostic {
_ => "",
};
+ let code = if self.code >= 900001 {
+ "".to_string()
+ } else {
+ colors::bold(format!("TS{} ", self.code)).to_string()
+ };
+
if !category.is_empty() {
- write!(
- f,
- "{} [{}]: ",
- colors::bold(&format!("TS{}", self.code)),
- category
- )
+ write!(f, "{}[{}]: ", code, category)
} else {
Ok(())
}
@@ -359,6 +362,24 @@ impl Diagnostics {
Diagnostics(diagnostics)
}
+ pub fn extend_graph_errors(
+ &mut self,
+ errors: HashMap<ModuleSpecifier, String>,
+ ) {
+ self.0.extend(errors.into_iter().map(|(s, e)| Diagnostic {
+ category: DiagnosticCategory::Error,
+ code: 900001,
+ start: None,
+ end: None,
+ message_text: Some(e),
+ message_chain: None,
+ source: None,
+ source_line: None,
+ file_name: Some(s.to_string()),
+ related_information: None,
+ }));
+ }
+
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
diff --git a/cli/module_graph.rs b/cli/module_graph.rs
index 8ea8b7f88..e56f26c15 100644
--- a/cli/module_graph.rs
+++ b/cli/module_graph.rs
@@ -1273,6 +1273,18 @@ impl Graph {
Ok(())
}
+ /// Retrieve the first module loading error from the graph and return it.
+ pub fn get_errors(&self) -> HashMap<ModuleSpecifier, String> {
+ self
+ .modules
+ .iter()
+ .filter_map(|(s, sl)| match sl {
+ ModuleSlot::Err(err) => Some((s.clone(), err.to_string())),
+ _ => None,
+ })
+ .collect()
+ }
+
/// Retrieve a map that contains a representation of each module in the graph
/// which can be used to provide code to a module loader without holding all
/// the state to be able to operate on the graph.
diff --git a/cli/ops/runtime_compiler.rs b/cli/ops/runtime_compiler.rs
index 099f2d555..dd500077a 100644
--- a/cli/ops/runtime_compiler.rs
+++ b/cli/ops/runtime_compiler.rs
@@ -118,12 +118,14 @@ async fn op_emit(
};
let graph = builder.get_graph();
let debug = program_state.flags.log_level == Some(log::Level::Debug);
- let (files, result_info) = graph.emit(EmitOptions {
+ let graph_errors = graph.get_errors();
+ let (files, mut result_info) = graph.emit(EmitOptions {
bundle_type,
check: args.check.unwrap_or(true),
debug,
maybe_user_config: args.compiler_options,
})?;
+ result_info.diagnostics.extend_graph_errors(graph_errors);
Ok(json!({
"diagnostics": result_info.diagnostics,
diff --git a/cli/tests/compiler_api_test.ts b/cli/tests/compiler_api_test.ts
index b9a08d5ca..2e0a8820c 100644
--- a/cli/tests/compiler_api_test.ts
+++ b/cli/tests/compiler_api_test.ts
@@ -456,3 +456,49 @@ Deno.test({
assert(files["deno:///bundle.js.map"]);
},
});
+
+Deno.test({
+ name: `Deno.emit() - graph errors as diagnostics`,
+ ignore: Deno.build.os === "windows",
+ async fn() {
+ const { diagnostics } = await Deno.emit("/a.ts", {
+ sources: {
+ "/a.ts": `import { b } from "./b.ts";
+ console.log(b);`,
+ },
+ });
+ assert(diagnostics);
+ assertEquals(diagnostics, [
+ {
+ category: 1,
+ code: 2305,
+ start: { line: 0, character: 9 },
+ end: { line: 0, character: 10 },
+ messageText:
+ `Module '"deno:///missing_dependency.d.ts"' has no exported member 'b'.`,
+ messageChain: null,
+ source: null,
+ sourceLine: 'import { b } from "./b.ts";',
+ fileName: "file:///a.ts",
+ relatedInformation: null,
+ },
+ {
+ category: 1,
+ code: 900001,
+ start: null,
+ end: null,
+ messageText: "Unable to find specifier in sources: file:///b.ts",
+ messageChain: null,
+ source: null,
+ sourceLine: null,
+ fileName: "file:///b.ts",
+ relatedInformation: null,
+ },
+ ]);
+ assert(
+ Deno.formatDiagnostics(diagnostics).includes(
+ "Unable to find specifier in sources: file:///b.ts",
+ ),
+ );
+ },
+});