Skip to content

Commit c26d33a

Browse files
feat: show info if unnecessary syntax is used (#566)
Closes partially #543 ### Summary of Changes Show an info if one of the following can be removed: * assignment (only wildcards as assignees) * body of class/enum * parameter list of annotation/enum variant * result list of function/segment * type parameter list of class/enum variant/function * union type (singular type argument) --------- Co-authored-by: megalinter-bot <[email protected]>
1 parent a877f4c commit c26d33a

File tree

52 files changed

+439
-158
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+439
-158
lines changed

src/language/validation/nameConvention.ts

-126
This file was deleted.

src/language/validation/names.ts

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { SdsDeclaration } from '../generated/ast.js';
2+
import { ValidationAcceptor } from 'langium';
3+
4+
export const CODE_NAMES_BLOCK_LAMBDA_PREFIX = 'names/block-lambda-prefix';
5+
export const CODE_NAMES_CASING = 'names/casing';
6+
7+
export const nameMustNotStartWithBlockLambdaPrefix = (node: SdsDeclaration, accept: ValidationAcceptor) => {
8+
const name = node.name ?? '';
9+
const blockLambdaPrefix = '__block_lambda_';
10+
if (name.startsWith(blockLambdaPrefix)) {
11+
accept(
12+
'error',
13+
"Names of declarations must not start with '__block_lambda_'. This is reserved for code generation of block lambdas.",
14+
{
15+
node,
16+
property: 'name',
17+
code: CODE_NAMES_BLOCK_LAMBDA_PREFIX,
18+
},
19+
);
20+
}
21+
};
22+
23+
export const nameShouldHaveCorrectCasing = (node: SdsDeclaration, accept: ValidationAcceptor): void => {
24+
switch (node.$type) {
25+
case 'SdsAnnotation':
26+
return nameShouldBeUpperCamelCase(node, 'annotations', accept);
27+
case 'SdsAttribute':
28+
return nameShouldBeLowerCamelCase(node, 'attributes', accept);
29+
case 'SdsBlockLambdaResult':
30+
return nameShouldBeLowerCamelCase(node, 'block lambda results', accept);
31+
case 'SdsClass':
32+
return nameShouldBeUpperCamelCase(node, 'classes', accept);
33+
case 'SdsEnum':
34+
return nameShouldBeUpperCamelCase(node, 'enums', accept);
35+
case 'SdsEnumVariant':
36+
return nameShouldBeUpperCamelCase(node, 'enum variants', accept);
37+
case 'SdsFunction':
38+
return nameShouldBeLowerCamelCase(node, 'functions', accept);
39+
case 'SdsModule':
40+
const name = node.name ?? '';
41+
const segments = name.split('.');
42+
if (name !== '' && !segments.every(isLowerCamelCase)) {
43+
accept('warning', 'All segments of the qualified name of a package should be lowerCamelCase.', {
44+
node,
45+
property: 'name',
46+
code: CODE_NAMES_CASING,
47+
});
48+
}
49+
return;
50+
case 'SdsParameter':
51+
return nameShouldBeLowerCamelCase(node, 'parameters', accept);
52+
case 'SdsPipeline':
53+
return nameShouldBeLowerCamelCase(node, 'pipelines', accept);
54+
case 'SdsPlaceholder':
55+
return nameShouldBeLowerCamelCase(node, 'placeholders', accept);
56+
case 'SdsResult':
57+
return nameShouldBeLowerCamelCase(node, 'results', accept);
58+
case 'SdsSchema':
59+
return nameShouldBeUpperCamelCase(node, 'schemas', accept);
60+
case 'SdsSegment':
61+
return nameShouldBeLowerCamelCase(node, 'segments', accept);
62+
case 'SdsTypeParameter':
63+
return nameShouldBeUpperCamelCase(node, 'type parameters', accept);
64+
}
65+
};
66+
67+
const nameShouldBeLowerCamelCase = (node: SdsDeclaration, nodeName: string, accept: ValidationAcceptor): void => {
68+
const name = node.name ?? '';
69+
if (!isLowerCamelCase(name)) {
70+
acceptCasingWarning(node, nodeName, 'lowerCamelCase', accept);
71+
}
72+
};
73+
74+
const isLowerCamelCase = (name: string): boolean => {
75+
return /^[a-z][a-zA-Z0-9]*$/gu.test(name);
76+
};
77+
78+
const nameShouldBeUpperCamelCase = (node: SdsDeclaration, nodeName: string, accept: ValidationAcceptor): void => {
79+
const name = node.name ?? '';
80+
if (!isUpperCamelCase(name)) {
81+
acceptCasingWarning(node, nodeName, 'UpperCamelCase', accept);
82+
}
83+
};
84+
85+
const isUpperCamelCase = (name: string): boolean => {
86+
return /^[A-Z][a-zA-Z0-9]*$/gu.test(name);
87+
};
88+
89+
const acceptCasingWarning = (
90+
node: SdsDeclaration,
91+
nodeName: string,
92+
expectedCasing: string,
93+
accept: ValidationAcceptor,
94+
) => {
95+
accept('warning', `Names of ${nodeName} should be ${expectedCasing}.`, {
96+
node,
97+
property: 'name',
98+
code: CODE_NAMES_CASING,
99+
});
100+
};

src/language/validation/safe-ds-validator.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
import { ValidationChecks } from 'langium';
22
import { SafeDsAstType } from '../generated/ast.js';
33
import type { SafeDsServices } from '../safe-ds-module.js';
4-
import { nameMustNotStartWithBlockLambdaPrefix, nameShouldHaveCorrectCasing } from './nameConvention.js';
4+
import { nameMustNotStartWithBlockLambdaPrefix, nameShouldHaveCorrectCasing } from './names.js';
5+
import {
6+
annotationParameterListShouldNotBeEmpty,
7+
assignmentShouldHaveMoreThanWildcardsAsAssignees,
8+
classBodyShouldNotBeEmpty,
9+
classTypeParameterListShouldNotBeEmpty,
10+
enumBodyShouldNotBeEmpty,
11+
enumVariantParameterListShouldNotBeEmpty,
12+
enumVariantTypeParameterListShouldNotBeEmpty,
13+
functionResultListShouldNotBeEmpty,
14+
functionTypeParameterListShouldNotBeEmpty,
15+
segmentResultListShouldNotBeEmpty,
16+
unionTypeShouldNotHaveASingularTypeArgument,
17+
} from './unnecessarySyntax.js';
518

619
/**
720
* Register custom validation checks.
@@ -10,7 +23,15 @@ export const registerValidationChecks = function (services: SafeDsServices) {
1023
const registry = services.validation.ValidationRegistry;
1124
const validator = services.validation.SafeDsValidator;
1225
const checks: ValidationChecks<SafeDsAstType> = {
26+
SdsAssignment: [assignmentShouldHaveMoreThanWildcardsAsAssignees],
27+
SdsAnnotation: [annotationParameterListShouldNotBeEmpty],
28+
SdsClass: [classBodyShouldNotBeEmpty, classTypeParameterListShouldNotBeEmpty],
1329
SdsDeclaration: [nameMustNotStartWithBlockLambdaPrefix, nameShouldHaveCorrectCasing],
30+
SdsEnum: [enumBodyShouldNotBeEmpty],
31+
SdsEnumVariant: [enumVariantParameterListShouldNotBeEmpty, enumVariantTypeParameterListShouldNotBeEmpty],
32+
SdsFunction: [functionResultListShouldNotBeEmpty, functionTypeParameterListShouldNotBeEmpty],
33+
SdsSegment: [segmentResultListShouldNotBeEmpty],
34+
SdsUnionType: [unionTypeShouldNotHaveASingularTypeArgument],
1435
};
1536
registry.register(checks, validator);
1637
};

0 commit comments

Comments
 (0)