diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2023-04-01 10:04:56 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-01 10:04:56 -0400 |
commit | 23b9be7b37c40f8c29f9ce50439ad0e25b85282c (patch) | |
tree | f2bea2e8daf5c02113e036fe72010bbc3fb61ff4 /cli | |
parent | c162647020c26de1d27064b488ca11525f1bc4bf (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.rs | 77 | ||||
-rw-r--r-- | cli/tsc/99_main_compiler.js | 17 |
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 |