Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions crates/vite_global_cli/src/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,10 @@ fn delegated_help_doc(command: &str) -> Option<HelpDoc> {
row("--fix", "Auto-fix format and lint issues"),
row("--no-fmt", "Skip format check"),
row("--no-lint", "Skip lint check"),
row(
"--type-check-only",
"Run only type checking, skipping format and lint rules",
),
row("-h, --help", "Print help"),
],
),
Expand Down
24 changes: 24 additions & 0 deletions packages/cli/binding/src/check/analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pub(super) struct LintFailure {
pub(super) enum LintMessageKind {
LintOnly,
LintAndTypeCheck,
TypeCheckOnly,
}

impl LintMessageKind {
Expand All @@ -56,20 +57,23 @@ impl LintMessageKind {
match self {
Self::LintOnly => "Found no warnings or lint errors",
Self::LintAndTypeCheck => "Found no warnings, lint errors, or type errors",
Self::TypeCheckOnly => "Found no type errors",
}
}

pub(super) fn warning_heading(self) -> &'static str {
match self {
Self::LintOnly => "Lint warnings found",
Self::LintAndTypeCheck => "Lint or type warnings found",
Self::TypeCheckOnly => "Type warnings found",
}
}

pub(super) fn issue_heading(self) -> &'static str {
match self {
Self::LintOnly => "Lint issues found",
Self::LintAndTypeCheck => "Lint or type issues found",
Self::TypeCheckOnly => "Type errors found",
}
}
}
Expand Down Expand Up @@ -252,4 +256,24 @@ mod tests {
assert_eq!(kind.warning_heading(), "Lint or type warnings found");
assert_eq!(kind.issue_heading(), "Lint or type issues found");
}

#[test]
fn lint_message_kind_type_check_only_messages() {
let kind = LintMessageKind::TypeCheckOnly;

assert_eq!(kind.success_label(), "Found no type errors");
assert_eq!(kind.warning_heading(), "Type warnings found");
assert_eq!(kind.issue_heading(), "Type errors found");
}

