Skip to content

Commit ba1e9a8

Browse files
authored
feat: stop validation after lexing/parsing errors (#662)
### Summary of Changes Linking or custom validation errors are no longer displayed if a document has lexing or parsing errors. This better highlights the criticality of those issues and ensures that users fix those first. It also prevents the display of some additional errors that were caused by the lexing or parsing errors.
1 parent 0157377 commit ba1e9a8

File tree

5 files changed

+28
-15
lines changed

5 files changed

+28
-15
lines changed

src/language/helpers/safe-ds-node-mapper.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@ import {
2929
SdsYield,
3030
} from '../generated/ast.js';
3131
import { CallableType, StaticType } from '../typing/model.js';
32-
import { findLocalReferences, getContainerOfType, Stream, stream } from 'langium';
32+
import { EMPTY_STREAM, findLocalReferences, getContainerOfType, Stream } from 'langium';
3333
import {
3434
getAbstractResults,
3535
getArguments,
36-
isNamedArgument,
37-
isNamedTypeArgument,
3836
getParameters,
3937
getTypeArguments,
4038
getTypeParameters,
39+
isNamedArgument,
40+
isNamedTypeArgument,
4141
} from './nodeProperties.js';
4242

4343
export class SafeDsNodeMapper {
@@ -155,13 +155,13 @@ export class SafeDsNodeMapper {
155155
*/
156156
parameterToReferences(node: SdsParameter | undefined): Stream<SdsReference> {
157157
if (!node) {
158-
return stream();
158+
return EMPTY_STREAM;
159159
}
160160

161161
const containingCallable = getContainerOfType(node, isSdsCallable);
162162
/* c8 ignore start */
163163
if (!containingCallable) {
164-
return stream();
164+
return EMPTY_STREAM;
165165
}
166166
/* c8 ignore stop */
167167

@@ -175,13 +175,13 @@ export class SafeDsNodeMapper {
175175
*/
176176
placeholderToReferences(node: SdsPlaceholder | undefined): Stream<SdsReference> {
177177
if (!node) {
178-
return stream();
178+
return EMPTY_STREAM;
179179
}
180180

181181
const containingBlock = getContainerOfType(node, isSdsBlock);
182182
/* c8 ignore start */
183183
if (!containingBlock) {
184-
return stream();
184+
return EMPTY_STREAM;
185185
}
186186
/* c8 ignore stop */
187187

@@ -195,12 +195,12 @@ export class SafeDsNodeMapper {
195195
*/
196196
resultToYields(node: SdsResult | undefined): Stream<SdsYield> {
197197
if (!node) {
198-
return stream();
198+
return EMPTY_STREAM;
199199
}
200200

201201
const containingSegment = getContainerOfType(node, isSdsSegment);
202202
if (!containingSegment) {
203-
return stream();
203+
return EMPTY_STREAM;
204204
}
205205

206206
return findLocalReferences(node, containingSegment)

src/language/safe-ds-module.ts

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { SafeDsTypeChecker } from './typing/safe-ds-type-checker.js';
2828
import { SafeDsCoreTypes } from './typing/safe-ds-core-types.js';
2929
import { SafeDsNodeKindProvider } from './lsp/safe-ds-node-kind-provider.js';
3030
import { SafeDsDocumentSymbolProvider } from './lsp/safe-ds-document-symbol-provider.js';
31+
import { SafeDsDocumentBuilder } from './workspace/safe-ds-document-builder.js';
3132

3233
/**
3334
* Declaration of custom services - add your own service classes here.
@@ -106,6 +107,7 @@ export const SafeDsSharedModule: Module<SafeDsSharedServices, DeepPartial<SafeDs
106107
NodeKindProvider: () => new SafeDsNodeKindProvider(),
107108
},
108109
workspace: {
110+
DocumentBuilder: (services) => new SafeDsDocumentBuilder(services),
109111
WorkspaceManager: (services) => new SafeDsWorkspaceManager(services),
110112
},
111113
};

src/language/typing/safe-ds-class-hierarchy.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { SafeDsServices } from '../safe-ds-module.js';
22
import { SafeDsClasses } from '../builtins/safe-ds-classes.js';
33
import { SdsClass } from '../generated/ast.js';
4-
import { stream, Stream } from 'langium';
4+
import { EMPTY_STREAM, stream, Stream } from 'langium';
55
import { getParentTypes } from '../helpers/nodeProperties.js';
66
import { SafeDsTypeComputer } from './safe-ds-type-computer.js';
77
import { ClassType } from './model.js';
@@ -39,7 +39,7 @@ export class SafeDsClassHierarchy {
3939
*/
4040
streamSuperclasses(node: SdsClass | undefined): Stream<SdsClass> {
4141
if (!node) {
42-
return stream();
42+
return EMPTY_STREAM;
4343
}
4444

4545
return stream(this.superclassesGenerator(node));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { BuildOptions, DefaultDocumentBuilder } from 'langium';
2+
3+
export class SafeDsDocumentBuilder extends DefaultDocumentBuilder {
4+
override updateBuildOptions: BuildOptions = {
5+
validation: {
6+
categories: ['built-in', 'fast'],
7+
stopAfterLexingErrors: true,
8+
stopAfterParsingErrors: true,
9+
},
10+
};
11+
}

tests/language/builtins/builtinFilesCorrectness.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,22 @@ import { URI } from 'langium';
88
import { locationToString } from '../../helpers/location.js';
99
import { AssertionError } from 'assert';
1010
import { isEmpty } from '../../../src/helpers/collectionUtils.js';
11+
import { loadDocuments } from '../../helpers/testResources.js';
1112

12-
const workspace = createSafeDsServices(NodeFileSystem).SafeDs.shared.workspace;
13+
const services = createSafeDsServices(NodeFileSystem).SafeDs;
1314
const builtinFiles = listBuiltinFiles();
1415

1516
describe('builtin files', () => {
1617
beforeAll(async () => {
17-
const documents = builtinFiles.map((uri) => workspace.LangiumDocuments.getOrCreateDocument(uri));
18-
await workspace.DocumentBuilder.build(documents, { validation: true });
18+
await loadDocuments(services, builtinFiles, { validation: true });
1919
});
2020

2121
const testCases = builtinFiles.map((uri) => ({
2222
uri,
2323
shortenedResourceName: uriToShortenedResourceName(uri, 'builtins'),
2424
}));
2525
it.each(testCases)('[$shortenedResourceName] should have no errors or warnings', async ({ uri }) => {
26-
const document = workspace.LangiumDocuments.getOrCreateDocument(uri);
26+
const document = services.shared.workspace.LangiumDocuments.getOrCreateDocument(uri);
2727

2828
const errorsOrWarnings =
2929
document.diagnostics?.filter(

0 commit comments

Comments
 (0)