Skip to content

Commit 3b13b72

Browse files
authored
fix(language): some references are not resolved; suppress validation on previous errors (#273)
* fix(language): some references are not resolved; suppress validation on previous errors * update * addressing comments
1 parent 4837cf5 commit 3b13b72

File tree

4 files changed

+46
-44
lines changed

4 files changed

+46
-44
lines changed

packages/ide/vscode/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "zenstack-v3",
33
"publisher": "zenstack",
4-
"version": "3.0.8",
4+
"version": "3.0.9",
55
"displayName": "ZenStack V3 Language Tools",
66
"description": "VSCode extension for ZenStack (v3) ZModel language",
77
"private": true,

packages/language/src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,11 @@ export async function loadDocument(
7070

7171
// build the document together with standard library, plugin modules, and imported documents
7272
await services.shared.workspace.DocumentBuilder.build([stdLib, ...pluginDocs, document, ...importedDocuments], {
73-
validation: true,
73+
validation: {
74+
stopAfterLexingErrors: true,
75+
stopAfterParsingErrors: true,
76+
stopAfterLinkingErrors: true,
77+
},
7478
});
7579

7680
const diagnostics = langiumDocuments.all
Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
1-
import { DefaultDocumentBuilder, type BuildOptions, type LangiumDocument } from 'langium';
1+
import { DefaultDocumentBuilder, type LangiumSharedCoreServices } from 'langium';
22

33
export class ZModelDocumentBuilder extends DefaultDocumentBuilder {
4-
override buildDocuments(documents: LangiumDocument[], options: BuildOptions, cancelToken: any): Promise<void> {
5-
return super.buildDocuments(
6-
documents,
7-
{
8-
...options,
9-
validation:
10-
// force overriding validation options
11-
options.validation === false || options.validation === undefined
12-
? options.validation
13-
: {
14-
stopAfterLexingErrors: true,
15-
stopAfterParsingErrors: true,
16-
stopAfterLinkingErrors: true,
17-
},
18-
},
19-
cancelToken,
20-
);
4+
constructor(services: LangiumSharedCoreServices) {
5+
super(services);
6+
7+
// override update build options to skip validation when there are
8+
// errors in the previous stages
9+
let validationOptions = this.updateBuildOptions.validation;
10+
const stopFlags = {
11+
stopAfterLinkingErrors: true,
12+
stopAfterLexingErrors: true,
13+
stopAfterParsingErrors: true,
14+
};
15+
if (validationOptions === true) {
16+
validationOptions = stopFlags;
17+
} else if (typeof validationOptions === 'object') {
18+
validationOptions = { ...validationOptions, ...stopFlags };
19+
}
20+
21+
this.updateBuildOptions = {
22+
...this.updateBuildOptions,
23+
validation: validationOptions,
24+
};
2125
}
2226
}

packages/language/src/zmodel-linker.ts

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import {
1010
type LangiumDocument,
1111
type LinkingError,
1212
type Reference,
13+
type ReferenceInfo,
1314
interruptAndCheck,
14-
isReference,
1515
} from 'langium';
1616
import { match } from 'ts-pattern';
1717
import {
@@ -94,31 +94,29 @@ export class ZModelLinker extends DefaultLinker {
9494
document.state = DocumentState.Linked;
9595
}
9696

97-
private linkReference(
98-
container: AstNode,
99-
property: string,
100-
document: LangiumDocument,
101-
extraScopes: ScopeProvider[],
102-
) {
103-
if (this.resolveFromScopeProviders(container, property, document, extraScopes)) {
97+
private linkReference(refInfo: ReferenceInfo, document: LangiumDocument, extraScopes: ScopeProvider[]) {
98+
const defaultRef = refInfo.reference as DefaultReference;
99+
if (defaultRef._ref) {
100+
// already linked
104101
return;
105102
}
106-
107-
const reference: DefaultReference = (container as any)[property];
108-
this.doLink({ reference, container, property }, document);
103+
if (this.resolveFromScopeProviders(refInfo.reference, document, extraScopes)) {
104+
// resolved from additional scope provider
105+
return;
106+
}
107+
// default linking
108+
this.doLink(refInfo, document);
109109
}
110110

111111
//#endregion
112112

113113
//#region Expression type resolving
114114

115115
private resolveFromScopeProviders(
116-
node: AstNode,
117-
property: string,
116+
reference: DefaultReference,
118117
document: LangiumDocument,
119118
providers: ScopeProvider[],
120119
) {
121-
const reference: DefaultReference = (node as any)[property];
122120
for (const provider of providers) {
123121
const target = provider(reference.$refText);
124122
if (target) {
@@ -276,7 +274,7 @@ export class ZModelLinker extends DefaultLinker {
276274
}
277275

278276
private resolveInvocation(node: InvocationExpr, document: LangiumDocument, extraScopes: ScopeProvider[]) {
279-
this.linkReference(node, 'function', document, extraScopes);
277+
this.linkReference({ reference: node.function, container: node, property: 'function' }, document, extraScopes);
280278
node.args.forEach((arg) => this.resolve(arg, document, extraScopes));
281279
if (node.function.ref) {
282280
const funcDecl = node.function.ref as FunctionDecl;
@@ -401,7 +399,7 @@ export class ZModelLinker extends DefaultLinker {
401399
if (isArrayExpr(node.value)) {
402400
node.value.items.forEach((item) => {
403401
if (isReferenceExpr(item)) {
404-
const resolved = this.resolveFromScopeProviders(item, 'target', document, [scopeProvider]);
402+
const resolved = this.resolveFromScopeProviders(item.target, document, [scopeProvider]);
405403
if (resolved) {
406404
this.resolveToDeclaredType(item, (resolved as DataField).type);
407405
} else {
@@ -414,7 +412,7 @@ export class ZModelLinker extends DefaultLinker {
414412
this.resolveToBuiltinTypeOrDecl(node.value, node.value.items[0].$resolvedType.decl, true);
415413
}
416414
} else if (isReferenceExpr(node.value)) {
417-
const resolved = this.resolveFromScopeProviders(node.value, 'target', document, [scopeProvider]);
415+
const resolved = this.resolveFromScopeProviders(node.value.target, document, [scopeProvider]);
418416
if (resolved) {
419417
this.resolveToDeclaredType(node.value, (resolved as DataField).type);
420418
} else {
@@ -495,13 +493,9 @@ export class ZModelLinker extends DefaultLinker {
495493
}
496494

497495
private resolveDefault(node: AstNode, document: LangiumDocument<AstNode>, extraScopes: ScopeProvider[]) {
498-
for (const [property, value] of Object.entries(node)) {
499-
if (!property.startsWith('$')) {
500-
if (isReference(value)) {
501-
this.linkReference(node, property, document, extraScopes);
502-
}
503-
}
504-
}
496+
AstUtils.streamReferences(node).forEach((ref) => {
497+
this.linkReference(ref, document, extraScopes);
498+
});
505499
for (const child of AstUtils.streamContents(node)) {
506500
this.resolve(child, document, extraScopes);
507501
}

0 commit comments

Comments
 (0)