fix(canon): keep repeated component prop names from redeclaring checks#3202
Conversation
A static attribute next to a bound attribute of the same name — most commonly class="card" beside :class="expr" — made the per-prop path introduced for static values emit the same check constant and the same prop type alias twice, so the virtual TS failed with TS2451/TS2300 redeclarations on real projects and masked the surrounding diagnostics. The child prop type alias is now declared once per distinct prop name, and every additional occurrence of a name gets an occurrence-suffixed check constant, so each authored value still checks against the child's prop type without colliding.
📝 WalkthroughWalkthroughVirtual TypeScript generation now emits one prop type alias per safe prop name, unique synthetic check constants for repeated attributes, and shared recursion for nested v-for and v-slot closure scopes. A regression test covers repeated static and dynamic ChangesRepeated component prop handling
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
vize
@vizejs/fresco
@vizejs/musea-mcp-server
oxlint-plugin-vize
@vizejs/rspack-plugin
@vizejs/unplugin
@vizejs/vite-plugin
@vizejs/vite-plugin-musea
@vizejs/musea-nuxt
@vizejs/nuxt
@vizeui/core
commit: |
PR BenchmarkBase:
Raw run timesCompile SFC
Lint
Format
Type check (1T)
Type check (max)
|
Detailed Test ReportCommit: Area Summary
Test InventoryTotal tracked cases: 9476 across 1465 files.
Files
Comment truncated at 64000 characters. Open the workflow run for the full job log. |
Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
PR BenchmarkBase:
Raw run timesCompile SFC
Lint
Format
Type check (1T)
Type check (max)
|
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/vize_canon/src/virtual_ts/scope/component_props.rs (1)
116-119: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueDefer computing
camel_prop_nameto avoid unnecessary allocations.Since
camel_prop_nameisn't required for the deduplication check, you can compute it after thecontinuestatement to avoid allocating strings for duplicate props.♻️ Proposed refactor
- let camel_prop_name = to_camel_case(prop.name.as_str()); let safe_prop_name = to_safe_identifier_fragment(prop.name.as_str()); if !declared_aliases.insert(safe_prop_name.clone()) { continue; } + let camel_prop_name = to_camel_case(prop.name.as_str());🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/vize_canon/src/virtual_ts/scope/component_props.rs` around lines 116 - 119, In the prop-processing flow, defer the to_camel_case computation for camel_prop_name until after the declared_aliases.insert deduplication check. Keep safe_prop_name and duplicate handling unchanged, and only allocate camel_prop_name for non-duplicate props.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@crates/vize_canon/src/virtual_ts/scope/component_props.rs`:
- Around line 116-119: In the prop-processing flow, defer the to_camel_case
computation for camel_prop_name until after the declared_aliases.insert
deduplication check. Keep safe_prop_name and duplicate handling unchanged, and
only allocate camel_prop_name for non-duplicate props.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 838b0dd6-5cce-4049-b38d-3772a79266fb
📒 Files selected for processing (1)
crates/vize_canon/src/virtual_ts/scope/component_props.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (27)
- GitHub Check: tool-benchmark
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: pr-benchmark
- GitHub Check: app-readiness
- GitHub Check: Analyze (python)
- GitHub Check: cargo-semver-checks (vize_croquis)
- GitHub Check: cargo-semver-checks (vize_atelier_vapor)
- GitHub Check: cargo-semver-checks (vize_atelier_dom)
- GitHub Check: cargo-semver-checks (vize_atelier_sfc)
- GitHub Check: cargo-semver-checks (vize_fresco)
- GitHub Check: Publish preview packages
- GitHub Check: vue-parity
- GitHub Check: cargo-semver-checks (vize_musea)
- GitHub Check: clippy-and-test
- GitHub Check: coverage
- GitHub Check: test-js-packages
- GitHub Check: cargo-semver-checks (vize_atelier_ssr)
- GitHub Check: check-vize-apps
- GitHub Check: criterion-ab
- GitHub Check: cargo-semver-checks (vize_atelier_core)
- GitHub Check: build-js-packages
- GitHub Check: test-scripts
- GitHub Check: editor-extensions
- GitHub Check: dialect-guard
- GitHub Check: check-js
- GitHub Check: security-audit
- GitHub Check: miri
🧰 Additional context used
📓 Path-based instructions (1)
crates/**
⚙️ CodeRabbit configuration file
crates/**: Focus on parser/compiler correctness, source locations, UTF-8/UTF-16 offset handling, and panic-free LSP behavior. Flag changes that only work for small fixtures but break real Vue/Nuxt projects.
Files:
crates/vize_canon/src/virtual_ts/scope/component_props.rs
🔇 Additional comments (1)
crates/vize_canon/src/virtual_ts/scope/component_props.rs (1)
395-397: 📐 Maintainability & Code Quality
let_chainsis supported on the pinned toolchain The crate targets Rust 1.95.0, soif let ... && matches!(...)is valid here and does not need to be rewritten.> Likely an incorrect or invalid review comment.
Detailed Test ReportCommit: Area Summary
Test InventoryTotal tracked cases: 9476 across 1465 files.
Files
Comment truncated at 64000 characters. Open the workflow run for the full job log. |
Tool BenchmarkMeasured: 2026-07-21T12:49:46.449Z
Fairness notes:
Commands: gh workflow run tool-benchmark.yml --ref <branch> -f file_count=3000 -f check_file_count=500 -f vite_file_count=1000 -f nuxt_file_count=250 -f large_blocks=300 -f runs=3 -f warmups=1 -f commit_results=true
node bench/generate.mjs 3000
node bench/compare-tools.mjs --input bench/__in__ --vize-bin target/release/vize --runs 3 --warmups 1 --check-file-count 500 --vite-file-count 1000 --nuxt-file-count 250 --large-blocks 300 --runner-label "blacksmith-32vcpu-ubuntu-2404" --out tool-benchmark-summary.md --json tool-benchmark-results.json --doc performance-blacksmith.mdVariant details and raw run timesSFC compile
Large SFC compile
Large SFC type check
Lint
Format
Type check
Vite build (end-to-end)
Nuxt SPA build (end-to-end)
|
Summary
Hotfix for a regression introduced by #3197 (static attribute prop checks): a static attribute next to a bound attribute of the same name — most commonly
class="card"beside:class="expr"— emitted the same__vize_prop_check_{idx}_{name}constant and the same__{Component}_{idx}_prop_{name}type alias twice, so the virtual TS failed withTS2451/TS2300redeclarations and masked surrounding diagnostics.Not caught earlier because the ecosystem lane's fixtures never combine a static and a bound occurrence of the same prop on one element, and the real-project matrix (misskey, reka-ui, nuxt-ui show exactly these collisions against their stale snapshots) has not run since #3197 merged — this would have turned the release-preflight matrix red on its next run.
Fix
__vize_prop_check_0_class,__vize_prop_check_0_class_2), so each authored value still checks against the child's prop type — both the static string and the bound expression remain covered.Verification
<HelloWorld :msg="count" class="card" :class="{ active: count > 0 }" />): the pre-fix binary reports twoTS2451redeclarations; the fixed binary reports only the two legitimateTS2322s.vize_canonsuite green (629 tests), fmt/clippy clean.Part of #2971
Need help on this PR? Tag
/codesmithwith what you need. Autofix is enabled.Summary by CodeRabbit