0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-02-01 12:16:11 -05:00

fix(check): compiler options from workspace members (#27785)

Co-authored-by: Nayeem Rahman <nayeemrmn99@gmail.com>
This commit is contained in:
David Sherret 2025-01-28 10:49:58 -05:00 committed by GitHub
parent 9931fb5cad
commit 4648fc4570
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
163 changed files with 1681 additions and 716 deletions

8
Cargo.lock generated
View file

@ -1514,9 +1514,9 @@ dependencies = [
[[package]]
name = "deno_config"
version = "0.45.0"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47a47412627aa0d08414eca0e8329128013ab70bdb2cdfdc5456c2214cf24c8f"
checksum = "08fe512a72c4300bd997c6849450a1f050da0c909a2a4fbdc44891647392bacf"
dependencies = [
"boxed_error",
"capacity_builder 0.5.0",
@ -1782,9 +1782,9 @@ dependencies = [
[[package]]
name = "deno_graph"
version = "0.87.0"
version = "0.87.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f56d4eb4b7c81ae920b6d18c45a1866924f93110caee80bbbc362dc28143f2bb"
checksum = "e4766f426e4258c481c3af019fb4bba31e3108e80b8b2a48bbeb68bfadcc8c18"
dependencies = [
"async-trait",
"capacity_builder 0.5.0",

View file

@ -54,7 +54,7 @@ deno_ast = { version = "=0.44.0", features = ["transpiling"] }
deno_core = { version = "0.333.0" }
deno_bench_util = { version = "0.181.0", path = "./bench_util" }
deno_config = { version = "=0.45.0", features = ["workspace"] }
deno_config = { version = "=0.46.0", features = ["workspace"] }
deno_lockfile = "=0.24.0"
deno_media_type = { version = "=0.2.5", features = ["module_specifier"] }
deno_npm = "=0.27.2"

View file

@ -72,7 +72,7 @@ deno_config = { workspace = true, features = ["sync", "workspace"] }
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
deno_doc = { version = "=0.164.0", features = ["rust", "comrak"] }
deno_error.workspace = true
deno_graph = { version = "=0.87.0" }
deno_graph = { version = "=0.87.2" }
deno_lib.workspace = true
deno_lint = { version = "0.70.0" }
deno_lockfile.workspace = true

View file

@ -1,12 +1,28 @@
// Copyright 2018-2025 the Deno authors. MIT license.
use std::collections::HashSet;
use std::sync::Arc;
use deno_config::deno_json::TsConfigForEmit;
use deno_ast::SourceMapOption;
use deno_config::deno_json::CompilerOptionsParseError;
use deno_config::deno_json::TsConfig;
use deno_config::deno_json::TsConfigType;
use deno_config::deno_json::TsConfigWithIgnoredOptions;
use deno_config::deno_json::TsTypeLib;
use deno_config::workspace::Workspace;
use deno_config::workspace::WorkspaceDirectory;
use deno_core::error::AnyError;
use deno_core::serde_json;
use deno_core::unsync::sync::AtomicFlag;
use deno_core::url::Url;
use deno_lib::util::hash::FastInsecureHasher;
use deno_lint::linter::LintConfig as DenoLintConfig;
use deno_semver::jsr::JsrDepPackageReq;
use deno_semver::jsr::JsrPackageReqReference;
use deno_semver::npm::NpmPackageReqReference;
use once_cell::sync::OnceCell;
use crate::util::collections::FolderScopedMap;
pub fn import_map_deps(
import_map: &serde_json::Value,
@ -102,17 +118,261 @@ fn value_to_dep_req(value: &str) -> Option<JsrDepPackageReq> {
}
}
pub fn check_warn_tsconfig(ts_config: &TsConfigForEmit) {
if let Some(ignored_options) = &ts_config.maybe_ignored_options {
log::warn!("{}", ignored_options);
fn check_warn_tsconfig(
ts_config: &TsConfigWithIgnoredOptions,
logged_warnings: &LoggedWarnings,
) {
for ignored_options in &ts_config.ignored_options {
if ignored_options
.maybe_specifier
.as_ref()
.map(|s| logged_warnings.folders.insert(s.clone()))
.unwrap_or(true)
{
log::warn!("{}", ignored_options);
}
}
let serde_json::Value::Object(obj) = &ts_config.ts_config.0 else {
return;
};
if obj.get("experimentalDecorators") == Some(&serde_json::Value::Bool(true)) {
if obj.get("experimentalDecorators") == Some(&serde_json::Value::Bool(true))
&& logged_warnings.experimental_decorators.raise()
{
log::warn!(
"{} experimentalDecorators compiler option is deprecated and may be removed at any time",
deno_runtime::colors::yellow("Warning"),
);
"{} experimentalDecorators compiler option is deprecated and may be removed at any time",
deno_runtime::colors::yellow("Warning"),
);
}
}
#[derive(Debug)]
pub struct TranspileAndEmitOptions {
pub transpile: deno_ast::TranspileOptions,
pub emit: deno_ast::EmitOptions,
// stored ahead of time so we don't have to recompute this a lot
pub pre_computed_hash: u64,
}
#[derive(Debug, Default)]
struct LoggedWarnings {
experimental_decorators: AtomicFlag,
folders: dashmap::DashSet<Url>,
}
#[derive(Default, Debug)]
struct MemoizedValues {
deno_window_check_tsconfig: OnceCell<Arc<TsConfig>>,
deno_worker_check_tsconfig: OnceCell<Arc<TsConfig>>,
emit_tsconfig: OnceCell<Arc<TsConfig>>,
transpile_options: OnceCell<Arc<TranspileAndEmitOptions>>,
}
#[derive(Debug)]
pub struct TsConfigFolderInfo {
pub dir: WorkspaceDirectory,
logged_warnings: Arc<LoggedWarnings>,
memoized: MemoizedValues,
}
impl TsConfigFolderInfo {
pub fn lib_tsconfig(
&self,
lib: TsTypeLib,
) -> Result<&Arc<TsConfig>, CompilerOptionsParseError> {
let cell = match lib {
TsTypeLib::DenoWindow => &self.memoized.deno_window_check_tsconfig,
TsTypeLib::DenoWorker => &self.memoized.deno_worker_check_tsconfig,
};
cell.get_or_try_init(|| {
let tsconfig_result = self
.dir
.to_resolved_ts_config(TsConfigType::Check { lib })?;
check_warn_tsconfig(&tsconfig_result, &self.logged_warnings);
Ok(Arc::new(tsconfig_result.ts_config))
})
}
pub fn emit_tsconfig(
&self,
) -> Result<&Arc<TsConfig>, CompilerOptionsParseError> {
self.memoized.emit_tsconfig.get_or_try_init(|| {
let tsconfig_result =
self.dir.to_resolved_ts_config(TsConfigType::Emit)?;
check_warn_tsconfig(&tsconfig_result, &self.logged_warnings);
Ok(Arc::new(tsconfig_result.ts_config))
})
}
pub fn transpile_options(
&self,
) -> Result<&Arc<TranspileAndEmitOptions>, CompilerOptionsParseError> {
self.memoized.transpile_options.get_or_try_init(|| {
let ts_config = self.emit_tsconfig()?;
ts_config_to_transpile_and_emit_options(ts_config.as_ref().clone())
.map(Arc::new)
.map_err(|source| CompilerOptionsParseError {
specifier: self
.dir
.maybe_deno_json()
.map(|d| d.specifier.clone())
.unwrap_or_else(|| {
// will never happen because each dir should have a
// deno.json if we got here
debug_assert!(false);
self.dir.dir_url().as_ref().clone()
}),
source,
})
})
}
}
#[derive(Debug)]
pub struct TsConfigResolver {
map: FolderScopedMap<TsConfigFolderInfo>,
}
impl TsConfigResolver {
pub fn from_workspace(workspace: &Arc<Workspace>) -> Self {
// separate the workspace into directories that have a tsconfig
let root_dir = workspace.resolve_member_dir(workspace.root_dir());
let logged_warnings = Arc::new(LoggedWarnings::default());
let mut map = FolderScopedMap::new(TsConfigFolderInfo {
dir: root_dir,
logged_warnings: logged_warnings.clone(),
memoized: Default::default(),
});
for (url, folder) in workspace.config_folders() {
let folder_has_compiler_options = folder
.deno_json
.as_ref()
.map(|d| d.json.compiler_options.is_some())
.unwrap_or(false);
if url != workspace.root_dir() && folder_has_compiler_options {
let dir = workspace.resolve_member_dir(url);
map.insert(
url.clone(),
TsConfigFolderInfo {
dir,
logged_warnings: logged_warnings.clone(),
memoized: Default::default(),
},
);
}
}
Self { map }
}
pub fn check_js_for_specifier(&self, specifier: &Url) -> bool {
self.folder_for_specifier(specifier).dir.check_js()
}
pub fn deno_lint_config(
&self,
specifier: &Url,
) -> Result<DenoLintConfig, AnyError> {
let transpile_options =
&self.transpile_and_emit_options(specifier)?.transpile;
// don't bother storing this in a cell because deno_lint requires an owned value
Ok(DenoLintConfig {
default_jsx_factory: (!transpile_options.jsx_automatic)
.then(|| transpile_options.jsx_factory.clone()),
default_jsx_fragment_factory: (!transpile_options.jsx_automatic)
.then(|| transpile_options.jsx_fragment_factory.clone()),
})
}
pub fn transpile_and_emit_options(
&self,
specifier: &Url,
) -> Result<&Arc<TranspileAndEmitOptions>, CompilerOptionsParseError> {
let value = self.map.get_for_specifier(specifier);
value.transpile_options()
}
pub fn folder_for_specifier(&self, specifier: &Url) -> &TsConfigFolderInfo {
self.folder_for_specifier_str(specifier.as_str())
}
pub fn folder_for_specifier_str(
&self,
specifier: &str,
) -> &TsConfigFolderInfo {
self.map.get_for_specifier_str(specifier)
}
pub fn folder_count(&self) -> usize {
self.map.count()
}
}
impl deno_graph::CheckJsResolver for TsConfigResolver {
fn resolve(&self, specifier: &deno_graph::ModuleSpecifier) -> bool {
self.check_js_for_specifier(specifier)
}
}
fn ts_config_to_transpile_and_emit_options(
config: deno_config::deno_json::TsConfig,
) -> Result<TranspileAndEmitOptions, serde_json::Error> {
let options: deno_config::deno_json::EmitConfigOptions =
serde_json::from_value(config.0)?;
let imports_not_used_as_values =
match options.imports_not_used_as_values.as_str() {
"preserve" => deno_ast::ImportsNotUsedAsValues::Preserve,
"error" => deno_ast::ImportsNotUsedAsValues::Error,
_ => deno_ast::ImportsNotUsedAsValues::Remove,
};
let (transform_jsx, jsx_automatic, jsx_development, precompile_jsx) =
match options.jsx.as_str() {
"react" => (true, false, false, false),
"react-jsx" => (true, true, false, false),
"react-jsxdev" => (true, true, true, false),
"precompile" => (false, false, false, true),
_ => (false, false, false, false),
};
let source_map = if options.inline_source_map {
SourceMapOption::Inline
} else if options.source_map {
SourceMapOption::Separate
} else {
SourceMapOption::None
};
let transpile = deno_ast::TranspileOptions {
use_ts_decorators: options.experimental_decorators,
use_decorators_proposal: !options.experimental_decorators,
emit_metadata: options.emit_decorator_metadata,
imports_not_used_as_values,
jsx_automatic,
jsx_development,
jsx_factory: options.jsx_factory,
jsx_fragment_factory: options.jsx_fragment_factory,
jsx_import_source: options.jsx_import_source,
precompile_jsx,
precompile_jsx_skip_elements: options.jsx_precompile_skip_elements,
precompile_jsx_dynamic_props: None,
transform_jsx,
var_decl_imports: false,
// todo(dsherret): support verbatim_module_syntax here properly
verbatim_module_syntax: false,
};
let emit = deno_ast::EmitOptions {
inline_sources: options.inline_sources,
remove_comments: false,
source_map,
source_map_base: None,
source_map_file: None,
};
let transpile_and_emit_options_hash = {
let mut hasher = FastInsecureHasher::new_without_deno_version();
hasher.write_hashable(&transpile);
hasher.write_hashable(&emit);
hasher.finish()
};
Ok(TranspileAndEmitOptions {
transpile,
emit,
pre_computed_hash: transpile_and_emit_options_hash,
})
}

View file

@ -17,11 +17,9 @@ use std::sync::Arc;
use deno_ast::MediaType;
use deno_ast::ModuleSpecifier;
use deno_ast::SourceMapOption;
use deno_cache_dir::file_fetcher::CacheSetting;
pub use deno_config::deno_json::BenchConfig;
pub use deno_config::deno_json::ConfigFile;
use deno_config::deno_json::ConfigFileError;
use deno_config::deno_json::FmtConfig;
pub use deno_config::deno_json::FmtOptionsConfig;
use deno_config::deno_json::LintConfig;
@ -30,8 +28,6 @@ use deno_config::deno_json::NodeModulesDirMode;
pub use deno_config::deno_json::ProseWrap;
use deno_config::deno_json::TestConfig;
pub use deno_config::deno_json::TsConfig;
pub use deno_config::deno_json::TsConfigForEmit;
pub use deno_config::deno_json::TsConfigType;
pub use deno_config::deno_json::TsTypeLib;
pub use deno_config::glob::FilePatterns;
use deno_config::workspace::Workspace;
@ -44,14 +40,12 @@ use deno_core::resolve_url_or_path;
use deno_core::serde_json;
use deno_core::url::Url;
use deno_graph::GraphKind;
pub use deno_json::check_warn_tsconfig;
use deno_lib::args::has_flag_env_var;
use deno_lib::args::npm_pkg_req_ref_to_binary_command;
use deno_lib::args::CaData;
use deno_lib::args::NPM_PROCESS_STATE;
use deno_lib::version::DENO_VERSION_INFO;
use deno_lib::worker::StorageKeyResolver;
use deno_lint::linter::LintConfig as DenoLintConfig;
use deno_npm::NpmSystemInfo;
use deno_runtime::deno_permissions::PermissionsOptions;
use deno_runtime::inspector_server::InspectorServer;
@ -114,62 +108,6 @@ pub fn jsr_api_url() -> &'static Url {
&JSR_API_URL
}
pub fn ts_config_to_transpile_and_emit_options(
config: deno_config::deno_json::TsConfig,
) -> Result<(deno_ast::TranspileOptions, deno_ast::EmitOptions), AnyError> {
let options: deno_config::deno_json::EmitConfigOptions =
serde_json::from_value(config.0)
.context("Failed to parse compilerOptions")?;
let imports_not_used_as_values =
match options.imports_not_used_as_values.as_str() {
"preserve" => deno_ast::ImportsNotUsedAsValues::Preserve,
"error" => deno_ast::ImportsNotUsedAsValues::Error,
_ => deno_ast::ImportsNotUsedAsValues::Remove,
};
let (transform_jsx, jsx_automatic, jsx_development, precompile_jsx) =
match options.jsx.as_str() {
"react" => (true, false, false, false),
"react-jsx" => (true, true, false, false),
"react-jsxdev" => (true, true, true, false),
"precompile" => (false, false, false, true),
_ => (false, false, false, false),
};
let source_map = if options.inline_source_map {
SourceMapOption::Inline
} else if options.source_map {
SourceMapOption::Separate
} else {
SourceMapOption::None
};
Ok((
deno_ast::TranspileOptions {
use_ts_decorators: options.experimental_decorators,
use_decorators_proposal: !options.experimental_decorators,
emit_metadata: options.emit_decorator_metadata,
imports_not_used_as_values,
jsx_automatic,
jsx_development,
jsx_factory: options.jsx_factory,
jsx_fragment_factory: options.jsx_fragment_factory,
jsx_import_source: options.jsx_import_source,
precompile_jsx,
precompile_jsx_skip_elements: options.jsx_precompile_skip_elements,
precompile_jsx_dynamic_props: None,
transform_jsx,
var_decl_imports: false,
// todo(dsherret): support verbatim_module_syntax here properly
verbatim_module_syntax: false,
},
deno_ast::EmitOptions {
inline_sources: options.inline_sources,
remove_comments: false,
source_map,
source_map_base: None,
source_map_file: None,
},
))
}
#[derive(Debug, Clone)]
pub struct ExternalImportMap {
pub path: PathBuf,
@ -751,13 +689,6 @@ impl CliOptions {
self.workspace().vendor_dir_path()
}
pub fn resolve_ts_config_for_emit(
&self,
config_type: TsConfigType,
) -> Result<TsConfigForEmit, ConfigFileError> {
self.workspace().resolve_ts_config_for_emit(config_type)
}
pub fn resolve_inspector_server(
&self,
) -> Result<Option<InspectorServer>, AnyError> {
@ -781,23 +712,6 @@ impl CliOptions {
self.maybe_lockfile.as_ref()
}
pub fn to_compiler_option_types(
&self,
) -> Result<Vec<deno_graph::ReferrerImports>, serde_json::Error> {
self
.workspace()
.to_compiler_option_types()
.map(|maybe_imports| {
maybe_imports
.into_iter()
.map(|(referrer, imports)| deno_graph::ReferrerImports {
referrer,
imports,
})
.collect()
})
}
pub fn resolve_fmt_options_for_members(
&self,
fmt_flags: &FmtFlags,
@ -849,23 +763,6 @@ impl CliOptions {
Ok(result)
}
pub fn resolve_deno_lint_config(&self) -> Result<DenoLintConfig, AnyError> {
let ts_config_result =
self.resolve_ts_config_for_emit(TsConfigType::Emit)?;
let (transpile_options, _) =
crate::args::ts_config_to_transpile_and_emit_options(
ts_config_result.ts_config,
)?;
Ok(DenoLintConfig {
default_jsx_factory: (!transpile_options.jsx_automatic)
.then_some(transpile_options.jsx_factory),
default_jsx_fragment_factory: (!transpile_options.jsx_automatic)
.then_some(transpile_options.jsx_fragment_factory),
})
}
pub fn resolve_workspace_test_options(
&self,
test_flags: &TestFlags,
@ -927,10 +824,6 @@ impl CliOptions {
&self.flags.ca_stores
}
pub fn check_js(&self) -> bool {
self.workspace().check_js()
}
pub fn coverage_dir(&self) -> Option<String> {
match &self.flags.subcommand {
DenoSubcommand::Test(test) => test

View file

@ -22,6 +22,8 @@ use deno_graph::Module;
use deno_graph::ModuleGraph;
use deno_lib::util::hash::FastInsecureHasher;
use crate::args::deno_json::TranspileAndEmitOptions;
use crate::args::deno_json::TsConfigResolver;
use crate::cache::EmitCache;
use crate::cache::ParsedSourceCache;
use crate::resolver::CliCjsTracker;
@ -31,10 +33,7 @@ pub struct Emitter {
cjs_tracker: Arc<CliCjsTracker>,
emit_cache: Arc<EmitCache>,
parsed_source_cache: Arc<ParsedSourceCache>,
transpile_and_emit_options:
Arc<(deno_ast::TranspileOptions, deno_ast::EmitOptions)>,
// cached hash of the transpile and emit options
transpile_and_emit_options_hash: u64,
tsconfig_resolver: Arc<TsConfigResolver>,
}
impl Emitter {
@ -42,21 +41,13 @@ impl Emitter {
cjs_tracker: Arc<CliCjsTracker>,
emit_cache: Arc<EmitCache>,
parsed_source_cache: Arc<ParsedSourceCache>,
transpile_options: deno_ast::TranspileOptions,
emit_options: deno_ast::EmitOptions,
tsconfig_resolver: Arc<TsConfigResolver>,
) -> Self {
let transpile_and_emit_options_hash = {
let mut hasher = FastInsecureHasher::new_without_deno_version();
hasher.write_hashable(&transpile_options);
hasher.write_hashable(&emit_options);
hasher.finish()
};
Self {
cjs_tracker,
emit_cache,
parsed_source_cache,
transpile_and_emit_options: Arc::new((transpile_options, emit_options)),
transpile_and_emit_options_hash,
tsconfig_resolver,
}
}
@ -103,9 +94,13 @@ impl Emitter {
specifier: &ModuleSpecifier,
module_kind: deno_ast::ModuleKind,
source: &str,
) -> Option<String> {
let source_hash = self.get_source_hash(module_kind, source);
self.emit_cache.get_emit_code(specifier, source_hash)
) -> Result<Option<String>, AnyError> {
let transpile_and_emit_options = self
.tsconfig_resolver
.transpile_and_emit_options(specifier)?;
let source_hash =
self.get_source_hash(module_kind, transpile_and_emit_options, source);
Ok(self.emit_cache.get_emit_code(specifier, source_hash))
}
pub async fn emit_parsed_source(
@ -115,14 +110,21 @@ impl Emitter {
module_kind: ModuleKind,
source: &Arc<str>,
) -> Result<String, EmitParsedSourceHelperError> {
let transpile_and_emit_options = self
.tsconfig_resolver
.transpile_and_emit_options(specifier)?;
// Note: keep this in sync with the sync version below
let helper = EmitParsedSourceHelper(self);
match helper.pre_emit_parsed_source(specifier, module_kind, source) {
match helper.pre_emit_parsed_source(
specifier,
module_kind,
transpile_and_emit_options,
source,
) {
PreEmitResult::Cached(emitted_text) => Ok(emitted_text),
PreEmitResult::NotCached { source_hash } => {
let parsed_source_cache = self.parsed_source_cache.clone();
let transpile_and_emit_options =
self.transpile_and_emit_options.clone();
let transpile_and_emit_options = transpile_and_emit_options.clone();
let transpiled_source = deno_core::unsync::spawn_blocking({
let specifier = specifier.clone();
let source = source.clone();
@ -133,8 +135,8 @@ impl Emitter {
media_type,
module_kind,
source.clone(),
&transpile_and_emit_options.0,
&transpile_and_emit_options.1,
&transpile_and_emit_options.transpile,
&transpile_and_emit_options.emit,
)
.map(|r| r.text)
}
@ -158,9 +160,17 @@ impl Emitter {
module_kind: deno_ast::ModuleKind,
source: &Arc<str>,
) -> Result<String, EmitParsedSourceHelperError> {
let transpile_and_emit_options = self
.tsconfig_resolver
.transpile_and_emit_options(specifier)?;
// Note: keep this in sync with the async version above
let helper = EmitParsedSourceHelper(self);
match helper.pre_emit_parsed_source(specifier, module_kind, source) {
match helper.pre_emit_parsed_source(
specifier,
module_kind,
transpile_and_emit_options,
source,
) {
PreEmitResult::Cached(emitted_text) => Ok(emitted_text),
PreEmitResult::NotCached { source_hash } => {
let transpiled_source = EmitParsedSourceHelper::transpile(
@ -169,8 +179,8 @@ impl Emitter {
media_type,
module_kind,
source.clone(),
&self.transpile_and_emit_options.0,
&self.transpile_and_emit_options.1,
&transpile_and_emit_options.transpile,
&transpile_and_emit_options.emit,
)?
.text;
helper.post_emit_parsed_source(
@ -190,7 +200,10 @@ impl Emitter {
module_kind: deno_ast::ModuleKind,
source: &Arc<str>,
) -> Result<(String, String), AnyError> {
let mut emit_options = self.transpile_and_emit_options.1.clone();
let transpile_and_emit_options = self
.tsconfig_resolver
.transpile_and_emit_options(specifier)?;
let mut emit_options = transpile_and_emit_options.emit.clone();
emit_options.inline_sources = false;
emit_options.source_map = SourceMapOption::Separate;
// strip off the path to have more deterministic builds as we don't care
@ -202,7 +215,7 @@ impl Emitter {
media_type,
module_kind,
source.clone(),
&self.transpile_and_emit_options.0,
&transpile_and_emit_options.transpile,
&emit_options,
)?;
Ok((source.text, source.source_map.unwrap()))
@ -232,7 +245,11 @@ impl Emitter {
// HMR doesn't work with embedded source maps for some reason, so set
// the option to not use them (though you should test this out because
// this statement is probably wrong)
let mut options = self.transpile_and_emit_options.1.clone();
let transpile_and_emit_options = self
.tsconfig_resolver
.transpile_and_emit_options(specifier)
.map_err(JsErrorBox::from_err)?;
let mut options = transpile_and_emit_options.emit.clone();
options.source_map = SourceMapOption::None;
let is_cjs = self
.cjs_tracker
@ -244,7 +261,7 @@ impl Emitter {
.map_err(JsErrorBox::from_err)?;
let transpiled_source = parsed_source
.transpile(
&self.transpile_and_emit_options.0,
&transpile_and_emit_options.transpile,
&deno_ast::TranspileModuleOptions {
module_kind: Some(ModuleKind::from_is_cjs(is_cjs)),
},
@ -275,10 +292,15 @@ impl Emitter {
/// A hashing function that takes the source code and uses the global emit
/// options then generates a string hash which can be stored to
/// determine if the cached emit is valid or not.
fn get_source_hash(&self, module_kind: ModuleKind, source_text: &str) -> u64 {
fn get_source_hash(
&self,
module_kind: ModuleKind,
transpile_and_emit: &TranspileAndEmitOptions,
source_text: &str,
) -> u64 {
FastInsecureHasher::new_without_deno_version() // stored in the transpile_and_emit_options_hash
.write_str(source_text)
.write_u64(self.transpile_and_emit_options_hash)
.write_u64(transpile_and_emit.pre_computed_hash)
.write_hashable(module_kind)
.finish()
}
@ -291,6 +313,11 @@ enum PreEmitResult {
#[derive(Debug, thiserror::Error, deno_error::JsError)]
pub enum EmitParsedSourceHelperError {
#[class(inherit)]
#[error(transparent)]
CompilerOptionsParse(
#[from] deno_config::deno_json::CompilerOptionsParseError,
),
#[class(inherit)]
#[error(transparent)]
ParseDiagnostic(#[from] deno_ast::ParseDiagnostic),
@ -310,9 +337,13 @@ impl<'a> EmitParsedSourceHelper<'a> {
&self,
specifier: &ModuleSpecifier,
module_kind: deno_ast::ModuleKind,
transpile_and_emit_options: &TranspileAndEmitOptions,
source: &Arc<str>,
) -> PreEmitResult {
let source_hash = self.0.get_source_hash(module_kind, source);
let source_hash =
self
.0
.get_source_hash(module_kind, transpile_and_emit_options, source);
if let Some(emit_code) =
self.0.emit_cache.get_emit_code(specifier, source_hash)

View file

@ -7,6 +7,7 @@ use std::path::PathBuf;
use std::sync::Arc;
use deno_cache_dir::npm::NpmCacheDir;
use deno_config::workspace::Workspace;
use deno_config::workspace::WorkspaceDirectory;
use deno_config::workspace::WorkspaceResolver;
use deno_core::anyhow::Context;
@ -50,13 +51,12 @@ use node_resolver::analyze::NodeCodeTranslator;
use once_cell::sync::OnceCell;
use sys_traits::EnvCurrentDir;
use crate::args::check_warn_tsconfig;
use crate::args::deno_json::TsConfigResolver;
use crate::args::CliOptions;
use crate::args::ConfigFlag;
use crate::args::DenoSubcommand;
use crate::args::Flags;
use crate::args::NpmInstallDepsProvider;
use crate::args::TsConfigType;
use crate::args::WorkspaceExternalImportMapLoader;
use crate::cache::Caches;
use crate::cache::CodeCache;
@ -296,6 +296,7 @@ struct CliFactoryServices {
root_cert_store_provider: Deferred<Arc<dyn RootCertStoreProvider>>,
root_permissions_container: Deferred<PermissionsContainer>,
text_only_progress_bar: Deferred<ProgressBar>,
tsconfig_resolver: Deferred<Arc<TsConfigResolver>>,
type_checker: Deferred<Arc<TypeChecker>>,
workspace_factory: Deferred<Arc<CliWorkspaceFactory>>,
workspace_external_import_map_loader:
@ -675,6 +676,10 @@ impl CliFactory {
self.resolver_factory()?.sloppy_imports_resolver()
}
pub fn workspace(&self) -> Result<&Arc<Workspace>, AnyError> {
Ok(&self.workspace_directory()?.workspace)
}
pub fn workspace_directory(
&self,
) -> Result<&Arc<WorkspaceDirectory>, AnyError> {
@ -773,20 +778,11 @@ impl CliFactory {
pub fn emitter(&self) -> Result<&Arc<Emitter>, AnyError> {
self.services.emitter.get_or_try_init(|| {
let cli_options = self.cli_options()?;
let ts_config_result =
cli_options.resolve_ts_config_for_emit(TsConfigType::Emit)?;
check_warn_tsconfig(&ts_config_result);
let (transpile_options, emit_options) =
crate::args::ts_config_to_transpile_and_emit_options(
ts_config_result.ts_config,
)?;
Ok(Arc::new(Emitter::new(
self.cjs_tracker()?.clone(),
self.emit_cache()?.clone(),
self.parsed_source_cache().clone(),
transpile_options,
emit_options,
self.tsconfig_resolver()?.clone(),
)))
})
}
@ -857,6 +853,13 @@ impl CliFactory {
Ok(self.resolver_factory()?.pkg_json_resolver())
}
pub fn tsconfig_resolver(&self) -> Result<&Arc<TsConfigResolver>, AnyError> {
self.services.tsconfig_resolver.get_or_try_init(|| {
let workspace = self.workspace()?;
Ok(Arc::new(TsConfigResolver::from_workspace(workspace)))
})
}
pub async fn type_checker(&self) -> Result<&Arc<TypeChecker>, AnyError> {
self
.services
@ -875,6 +878,7 @@ impl CliFactory {
self.npm_installer_if_managed()?.cloned(),
self.npm_resolver().await?.clone(),
self.sys(),
self.tsconfig_resolver()?.clone(),
)))
})
.await
@ -905,6 +909,7 @@ impl CliFactory {
self.resolver().await?.clone(),
self.root_permissions_container()?.clone(),
self.sys(),
self.tsconfig_resolver()?.clone(),
)))
})
.await

View file

@ -585,7 +585,7 @@ mod tests {
// in deno_graph
async fn test_fetch_remote_encoded(
fixture: &str,
charset: &str,
expected_charset: &str,
expected: &str,
) {
let url_str = format!("http://127.0.0.1:4545/encoding/{fixture}");
@ -597,15 +597,20 @@ mod tests {
Some(&headers),
);
assert_eq!(
deno_graph::source::decode_source(&specifier, file.source, maybe_charset)
.unwrap()
.as_ref(),
deno_media_type::encoding::decode_arc_source(
maybe_charset.unwrap_or_else(|| {
deno_media_type::encoding::detect_charset(&specifier, &file.source)
}),
file.source
)
.unwrap()
.as_ref(),
expected
);
assert_eq!(media_type, MediaType::TypeScript);
assert_eq!(
headers.get("content-type").unwrap(),
&format!("application/typescript;charset={charset}")
&format!("application/typescript;charset={expected_charset}")
);
}
@ -614,9 +619,12 @@ mod tests {
let specifier = ModuleSpecifier::from_file_path(p).unwrap();
let (file, _) = test_fetch(&specifier).await;
assert_eq!(
deno_graph::source::decode_source(&specifier, file.source, None)
.unwrap()
.as_ref(),
deno_media_type::encoding::decode_arc_source(
deno_media_type::encoding::detect_charset(&specifier, &file.source),
file.source
)
.unwrap()
.as_ref(),
expected
);
}

View file

@ -1,11 +1,13 @@
// Copyright 2018-2025 the Deno authors. MIT license.
use std::collections::BTreeMap;
use std::collections::HashSet;
use std::error::Error;
use std::path::PathBuf;
use std::sync::Arc;
use deno_config::deno_json;
use deno_config::deno_json::CompilerOptionTypesDeserializeError;
use deno_config::deno_json::JsxImportSourceConfig;
use deno_config::deno_json::NodeModulesDirMode;
use deno_config::workspace::JsrPackageConfig;
@ -19,6 +21,7 @@ use deno_graph::source::Loader;
use deno_graph::source::LoaderChecksum;
use deno_graph::source::ResolutionKind;
use deno_graph::source::ResolveError;
use deno_graph::CheckJsOption;
use deno_graph::FillFromLockfileOptions;
use deno_graph::GraphKind;
use deno_graph::JsrLoadError;
@ -40,6 +43,7 @@ use deno_semver::package::PackageNv;
use deno_semver::SmallStackString;
use crate::args::config_to_deno_graph_workspace_member;
use crate::args::deno_json::TsConfigResolver;
use crate::args::jsr_url;
use crate::args::CliLockfile;
use crate::args::CliOptions;
@ -67,8 +71,8 @@ use crate::util::file_watcher::WatcherCommunicator;
use crate::util::fs::canonicalize_path;
#[derive(Clone)]
pub struct GraphValidOptions {
pub check_js: bool,
pub struct GraphValidOptions<'a> {
pub check_js: CheckJsOption<'a>,
pub kind: GraphKind,
/// Whether to exit the process for integrity check errors such as
/// lockfile checksum mismatches and JSR integrity failures.
@ -136,8 +140,8 @@ pub fn fill_graph_from_lockfile(
}
#[derive(Clone)]
pub struct GraphWalkErrorsOptions {
pub check_js: bool,
pub struct GraphWalkErrorsOptions<'a> {
pub check_js: CheckJsOption<'a>,
pub kind: GraphKind,
}
@ -147,7 +151,7 @@ pub fn graph_walk_errors<'a>(
graph: &'a ModuleGraph,
sys: &'a CliSys,
roots: &'a [ModuleSpecifier],
options: GraphWalkErrorsOptions,
options: GraphWalkErrorsOptions<'a>,
) -> impl Iterator<Item = JsErrorBox> + 'a {
graph
.walk(
@ -455,7 +459,6 @@ impl ModuleGraphCreator {
check::CheckOptions {
build_fast_check_graph: true,
lib: self.options.ts_type_lib_window(),
log_ignored_options: true,
reload: self.options.reload_flag(),
type_check_mode: self.options.type_check_mode(),
},
@ -472,6 +475,9 @@ pub struct BuildFastCheckGraphOptions<'a> {
#[derive(Debug, thiserror::Error, deno_error::JsError)]
pub enum BuildGraphWithNpmResolutionError {
#[class(inherit)]
#[error(transparent)]
CompilerOptionTypesDeserialize(#[from] CompilerOptionTypesDeserializeError),
#[class(inherit)]
#[error(transparent)]
SerdeJson(#[from] serde_json::Error),
@ -508,6 +514,7 @@ pub struct ModuleGraphBuilder {
resolver: Arc<CliResolver>,
root_permissions_container: PermissionsContainer,
sys: CliSys,
tsconfig_resolver: Arc<TsConfigResolver>,
}
impl ModuleGraphBuilder {
@ -529,6 +536,7 @@ impl ModuleGraphBuilder {
resolver: Arc<CliResolver>,
root_permissions_container: PermissionsContainer,
sys: CliSys,
tsconfig_resolver: Arc<TsConfigResolver>,
) -> Self {
Self {
caches,
@ -547,6 +555,7 @@ impl ModuleGraphBuilder {
resolver,
root_permissions_container,
sys,
tsconfig_resolver,
}
}
@ -631,7 +640,16 @@ impl ModuleGraphBuilder {
}
let maybe_imports = if options.graph_kind.include_types() {
self.cli_options.to_compiler_option_types()?
// Resolve all the imports from every deno.json. We'll separate
// them later based on the folder we're type checking.
let mut imports = Vec::new();
for deno_json in self.cli_options.workspace().deno_jsons() {
let maybe_imports = deno_json.to_compiler_option_types()?;
imports.extend(maybe_imports.into_iter().map(|(referrer, imports)| {
deno_graph::ReferrerImports { referrer, imports }
}));
}
imports
} else {
Vec::new()
};
@ -847,7 +865,7 @@ impl ModuleGraphBuilder {
} else {
GraphKind::CodeOnly
},
check_js: self.cli_options.check_js(),
check_js: CheckJsOption::Custom(self.tsconfig_resolver.as_ref()),
exit_integrity_errors: true,
},
)
@ -857,14 +875,23 @@ impl ModuleGraphBuilder {
&self,
) -> Result<CliGraphResolver, deno_json::ToMaybeJsxImportSourceConfigError>
{
let jsx_import_source_config = self
let jsx_import_source_config_unscoped = self
.cli_options
.workspace()
.start_dir
.to_maybe_jsx_import_source_config()?;
let mut jsx_import_source_config_by_scope = BTreeMap::default();
for (dir_url, _) in self.cli_options.workspace().config_folders() {
let dir = self.cli_options.workspace().resolve_member_dir(dir_url);
let jsx_import_source_config_unscoped =
dir.to_maybe_jsx_import_source_config()?;
jsx_import_source_config_by_scope
.insert(dir_url.clone(), jsx_import_source_config_unscoped);
}
Ok(CliGraphResolver {
cjs_tracker: &self.cjs_tracker,
resolver: &self.resolver,
jsx_import_source_config,
jsx_import_source_config_unscoped,
jsx_import_source_config_by_scope,
})
}
}
@ -1100,7 +1127,7 @@ pub fn has_graph_root_local_dependent_changed(
follow_dynamic: true,
kind: GraphKind::All,
prefer_fast_check_graph: true,
check_js: true,
check_js: CheckJsOption::True,
},
);
while let Some((s, _)) = dependent_specifiers.next() {
@ -1227,28 +1254,47 @@ fn format_deno_graph_error(err: &dyn Error) -> String {
struct CliGraphResolver<'a> {
cjs_tracker: &'a CliCjsTracker,
resolver: &'a CliResolver,
jsx_import_source_config: Option<JsxImportSourceConfig>,
jsx_import_source_config_unscoped: Option<JsxImportSourceConfig>,
jsx_import_source_config_by_scope:
BTreeMap<Arc<ModuleSpecifier>, Option<JsxImportSourceConfig>>,
}
impl<'a> CliGraphResolver<'a> {
fn resolve_jsx_import_source_config(
&self,
referrer: &ModuleSpecifier,
) -> Option<&JsxImportSourceConfig> {
self
.jsx_import_source_config_by_scope
.iter()
.rfind(|(s, _)| referrer.as_str().starts_with(s.as_str()))
.map(|(_, c)| c.as_ref())
.unwrap_or(self.jsx_import_source_config_unscoped.as_ref())
}
}
impl<'a> deno_graph::source::Resolver for CliGraphResolver<'a> {
fn default_jsx_import_source(&self) -> Option<String> {
fn default_jsx_import_source(
&self,
referrer: &ModuleSpecifier,
) -> Option<String> {
self
.jsx_import_source_config
.as_ref()
.resolve_jsx_import_source_config(referrer)
.and_then(|c| c.default_specifier.clone())
}
fn default_jsx_import_source_types(&self) -> Option<String> {
fn default_jsx_import_source_types(
&self,
referrer: &ModuleSpecifier,
) -> Option<String> {
self
.jsx_import_source_config
.as_ref()
.resolve_jsx_import_source_config(referrer)
.and_then(|c| c.default_types_specifier.clone())
}
fn jsx_import_source_module(&self) -> &str {
fn jsx_import_source_module(&self, referrer: &ModuleSpecifier) -> &str {
self
.jsx_import_source_config
.as_ref()
.resolve_jsx_import_source_config(referrer)
.map(|c| c.module.as_str())
.unwrap_or(deno_graph::source::DEFAULT_JSX_IMPORT_SOURCE_MODULE)
}

View file

@ -3,6 +3,7 @@
use std::hash::Hasher;
/// A very fast insecure hasher that uses the xxHash algorithm.
#[derive(Debug, Clone)]
pub struct FastInsecureHasher(twox_hash::XxHash64);
impl FastInsecureHasher {

View file

@ -18,6 +18,7 @@ use deno_config::deno_json::LintConfig;
use deno_config::deno_json::NodeModulesDirMode;
use deno_config::deno_json::TestConfig;
use deno_config::deno_json::TsConfig;
use deno_config::deno_json::TsConfigWithIgnoredOptions;
use deno_config::glob::FilePatterns;
use deno_config::glob::PathOrPatternSet;
use deno_config::workspace::CreateResolverOptions;
@ -1168,14 +1169,13 @@ impl Default for LspTsConfig {
}
impl LspTsConfig {
pub fn new(config_file: Option<&ConfigFile>) -> Self {
let mut ts_config = Self::default();
match ts_config.inner.merge_tsconfig_from_config_file(config_file) {
Ok(Some(ignored_options)) => lsp_warn!("{}", ignored_options),
Err(err) => lsp_warn!("{}", err),
_ => {}
pub fn new(raw_ts_config: TsConfigWithIgnoredOptions) -> Self {
let mut base_ts_config = Self::default();
for ignored_options in &raw_ts_config.ignored_options {
lsp_warn!("{}", ignored_options)
}
ts_config
base_ts_config.inner.merge_mut(raw_ts_config.ts_config);
base_ts_config
}
}
@ -1425,9 +1425,10 @@ impl ConfigData {
.unwrap_or_default(),
);
let ts_config = LspTsConfig::new(
member_dir.workspace.root_deno_json().map(|c| c.as_ref()),
);
let ts_config = member_dir
.to_raw_user_provided_tsconfig()
.map(LspTsConfig::new)
.unwrap_or_default();
let deno_lint_config =
if ts_config.inner.0.get("jsx").and_then(|v| v.as_str()) == Some("react")
@ -1673,7 +1674,6 @@ impl ConfigData {
) -> Option<JsxImportSourceConfig> {
self
.member_dir
.workspace
.to_maybe_jsx_import_source_config()
.ok()
.flatten()

View file

@ -23,6 +23,7 @@ use deno_core::unsync::spawn;
use deno_core::url;
use deno_core::url::Url;
use deno_core::ModuleSpecifier;
use deno_graph::CheckJsOption;
use deno_graph::GraphKind;
use deno_graph::Resolution;
use deno_lib::args::get_root_cert_store;
@ -279,7 +280,7 @@ impl LanguageServer {
&roots,
graph_util::GraphValidOptions {
kind: GraphKind::All,
check_js: false,
check_js: CheckJsOption::False,
exit_integrity_errors: false,
},
)?;

View file

@ -153,7 +153,7 @@ impl LspScopeResolver {
let maybe_jsx_import_source_config =
config_data.and_then(|d| d.maybe_jsx_import_source_config());
let graph_imports = config_data
.and_then(|d| d.member_dir.workspace.to_compiler_option_types().ok())
.and_then(|d| d.member_dir.to_compiler_option_types().ok())
.map(|imports| {
Arc::new(
imports
@ -988,19 +988,25 @@ pub struct SingleReferrerGraphResolver<'a> {
}
impl<'a> deno_graph::source::Resolver for SingleReferrerGraphResolver<'a> {
fn default_jsx_import_source(&self) -> Option<String> {
fn default_jsx_import_source(
&self,
_referrer: &ModuleSpecifier,
) -> Option<String> {
self
.jsx_import_source_config
.and_then(|c| c.default_specifier.clone())
}
fn default_jsx_import_source_types(&self) -> Option<String> {
fn default_jsx_import_source_types(
&self,
_referrer: &ModuleSpecifier,
) -> Option<String> {
self
.jsx_import_source_config
.and_then(|c| c.default_types_specifier.clone())
}
fn jsx_import_source_module(&self) -> &str {
fn jsx_import_source_module(&self, _referrer: &ModuleSpecifier) -> &str {
self
.jsx_import_source_config
.map(|c| c.module.as_str())

View file

@ -219,7 +219,6 @@ impl ModuleLoadPreparer {
check::CheckOptions {
build_fast_check_graph: true,
lib,
log_ignored_options: false,
reload: self.options.reload_flag(),
type_check_mode: self.options.type_check_mode(),
},

File diff suppressed because it is too large Load diff

View file

@ -20,7 +20,6 @@ use deno_terminal::colors;
use rand::Rng;
use super::installer::infer_name_from_url;
use crate::args::check_warn_tsconfig;
use crate::args::CompileFlags;
use crate::args::Flags;
use crate::factory::CliFactory;
@ -84,9 +83,6 @@ pub async fn compile(
graph
};
let ts_config_for_emit = cli_options
.resolve_ts_config_for_emit(deno_config::deno_json::TsConfigType::Emit)?;
check_warn_tsconfig(&ts_config_for_emit);
log::info!(
"{} {} to {}",
colors::green("Compile"),

View file

@ -608,7 +608,7 @@ pub fn cover_files(
let module_kind = ModuleKind::from_is_cjs(
cjs_tracker.is_maybe_cjs(&file.specifier, file.media_type)?,
);
Some(match emitter.maybe_cached_emit(&file.specifier, module_kind, &file.source) {
Some(match emitter.maybe_cached_emit(&file.specifier, module_kind, &file.source)? {
Some(code) => code,
None => {
return Err(anyhow!(

View file

@ -16,6 +16,7 @@ use deno_doc::html::UrlResolveKind;
use deno_doc::html::UsageComposer;
use deno_doc::html::UsageComposerEntry;
use deno_graph::source::NullFileSystem;
use deno_graph::CheckJsOption;
use deno_graph::EsParser;
use deno_graph::GraphKind;
use deno_graph::ModuleAnalyzer;
@ -148,7 +149,7 @@ pub async fn doc(
&sys,
&module_specifiers,
GraphWalkErrorsOptions {
check_js: false,
check_js: CheckJsOption::False,
kind: GraphKind::TypesOnly,
},
);

View file

@ -68,6 +68,7 @@ pub async fn kernel(
let permissions =
PermissionsContainer::allow_all(factory.permission_desc_parser()?.clone());
let npm_installer = factory.npm_installer_if_managed()?.cloned();
let tsconfig_resolver = factory.tsconfig_resolver()?;
let resolver = factory.resolver().await?.clone();
let worker_factory = factory.create_cli_main_worker_factory().await?;
let (stdio_tx, stdio_rx) = mpsc::unbounded_channel();
@ -117,6 +118,7 @@ pub async fn kernel(
cli_options,
npm_installer,
resolver,
tsconfig_resolver,
worker,
main_module,
test_event_receiver,

View file

@ -27,12 +27,12 @@ use deno_core::unsync::future::LocalFutureExt;
use deno_core::unsync::future::SharedLocal;
use deno_graph::ModuleGraph;
use deno_lint::diagnostic::LintDiagnostic;
use deno_lint::linter::LintConfig as DenoLintConfig;
use log::debug;
use reporters::create_reporter;
use reporters::LintReporter;
use serde::Serialize;
use crate::args::deno_json::TsConfigResolver;
use crate::args::CliOptions;
use crate::args::Flags;
use crate::args::LintFlags;
@ -86,7 +86,7 @@ pub async fn lint(
let cli_options = factory.cli_options()?;
let lint_rule_provider = factory.lint_rule_provider().await?;
let is_stdin = lint_flags.is_stdin();
let deno_lint_config = cli_options.resolve_deno_lint_config()?;
let tsconfig_resolver = factory.tsconfig_resolver()?;
let workspace_lint_options =
cli_options.resolve_workspace_lint_options(&lint_flags)?;
let success = if is_stdin {
@ -95,13 +95,14 @@ pub async fn lint(
lint_rule_provider,
workspace_lint_options,
lint_flags,
deno_lint_config,
tsconfig_resolver,
)?
} else {
let mut linter = WorkspaceLinter::new(
factory.caches()?.clone(),
lint_rule_provider,
factory.module_graph_creator().await?.clone(),
tsconfig_resolver.clone(),
cli_options.start_dir.clone(),
&workspace_lint_options,
);
@ -112,7 +113,6 @@ pub async fn lint(
.lint_files(
cli_options,
paths_with_options.options,
deno_lint_config.clone(),
paths_with_options.dir,
paths_with_options.paths,
)
@ -135,7 +135,6 @@ async fn lint_with_watch_inner(
) -> Result<(), AnyError> {
let factory = CliFactory::from_flags(flags);
let cli_options = factory.cli_options()?;
let lint_config = cli_options.resolve_deno_lint_config()?;
let mut paths_with_options_batches =
resolve_paths_with_options_batches(cli_options, &lint_flags)?;
for paths_with_options in &mut paths_with_options_batches {
@ -162,6 +161,7 @@ async fn lint_with_watch_inner(
factory.caches()?.clone(),
factory.lint_rule_provider().await?,
factory.module_graph_creator().await?.clone(),
factory.tsconfig_resolver()?.clone(),
cli_options.start_dir.clone(),
&cli_options.resolve_workspace_lint_options(&lint_flags)?,
);
@ -170,7 +170,6 @@ async fn lint_with_watch_inner(
.lint_files(
cli_options,
paths_with_options.options,
lint_config.clone(),
paths_with_options.dir,
paths_with_options.paths,
)
@ -242,6 +241,7 @@ struct WorkspaceLinter {
caches: Arc<Caches>,
lint_rule_provider: LintRuleProvider,
module_graph_creator: Arc<ModuleGraphCreator>,
tsconfig_resolver: Arc<TsConfigResolver>,
workspace_dir: Arc<WorkspaceDirectory>,
reporter_lock: Arc<Mutex<Box<dyn LintReporter + Send>>>,
workspace_module_graph: Option<WorkspaceModuleGraphFuture>,
@ -254,6 +254,7 @@ impl WorkspaceLinter {
caches: Arc<Caches>,
lint_rule_provider: LintRuleProvider,
module_graph_creator: Arc<ModuleGraphCreator>,
tsconfig_resolver: Arc<TsConfigResolver>,
workspace_dir: Arc<WorkspaceDirectory>,
workspace_options: &WorkspaceLintOptions,
) -> Self {
@ -263,6 +264,7 @@ impl WorkspaceLinter {
caches,
lint_rule_provider,
module_graph_creator,
tsconfig_resolver,
workspace_dir,
reporter_lock,
workspace_module_graph: None,
@ -275,7 +277,6 @@ impl WorkspaceLinter {
&mut self,
cli_options: &Arc<CliOptions>,
lint_options: LintOptions,
lint_config: DenoLintConfig,
member_dir: WorkspaceDirectory,
paths: Vec<PathBuf>,
) -> Result<(), AnyError> {
@ -297,7 +298,9 @@ impl WorkspaceLinter {
let linter = Arc::new(CliLinter::new(CliLinterOptions {
configured_rules: lint_rules,
fix: lint_options.fix,
deno_lint_config: lint_config,
deno_lint_config: self
.tsconfig_resolver
.deno_lint_config(member_dir.dir_url())?,
}));
let has_error = self.has_error.clone();
@ -530,7 +533,7 @@ fn lint_stdin(
lint_rule_provider: LintRuleProvider,
workspace_lint_options: WorkspaceLintOptions,
lint_flags: LintFlags,
deno_lint_config: DenoLintConfig,
tsconfig_resolver: &TsConfigResolver,
) -> Result<bool, AnyError> {
let start_dir = &cli_options.start_dir;
let reporter_lock = Arc::new(Mutex::new(create_reporter(
@ -538,6 +541,8 @@ fn lint_stdin(
)));
let lint_config = start_dir
.to_lint_config(FilePatterns::new_with_base(start_dir.dir_path()))?;
let deno_lint_config =
tsconfig_resolver.deno_lint_config(start_dir.dir_url())?;
let lint_options = LintOptions::resolve(lint_config, &lint_flags);
let configured_rules = lint_rule_provider.resolve_lint_rules_err_empty(
lint_options.rules,

View file

@ -123,7 +123,7 @@ impl GraphDiagnosticsCollector {
};
let options = WalkOptions {
check_js: true,
check_js: deno_graph::CheckJsOption::True,
follow_dynamic: true,
// search the entire graph and not just the fast check subset
prefer_fast_check_graph: false,

View file

@ -364,14 +364,13 @@ impl PublishPreparer {
} else {
// fast check passed, type check the output as a temporary measure
// until we know that it's reliable and stable
let (graph, check_diagnostics) = self
let mut diagnostics_by_folder = self
.type_checker
.check_diagnostics(
graph,
CheckOptions {
build_fast_check_graph: false, // already built
lib: self.cli_options.ts_type_lib_window(),
log_ignored_options: false,
reload: self.cli_options.reload_flag(),
type_check_mode: self.cli_options.type_check_mode(),
},
@ -379,20 +378,23 @@ impl PublishPreparer {
.await?;
// ignore unused parameter diagnostics that may occur due to fast check
// not having function body implementations
let check_diagnostics =
check_diagnostics.filter(|d| d.include_when_remote());
if !check_diagnostics.is_empty() {
bail!(
concat!(
"Failed ensuring public API type output is valid.\n\n",
"{:#}\n\n",
"You may have discovered a bug in Deno. Please open an issue at: ",
"https://github.com/denoland/deno/issues/"
),
check_diagnostics
);
for result in diagnostics_by_folder.by_ref() {
let check_diagnostics = result?;
let check_diagnostics =
check_diagnostics.filter(|d| d.include_when_remote());
if check_diagnostics.has_diagnostic() {
bail!(
concat!(
"Failed ensuring public API type output is valid.\n\n",
"{:#}\n\n",
"You may have discovered a bug in Deno. Please open an issue at: ",
"https://github.com/denoland/deno/issues/"
),
check_diagnostics
);
}
}
Ok(graph)
Ok(diagnostics_by_folder.into_graph())
}
}
}

View file

@ -168,6 +168,7 @@ pub async fn run(
let npm_installer = factory.npm_installer_if_managed()?.cloned();
let resolver = factory.resolver().await?.clone();
let file_fetcher = factory.file_fetcher()?;
let tsconfig_resolver = factory.tsconfig_resolver()?;
let worker_factory = factory.create_cli_main_worker_factory().await?;
let history_file_path = factory
.deno_dir()
@ -190,6 +191,7 @@ pub async fn run(
cli_options,
npm_installer,
resolver,
tsconfig_resolver,
worker,
main_module.clone(),
test_event_receiver,

View file

@ -42,6 +42,7 @@ use regex::Match;
use regex::Regex;
use tokio::sync::Mutex;
use crate::args::deno_json::TsConfigResolver;
use crate::args::CliOptions;
use crate::cdp;
use crate::colors;
@ -203,6 +204,7 @@ impl ReplSession {
cli_options: &CliOptions,
npm_installer: Option<Arc<NpmInstaller>>,
resolver: Arc<CliResolver>,
tsconfig_resolver: &TsConfigResolver,
mut worker: MainWorker,
main_module: ModuleSpecifier,
test_event_receiver: TestEventReceiver,
@ -258,13 +260,10 @@ impl ReplSession {
cli_options.initial_cwd().to_string_lossy(),
)
})?;
let ts_config_for_emit = cli_options
.resolve_ts_config_for_emit(deno_config::deno_json::TsConfigType::Emit)?;
let (transpile_options, _) =
crate::args::ts_config_to_transpile_and_emit_options(
ts_config_for_emit.ts_config,
)?;
let experimental_decorators = transpile_options.use_ts_decorators;
let experimental_decorators = tsconfig_resolver
.transpile_and_emit_options(&cwd_url)?
.transpile
.use_ts_decorators;
let mut repl_session = ReplSession {
npm_installer,
resolver,

View file

@ -351,16 +351,17 @@ impl Diagnostics {
/// Return a set of diagnostics where only the values where the predicate
/// returns `true` are included.
pub fn filter<P>(self, predicate: P) -> Self
where
P: FnMut(&Diagnostic) -> bool,
{
pub fn filter(self, predicate: impl FnMut(&Diagnostic) -> bool) -> Self {
let diagnostics = self.0.into_iter().filter(predicate).collect();
Self(diagnostics)
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
pub fn retain(&mut self, predicate: impl FnMut(&Diagnostic) -> bool) {
self.0.retain(predicate);
}
pub fn has_diagnostic(&self) -> bool {
!self.0.is_empty()
}
/// Modifies all the diagnostics to have their display positions
@ -430,23 +431,27 @@ impl Serialize for Diagnostics {
impl fmt::Display for Diagnostics {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut i = 0;
for item in &self.0 {
if i > 0 {
write!(f, "\n\n")?;
}
write!(f, "{item}")?;
i += 1;
display_diagnostics(f, self)?;
if self.0.len() > 1 {
write!(f, "\n\nFound {} errors.", self.0.len())?;
}
if i > 1 {
write!(f, "\n\nFound {i} errors.")?;
}
Ok(())
}
}
fn display_diagnostics(
f: &mut fmt::Formatter,
diagnostics: &Diagnostics,
) -> fmt::Result {
for (i, item) in diagnostics.0.iter().enumerate() {
if i > 0 {
write!(f, "\n\n")?;
}
write!(f, "{item}")?;
}
Ok(())
}
impl Error for Diagnostics {}
#[cfg(test)]

View file

@ -366,7 +366,7 @@ pub struct RequestNpmState {
pub struct Request {
/// The TypeScript compiler options which will be serialized and sent to
/// tsc.
pub config: TsConfig,
pub config: Arc<TsConfig>,
/// Indicates to the tsc runtime if debug logging should occur.
pub debug: bool,
pub graph: Arc<ModuleGraph>,
@ -1279,7 +1279,7 @@ mod tests {
graph
.build(vec![specifier.clone()], &loader, Default::default())
.await;
let config = TsConfig::new(json!({
let config = Arc::new(TsConfig::new(json!({
"allowJs": true,
"checkJs": false,
"esModuleInterop": true,
@ -1294,7 +1294,7 @@ mod tests {
"strict": true,
"target": "esnext",
"tsBuildInfoFile": "internal:///.tsbuildinfo",
}));
})));
let request = Request {
config,
debug: false,
@ -1529,7 +1529,7 @@ mod tests {
let actual = test_exec(&specifier)
.await
.expect("exec should not have errored");
assert!(actual.diagnostics.is_empty());
assert!(!actual.diagnostics.has_diagnostic());
assert!(actual.maybe_tsbuildinfo.is_some());
assert_eq!(actual.stats.0.len(), 12);
}
@ -1540,7 +1540,7 @@ mod tests {
let actual = test_exec(&specifier)
.await
.expect("exec should not have errored");
assert!(actual.diagnostics.is_empty());
assert!(!actual.diagnostics.has_diagnostic());
assert!(actual.maybe_tsbuildinfo.is_some());
assert_eq!(actual.stats.0.len(), 12);
}
@ -1551,6 +1551,6 @@ mod tests {
let actual = test_exec(&specifier)
.await
.expect("exec should not have errored");
assert!(actual.diagnostics.is_empty());
assert!(!actual.diagnostics.has_diagnostic());
}
}

70
cli/util/collections.rs Normal file
View file

@ -0,0 +1,70 @@
// Copyright 2018-2025 the Deno authors. MIT license.
use std::collections::BTreeMap;
use std::sync::Arc;
use deno_core::url::Url;
/// A map that stores values scoped to a specific directory
/// on the file system.
///
/// The root directory is considered "unscoped" so values that
/// fall outside the other directories land here (ex. remote modules).
pub struct FolderScopedMap<TValue> {
unscoped: TValue,
scoped: BTreeMap<Arc<Url>, TValue>,
}
impl<TValue> std::fmt::Debug for FolderScopedMap<TValue>
where
TValue: std::fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FolderScopedMap")
.field("unscoped", &self.unscoped)
.field("scoped", &self.scoped)
.finish()
}
}
impl<TValue> Default for FolderScopedMap<TValue>
where
TValue: Default,
{
fn default() -> Self {
Self::new(Default::default())
}
}
impl<TValue> FolderScopedMap<TValue> {
pub fn new(unscoped: TValue) -> Self {
Self {
unscoped,
scoped: Default::default(),
}
}
pub fn count(&self) -> usize {
// +1 for unscoped
self.scoped.len() + 1
}
pub fn get_for_specifier(&self, specifier: &Url) -> &TValue {
self.get_for_specifier_str(specifier.as_str())
}
pub fn get_for_specifier_str(&self, specifier: &str) -> &TValue {
self
.scoped
.iter()
.rfind(|(s, _)| specifier.starts_with(s.as_str()))
.map(|(_, v)| v)
.unwrap_or(&self.unscoped)
}
pub fn insert(&mut self, dir_url: Arc<Url>, value: TValue) {
debug_assert!(dir_url.path().ends_with("/")); // must be a dir url
debug_assert_eq!(dir_url.scheme(), "file");
self.scoped.insert(dir_url, value);
}
}

View file

@ -2,6 +2,7 @@
// Note: Only add code in this folder that has no application specific logic
pub mod archive;
pub mod collections;
pub mod console;
pub mod diff;
pub mod display;

View file

@ -146,7 +146,7 @@ fn check_error_in_dep_then_fix() {
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_matches_text("Check [WILDCARD]main.ts\nTS234[WILDCARD]");
output.assert_exit_code(1);
temp_dir.write("greet.ts", correct_code);
@ -155,7 +155,7 @@ fn check_error_in_dep_then_fix() {
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_matches_text("Check [WILDCARD]main.ts\nTS234[WILDCARD]");
output.assert_exit_code(1);
}
@ -179,7 +179,7 @@ fn json_module_check_then_error() {
temp_dir.write("test.json", incorrect_code);
check_command
.run()
.assert_matches_text("Check [WILDCARD]main.ts\nerror: TS2551[WILDCARD]")
.assert_matches_text("Check [WILDCARD]main.ts\nTS2551[WILDCARD]")
.assert_exit_code(1);
}
@ -242,6 +242,6 @@ fn npm_module_check_then_error() {
check_command
.run()
.assert_matches_text("Check [WILDCARD]main.ts\nerror: TS2305[WILDCARD]has no exported member 'oldName'[WILDCARD]")
.assert_matches_text("Check [WILDCARD]main.ts\nTS2305[WILDCARD]has no exported member 'oldName'[WILDCARD]")
.assert_exit_code(1);
}

View file

@ -495,7 +495,7 @@ fn check_local_by_default2() {
])
.run()
.assert_matches_text(
r#"[WILDCARD]error: TS2322 [ERROR]: Type '12' is not assignable to type '"b"'.[WILDCARD]"#,
r#"[WILDCARD]TS2322 [ERROR]: Type '12' is not assignable to type '"b"'.[WILDCARD]"#,
)
.assert_exit_code(1);
}

View file

@ -64,7 +64,7 @@ fn fast_check_cache() {
// ensure cache works
let output = check_debug_cmd.run();
assert_contains!(output.combined_output(), "Already type checked.");
assert_contains!(output.combined_output(), "Already type checked");
// now validated
type_check_cache_path.remove_file();
@ -97,10 +97,12 @@ fn fast_check_cache() {
.run()
.assert_matches_text(
"Check file:///[WILDCARD]main.ts
error: TS2322 [ERROR]: Type 'string' is not assignable to type 'number'.
TS2322 [ERROR]: Type 'string' is not assignable to type 'number'.
export function asdf(a: number) { let err: number = ''; return Math.random(); }
~~~
at http://127.0.0.1:4250/@denotest/add/1.0.0/other.ts:2:39
error: Type checking failed.
",
)
.assert_exit_code(1);

View file

@ -2158,7 +2158,7 @@ fn ts_dependency_recompilation() {
let stdout_output = std::str::from_utf8(&output.stdout).unwrap().trim();
let stderr_output = std::str::from_utf8(&output.stderr).unwrap().trim();
// error: TS2345 [ERROR]: Argument of type '5' is not assignable to parameter of type 'string'.
// TS2345 [ERROR]: Argument of type '5' is not assignable to parameter of type 'string'.
assert!(stderr_output.contains("TS2345"));
assert!(!output.status.success());
assert!(stdout_output.is_empty());

View file

@ -1148,7 +1148,7 @@ async fn test_watch_doc() {
);
assert_eq!(
next_line(&mut stderr_lines).await.unwrap(),
"error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'."
"TS2322 [ERROR]: Type 'number' is not assignable to type 'string'."
);
assert_eq!(
next_line(&mut stderr_lines).await.unwrap(),

View file

@ -1,4 +1,6 @@
error: TS2322 [ERROR]: Type '12' is not assignable to type '"b"'.
TS2322 [ERROR]: Type '12' is not assignable to type '"b"'.
const b: "b" = 12;
^
at [WILDCARD]/check_local_by_default2.ts:3:7
error: Type checking failed.

View file

@ -1,5 +1,7 @@
Check [WILDCARD]/no_run.ts
error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
const _value: string = 1;
~~~~~~
at [WILDCARD]/no_run.ts:1:7
error: Type checking failed.

View file

@ -1,4 +1,6 @@
error: TS2322 [ERROR]: Type '12' is not assignable to type '"a"'.
TS2322 [ERROR]: Type '12' is not assignable to type '"a"'.
export const a: "a" = 12;
^
at http://localhost:4545/subdir/type_error.ts:1:14
error: Type checking failed.

View file

@ -1,4 +1,6 @@
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 the top of your entrypoint (main file): /// <reference lib="deno.ns" />
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 the top of your entrypoint (main file): /// <reference lib="deno.ns" />
Deno;
~~~~
at file:///[WILDCARD]/deno_not_found/main.ts:4:1
error: Type checking failed.

View file

@ -1,4 +1,6 @@
error: TS1039 [ERROR]: Initializers are not allowed in ambient contexts.
TS1039 [ERROR]: Initializers are not allowed in ambient contexts.
export const a: string = Deno.version.deno;
~~~~~~~~~~~~~~~~~
at file:///[WILDCARD]/check_dts.d.ts:2:26
error: Type checking failed.

View file

@ -1,4 +1,6 @@
error: TS2304 [ERROR]: Cannot find name 'nothing'.
TS2304 [ERROR]: Cannot find name 'nothing'.
export { nothing };
~~~~~~~
at [WILDCARD]
error: Type checking failed.

View file

@ -1,4 +1,6 @@
error: TS2304 [ERROR]: Cannot find name 'nothing'.
TS2304 [ERROR]: Cannot find name 'nothing'.
export { nothing };
~~~~~~~
at [WILDCARD]
error: Type checking failed.

View file

@ -1,4 +1,4 @@
error: TS2322 [ERROR]: Type '{ propertyWithAnExceedinglyLongName1: string; propertyWithAnExceedinglyLongName2: string; propertyWithAnExceedinglyLongName3: string; propertyWithAnExceedinglyLongName4: string; propertyWithAnExceedinglyLongName5: string; propertyWithAnExceedinglyLongName6: string; propertyWithAnExceedinglyLongName7: string; propertyWithAnExceedinglyLongName8: string; }' is not assignable to type 'string'.
TS2322 [ERROR]: Type '{ propertyWithAnExceedinglyLongName1: string; propertyWithAnExceedinglyLongName2: string; propertyWithAnExceedinglyLongName3: string; propertyWithAnExceedinglyLongName4: string; propertyWithAnExceedinglyLongName5: string; propertyWithAnExceedinglyLongName6: string; propertyWithAnExceedinglyLongName7: string; propertyWithAnExceedinglyLongName8: string; }' is not assignable to type 'string'.
const _s: string = x;
~~
at file:///[WILDCARD]/no_error_truncation/main.ts:12:7
@ -9,3 +9,5 @@ const _s: string = x;
at file:///[WILDCARD]/no_error_truncation/main.ts:12:20
Found 2 errors.
error: Type checking failed.

View file

@ -1,5 +1,7 @@
error: TS2769 [ERROR]: No overload matches this call.
TS2769 [ERROR]: No overload matches this call.
[WILDCARD]
const _data = fs.readFileSync("./node_builtin.js", 123);
~~~
at file:///[WILDCARD]/mod.js:3:52
error: Type checking failed.

View file

@ -1,4 +1,4 @@
error: TS2769 [ERROR]: No overload matches this call.
TS2769 [ERROR]: No overload matches this call.
[WILDCARD]
const _data = fs.readFileSync("./node_builtin.js", 123);
~~~
@ -11,3 +11,5 @@ const _testString: number[] = builtinModules;
at file:///[WILDCARD]/mod.ts:9:7
Found 2 errors.
error: Type checking failed.

View file

@ -1,4 +1,4 @@
error: TS2581 [ERROR]: Cannot find name '$'. Did you mean to import jQuery? Try adding `import $ from "npm:jquery";`.
TS2581 [ERROR]: Cannot find name '$'. Did you mean to import jQuery? Try adding `import $ from "npm:jquery";`.
$;
^
at file:///[WILDCARD]/npm_install_diagnostics/main.ts:1:1
@ -9,3 +9,5 @@ process;
at file:///[WILDCARD]/npm_install_diagnostics/main.ts:2:1
Found 2 errors.
error: Type checking failed.

View file

@ -0,0 +1,14 @@
{
"tests": {
"discover": {
"args": "check main.ts member/mod.ts",
"output": "check_discover.out",
"exitCode": 1
},
"config_flag": {
"args": "check --config deno.json main.ts member/mod.ts",
"output": "check_config_flag.out",
"exitCode": 1
}
}
}

View file

@ -0,0 +1,20 @@
Check file:///[WILDLINE]/main.ts
TS2304 [ERROR]: Cannot find name 'onmessage'.
onmessage;
~~~~~~~~~
at file:///[WILDLINE]/main.ts:8:1
TS2304 [ERROR]: Cannot find name 'onmessage'.
onmessage;
~~~~~~~~~
at file:///[WILDLINE]/member/mod.ts:5:1
Found 2 errors.
Check file:///[WILDLINE]/member/mod.ts
TS2304 [ERROR]: Cannot find name 'localStorage'.
localStorage;
~~~~~~~~~~~~
at file:///[WILDLINE]/member/mod.ts:2:1
error: Type checking failed.

View file

@ -0,0 +1,20 @@
Check file:///[WILDLINE]/main.ts
TS2304 [ERROR]: Cannot find name 'onmessage'.
onmessage;
~~~~~~~~~
at file:///[WILDLINE]/main.ts:8:1
TS2304 [ERROR]: Cannot find name 'onmessage'.
onmessage;
~~~~~~~~~
at file:///[WILDLINE]/member/mod.ts:5:1
Found 2 errors.
Check file:///[WILDLINE]/member/mod.ts
TS2304 [ERROR]: Cannot find name 'localStorage'.
localStorage;
~~~~~~~~~~~~
at file:///[WILDLINE]/member/mod.ts:2:1
error: Type checking failed.

View file

@ -0,0 +1,3 @@
{
"workspace": ["member"]
}

View file

@ -0,0 +1,8 @@
// We should get diagnostics from this import under this check scope.
import "./member/mod.ts";
// Only defined for window.
localStorage;
// Only defined for worker.
onmessage;

View file

@ -0,0 +1,5 @@
{
"compilerOptions": {
"lib": ["deno.worker"]
}
}

View file

@ -0,0 +1,5 @@
// Only defined for window.
localStorage;
// Only defined for worker.
onmessage;

View file

@ -1,7 +1,9 @@
Download http://localhost:4260/@denotest%2fcjs-default-export
Download http://localhost:4260/@denotest/cjs-default-export/1.0.0.tgz
Check file:///[WILDCARD]/main.ts
error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
export const Test: string = cjsDefault.default();
~~~~
at file:///[WILDCARD]/main.ts:4:14
error: Type checking failed.

View file

@ -1,5 +1,7 @@
Check file:///[WILDLINE]/exists_and_try_uses.ts
error: TS1192 [ERROR]: Module '"file:///[WILDLINE]/app.css"' has no default export.
TS1192 [ERROR]: Module '"file:///[WILDLINE]/app.css"' has no default export.
import test from "./app.css";
~~~~
at file:///[WILDLINE]/exists_and_try_uses.ts:1:8
error: Type checking failed.

View file

@ -1,3 +1,5 @@
Check [WILDLINE]exists.ts
error: TS2307 [ERROR]: Cannot find module 'file:///[WILDLINE]/not_exists.css'.
TS2307 [ERROR]: Cannot find module 'file:///[WILDLINE]/not_exists.css'.
at file:///[WILDLINE]/not_exists.ts:1:8
error: Type checking failed.

View file

@ -1,3 +1,5 @@
Check file:///[WILDLINE]/dts_importing_non_existent/index.js
error: TS2307 [ERROR]: Cannot find module 'file:///[WILDLINE]/test'.
TS2307 [ERROR]: Cannot find module 'file:///[WILDLINE]/test'.
at file:///[WILDLINE]/index.d.ts:1:22
error: Type checking failed.

View file

@ -12,12 +12,12 @@
},
"glob_star": {
"args": "check **/*.ts",
"output": "Check [WILDLINE]main.ts\nCheck [WILDLINE]sub_dir/main.ts\nerror: TS2322[WILDCARD]",
"output": "Check [WILDLINE]main.ts\nCheck [WILDLINE]sub_dir/main.ts\nTS2322[WILDCARD]",
"exitCode": 1
},
"sub_dir": {
"args": "check sub_dir",
"output": "Check [WILDLINE]sub_dir/main.ts\nerror: TS2322[WILDCARD]",
"output": "Check [WILDLINE]sub_dir/main.ts\nTS2322[WILDCARD]",
"exitCode": 1
}
}

View file

@ -1,5 +1,7 @@
Download http://localhost:4545/check/import_non_existent.ts
Download http://localhost:4545/check/non-existent-module.ts
Check file:///[WILDLINE]/import_remote.ts
error: TS2307 [ERROR]: Cannot find module 'http://localhost:4545/check/non-existent-module.ts'.
TS2307 [ERROR]: Cannot find module 'http://localhost:4545/check/non-existent-module.ts'.
at http://localhost:4545/check/import_non_existent.ts:1:22
error: Type checking failed.

View file

@ -1,6 +1,8 @@
Download http://localhost:4545/add.ts
Check file:///[WILDLINE]main.js
error: TS2345 [ERROR]: Argument of type 'string' is not assignable to parameter of type '(a: number, b: number) => number'.
TS2345 [ERROR]: Argument of type 'string' is not assignable to parameter of type '(a: number, b: number) => number'.
addHere("");
~~
at file:///[WILDLINE]main.js:12:9
error: Type checking failed.

View file

@ -7,7 +7,9 @@ Download http://localhost:4260/loose-envify/loose-envify-1.4.0.tgz
Download http://localhost:4260/js-tokens/js-tokens-4.0.0.tgz
[UNORDERED_END]
Check file:///[WILDCARD]/jsx_not_checked/main.jsx
error: TS2345 [ERROR]: Argument of type 'string' is not assignable to parameter of type 'number'.
TS2345 [ERROR]: Argument of type 'string' is not assignable to parameter of type 'number'.
console.log(add("1", "2"));
~~~
at file:///[WILDCARD]/other.ts:5:17
error: Type checking failed.

View file

@ -1,4 +1,4 @@
error: TS2769 [ERROR]: No overload matches this call.
TS2769 [ERROR]: No overload matches this call.
Overload 1 of 3, '(s: string, b: boolean): void', gave the following error.
Argument of type 'number' is not assignable to parameter of type 'boolean'.
Overload 2 of 3, '(ss: string[], b: boolean): void', gave the following error.
@ -8,3 +8,5 @@ error: TS2769 [ERROR]: No overload matches this call.
foo("hello", 42);
~~~
at [WILDLINE]/message_chain_formatting.ts:8:1
error: Type checking failed.

View file

@ -1,9 +1,11 @@
Download http://localhost:4545/remote.ts
Check file:///[WILDLINE]/module_not_found/main.ts
error: TS2307 [ERROR]: Cannot find module 'file:///[WILDLINE]/other.js'.
TS2307 [ERROR]: Cannot find module 'file:///[WILDLINE]/other.js'.
at file:///[WILDLINE]/main.ts:1:22
TS2307 [ERROR]: Cannot find module 'http://localhost:4545/remote.ts'.
at file:///[WILDLINE]/main.ts:2:24
Found 2 errors.
error: Type checking failed.

View file

@ -1,2 +1,4 @@
Check file:///[WILDLINE]/non_existent.ts
error: TS2307 [ERROR]: Cannot find module 'file:///[WILDLINE]/non_existent.ts'.
TS2307 [ERROR]: Cannot find module 'file:///[WILDLINE]/non_existent.ts'.
error: Type checking failed.

View file

@ -1,3 +1,5 @@
Download http://localhost:4545/missing_non_existent.ts
Check http://localhost:4545/missing_non_existent.ts
error: TS2307 [ERROR]: Cannot find module 'http://localhost:4545/missing_non_existent.ts'.
TS2307 [ERROR]: Cannot find module 'http://localhost:4545/missing_non_existent.ts'.
error: Type checking failed.

View file

@ -1,5 +1,7 @@
Check file:///[WILDCARD]/main.ts
error: TS4114 [ERROR]: This member must have an 'override' modifier because it overrides a member in the base class 'Greet'.
TS4114 [ERROR]: This member must have an 'override' modifier because it overrides a member in the base class 'Greet'.
greet() {}
~~~~~
at file:///[WILDCARD]/no_implicit_override/main.ts:6:3
error: Type checking failed.

View file

@ -1,5 +1,7 @@
Check file:///[WILDLINE]/index.ts
error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
const result: string = add(1, 2);
~~~~~~
at file:///[WILDLINE]/index.ts:4:7
error: Type checking failed.

View file

@ -1,4 +1,6 @@
error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
const _test: string = getValue();
~~~~~
at file:///[WILDCARD]/fail_check.ts:3:7
error: Type checking failed.

View file

@ -1,4 +1,4 @@
error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
const _strValue1: string = NUMBER_VALUE;
~~~~~~~~~~
at file:///[WILDCARD]/main.ts:8:7
@ -9,3 +9,5 @@ const _strValue2: string = test.getValue();
at file:///[WILDCARD]/main.ts:9:7
Found 2 errors.
error: Type checking failed.

View file

@ -1,5 +1,7 @@
Check [WILDCARD]/main.ts
error: TS2345 [ERROR]: Argument of type 'string' is not assignable to parameter of type 'AsyncIterable<string> | (Iterable<string | PromiseLike<string>> & object)'.
TS2345 [ERROR]: Argument of type 'string' is not assignable to parameter of type 'AsyncIterable<string> | (Iterable<string | PromiseLike<string>> & object)'.
ReadableStream.from("string");
~~~~~~~~
at [WILDCARD]/main.ts:1:21
error: Type checking failed.

View file

@ -1,6 +1,8 @@
Check [WILDCARD]/mod.ts
Check [WILDCARD]/mod.ts$2-5.ts
error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
const sum: string = add(1, 2);
~~~
at [WILDCARD]/mod.ts$2-5.ts:2:7
error: Type checking failed.

View file

@ -1,7 +1,9 @@
Check [WILDCARD]/markdown.md$11-14.js
Check [WILDCARD]/markdown.md$17-20.ts
Check [WILDCARD]/markdown.md$29-32.ts
error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
const a: string = 42;
^
at [WILDCARD]/markdown.md$29-32.ts:1:7
error: Type checking failed.

View file

@ -1,4 +1,6 @@
[# It should be resolving relative the config in sub_dir instead of the cwd]
Check file:///[WILDLINE]/main.ts
error: TS2307 [ERROR]: Cannot find module 'file:///[WILDLINE]/sub_dir/a.d.ts'.
TS2307 [ERROR]: Cannot find module 'file:///[WILDLINE]/sub_dir/a.d.ts'.
at file:///[WILDLINE]/sub_dir/deno.json:1:1
error: Type checking failed.

View file

@ -1,5 +1,7 @@
Check file:///[WILDLINE]main.ts
error: TS2339 [ERROR]: Property 'listenDatagram' does not exist on type 'typeof Deno'. 'Deno.listenDatagram' is an unstable API. If not, try changing the 'lib' compiler option to include 'deno.unstable' or add a triple-slash directive to the top of your entrypoint (main file): /// <reference lib="deno.unstable" />
TS2339 [ERROR]: Property 'listenDatagram' does not exist on type 'typeof Deno'. 'Deno.listenDatagram' is an unstable API. If not, try changing the 'lib' compiler option to include 'deno.unstable' or add a triple-slash directive to the top of your entrypoint (main file): /// <reference lib="deno.unstable" />
Deno.listenDatagram({
~~~~~~~~~~~~~~
at file:///[WILDLINE]/main.ts:5:6
error: Type checking failed.

View file

@ -1,5 +1,7 @@
Check file:///[WILDLINE]/no_default_lib.ts
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 the top of your entrypoint (main file): /// <reference lib="deno.ns" />
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 the top of your entrypoint (main file): /// <reference lib="deno.ns" />
console.log(Deno);
~~~~
at file:///[WILDLINE]/no_default_lib.ts:5:13
error: Type checking failed.

View file

@ -1,5 +1,7 @@
Check file:///[WILDCARD]/main.ts
error: TS18046 [ERROR]: 'e' is of type 'unknown'.
TS18046 [ERROR]: 'e' is of type 'unknown'.
console.log(e.message);
^
at file://[WILDCARD]/use_unknown_in_catch_variables/main.ts:4:15
error: Type checking failed.

View file

@ -1,6 +1,8 @@
Download http://localhost:4545/wasm/math.wasm
Check file:///[WILDLINE]/main.ts
error: TS2345 [ERROR]: Argument of type 'string' is not assignable to parameter of type 'number'.
TS2345 [ERROR]: Argument of type 'string' is not assignable to parameter of type 'number'.
console.log(add(1, ""));
~~
at file:///[WILDLINE]/main.ts:3:20
error: Type checking failed.

View file

@ -2,7 +2,7 @@
"tests": {
"root": {
// todo(dsherret): should be possible to not provide args here
"args": "check package-a/mod.ts package-b/mod.ts",
"args": "check package-a/mod.ts package-b/mod.ts package-c/mod.ts package-d/mod.ts",
"output": "root.out",
"exitCode": 1
},

View file

@ -1,6 +1,8 @@
{
"workspace": [
"./package-a",
"./package-b"
"./package-b",
"./package-c",
"./package-d"
]
}

View file

@ -0,0 +1 @@
console.log(Math.pow(""));

View file

@ -0,0 +1,5 @@
{
"compilerOptions": {
"checkJs": true
}
}

View file

@ -0,0 +1 @@
import "./check.js";

View file

@ -0,0 +1 @@
console.log(Math.pow(""));

View file

@ -0,0 +1,5 @@
{
"compilerOptions": {
"checkJs": false
}
}

View file

@ -0,0 +1 @@
import "./check.js";

View file

@ -1,5 +1,7 @@
Check file:///[WILDLINE]/package-b/mod.ts
error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
const test: string = add(1, 2);
~~~~
at [WILDLINE]
error: Type checking failed.

View file

@ -1,6 +1,20 @@
Check file:///[WILDLINE]/package-a/mod.ts
Check file:///[WILDLINE]/package-b/mod.ts
error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
Check file:///[WILDLINE]/package-d/mod.ts
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
const test: string = add(1, 2);
~~~~
at [WILDLINE]
at file:///[WILDLINE]/package-b/mod.ts:3:7
Check file:///[WILDLINE]/package-c/mod.ts
TS2554 [ERROR]: Expected 2 arguments, but got 1.
console.log(Math.pow(""));
~~~
at file:///[WILDLINE]/package-c/check.js:1:18
An argument for 'y' was not provided.
pow(x: number, y: number): number;
~~~~~~~~~
at asset:///lib.es5.d.ts:744:20
error: Type checking failed.

View file

@ -0,0 +1,9 @@
{
"tests": {
"root": {
"args": "check package-a/mod.ts package-b/mod.ts package-c/mod.ts",
"output": "root.out",
"exitCode": 1
}
}
}

View file

@ -0,0 +1,7 @@
{
"workspace": [
"./package-a",
"./package-b",
"./package-c"
]
}

View file

@ -0,0 +1,8 @@
{
"compilerOptions": {
"types": [
"./globals.d.ts",
"./other-globals.d.ts"
]
}
}

View file

@ -0,0 +1 @@
declare var myPackageAGlobal: string;

View file

@ -0,0 +1,2 @@
console.log(myPackageAGlobal);
console.log(myPackageBGlobal);

View file

@ -0,0 +1,7 @@
{
"compilerOptions": {
"types": [
"./globals.d.ts"
]
}
}

View file

@ -0,0 +1 @@
declare var myPackageBGlobal: string;

View file

@ -0,0 +1,2 @@
console.log(myPackageAGlobal);
console.log(myPackageBGlobal);

View file

@ -0,0 +1,13 @@
{
// the config for this package should be grouped together with
// package-a because it's the same
"compilerOptions": {
"types": [
// these are swapped with what's in package-a and Deno should
// still handle type checking them together because the config
// is the same
"../package-a/other-globals.d.ts",
"../package-a/globals.d.ts"
]
}
}

View file

@ -0,0 +1 @@
console.log(myPackageAGlobal);

View file

@ -0,0 +1,24 @@
Check file:///[WILDLINE]/package-a/mod.ts
Check file:///[WILDLINE]/package-c/mod.ts
TS2552 [ERROR]: Cannot find name 'myPackageBGlobal'. Did you mean 'myPackageAGlobal'?
console.log(myPackageBGlobal);
~~~~~~~~~~~~~~~~
at file:///[WILDLINE]/package-a/mod.ts:2:13
'myPackageAGlobal' is declared here.
declare var myPackageAGlobal: string;
~~~~~~~~~~~~~~~~
at file:///[WILDLINE]/package-a/globals.d.ts:1:13
Check file:///[WILDLINE]/package-b/mod.ts
TS2552 [ERROR]: Cannot find name 'myPackageAGlobal'. Did you mean 'myPackageBGlobal'?
console.log(myPackageAGlobal);
~~~~~~~~~~~~~~~~
at file:///[WILDLINE]/package-b/mod.ts:1:13
'myPackageBGlobal' is declared here.
declare var myPackageBGlobal: string;
~~~~~~~~~~~~~~~~
at file:///[WILDLINE]/package-b/globals.d.ts:1:13
error: Type checking failed.

View file

@ -9,7 +9,7 @@ Download http://127.0.0.1:4250/@denotest/subset-type-graph/0.1.0/mod.ts
Download http://127.0.0.1:4250/@denotest/subset-type-graph-invalid/0.1.0/mod.ts
[UNORDERED_END]
Check file:///[WILDCARD]/subset_type_graph/main.ts
error: TS2322 [ERROR]: Type 'string' is not assignable to type 'number'.
TS2322 [ERROR]: Type 'string' is not assignable to type 'number'.
const invalidTypeCheck: number = "";
~~~~~~~~~~~~~~~~
at http://127.0.0.1:4250/@denotest/subset-type-graph-invalid/0.1.0/mod.ts:11:7
@ -45,3 +45,5 @@ new Foo2().method2();
at http://127.0.0.1:4250/@denotest/subset-type-graph-invalid/0.1.0/mod.ts:2:3
Found 5 errors.
error: Type checking failed.

View file

@ -1,16 +1,5 @@
{
"steps": [
{
"args": "lint",
"cwd": "./react",
"output": "react.out",
"exitCode": 0
},
{
"args": "lint",
"cwd": "./react-jsx",
"output": "react-jsx.out",
"exitCode": 1
}
]
"args": "lint",
"output": "lint.out",
"exitCode": 1
}

View file

@ -0,0 +1,6 @@
{
"workspace": [
"react",
"react-jsx"
]
}

Some files were not shown because too many files have changed in this diff Show more