From b4586ccf3deb52e40a3aee5974aca8410723d4b8 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Wed, 24 Sep 2025 08:31:23 -0700 Subject: [PATCH 1/3] fix(language): some references are not resolved; suppress validation on previous errors --- packages/language/src/index.ts | 6 ++- .../language/src/zmodel-document-builder.ts | 40 ++++++++++--------- packages/language/src/zmodel-linker.ts | 9 +---- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/packages/language/src/index.ts b/packages/language/src/index.ts index 6b2cb56a..4b578f31 100644 --- a/packages/language/src/index.ts +++ b/packages/language/src/index.ts @@ -70,7 +70,11 @@ export async function loadDocument( // build the document together with standard library, plugin modules, and imported documents await services.shared.workspace.DocumentBuilder.build([stdLib, ...pluginDocs, document, ...importedDocuments], { - validation: true, + validation: { + stopAfterLexingErrors: true, + stopAfterParsingErrors: true, + stopAfterLinkingErrors: true, + }, }); const diagnostics = langiumDocuments.all diff --git a/packages/language/src/zmodel-document-builder.ts b/packages/language/src/zmodel-document-builder.ts index 8e55e267..cddfc80b 100644 --- a/packages/language/src/zmodel-document-builder.ts +++ b/packages/language/src/zmodel-document-builder.ts @@ -1,22 +1,26 @@ -import { DefaultDocumentBuilder, type BuildOptions, type LangiumDocument } from 'langium'; +import { DefaultDocumentBuilder, type LangiumSharedCoreServices } from 'langium'; export class ZModelDocumentBuilder extends DefaultDocumentBuilder { - override buildDocuments(documents: LangiumDocument[], options: BuildOptions, cancelToken: any): Promise { - return super.buildDocuments( - documents, - { - ...options, - validation: - // force overriding validation options - options.validation === false || options.validation === undefined - ? options.validation - : { - stopAfterLexingErrors: true, - stopAfterParsingErrors: true, - stopAfterLinkingErrors: true, - }, - }, - cancelToken, - ); + constructor(services: LangiumSharedCoreServices) { + super(services); + + // override update build options to skip validation when there are + // errors in the previous stages + let validationOptions = this.updateBuildOptions.validation; + const stopFlags = { + stopAfterLinkingErrors: true, + stopAfterLexingErrors: true, + stopAfterParsingErrors: true, + }; + if (validationOptions === true) { + validationOptions = stopFlags; + } else if (typeof validationOptions === 'object') { + validationOptions = { ...validationOptions, ...stopFlags }; + } + + this.updateBuildOptions = { + ...this.updateBuildOptions, + validation: validationOptions, + }; } } diff --git a/packages/language/src/zmodel-linker.ts b/packages/language/src/zmodel-linker.ts index 65a2cb84..ee0c6993 100644 --- a/packages/language/src/zmodel-linker.ts +++ b/packages/language/src/zmodel-linker.ts @@ -11,7 +11,6 @@ import { type LinkingError, type Reference, interruptAndCheck, - isReference, } from 'langium'; import { match } from 'ts-pattern'; import { @@ -495,13 +494,7 @@ export class ZModelLinker extends DefaultLinker { } private resolveDefault(node: AstNode, document: LangiumDocument, extraScopes: ScopeProvider[]) { - for (const [property, value] of Object.entries(node)) { - if (!property.startsWith('$')) { - if (isReference(value)) { - this.linkReference(node, property, document, extraScopes); - } - } - } + AstUtils.streamReferences(node).forEach((ref) => this.doLink(ref, document)); for (const child of AstUtils.streamContents(node)) { this.resolve(child, document, extraScopes); } From 7599235ccbab397a740c82a803a4e46e557a23fd Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Wed, 24 Sep 2025 08:47:09 -0700 Subject: [PATCH 2/3] update --- packages/ide/vscode/package.json | 2 +- packages/language/src/zmodel-linker.ts | 28 ++++++++++---------------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/packages/ide/vscode/package.json b/packages/ide/vscode/package.json index 00efbd79..ac3667af 100644 --- a/packages/ide/vscode/package.json +++ b/packages/ide/vscode/package.json @@ -1,7 +1,7 @@ { "name": "zenstack-v3", "publisher": "zenstack", - "version": "3.0.8", + "version": "3.0.9", "displayName": "ZenStack V3 Language Tools", "description": "VSCode extension for ZenStack (v3) ZModel language", "private": true, diff --git a/packages/language/src/zmodel-linker.ts b/packages/language/src/zmodel-linker.ts index ee0c6993..91f6850d 100644 --- a/packages/language/src/zmodel-linker.ts +++ b/packages/language/src/zmodel-linker.ts @@ -10,6 +10,7 @@ import { type LangiumDocument, type LinkingError, type Reference, + type ReferenceInfo, interruptAndCheck, } from 'langium'; import { match } from 'ts-pattern'; @@ -93,18 +94,11 @@ export class ZModelLinker extends DefaultLinker { document.state = DocumentState.Linked; } - private linkReference( - container: AstNode, - property: string, - document: LangiumDocument, - extraScopes: ScopeProvider[], - ) { - if (this.resolveFromScopeProviders(container, property, document, extraScopes)) { + private linkReference(refInfo: ReferenceInfo, document: LangiumDocument, extraScopes: ScopeProvider[]) { + if (this.resolveFromScopeProviders(refInfo.reference, document, extraScopes)) { return; } - - const reference: DefaultReference = (container as any)[property]; - this.doLink({ reference, container, property }, document); + this.doLink(refInfo, document); } //#endregion @@ -112,12 +106,10 @@ export class ZModelLinker extends DefaultLinker { //#region Expression type resolving private resolveFromScopeProviders( - node: AstNode, - property: string, + reference: DefaultReference, document: LangiumDocument, providers: ScopeProvider[], ) { - const reference: DefaultReference = (node as any)[property]; for (const provider of providers) { const target = provider(reference.$refText); if (target) { @@ -275,7 +267,7 @@ export class ZModelLinker extends DefaultLinker { } private resolveInvocation(node: InvocationExpr, document: LangiumDocument, extraScopes: ScopeProvider[]) { - this.linkReference(node, 'function', document, extraScopes); + this.linkReference({ reference: node.function, container: node, property: 'function' }, document, extraScopes); node.args.forEach((arg) => this.resolve(arg, document, extraScopes)); if (node.function.ref) { const funcDecl = node.function.ref as FunctionDecl; @@ -400,7 +392,7 @@ export class ZModelLinker extends DefaultLinker { if (isArrayExpr(node.value)) { node.value.items.forEach((item) => { if (isReferenceExpr(item)) { - const resolved = this.resolveFromScopeProviders(item, 'target', document, [scopeProvider]); + const resolved = this.resolveFromScopeProviders(item.target, document, [scopeProvider]); if (resolved) { this.resolveToDeclaredType(item, (resolved as DataField).type); } else { @@ -413,7 +405,7 @@ export class ZModelLinker extends DefaultLinker { this.resolveToBuiltinTypeOrDecl(node.value, node.value.items[0].$resolvedType.decl, true); } } else if (isReferenceExpr(node.value)) { - const resolved = this.resolveFromScopeProviders(node.value, 'target', document, [scopeProvider]); + const resolved = this.resolveFromScopeProviders(node.value.target, document, [scopeProvider]); if (resolved) { this.resolveToDeclaredType(node.value, (resolved as DataField).type); } else { @@ -494,7 +486,9 @@ export class ZModelLinker extends DefaultLinker { } private resolveDefault(node: AstNode, document: LangiumDocument, extraScopes: ScopeProvider[]) { - AstUtils.streamReferences(node).forEach((ref) => this.doLink(ref, document)); + AstUtils.streamReferences(node).forEach((ref) => { + this.linkReference(ref, document, extraScopes); + }); for (const child of AstUtils.streamContents(node)) { this.resolve(child, document, extraScopes); } From bc004983c972c6b7bc710d420ff8e48aa30d090a Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Wed, 24 Sep 2025 09:13:25 -0700 Subject: [PATCH 3/3] addressing comments --- packages/language/src/zmodel-linker.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/language/src/zmodel-linker.ts b/packages/language/src/zmodel-linker.ts index 91f6850d..9b045283 100644 --- a/packages/language/src/zmodel-linker.ts +++ b/packages/language/src/zmodel-linker.ts @@ -95,9 +95,16 @@ export class ZModelLinker extends DefaultLinker { } private linkReference(refInfo: ReferenceInfo, document: LangiumDocument, extraScopes: ScopeProvider[]) { + const defaultRef = refInfo.reference as DefaultReference; + if (defaultRef._ref) { + // already linked + return; + } if (this.resolveFromScopeProviders(refInfo.reference, document, extraScopes)) { + // resolved from additional scope provider return; } + // default linking this.doLink(refInfo, document); }