- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 11
fix(language): ref resolution failure causes exception in validator #269
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| WalkthroughAdds ZModelDocumentBuilder and registers it in the shared module; validators now run unconditionally; utilities tolerate unresolved mixin/baseModel references; test names/content adjusted; VS Code extension version bumped from 3.0.6 to 3.0.8. Changes
 Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
 Poem
 Pre-merge checks and finishing touches✅ Passed checks (3 passed)
 ✨ Finishing touches
 🧪 Generate unit tests
 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  | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes a bug where unresolved references in mixins and base models would cause exceptions in the validator. The fix replaces invariant assertions with conditional checks to gracefully handle missing references.
- Replaced invariantcalls with null checks for mixin and base model references
- Updated VS Code extension version from 3.0.6 to 3.0.8
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description | 
|---|---|
| packages/language/src/utils.ts | Replaced invariant assertions with conditional checks for ref resolution | 
| packages/ide/vscode/package.json | Version bump to 3.0.8 | 
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| Claude finished @ymc9's task —— View job Pull Request ReviewTodo List: 
 Code Quality AnalysisThis PR addresses a validator exception issue by replacing  Positive Aspects:
 Potential Concerns:
 Recommendations:
 Security & Performance
 Test CoverageThe fix appears to lack test coverage. Consider adding: 
 Version BumpThe VSCode extension version bump from 3.0.6 to 3.0.8 seems appropriate for a bug fix release. Overall AssessmentThis is a solid defensive fix that prevents validator crashes. The approach is pragmatic, though ideally it would include better error reporting. The silent failure approach may be acceptable if this occurs during incremental parsing/validation where complete resolution isn't expected. Recommendation: Approve with consideration for adding warning logs in a follow-up PR. | 
| Claude finished @ymc9's task —— View job Pull Request ReviewTodo List: 
 Code Quality AnalysisThis PR addresses a validator exception issue by replacing  Positive Aspects:
 Potential Concerns:
 Recommendations:
 Security & Performance
 Test CoverageThe fix appears to lack test coverage. Consider adding: 
 Version BumpThe VSCode extension version bump from 3.0.6 to 3.0.8 seems appropriate for a bug fix release. Overall AssessmentThis is a solid defensive fix that prevents validator crashes. The approach is pragmatic, though ideally it would include better error reporting. The silent failure approach may be acceptable if this occurs during incremental parsing/validation where complete resolution isn't expected. Recommendation: Approve with consideration for adding warning logs in a follow-up PR. | 
| Claude finished @ymc9's task —— View job Pull Request ReviewTodo List: 
 Code Quality AnalysisThis PR addresses a validator exception issue by replacing  Positive Aspects:
 Potential Concerns:
 Recommendations:
 Security & Performance
 Test CoverageThe fix appears to lack test coverage. Consider adding: 
 Version BumpThe VSCode extension version bump from 3.0.6 to 3.0.8 seems appropriate for a bug fix release. Overall AssessmentThis is a solid defensive fix that prevents validator crashes. The approach is pragmatic, though ideally it would include better error reporting. The silent failure approach may be acceptable if this occurs during incremental parsing/validation where complete resolution isn't expected. Recommendation: Approve with consideration for adding warning logs in a follow-up PR. | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
