From 673c389a1b9ed903ec76523c0520f10b737d2286 Mon Sep 17 00:00:00 2001 From: JeremyDev87 Date: Tue, 5 May 2026 21:13:36 +0900 Subject: [PATCH] =?UTF-8?q?fix(tsconfig):=20node=5Fmodules=20exclude=20?= =?UTF-8?q?=EB=85=B8=EC=9D=B4=EC=A6=88=20=EC=99=84=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TypeScript 기본 exclude 디렉터리와 동일한 node_modules/bower_components/jspm_packages no-op exclude는 기본 audit finding에서 제외합니다. 비기본 exclude no-op finding과 empty include warning은 기존 계약대로 유지하고 regression test로 고정했습니다. Closes #105 --- crates/maximus-checks/src/tsconfig.rs | 17 +++++++ .../maximus-checks/tests/tsconfig_checks.rs | 44 +++++++++++++++---- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/crates/maximus-checks/src/tsconfig.rs b/crates/maximus-checks/src/tsconfig.rs index e246f86..ef14a5e 100644 --- a/crates/maximus-checks/src/tsconfig.rs +++ b/crates/maximus-checks/src/tsconfig.rs @@ -1178,6 +1178,10 @@ fn collect_include_exclude_pattern_findings( let removed_count = matches.len(); if removed_count == 0 { + if is_default_excluded_directory_pattern(pattern) { + continue; + } + findings.push(make_finding(FindingInput { id: format!( "tsconfig-patterns:{}:exclude:{pattern}", @@ -1246,6 +1250,19 @@ fn is_next_generated_types_pattern(pattern: &str) -> bool { pattern == ".next/types/**/*.ts" || pattern == "./.next/types/**/*.ts" } +fn is_default_excluded_directory_pattern(pattern: &str) -> bool { + let normalized = pattern.trim().replace('\\', "/"); + let normalized = normalized + .strip_prefix("./") + .unwrap_or(&normalized) + .trim_end_matches('/'); + + matches!( + normalized, + "node_modules" | "bower_components" | "jspm_packages" + ) +} + fn collect_output_path_overlap_findings( findings: &mut Vec, project_root: &Path, diff --git a/crates/maximus-checks/tests/tsconfig_checks.rs b/crates/maximus-checks/tests/tsconfig_checks.rs index ee75efa..fc6743c 100644 --- a/crates/maximus-checks/tests/tsconfig_checks.rs +++ b/crates/maximus-checks/tests/tsconfig_checks.rs @@ -883,6 +883,19 @@ fn tsconfig_pattern_severity_contract_keeps_noop_excludes_non_blocking() { .join("noop-node-modules-exclude/src/index.ts"), "export const ok = true;\n", ); + write( + fixture.path().join("noop-generated-exclude/tsconfig.json"), + r#" + { + "include": ["src/**/*.ts"], + "exclude": ["generated/**/*.ts"] + } + "#, + ); + write( + fixture.path().join("noop-generated-exclude/src/index.ts"), + "export const ok = true;\n", + ); let project = discover_project(fixture.path()).expect("project should discover"); let outcome = run_tsconfig_check(&project).expect("check should run"); @@ -913,33 +926,48 @@ fn tsconfig_pattern_severity_contract_keeps_noop_excludes_non_blocking() { .join("noop-node-modules-exclude/tsconfig.json") .to_string_lossy() ); + assert!( + outcome + .findings + .iter() + .all(|finding| finding.id != noop_exclude_id), + "default node_modules exclude should not report no-op audit noise" + ); + + let non_default_noop_exclude_id = format!( + "tsconfig-patterns:{}:exclude:generated/**/*.ts", + fixture + .path() + .join("noop-generated-exclude/tsconfig.json") + .to_string_lossy() + ); assert_has_finding( &outcome.findings, - &noop_exclude_id, + &non_default_noop_exclude_id, Severity::Info, "Exclude pattern does not filter any included files", &format!( - "exclude pattern \"node_modules\" removed 0 files from 1 included file(s) under base dir {}.", + "exclude pattern \"generated/**/*.ts\" removed 0 files from 1 included file(s) under base dir {}.", fixture .path() - .join("noop-node-modules-exclude") + .join("noop-generated-exclude") .to_string_lossy() ), "Remove or tighten exclude entries that do not change the effective TypeScript input set.", Some( fixture .path() - .join("noop-node-modules-exclude/tsconfig.json"), + .join("noop-generated-exclude/tsconfig.json"), ), ); - let noop_exclude_finding = outcome + let non_default_noop_exclude_finding = outcome .findings .iter() - .find(|finding| finding.id == noop_exclude_id) - .expect("no-op node_modules exclude finding should exist"); + .find(|finding| finding.id == non_default_noop_exclude_id) + .expect("non-default no-op exclude finding should exist"); let summary = summarize_findings( - std::slice::from_ref(noop_exclude_finding), + std::slice::from_ref(non_default_noop_exclude_finding), &outcome.fixes, &StructureReport { is_monorepo: false,