From 45a3f6b0c423de4ffcf530a7220b2f60b2d158ea Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Thu, 21 Sep 2023 11:48:01 +0200 Subject: [PATCH 1/4] refactor: attach checks for emptiness directly to bodies of classes and enums --- src/language/validation/safe-ds-validator.ts | 5 +++-- src/language/validation/style.ts | 13 ++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/language/validation/safe-ds-validator.ts b/src/language/validation/safe-ds-validator.ts index e4afd988b..8a38fc9bd 100644 --- a/src/language/validation/safe-ds-validator.ts +++ b/src/language/validation/safe-ds-validator.ts @@ -30,9 +30,10 @@ export const registerValidationChecks = function (services: SafeDsServices) { SdsAssignment: [assignmentShouldHaveMoreThanWildcardsAsAssignees], SdsAnnotation: [annotationParameterListShouldNotBeEmpty], SdsAttribute: [attributeMustHaveTypeHint], - SdsClass: [classBodyShouldNotBeEmpty, classTypeParameterListShouldNotBeEmpty], + SdsClass: [classTypeParameterListShouldNotBeEmpty], + SdsClassBody: [classBodyShouldNotBeEmpty], SdsDeclaration: [nameMustNotStartWithBlockLambdaPrefix, nameShouldHaveCorrectCasing], - SdsEnum: [enumBodyShouldNotBeEmpty], + SdsEnumBody: [enumBodyShouldNotBeEmpty], SdsEnumVariant: [enumVariantParameterListShouldNotBeEmpty, enumVariantTypeParameterListShouldNotBeEmpty], SdsFunction: [functionResultListShouldNotBeEmpty, functionTypeParameterListShouldNotBeEmpty], SdsModule: [moduleDeclarationsMustMatchFileKind, moduleWithDeclarationsMustStatePackage], diff --git a/src/language/validation/style.ts b/src/language/validation/style.ts index 442d0aa92..b034e88f9 100644 --- a/src/language/validation/style.ts +++ b/src/language/validation/style.ts @@ -3,7 +3,8 @@ import { SdsAnnotation, SdsAssignment, SdsClass, - SdsEnum, + SdsClassBody, + SdsEnumBody, SdsEnumVariant, SdsFunction, SdsSegment, @@ -44,21 +45,19 @@ export const assignmentShouldHaveMoreThanWildcardsAsAssignees = ( // Unnecessary bodies // ----------------------------------------------------------------------------- -export const classBodyShouldNotBeEmpty = (node: SdsClass, accept: ValidationAcceptor) => { - if (node.body && isEmpty(node.body.members)) { +export const classBodyShouldNotBeEmpty = (node: SdsClassBody, accept: ValidationAcceptor) => { + if (isEmpty(node.members)) { accept('info', 'This body can be removed.', { node, - property: 'body', code: CODE_STYLE_UNNECESSARY_BODY, }); } }; -export const enumBodyShouldNotBeEmpty = (node: SdsEnum, accept: ValidationAcceptor) => { - if (node.body && isEmpty(node.body.variants)) { +export const enumBodyShouldNotBeEmpty = (node: SdsEnumBody, accept: ValidationAcceptor) => { + if (isEmpty(node.variants)) { accept('info', 'This body can be removed.', { node, - property: 'body', code: CODE_STYLE_UNNECESSARY_BODY, }); } From f26da6ee367bafc139391e0ea46ac2d83ebc4e65 Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Thu, 21 Sep 2023 11:49:15 +0200 Subject: [PATCH 2/4] refactor: attach checks for emptiness directly to type parameter lists --- src/language/validation/safe-ds-validator.ts | 10 +++----- src/language/validation/style.ts | 27 +++----------------- 2 files changed, 7 insertions(+), 30 deletions(-) diff --git a/src/language/validation/safe-ds-validator.ts b/src/language/validation/safe-ds-validator.ts index 8a38fc9bd..3c069e2e4 100644 --- a/src/language/validation/safe-ds-validator.ts +++ b/src/language/validation/safe-ds-validator.ts @@ -6,13 +6,11 @@ import { annotationParameterListShouldNotBeEmpty, assignmentShouldHaveMoreThanWildcardsAsAssignees, classBodyShouldNotBeEmpty, - classTypeParameterListShouldNotBeEmpty, enumBodyShouldNotBeEmpty, enumVariantParameterListShouldNotBeEmpty, - enumVariantTypeParameterListShouldNotBeEmpty, functionResultListShouldNotBeEmpty, - functionTypeParameterListShouldNotBeEmpty, segmentResultListShouldNotBeEmpty, + typeParameterListShouldNotBeEmpty, unionTypeShouldNotHaveASingularTypeArgument, } from './style.js'; import { templateStringMustHaveExpressionBetweenTwoStringParts } from './other/expressions/templateStrings.js'; @@ -30,17 +28,17 @@ export const registerValidationChecks = function (services: SafeDsServices) { SdsAssignment: [assignmentShouldHaveMoreThanWildcardsAsAssignees], SdsAnnotation: [annotationParameterListShouldNotBeEmpty], SdsAttribute: [attributeMustHaveTypeHint], - SdsClass: [classTypeParameterListShouldNotBeEmpty], SdsClassBody: [classBodyShouldNotBeEmpty], SdsDeclaration: [nameMustNotStartWithBlockLambdaPrefix, nameShouldHaveCorrectCasing], SdsEnumBody: [enumBodyShouldNotBeEmpty], - SdsEnumVariant: [enumVariantParameterListShouldNotBeEmpty, enumVariantTypeParameterListShouldNotBeEmpty], - SdsFunction: [functionResultListShouldNotBeEmpty, functionTypeParameterListShouldNotBeEmpty], + SdsEnumVariant: [enumVariantParameterListShouldNotBeEmpty], + SdsFunction: [functionResultListShouldNotBeEmpty], SdsModule: [moduleDeclarationsMustMatchFileKind, moduleWithDeclarationsMustStatePackage], SdsParameter: [parameterMustHaveTypeHint], SdsResult: [resultMustHaveTypeHint], SdsSegment: [segmentResultListShouldNotBeEmpty], SdsTemplateString: [templateStringMustHaveExpressionBetweenTwoStringParts], + SdsTypeParameterList: [typeParameterListShouldNotBeEmpty], SdsUnionType: [unionTypeShouldNotHaveASingularTypeArgument], SdsYield: [yieldMustNotBeUsedInPipeline], }; diff --git a/src/language/validation/style.ts b/src/language/validation/style.ts index b034e88f9..e2b0d293b 100644 --- a/src/language/validation/style.ts +++ b/src/language/validation/style.ts @@ -2,12 +2,12 @@ import { isSdsWildcard, SdsAnnotation, SdsAssignment, - SdsClass, SdsClassBody, SdsEnumBody, SdsEnumVariant, SdsFunction, SdsSegment, + SdsTypeParameterList, SdsUnionType, } from '../generated/ast.js'; import { ValidationAcceptor } from 'langium'; @@ -115,31 +115,10 @@ export const segmentResultListShouldNotBeEmpty = (node: SdsSegment, accept: Vali // Unnecessary type parameter lists // ----------------------------------------------------------------------------- -export const classTypeParameterListShouldNotBeEmpty = (node: SdsClass, accept: ValidationAcceptor) => { - if (node.typeParameterList && isEmpty(node.typeParameterList.typeParameters)) { +export const typeParameterListShouldNotBeEmpty = (node: SdsTypeParameterList, accept: ValidationAcceptor) => { + if (isEmpty(node.typeParameters)) { accept('info', 'This type parameter list can be removed.', { node, - property: 'typeParameterList', - code: CODE_STYLE_UNNECESSARY_TYPE_PARAMETER_LIST, - }); - } -}; - -export const enumVariantTypeParameterListShouldNotBeEmpty = (node: SdsEnumVariant, accept: ValidationAcceptor) => { - if (node.typeParameterList && isEmpty(node.typeParameterList.typeParameters)) { - accept('info', 'This type parameter list can be removed.', { - node, - property: 'typeParameterList', - code: CODE_STYLE_UNNECESSARY_TYPE_PARAMETER_LIST, - }); - } -}; - -export const functionTypeParameterListShouldNotBeEmpty = (node: SdsFunction, accept: ValidationAcceptor) => { - if (node.typeParameterList && isEmpty(node.typeParameterList.typeParameters)) { - accept('info', 'This type parameter list can be removed.', { - node, - property: 'typeParameterList', code: CODE_STYLE_UNNECESSARY_TYPE_PARAMETER_LIST, }); } From 9fef7016b78dcc5a599630a17b7e2f2bf8bdd631 Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Thu, 21 Sep 2023 11:56:50 +0200 Subject: [PATCH 3/4] feat: show info that empty constraint lists can be removed --- src/language/validation/safe-ds-validator.ts | 26 +++++++++++-------- src/language/validation/style.ts | 15 +++++++++++ .../main.sdstest | 9 +++++++ .../main.sdstest | 9 +++++++ .../main.sdstest | 11 ++++++++ .../main.sdstest | 9 +++++++ 6 files changed, 68 insertions(+), 11 deletions(-) create mode 100644 tests/resources/validation/style/unnecessary constraint list in annotation/main.sdstest create mode 100644 tests/resources/validation/style/unnecessary constraint list in class/main.sdstest create mode 100644 tests/resources/validation/style/unnecessary constraint list in enum variant/main.sdstest create mode 100644 tests/resources/validation/style/unnecessary constraint list in function/main.sdstest diff --git a/src/language/validation/safe-ds-validator.ts b/src/language/validation/safe-ds-validator.ts index 34a672cb2..febd5f52f 100644 --- a/src/language/validation/safe-ds-validator.ts +++ b/src/language/validation/safe-ds-validator.ts @@ -1,11 +1,11 @@ -import { ValidationChecks } from 'langium'; -import { SafeDsAstType } from '../generated/ast.js'; -import type { SafeDsServices } from '../safe-ds-module.js'; -import { nameMustNotStartWithBlockLambdaPrefix, nameShouldHaveCorrectCasing } from './names.js'; +import {ValidationChecks} from 'langium'; +import {SafeDsAstType} from '../generated/ast.js'; +import type {SafeDsServices} from '../safe-ds-module.js'; +import {nameMustNotStartWithBlockLambdaPrefix, nameShouldHaveCorrectCasing} from './names.js'; import { annotationParameterListShouldNotBeEmpty, assignmentShouldHaveMoreThanWildcardsAsAssignees, - classBodyShouldNotBeEmpty, + classBodyShouldNotBeEmpty, constraintListShouldNotBeEmpty, enumBodyShouldNotBeEmpty, enumVariantParameterListShouldNotBeEmpty, functionResultListShouldNotBeEmpty, @@ -13,11 +13,13 @@ import { typeParameterListShouldNotBeEmpty, unionTypeShouldNotHaveASingularTypeArgument, } from './style.js'; -import { templateStringMustHaveExpressionBetweenTwoStringParts } from './other/expressions/templateStrings.js'; -import { yieldMustNotBeUsedInPipeline } from './other/statements/assignments.js'; -import { attributeMustHaveTypeHint, parameterMustHaveTypeHint, resultMustHaveTypeHint } from './types.js'; -import { moduleDeclarationsMustMatchFileKind, moduleWithDeclarationsMustStatePackage } from './other/modules.js'; -import { typeParameterConstraintLeftOperandMustBeOwnTypeParameter } from './other/declarations/typeParameterConstraints.js'; +import {templateStringMustHaveExpressionBetweenTwoStringParts} from './other/expressions/templateStrings.js'; +import {yieldMustNotBeUsedInPipeline} from './other/statements/assignments.js'; +import {attributeMustHaveTypeHint, parameterMustHaveTypeHint, resultMustHaveTypeHint} from './types.js'; +import {moduleDeclarationsMustMatchFileKind, moduleWithDeclarationsMustStatePackage} from './other/modules.js'; +import { + typeParameterConstraintLeftOperandMustBeOwnTypeParameter +} from './other/declarations/typeParameterConstraints.js'; /** * Register custom validation checks. @@ -30,6 +32,7 @@ export const registerValidationChecks = function (services: SafeDsServices) { SdsAnnotation: [annotationParameterListShouldNotBeEmpty], SdsAttribute: [attributeMustHaveTypeHint], SdsClassBody: [classBodyShouldNotBeEmpty], + SdsConstraintList: [constraintListShouldNotBeEmpty], SdsDeclaration: [nameMustNotStartWithBlockLambdaPrefix, nameShouldHaveCorrectCasing], SdsEnumBody: [enumBodyShouldNotBeEmpty], SdsEnumVariant: [enumVariantParameterListShouldNotBeEmpty], @@ -50,4 +53,5 @@ export const registerValidationChecks = function (services: SafeDsServices) { /** * Implementation of custom validations. */ -export class SafeDsValidator {} +export class SafeDsValidator { +} diff --git a/src/language/validation/style.ts b/src/language/validation/style.ts index e2b0d293b..2df07a734 100644 --- a/src/language/validation/style.ts +++ b/src/language/validation/style.ts @@ -3,6 +3,7 @@ import { SdsAnnotation, SdsAssignment, SdsClassBody, + SdsConstraintList, SdsEnumBody, SdsEnumVariant, SdsFunction, @@ -16,6 +17,7 @@ import { isEmpty } from 'radash'; export const CODE_STYLE_UNNECESSARY_ASSIGNMENT = 'style/unnecessary-assignment'; export const CODE_STYLE_UNNECESSARY_ARGUMENT_LIST = 'style/unnecessary-argument-list'; export const CODE_STYLE_UNNECESSARY_BODY = 'style/unnecessary-body'; +export const CODE_STYLE_UNNECESSARY_CONSTRAINT_LIST = 'style/unnecessary-constraint-list'; export const CODE_STYLE_UNNECESSARY_ELVIS_OPERATOR = 'style/unnecessary-elvis-operator'; export const CODE_STYLE_UNNECESSARY_SAFE_ACCESS = 'style/unnecessary-safe-access'; export const CODE_STYLE_UNNECESSARY_PARAMETER_LIST = 'style/unnecessary-parameter-list'; @@ -63,6 +65,19 @@ export const enumBodyShouldNotBeEmpty = (node: SdsEnumBody, accept: ValidationAc } }; +// ----------------------------------------------------------------------------- +// Unnecessary constraint list +// ----------------------------------------------------------------------------- + +export const constraintListShouldNotBeEmpty = (node: SdsConstraintList, accept: ValidationAcceptor) => { + if (isEmpty(node.constraints)) { + accept('info', 'This constraint list can be removed.', { + node, + code: CODE_STYLE_UNNECESSARY_CONSTRAINT_LIST, + }); + } +}; + // ----------------------------------------------------------------------------- // Unnecessary parameter lists // ----------------------------------------------------------------------------- diff --git a/tests/resources/validation/style/unnecessary constraint list in annotation/main.sdstest b/tests/resources/validation/style/unnecessary constraint list in annotation/main.sdstest new file mode 100644 index 000000000..19fb92a9d --- /dev/null +++ b/tests/resources/validation/style/unnecessary constraint list in annotation/main.sdstest @@ -0,0 +1,9 @@ +package tests.validation.style.unnecessaryConstraintListInAnnotation + +// $TEST$ info "This constraint list can be removed." +annotation MyAnnotation1 »where {}« + +// $TEST$ no info "This constraint list can be removed." +annotation MyAnnotation2 »where { + T sub Int +}« diff --git a/tests/resources/validation/style/unnecessary constraint list in class/main.sdstest b/tests/resources/validation/style/unnecessary constraint list in class/main.sdstest new file mode 100644 index 000000000..254eeb421 --- /dev/null +++ b/tests/resources/validation/style/unnecessary constraint list in class/main.sdstest @@ -0,0 +1,9 @@ +package tests.validation.style.unnecessaryConstraintListInClass + +// $TEST$ info "This constraint list can be removed." +class MyClass1 »where {}« + +// $TEST$ no info "This constraint list can be removed." +class MyClass2 »where { + T sub Int +}« diff --git a/tests/resources/validation/style/unnecessary constraint list in enum variant/main.sdstest b/tests/resources/validation/style/unnecessary constraint list in enum variant/main.sdstest new file mode 100644 index 000000000..4c058c694 --- /dev/null +++ b/tests/resources/validation/style/unnecessary constraint list in enum variant/main.sdstest @@ -0,0 +1,11 @@ +package tests.validation.style.unnecessaryConstraintInEnumVariant + +enum MyEnum { + // $TEST$ info "This constraint list can be removed." + MyVariant1 »where {}« + + // $TEST$ no info "This constraint list can be removed." + MyVariant2() »where { + T sub Int + }« +} diff --git a/tests/resources/validation/style/unnecessary constraint list in function/main.sdstest b/tests/resources/validation/style/unnecessary constraint list in function/main.sdstest new file mode 100644 index 000000000..fa82757b9 --- /dev/null +++ b/tests/resources/validation/style/unnecessary constraint list in function/main.sdstest @@ -0,0 +1,9 @@ +package tests.validation.style.unnecessaryConstraintListInFunction + +// $TEST$ info "This constraint list can be removed." +fun myFunction1() »where {}« + +// $TEST$ no info "This constraint list can be removed." +fun myFunction2() »where { + T sub Int +}« From aab559fed780c22d226de76198732a8085eb18a1 Mon Sep 17 00:00:00 2001 From: megalinter-bot <129584137+megalinter-bot@users.noreply.github.com> Date: Thu, 21 Sep 2023 09:59:13 +0000 Subject: [PATCH 4/4] style: apply automated linter fixes --- src/language/validation/safe-ds-validator.ts | 26 +++++++++----------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/language/validation/safe-ds-validator.ts b/src/language/validation/safe-ds-validator.ts index febd5f52f..633cad68e 100644 --- a/src/language/validation/safe-ds-validator.ts +++ b/src/language/validation/safe-ds-validator.ts @@ -1,11 +1,12 @@ -import {ValidationChecks} from 'langium'; -import {SafeDsAstType} from '../generated/ast.js'; -import type {SafeDsServices} from '../safe-ds-module.js'; -import {nameMustNotStartWithBlockLambdaPrefix, nameShouldHaveCorrectCasing} from './names.js'; +import { ValidationChecks } from 'langium'; +import { SafeDsAstType } from '../generated/ast.js'; +import type { SafeDsServices } from '../safe-ds-module.js'; +import { nameMustNotStartWithBlockLambdaPrefix, nameShouldHaveCorrectCasing } from './names.js'; import { annotationParameterListShouldNotBeEmpty, assignmentShouldHaveMoreThanWildcardsAsAssignees, - classBodyShouldNotBeEmpty, constraintListShouldNotBeEmpty, + classBodyShouldNotBeEmpty, + constraintListShouldNotBeEmpty, enumBodyShouldNotBeEmpty, enumVariantParameterListShouldNotBeEmpty, functionResultListShouldNotBeEmpty, @@ -13,13 +14,11 @@ import { typeParameterListShouldNotBeEmpty, unionTypeShouldNotHaveASingularTypeArgument, } from './style.js'; -import {templateStringMustHaveExpressionBetweenTwoStringParts} from './other/expressions/templateStrings.js'; -import {yieldMustNotBeUsedInPipeline} from './other/statements/assignments.js'; -import {attributeMustHaveTypeHint, parameterMustHaveTypeHint, resultMustHaveTypeHint} from './types.js'; -import {moduleDeclarationsMustMatchFileKind, moduleWithDeclarationsMustStatePackage} from './other/modules.js'; -import { - typeParameterConstraintLeftOperandMustBeOwnTypeParameter -} from './other/declarations/typeParameterConstraints.js'; +import { templateStringMustHaveExpressionBetweenTwoStringParts } from './other/expressions/templateStrings.js'; +import { yieldMustNotBeUsedInPipeline } from './other/statements/assignments.js'; +import { attributeMustHaveTypeHint, parameterMustHaveTypeHint, resultMustHaveTypeHint } from './types.js'; +import { moduleDeclarationsMustMatchFileKind, moduleWithDeclarationsMustStatePackage } from './other/modules.js'; +import { typeParameterConstraintLeftOperandMustBeOwnTypeParameter } from './other/declarations/typeParameterConstraints.js'; /** * Register custom validation checks. @@ -53,5 +52,4 @@ export const registerValidationChecks = function (services: SafeDsServices) { /** * Implementation of custom validations. */ -export class SafeDsValidator { -} +export class SafeDsValidator {}