diff --git a/cli/tests/integration/check_tests.rs b/cli/tests/integration/check_tests.rs
index 0f1c8cb590..1b00cadbee 100644
--- a/cli/tests/integration/check_tests.rs
+++ b/cli/tests/integration/check_tests.rs
@@ -105,6 +105,18 @@ itest!(check_broadcast_channel_unstable {
exit_code: 0,
});
+itest!(check_deno_not_found {
+ args: "check --quiet check/deno_not_found/main.ts",
+ output: "check/deno_not_found/main.out",
+ exit_code: 1,
+});
+
+itest!(check_deno_unstable_not_found {
+ args: "check --quiet check/deno_unstable_not_found/main.ts",
+ output: "check/deno_unstable_not_found/main.out",
+ exit_code: 1,
+});
+
#[test]
fn cache_switching_config_then_no_config() {
let context = TestContext::default();
diff --git a/cli/tests/testdata/check/deno_not_found/main.out b/cli/tests/testdata/check/deno_not_found/main.out
new file mode 100644
index 0000000000..39852ab952
--- /dev/null
+++ b/cli/tests/testdata/check/deno_not_found/main.out
@@ -0,0 +1,4 @@
+error: TS2304 [ERROR]: Cannot find name 'Deno'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'deno.ns' or add a triple-slash directive to your entrypoint: ///
+Deno;
+~~~~
+ at file:///[WILDCARD]/check/deno_not_found/main.ts:4:1
diff --git a/cli/tests/testdata/check/deno_not_found/main.ts b/cli/tests/testdata/check/deno_not_found/main.ts
new file mode 100644
index 0000000000..3269f047a7
--- /dev/null
+++ b/cli/tests/testdata/check/deno_not_found/main.ts
@@ -0,0 +1,4 @@
+///
+///
+
+Deno;
diff --git a/cli/tests/testdata/check/deno_unstable_not_found/main.out b/cli/tests/testdata/check/deno_unstable_not_found/main.out
new file mode 100644
index 0000000000..dfe3cf3174
--- /dev/null
+++ b/cli/tests/testdata/check/deno_unstable_not_found/main.out
@@ -0,0 +1,16 @@
+error: TS2551 [ERROR]: Property 'openKv' does not exist on type 'typeof Deno'. Did you mean 'open'? 'Deno.openKv' is an unstable API. Did you forget to run with the '--unstable' flag, or did you mean 'open'? If not, try changing the 'lib' compiler option to include 'deno.unstable' or add a triple-slash directive to your entrypoint: ///
+Deno.openKv;
+ ~~~~~~
+ at file:///[WILDCARD]/deno_unstable_not_found/main.ts:1:6
+
+ 'open' is declared here.
+ export function open(
+ ~~~~
+ at asset:///lib.deno.ns.d.ts:1667:19
+
+TS2339 [ERROR]: Property 'createHttpClient' does not exist on type 'typeof Deno'. 'Deno.createHttpClient' is an unstable API. Did you forget to run with the '--unstable' flag? If not, try changing the 'lib' compiler option to include 'deno.unstable' or add a triple-slash directive to your entrypoint: ///
+Deno.createHttpClient;
+ ~~~~~~~~~~~~~~~~
+ at file:///[WILDCARD]/deno_unstable_not_found/main.ts:2:6
+
+Found 2 errors.
diff --git a/cli/tests/testdata/check/deno_unstable_not_found/main.ts b/cli/tests/testdata/check/deno_unstable_not_found/main.ts
new file mode 100644
index 0000000000..6661bd205c
--- /dev/null
+++ b/cli/tests/testdata/check/deno_unstable_not_found/main.ts
@@ -0,0 +1,2 @@
+Deno.openKv;
+Deno.createHttpClient;
diff --git a/cli/tests/testdata/run/unstable_disabled.out b/cli/tests/testdata/run/unstable_disabled.out
index f3de913e62..fb8d3ee05c 100644
--- a/cli/tests/testdata/run/unstable_disabled.out
+++ b/cli/tests/testdata/run/unstable_disabled.out
@@ -1,5 +1,5 @@
[WILDCARD]
-error: TS2339 [ERROR]: Property 'umask' does not exist on type 'typeof Deno'. 'Deno.umask' is an unstable API. Did you forget to run with the '--unstable' flag?
+error: TS2339 [ERROR]: Property 'umask' does not exist on type 'typeof Deno'. 'Deno.umask' is an unstable API. Did you forget to run with the '--unstable' flag? If not, try changing the 'lib' compiler option to include 'deno.unstable' or add a triple-slash directive to your entrypoint: ///
console.log(Deno.umask);
~~~~~
at [WILDCARD]/unstable.ts:1:18
diff --git a/cli/tsc/99_main_compiler.js b/cli/tsc/99_main_compiler.js
index 56ac5522b0..2190dda994 100644
--- a/cli/tsc/99_main_compiler.js
+++ b/cli/tsc/99_main_compiler.js
@@ -29,6 +29,37 @@ delete Object.prototype.__proto__;
/** @type {Map} */
const normalizedToOriginalMap = new Map();
+ /** @type {ReadonlySet} */
+ const unstableDenoProps = new Set([
+ "AtomicOperation",
+ "CreateHttpClientOptions",
+ "DatagramConn",
+ "HttpClient",
+ "Kv",
+ "KvListIterator",
+ "KvU64",
+ "UnsafeCallback",
+ "UnsafePointer",
+ "UnsafePointerView",
+ "UnsafeFnPointer",
+ "UnixConnectOptions",
+ "UnixListenOptions",
+ "createHttpClient",
+ "dlopen",
+ "flock",
+ "flockSync",
+ "funlock",
+ "funlockSync",
+ "listen",
+ "listenDatagram",
+ "openKv",
+ "upgradeHttp",
+ "umask",
+ ]);
+ const unstableMsgSuggestion =
+ "If not, try changing the 'lib' compiler option to include 'deno.unstable' " +
+ 'or add a triple-slash directive to your entrypoint: /// ';
+
/**
* @param {unknown} value
* @returns {value is ts.CreateSourceFileOptions}
@@ -303,6 +334,49 @@ delete Object.prototype.__proto__;
return isNodeSourceFile;
});
+ /**
+ * @param msg {string}
+ * @param code {number}
+ */
+ function formatMessage(msg, code) {
+ switch (code) {
+ case 2304: {
+ if (msg === "Cannot find name 'Deno'.") {
+ msg += " Do you need to change your target library? " +
+ "Try changing the 'lib' compiler option to include 'deno.ns' " +
+ 'or add a triple-slash directive to your entrypoint: /// ';
+ }
+ return msg;
+ }
+ case 2339: {
+ const property = getProperty();
+ if (property && unstableDenoProps.has(property)) {
+ return `${msg} 'Deno.${property}' is an unstable API. Did you forget to run with the '--unstable' flag? ${unstableMsgSuggestion}`;
+ }
+ return msg;
+ }
+ default: {
+ const property = getProperty();
+ if (property && unstableDenoProps.has(property)) {
+ const suggestion = getMsgSuggestion();
+ if (suggestion) {
+ return `${msg} 'Deno.${property}' is an unstable API. Did you forget to run with the '--unstable' flag, or did you mean '${suggestion}'? ${unstableMsgSuggestion}`;
+ }
+ }
+ return msg;
+ }
+ }
+
+ function getProperty() {
+ return /Property '([^']+)' does not exist on type 'typeof Deno'/
+ .exec(msg)?.[1];
+ }
+
+ function getMsgSuggestion() {
+ return / Did you mean '([^']+)'\?/.exec(msg)?.[1];
+ }
+ }
+
/** @param {ts.DiagnosticRelatedInformation} diagnostic */
function fromRelatedInformation({
start,
@@ -316,7 +390,7 @@ delete Object.prototype.__proto__;
if (typeof msgText === "object") {
messageChain = msgText;
} else {
- messageText = msgText;
+ messageText = formatMessage(msgText, ri.code);
}
if (start !== undefined && length !== undefined && file) {
const startPos = file.getLineAndCharacterOfPosition(start);
@@ -341,7 +415,7 @@ delete Object.prototype.__proto__;
}
/** @param {readonly ts.Diagnostic[]} diagnostics */
- function fromTypeScriptDiagnostic(diagnostics) {
+ function fromTypeScriptDiagnostics(diagnostics) {
return diagnostics.map(({ relatedInformation: ri, source, ...diag }) => {
/** @type {any} */
const value = fromRelatedInformation(diag);
@@ -864,7 +938,7 @@ delete Object.prototype.__proto__;
performanceProgram({ program });
ops.op_respond({
- diagnostics: fromTypeScriptDiagnostic(diagnostics),
+ diagnostics: fromTypeScriptDiagnostics(diagnostics),
stats: performanceEnd(),
});
debug("<<< exec stop");
@@ -1055,7 +1129,7 @@ delete Object.prototype.__proto__;
/** @type {Record} */
const diagnosticMap = {};
for (const specifier of request.specifiers) {
- diagnosticMap[specifier] = fromTypeScriptDiagnostic([
+ diagnosticMap[specifier] = fromTypeScriptDiagnostics([
...languageService.getSemanticDiagnostics(specifier),
...languageService.getSuggestionDiagnostics(specifier),
...languageService.getSyntacticDiagnostics(specifier),
diff --git a/cli/tsc/diagnostics.rs b/cli/tsc/diagnostics.rs
index edddb0f6f8..08fa3e8dab 100644
--- a/cli/tsc/diagnostics.rs
+++ b/cli/tsc/diagnostics.rs
@@ -6,71 +6,11 @@ use deno_core::serde::Deserialize;
use deno_core::serde::Deserializer;
use deno_core::serde::Serialize;
use deno_core::serde::Serializer;
-use lazy_regex::lazy_regex;
-use once_cell::sync::Lazy;
-use regex::Regex;
use std::error::Error;
use std::fmt;
const MAX_SOURCE_LINE_LENGTH: usize = 150;
-const UNSTABLE_DENO_PROPS: &[&str] = &[
- "CreateHttpClientOptions",
- "DatagramConn",
- "HttpClient",
- "UnixConnectOptions",
- "UnixListenOptions",
- "connect",
- "createHttpClient",
- "listen",
- "listenDatagram",
- "dlopen",
- "removeSignalListener",
- "shutdown",
- "umask",
-];
-
-static MSG_MISSING_PROPERTY_DENO: Lazy =
- lazy_regex!(r#"Property '([^']+)' does not exist on type 'typeof Deno'"#);
-
-static MSG_SUGGESTION: Lazy =
- lazy_regex!(r#" Did you mean '([^']+)'\?"#);
-
-/// Potentially convert a "raw" diagnostic message from TSC to something that
-/// provides a more sensible error message given a Deno runtime context.
-fn format_message(msg: &str, code: &u64) -> String {
- match code {
- 2339 => {
- if let Some(captures) = MSG_MISSING_PROPERTY_DENO.captures(msg) {
- if let Some(property) = captures.get(1) {
- if UNSTABLE_DENO_PROPS.contains(&property.as_str()) {
- return format!("{} 'Deno.{}' is an unstable API. Did you forget to run with the '--unstable' flag?", msg, property.as_str());
- }
- }
- }
-
- msg.to_string()
- }
- 2551 => {
- if let (Some(caps_property), Some(caps_suggestion)) = (
- MSG_MISSING_PROPERTY_DENO.captures(msg),
- MSG_SUGGESTION.captures(msg),
- ) {
- if let (Some(property), Some(suggestion)) =
- (caps_property.get(1), caps_suggestion.get(1))
- {
- if UNSTABLE_DENO_PROPS.contains(&property.as_str()) {
- return format!("{} 'Deno.{}' is an unstable API. Did you forget to run with the '--unstable' flag, or did you mean '{}'?", MSG_SUGGESTION.replace(msg, ""), property.as_str(), suggestion.as_str());
- }
- }
- }
-
- msg.to_string()
- }
- _ => msg.to_string(),
- }
-}
-
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum DiagnosticCategory {
Warning,
@@ -227,7 +167,7 @@ impl Diagnostic {
f,
"{:indent$}{}",
"",
- format_message(&self.message_text.clone().unwrap(), &self.code),
+ self.message_text.as_deref().unwrap_or_default(),
indent = level,
)
}
diff --git a/runtime/js/90_deno_ns.js b/runtime/js/90_deno_ns.js
index ffa4bf5296..00c6d6b475 100644
--- a/runtime/js/90_deno_ns.js
+++ b/runtime/js/90_deno_ns.js
@@ -152,6 +152,7 @@ const denoNs = {
ChildProcess: process.ChildProcess,
};
+// when editing this list, also update unstableDenoProps in cli/tsc/99_main_compiler.js
const denoNsUnstable = {
listenDatagram: net.createListenDatagram(
ops.op_net_listen_udp,