#[test]
fn lint_message_kind_from_lint_config_does_not_return_type_check_only() {
assert_eq!(LintMessageKind::from_lint_config(None), LintMessageKind::LintOnly);
assert_eq!(
LintMessageKind::from_lint_config(Some(&json!({
"options": { "typeCheck": true }
}))),
LintMessageKind::LintAndTypeCheck
);
}
}
25 changes: 22 additions & 3 deletions packages/cli/binding/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub(crate) async fn execute_check(
fix: bool,
no_fmt: bool,
no_lint: bool,
type_check_only: bool,
paths: Vec<String>,
envs: &Arc<FxHashMap<Arc<OsStr>, Arc<OsStr>>>,
cwd: &AbsolutePathBuf,
Expand All @@ -35,13 +36,25 @@ pub(crate) async fn execute_check(
return Ok(ExitStatus(1));
}

if type_check_only && no_lint {
output::error("Conflicting flags");
print_summary_line("`vp check --type-check-only` cannot be used with `--no-lint`");
return Ok(ExitStatus(1));
}

if type_check_only && fix {
output::error("Conflicting flags");
print_summary_line("`vp check --type-check-only` cannot be used with `--fix`");
return Ok(ExitStatus(1));
}

let mut status = ExitStatus::SUCCESS;
let has_paths = !paths.is_empty();
let mut fmt_fix_started: Option<Instant> = None;
let mut deferred_lint_pass: Option<(String, String)> = None;
let resolved_vite_config = resolver.resolve_universal_vite_config().await?;

if !no_fmt {
if !no_fmt && !type_check_only {
let mut args = if fix { vec![] } else { vec!["--check".to_string()] };
if has_paths {
args.push("--no-error-on-unmatched-pattern".to_string());
Expand Down Expand Up @@ -115,8 +128,11 @@ pub(crate) async fn execute_check(
}

if !no_lint {
let lint_message_kind =
LintMessageKind::from_lint_config(resolved_vite_config.lint.as_ref());
let lint_message_kind = if type_check_only {
LintMessageKind::TypeCheckOnly
} else {
LintMessageKind::from_lint_config(resolved_vite_config.lint.as_ref())
};
let mut args = Vec::new();
if fix {
args.push("--fix".to_string());
Expand All @@ -127,6 +143,9 @@ pub(crate) async fn execute_check(
// parser think linting never started. Force the default reporter here so the
// captured output is stable across local and CI environments.
args.push("--format=default".to_string());
if type_check_only {
args.push("--type-check-only".to_string());
}
if has_paths {
args.extend(paths.iter().cloned());
}
Expand Down
12 changes: 10 additions & 2 deletions packages/cli/binding/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,17 @@ async fn execute_direct_subcommand(
let cwd_arc: Arc<AbsolutePath> = cwd.clone().into();

let status = match subcommand {
SynthesizableSubcommand::Check { fix, no_fmt, no_lint, paths } => {
SynthesizableSubcommand::Check { fix, no_fmt, no_lint, type_check_only, paths } => {
return crate::check::execute_check(
&resolver, fix, no_fmt, no_lint, paths, &envs, cwd, &cwd_arc,
&resolver,
fix,
no_fmt,
no_lint,
type_check_only,
paths,
&envs,
cwd,
&cwd_arc,
)
.await;
}
Expand Down
3 changes: 3 additions & 0 deletions packages/cli/binding/src/cli/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ pub enum SynthesizableSubcommand {
/// Skip lint check
#[arg(long = "no-lint")]
no_lint: bool,
/// Run only type checking, skipping format and lint rules
#[arg(long = "type-check-only")]
type_check_only: bool,
/// File paths to check (passed through to fmt and lint)
#[arg(trailing_var_arg = true)]
paths: Vec<String>,
Expand Down
27 changes: 15 additions & 12 deletions packages/cli/snap-tests-global/command-check-help/snap.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ Usage: vp check [OPTIONS] [PATHS]...
Run format, lint, and type checks.

Options:
--fix Auto-fix format and lint issues
--no-fmt Skip format check
--no-lint Skip lint check
-h, --help Print help
--fix Auto-fix format and lint issues
--no-fmt Skip format check
--no-lint Skip lint check
--type-check-only Run only type checking, skipping format and lint rules
-h, --help Print help

Examples:
vp check
Expand All @@ -27,10 +28,11 @@ Usage: vp check [OPTIONS] [PATHS]...
Run format, lint, and type checks.

Options:
--fix Auto-fix format and lint issues
--no-fmt Skip format check
--no-lint Skip lint check
-h, --help Print help
--fix Auto-fix format and lint issues
--no-fmt Skip format check
--no-lint Skip lint check
--type-check-only Run only type checking, skipping format and lint rules
-h, --help Print help

Examples:
vp check
Expand All @@ -48,10 +50,11 @@ Usage: vp check [OPTIONS] [PATHS]...
Run format, lint, and type checks.

Options:
--fix Auto-fix format and lint issues
--no-fmt Skip format check
--no-lint Skip lint check
-h, --help Print help
--fix Auto-fix format and lint issues
--no-fmt Skip format check
--no-lint Skip lint check
--type-check-only Run only type checking, skipping format and lint rules
-h, --help Print help

Examples:
vp check
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "check-type-check-only-conflict-fix",
"version": "0.0.0",
"private": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[1]> vp check --type-check-only --fix
error: Conflicting flags

`vp check --type-check-only` cannot be used with `--fix`
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"env": {
"VITE_DISABLE_AUTO_INSTALL": "1"
},
"commands": ["vp check --type-check-only --fix"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "check-type-check-only-conflict-no-lint",
"version": "0.0.0",
"private": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[1]> vp check --type-check-only --no-lint
error: Conflicting flags

`vp check --type-check-only` cannot be used with `--no-lint`
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"env": {
"VITE_DISABLE_AUTO_INSTALL": "1"
},
"commands": ["vp check --type-check-only --no-lint"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "check-type-check-only-fail",
"version": "0.0.0",
"private": true
}
11 changes: 11 additions & 0 deletions packages/cli/snap-tests/check-type-check-only-fail/snap.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[1]> vp check --type-check-only
error: Type errors found
× typescript(TS2322): Type 'string' is not assignable to type 'number'.
╭─[src/index.ts:2:9]
1 │ export function hello(): number {
2 │ const value: number = "not a number";
· ─────
3 │ return value;
╰────

Found 1 error and 0 warnings in 2 files (<variable>ms, <variable> threads)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export function hello(): number {
const value: number = "not a number";
return value;
}
6 changes: 6 additions & 0 deletions packages/cli/snap-tests/check-type-check-only-fail/steps.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"env": {
"VITE_DISABLE_AUTO_INSTALL": "1"
},
"commands": ["vp check --type-check-only"]
}
12 changes: 12 additions & 0 deletions packages/cli/snap-tests/check-type-check-only-fail/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "esnext",
"module": "nodenext",
"moduleResolution": "nodenext",
"strict": true,
"noEmit": true,
"allowImportingTsExtensions": true,
"skipLibCheck": true
},
"include": ["src"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default {
lint: {
options: {
typeAware: true,
typeCheck: true,
},
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "check-type-check-only-no-typecheck-config",
"version": "0.0.0",
"private": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[1]> vp check --type-check-only
error: Type errors found
× typescript(TS2322): Type 'string' is not assignable to type 'number'.
╭─[src/index.ts:2:9]
1 │ export function hello(): number {
2 │ const value: number = "not a number";
· ─────
3 │ return value;
╰────

Found 1 error and 0 warnings in 2 files (<variable>ms, <variable> threads)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export function hello(): number {
const value: number = "not a number";
return value;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"env": {
"VITE_DISABLE_AUTO_INSTALL": "1"
},
"commands": ["vp check --type-check-only"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "esnext",
"module": "nodenext",
"moduleResolution": "nodenext",
"strict": true,
"noEmit": true,
"allowImportingTsExtensions": true,
"skipLibCheck": true
},
"include": ["src"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default {
lint: {
options: {
typeAware: true,
typeCheck: false,
},
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "check-type-check-only-pass",
"version": "0.0.0",
"private": true
}
2 changes: 2 additions & 0 deletions packages/cli/snap-tests/check-type-check-only-pass/snap.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
> vp check --type-check-only
pass: Found no type errors in 2 files (<variable>ms, <variable> threads)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function hello(): string {
return "hello";
}
6 changes: 6 additions & 0 deletions packages/cli/snap-tests/check-type-check-only-pass/steps.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"env": {
"VITE_DISABLE_AUTO_INSTALL": "1"
},
"commands": ["vp check --type-check-only"]
}
12 changes: 12 additions & 0 deletions packages/cli/snap-tests/check-type-check-only-pass/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "esnext",
"module": "nodenext",
"moduleResolution": "nodenext",
"strict": true,
"noEmit": true,
"allowImportingTsExtensions": true,
"skipLibCheck": true
},
"include": ["src"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default {
lint: {
options: {
typeAware: true,
typeCheck: true,
},
},
};
Loading