feat(cli): improve validate command with JSON output and file filter#2790
feat(cli): improve validate command with JSON output and file filter#2790
Conversation
Co-Authored-By: Claude Opus 4.6 <[email protected]>
🦋 Changeset detectedLatest commit: e325972 The changes in this PR will be included in the next version bump. This PR includes changesets to release 20 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Co-Authored-By: Claude Opus 4.6 <[email protected]>
📝 WalkthroughWalkthroughExtends the Changes
Sequence Diagram(s)sequenceDiagram
participant CLI as Validate Command
participant LS as Language Services
participant Layout as Layout Validator
participant Filter as File Filter
participant Output as Output Handler
CLI->>LS: init(printErrors based on --json, throwIfInvalid: false)
LS->>LS: getErrors() from userDocuments
LS-->>CLI: model diagnostics
alt layout enabled
CLI->>Layout: diagrams(project)
Layout-->>CLI: layout diagnostics
end
CLI->>Filter: apply --file filters
Filter-->>CLI: filtered diagnostics
alt --json
CLI->>Output: serialize ValidateResult (stats + diagnostics)
Output-->>CLI: print JSON
else
CLI->>Output: log layout diagnostics (if any)
CLI->>Output: log summary and success/failure
end
CLI->>CLI: set process.exitCode (0 or 1)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
📝 Coding Plan
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 |
Signed-off-by: Denis Davydkov <[email protected]>
There was a problem hiding this comment.
🧹 Nitpick comments (4)
packages/language-services/src/common/LikeC4.ts (3)
197-202: Consider iterating to count instead of spreading.Spreading the iterator into an array allocates memory just to get the count. If
userDocumentsis large, this could be inefficient.♻️ Alternative using iteration
documentCount(): number { - return [...this.LangiumDocuments.userDocuments].length + let count = 0 + for (const _ of this.LangiumDocuments.userDocuments) { + count++ + } + return count }Alternatively, if
LangiumDocumentsexposes asizeorcountproperty on the underlying collection, that would be even better.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/language-services/src/common/LikeC4.ts` around lines 197 - 202, The documentCount() implementation currently spreads this.LangiumDocuments.userDocuments into an array which allocates memory; change it to count via iteration (or use an existing size/length property on the underlying collection if available) to avoid allocation — iterate this.LangiumDocuments.userDocuments with a simple counter and return the counter in documentCount(), referencing the documentCount method and this.LangiumDocuments.userDocuments when locating the change.
21-23: Consider documenting the magic number.
severity === 1corresponds toDiagnosticSeverity.Errorfrom the LSP specification. A brief comment would improve readability.📝 Suggested documentation
+/** Checks if a diagnostic is an error (DiagnosticSeverity.Error === 1 in LSP). */ const isErrorDiagnostic = (diagnostic: { severity?: number }): boolean => { return diagnostic.severity === 1 }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/language-services/src/common/LikeC4.ts` around lines 21 - 23, The check in isErrorDiagnostic uses the magic number diagnostic.severity === 1; replace or document this by referencing the LSP enum (DiagnosticSeverity.Error) — either import/define a named constant like DiagnosticSeverity.Error and use it in the comparison, or add a one-line comment above isErrorDiagnostic explaining that 1 corresponds to DiagnosticSeverity.Error from the LSP spec; update the function isErrorDiagnostic to use the named constant or include the comment for clarity.
157-161: Use optional chaining for cleaner code.The static analysis tool correctly identifies that optional chaining would be more concise here.
♻️ Suggested refactor
hasErrors(): boolean { - return this.LangiumDocuments.userDocuments.some(doc => { - return doc.diagnostics && doc.diagnostics.some(isErrorDiagnostic) - }) + return this.LangiumDocuments.userDocuments.some(doc => + doc.diagnostics?.some(isErrorDiagnostic) ?? false + ) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/language-services/src/common/LikeC4.ts` around lines 157 - 161, The hasErrors() method is verbose; simplify by using optional chaining on doc.diagnostics when checking for error diagnostics. Update the implementation in LikeC4.hasErrors to use this.LangiumDocuments.userDocuments.some(doc => doc.diagnostics?.some(isErrorDiagnostic)) (or equivalent) so you avoid explicit && checks and make the code more concise and readable.packages/likec4/src/cli/validate/index.ts (1)
145-154: ClarifyfilteredFilessemantics in stats.When no file filter is applied,
filteredFilesis set tototalFiles(total documents parsed). However, when a filter is applied,filteredFilesis the count of unique files with errors. This asymmetry may confuse consumers of the JSON output.Consider whether
filteredFilesshould consistently represent "files with errors" or "files considered in validation."📝 Option: Consistent "files with errors" semantics
+ const allFileSet = new Set(allErrors.map(e => e.file)) const filteredFileSet = new Set(filteredErrors.map(e => e.file)) const result: ValidateResult = { valid, errors: filteredErrors, stats: { totalFiles, totalErrors, - filteredFiles: fileFilter ? filteredFileSet.size : totalFiles, + filteredFiles: fileFilter ? filteredFileSet.size : allFileSet.size, filteredErrors: filteredErrors.length, }, }Alternatively, document the current behavior clearly in a JSDoc comment on
ValidateResult.stats.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/likec4/src/cli/validate/index.ts` around lines 145 - 154, The stats field is inconsistent: filteredFiles currently equals totalFiles when no fileFilter is set but equals the count of unique error files when a filter is applied; make it consistent by defining filteredFiles to always mean "files with errors." Update the construction of result.stats in the block that builds ValidateResult so filteredFiles is always set to filteredFileSet.size (ensure filteredFileSet is populated with files that have errors regardless of fileFilter), and add or update a JSDoc on ValidateResult.stats to state that filteredFiles represents the number of files with validation errors.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/language-services/src/common/LikeC4.ts`:
- Around line 197-202: The documentCount() implementation currently spreads
this.LangiumDocuments.userDocuments into an array which allocates memory; change
it to count via iteration (or use an existing size/length property on the
underlying collection if available) to avoid allocation — iterate
this.LangiumDocuments.userDocuments with a simple counter and return the counter
in documentCount(), referencing the documentCount method and
this.LangiumDocuments.userDocuments when locating the change.
- Around line 21-23: The check in isErrorDiagnostic uses the magic number
diagnostic.severity === 1; replace or document this by referencing the LSP enum
(DiagnosticSeverity.Error) — either import/define a named constant like
DiagnosticSeverity.Error and use it in the comparison, or add a one-line comment
above isErrorDiagnostic explaining that 1 corresponds to
DiagnosticSeverity.Error from the LSP spec; update the function
isErrorDiagnostic to use the named constant or include the comment for clarity.
- Around line 157-161: The hasErrors() method is verbose; simplify by using
optional chaining on doc.diagnostics when checking for error diagnostics. Update
the implementation in LikeC4.hasErrors to use
this.LangiumDocuments.userDocuments.some(doc =>
doc.diagnostics?.some(isErrorDiagnostic)) (or equivalent) so you avoid explicit
&& checks and make the code more concise and readable.
In `@packages/likec4/src/cli/validate/index.ts`:
- Around line 145-154: The stats field is inconsistent: filteredFiles currently
equals totalFiles when no fileFilter is set but equals the count of unique error
files when a filter is applied; make it consistent by defining filteredFiles to
always mean "files with errors." Update the construction of result.stats in the
block that builds ValidateResult so filteredFiles is always set to
filteredFileSet.size (ensure filteredFileSet is populated with files that have
errors regardless of fileFilter), and add or update a JSDoc on
ValidateResult.stats to state that filteredFiles represents the number of files
with validation errors.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c0d4fe39-f10e-49e0-826b-43fd2c040baf
📒 Files selected for processing (6)
.changeset/improve-validate-command.mdpackages/language-services/src/common/LikeC4.tspackages/likec4/src/cli/check-update/utils.tspackages/likec4/src/cli/index.tspackages/likec4/src/cli/options.tspackages/likec4/src/cli/validate/index.ts
…kec4 into feat/cli-validate-improvements
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/language-services/src/common/LikeC4.ts (1)
167-169: Use optional chaining inhasErrors()for cleaner boolean logic.The current expression works, but optional chaining + nullish coalescing is more idiomatic. Note that the same method (
printErrors()) on line 177 already uses this pattern (doc.diagnostics?.filter(isErrorDiagnostic) ?? []).Proposed diff
hasErrors(): boolean { - return this.LangiumDocuments.userDocuments.some(doc => { - return doc.diagnostics && doc.diagnostics.some(isErrorDiagnostic) - }) + return this.LangiumDocuments.userDocuments.some(doc => { + return doc.diagnostics?.some(isErrorDiagnostic) ?? false + }) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/language-services/src/common/LikeC4.ts` around lines 167 - 169, The hasErrors() method currently uses explicit truthiness checks for doc.diagnostics; update it to use optional chaining and nullish coalescing like printErrors() does: inside the arrow passed to this.LangiumDocuments.userDocuments.some, replace the existing doc.diagnostics && doc.diagnostics.some(...) logic with an expression that calls doc.diagnostics?.some(isErrorDiagnostic) ?? false so missing diagnostics are treated as false; this keeps behavior identical but uses the more idiomatic optional chaining pattern.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/language-services/src/common/LikeC4.ts`:
- Around line 167-169: The hasErrors() method currently uses explicit truthiness
checks for doc.diagnostics; update it to use optional chaining and nullish
coalescing like printErrors() does: inside the arrow passed to
this.LangiumDocuments.userDocuments.some, replace the existing doc.diagnostics
&& doc.diagnostics.some(...) logic with an expression that calls
doc.diagnostics?.some(isErrorDiagnostic) ?? false so missing diagnostics are
treated as false; this keeps behavior identical but uses the more idiomatic
optional chaining pattern.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ac80998f-0c75-41af-ac20-059a11451f77
📒 Files selected for processing (1)
packages/language-services/src/common/LikeC4.ts
Summary
--jsonflag for structured JSON output fromlikec4 validate--fileflag to filter validation errors to specific files--no-layoutflag to skip layout drift checksdocumentCount()method to language servicesSplit from #2782 (CLI changes only, SKILL work remains in #2782).
Test plan
likec4 validatereturns exit code 0 on success, 1 on failurelikec4 validate --jsonoutputs structured JSONlikec4 validate --file <path>filters to specific filelikec4 validate --no-layoutskips layout drift checks🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
likec4 validatewith options:--json,--file(filter),--no-layout, and--project.Bug Fixes / Behavior