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 +}«