packages/language/src/validator.ts (1)
51-85: Unconditional validations: verify no noise on stdlib or partially‑linked docsRunning all checks unconditionally is fine given the new builder settings; please confirm it doesn’t surface diagnostics for stdlib/plugin modules or when linking is incomplete.
Minor perf refactor: reuse validator instances instead of re‑instantiating per node.
- checkModel(node: Model, accept: ValidationAcceptor): void { - new SchemaValidator(this.services.shared.workspace.LangiumDocuments).validate(node, accept); - } + checkModel(node: Model, accept: ValidationAcceptor): void { + this.schemaValidator.validate(node, accept); + } - checkDataSource(node: DataSource, accept: ValidationAcceptor): void { - new DataSourceValidator().validate(node, accept); - } + checkDataSource(node: DataSource, accept: ValidationAcceptor): void { + this.dataSourceValidator.validate(node, accept); + } - checkDataModel(node: DataModel, accept: ValidationAcceptor): void { - new DataModelValidator().validate(node, accept); - } + checkDataModel(node: DataModel, accept: ValidationAcceptor): void { + this.dataModelValidator.validate(node, accept); + } - checkTypeDef(node: TypeDef, accept: ValidationAcceptor): void { - new TypeDefValidator().validate(node, accept); - } + checkTypeDef(node: TypeDef, accept: ValidationAcceptor): void { + this.typeDefValidator.validate(node, accept); + } - checkEnum(node: Enum, accept: ValidationAcceptor): void { - new EnumValidator().validate(node, accept); - } + checkEnum(node: Enum, accept: ValidationAcceptor): void { + this.enumValidator.validate(node, accept); + } - checkAttribute(node: Attribute, accept: ValidationAcceptor): void { - new AttributeValidator().validate(node, accept); - } + checkAttribute(node: Attribute, accept: ValidationAcceptor): void { + this.attributeValidator.validate(node, accept); + } - checkExpression(node: Expression, accept: ValidationAcceptor): void { - new ExpressionValidator().validate(node, accept); - } + checkExpression(node: Expression, accept: ValidationAcceptor): void { + this.expressionValidator.validate(node, accept); + } - checkFunctionInvocation(node: InvocationExpr, accept: ValidationAcceptor): void { - new FunctionInvocationValidator().validate(node, accept); - } + checkFunctionInvocation(node: InvocationExpr, accept: ValidationAcceptor): void { + this.functionInvocationValidator.validate(node, accept); + } - checkFunctionDecl(node: FunctionDecl, accept: ValidationAcceptor): void { - new FunctionDeclValidator().validate(node, accept); - } + checkFunctionDecl(node: FunctionDecl, accept: ValidationAcceptor): void { + this.functionDeclValidator.validate(node, accept); + }Add these fields to the class:
// inside ZModelValidator private readonly schemaValidator: SchemaValidator; private readonly dataSourceValidator = new DataSourceValidator(); private readonly dataModelValidator = new DataModelValidator(); private readonly typeDefValidator = new TypeDefValidator(); private readonly enumValidator = new EnumValidator(); private readonly attributeValidator = new AttributeValidator(); private readonly expressionValidator = new ExpressionValidator(); private readonly functionInvocationValidator = new FunctionInvocationValidator(); private readonly functionDeclValidator = new FunctionDeclValidator(); constructor(protected readonly services: ZModelServices) { this.schemaValidator = new SchemaValidator(services.shared.workspace.LangiumDocuments); }packages/language/src/zmodel-document-builder.ts (2)
8-17: Preserve caller’s other validation options (deep‑merge instead of overwrite)If a caller passes a custom validation object, it gets replaced. Merge and force only the stop‑after flags.
- validation: - // force overriding validation options - options.validation === false || options.validation === undefined - ? options.validation - : { - stopAfterLexingErrors: true, - stopAfterParsingErrors: true, - stopAfterLinkingErrors: true, - }, + validation: + options.validation === false || options.validation === undefined + ? options.validation + : { + ...(typeof options.validation === 'object' ? options.validation : {}), + stopAfterLexingErrors: true, + stopAfterParsingErrors: true, + stopAfterLinkingErrors: true, + },
4-4: Type the cancellation tokenUse a proper
CancellationTokentype for better API clarity.-import { DefaultDocumentBuilder, type BuildOptions, type LangiumDocument } from 'langium'; +import { DefaultDocumentBuilder, type BuildOptions, type LangiumDocument } from 'langium'; +import type { CancellationToken } from 'vscode-jsonrpc'; -export class ZModelDocumentBuilder extends DefaultDocumentBuilder { - override buildDocuments(documents: LangiumDocument[], options: BuildOptions, cancelToken: any): Promise<void> { +export class ZModelDocumentBuilder extends DefaultDocumentBuilder { + override buildDocuments( + documents: LangiumDocument[], + options: BuildOptions, + cancelToken: CancellationToken, + ): Promise<void> {
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
- packages/language/src/module.ts(2 hunks)
- packages/language/src/utils.ts(3 hunks)
- packages/language/src/validator.ts(2 hunks)
- packages/language/src/zmodel-document-builder.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
{packages,samples,tests}/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place packages only under
packages/,samples/, ortests/
Files:
- packages/language/src/module.ts
- packages/language/src/utils.ts
- packages/language/src/validator.ts
- packages/language/src/zmodel-document-builder.ts
🧬 Code graph analysis (3)
packages/language/src/module.ts (1)
packages/language/src/zmodel-document-builder.ts (1)
ZModelDocumentBuilder(3-22)
packages/language/src/utils.ts (1)
packages/language/src/generated/ast.ts (4)
TypeDef(725-733)
TypeDef(735-735)
isTypeDef(737-739)
isDataModel(391-393)
packages/language/src/validator.ts (1)
packages/language/src/validators/schema-validator.ts (1)
SchemaValidator(10-58)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: build-test (20.x, sqlite)
- GitHub Check: build-test (20.x, postgresql)
🔇 Additional comments (3)
packages/language/src/utils.ts (2)
522-525: Good: guard unresolved refs to prevent pre‑link exceptionsThe defensive checks on
mixin.refanddecl.baseModel.refmake field/attribute aggregation resilient during early phases.Confirm that skipping unresolved mixins/base models is acceptable for callers that may rely on partial results pre‑link (no hidden regressions in validations or codegen).
Also applies to: 528-531, 548-551, 554-557
174-177: Avoid regression: prefer mixin.ref with fallback to name lookupOnly searching decl.$container.declarations can miss imported mixins that resolve after linking — use mixin.ref when present and fall back to name lookup pre-link.
File: packages/language/src/utils.ts (lines 174–177)
- const baseDecl = decl.$container.declarations.find( - (d): d is TypeDef => isTypeDef(d) && d.name === mixin.$refText, - ); + const baseDecl = + mixin.ref ?? + decl.$container.declarations.find( + (d): d is TypeDef => isTypeDef(d) && d.name === mixin.$refText, + );packages/language/src/module.ts (1)
53-53: LGTM: register custom DocumentBuilderBinding
DocumentBuildertoZModelDocumentBuilderin shared services is correct and composes cleanly with the existingWorkspaceManager.
| Claude finished @ymc9's task —— View job Pull Request ReviewTodo List: 
 Code Quality AnalysisThis PR addresses a validator exception issue by replacing  Positive Aspects:
 Potential Concerns:
 Specific Issues Found:
 Recommendations:
 Security & Performance
 Test CoverageThe PR includes minimal test changes in  
 Version BumpThe VSCode extension version bump from 3.0.6 to 3.0.8 is appropriate for a bug fix release. Overall AssessmentThis is a solid defensive fix that prevents validator crashes during incremental parsing/validation phases. The approach is pragmatic for handling incomplete reference resolution in development environments. However, the silent failure approach should ideally include better error reporting for debugging purposes. The architectural changes with  Recommendation: Approve with consideration for adding warning logs and performance optimizations in follow-up PRs. | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/language/test/expression-validation.test.ts (1)
26-26: Make the second test title specificAvoid numeric suffixes; be explicit about what’s compared.
Proposed change:
-it('should reject model comparison2', async () => { +it('should reject comparing relation field to this (User.profile vs User)', async () => {
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
- packages/language/test/expression-validation.test.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
{packages,samples,tests}/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place packages only under
packages/,samples/, ortests/
Files:
- packages/language/test/expression-validation.test.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: build-test (20.x, sqlite)
- GitHub Check: build-test (20.x, postgresql)
- GitHub Check: claude-review
🔇 Additional comments (2)
packages/language/test/expression-validation.test.ts (2)
18-18: Good fix: relation scalar field addedAdding
authorId Intcorrectly satisfies the@relation(fields: [authorId], references: [id])requirement and avoids unrelated schema errors masking the intended validation.
5-5: Rename test to a descriptive title; loadSchemaWithError already checks substringsReplace the test title as suggested — no changes needed to the error assertions: loadSchemaWithError checks case-insensitive substring matches for string errors and supports RegExp.
-it('should reject model comparison1', async () => { +it('should reject comparing relation field to this (Post.author vs Post)', async () => {
Summary by CodeRabbit