summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2023-04-01 10:04:56 -0400
committerGitHub <noreply@github.com>2023-04-01 10:04:56 -0400
commit23b9be7b37c40f8c29f9ce50439ad0e25b85282c (patch)
treef2bea2e8daf5c02113e036fe72010bbc3fb61ff4 /cli
parentc162647020c26de1d27064b488ca11525f1bc4bf (diff)
fix(check): ensure diagnostics caused by changes in other files get invalidated between runs (#18541)
Regression caused by the performance improvement in #18329. Figuring this out was hard. It's luckily still fast after this change. Closes #18516
Diffstat (limited to 'cli')
-rw-r--r--cli/tests/integration/check_tests.rs77
-rw-r--r--cli/tsc/99_main_compiler.js17
2 files changed, 63 insertions, 31 deletions
diff --git a/cli/tests/integration/check_tests.rs b/cli/tests/integration/check_tests.rs
index 7e6fbd836..84ddd53be 100644
--- a/cli/tests/integration/check_tests.rs
+++ b/cli/tests/integration/check_tests.rs
@@ -1,10 +1,10 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-use std::process::Command;
use test_util as util;
use util::env_vars_for_npm_tests;
use util::env_vars_for_npm_tests_no_sync_download;
use util::TestContext;
+use util::TestContextBuilder;
itest!(_095_check_with_bare_import {
args: "check cache/095_cache_with_bare_import.ts",
@@ -214,36 +214,20 @@ fn typecheck_core() {
#[test]
fn ts_no_recheck_on_redirect() {
- // TODO: port to test builder
- let deno_dir = util::new_deno_dir();
- let e = util::deno_exe_path();
-
- let redirect_ts = util::testdata_path().join("run/017_import_redirect.ts");
- assert!(redirect_ts.is_file());
- let mut cmd = Command::new(e.clone());
- cmd.env("DENO_DIR", deno_dir.path());
- let mut initial = cmd
- .current_dir(util::testdata_path())
- .arg("run")
- .arg("--check")
- .arg(redirect_ts.clone())
- .spawn()
- .expect("failed to span script");
- let status_initial =
- initial.wait().expect("failed to wait for child process");
- assert!(status_initial.success());
-
- let mut cmd = Command::new(e);
- cmd.env("DENO_DIR", deno_dir.path());
- let output = cmd
- .current_dir(util::testdata_path())
- .arg("run")
- .arg("--check")
- .arg(redirect_ts)
- .output()
- .expect("failed to spawn script");
-
- assert!(std::str::from_utf8(&output.stderr).unwrap().is_empty());
+ let test_context = TestContext::default();
+ let check_command = test_context.new_command().args_vec([
+ "run",
+ "--check",
+ "run/017_import_redirect.ts",
+ ]);
+
+ // run once
+ let output = check_command.run();
+ output.assert_matches_text("[WILDCARD]Check file://[WILDCARD]");
+
+ // run again
+ let output = check_command.run();
+ output.assert_matches_text("Hello\n");
}
itest!(check_dts {
@@ -288,3 +272,34 @@ itest!(package_json_with_deno_json {
http_server: true,
exit_code: 1,
});
+
+#[test]
+fn check_error_in_dep_then_fix() {
+ let test_context = TestContextBuilder::new().use_temp_cwd().build();
+ let temp_dir = test_context.temp_dir();
+ let correct_code =
+ "export function greet(name: string) {\n return `Hello ${name}`;\n}\n";
+ let incorrect_code =
+ "export function greet(name: number) {\n return `Hello ${name}`;\n}\n";
+
+ temp_dir.write(
+ "main.ts",
+ "import { greet } from './greet.ts';\n\nconsole.log(greet('world'));\n",
+ );
+ temp_dir.write("greet.ts", incorrect_code);
+
+ let check_command = test_context.new_command().args_vec(["check", "main.ts"]);
+
+ let output = check_command.run();
+ output.assert_matches_text("Check [WILDCARD]main.ts\nerror: TS234[WILDCARD]");
+ output.assert_exit_code(1);
+
+ temp_dir.write("greet.ts", correct_code);
+ let output = check_command.run();
+ output.assert_matches_text("Check [WILDCARD]main.ts\n");
+
+ temp_dir.write("greet.ts", incorrect_code);
+ let output = check_command.run();
+ output.assert_matches_text("Check [WILDCARD]main.ts\nerror: TS234[WILDCARD]");
+ output.assert_exit_code(1);
+}
diff --git a/cli/tsc/99_main_compiler.js b/cli/tsc/99_main_compiler.js
index b8189278c..2f565770c 100644
--- a/cli/tsc/99_main_compiler.js
+++ b/cli/tsc/99_main_compiler.js
@@ -824,6 +824,23 @@ delete Object.prototype.__proto__;
return sourceFile;
})
: undefined;
+
+ if (checkFiles != null) {
+ // When calling program.getSemanticDiagnostics(...) with a source file, we
+ // need to call this code first in order to get it to invalidate cached
+ // diagnostics correctly. This is what program.getSemanticDiagnostics()
+ // does internally when calling without any arguments.
+ const checkFileNames = new Set(checkFiles.map((f) => f.fileName));
+ while (
+ program.getSemanticDiagnosticsOfNextAffectedFile(
+ undefined,
+ /* ignoreSourceFile */ (s) => !checkFileNames.has(s.fileName),
+ )
+ ) {
+ // keep going until there are no more affected files
+ }
+ }
+
const diagnostics = [
...program.getConfigFileParsingDiagnostics(),
...(checkFiles == null