From 28033057738dacb9c3e486b83e28549277353526 Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Wed, 20 Sep 2023 16:56:20 +0200 Subject: [PATCH] feat: port additional checks (#567) Closes partially #543 ### Summary of Changes Port additional checks from old Xtext version: * Template string without expression between string parts * Yield in pipeline * Missing type hints * Missing package in module with declarations * Declarations in module that are not allowed by the file type --------- Co-authored-by: megalinter-bot <129584137+megalinter-bot@users.noreply.github.com> --- src/language/validation/names.ts | 10 ++-- .../other/expressions/templateStrings.ts | 21 ++++++++ src/language/validation/other/modules.ts | 48 +++++++++++++++++++ .../other/statements/assignments.ts | 15 ++++++ src/language/validation/safe-ds-validator.ts | 12 ++++- .../{unnecessarySyntax.ts => style.ts} | 0 src/language/validation/types.ts | 42 ++++++++++++++++ .../missing template expression/main.sdstest | 11 +++++ .../main.sdspipe | 33 +++++++++++++ .../declarations in stub files/main.sdsstub | 33 +++++++++++++ .../declarations in test files/main.sdsstub | 33 +++++++++++++ .../pipeline file (empty).sdspipe | 1 + .../pipeline file (only annotations).sdspipe | 3 ++ .../pipeline file (only imports).sdspipe | 3 ++ ...le (with declarations and package).sdspipe | 7 +++ ...(with declarations but no package).sdspipe | 5 ++ .../stub file (empty).sdsstub | 1 + .../stub file (only annotations).sdsstub | 3 ++ .../stub file (only imports).sdsstub | 3 ++ ...le (with declarations and package).sdsstub | 7 +++ ...(with declarations but no package).sdsstub | 5 ++ .../yield forbidden in pipeline/main.sdstest | 16 +++++++ .../unnecessary assignment/main.sdstest | 2 +- .../unnecessary body in class/main.sdstest | 2 +- .../unnecessary body in enum/main.sdstest | 2 +- .../main.sdstest | 2 +- .../main.sdstest | 2 +- .../main.sdstest | 2 +- .../main.sdstest | 2 +- .../main.sdstest | 2 +- .../main.sdstest | 2 +- .../main.sdstest | 2 +- .../unnecessary union type/main.sdstest | 2 +- .../missing for attribute/main.sdstest | 9 ++++ .../missing for parameter/main.sdstest | 39 +++++++++++++++ .../missing for result/main.sdstest | 21 ++++++++ 36 files changed, 386 insertions(+), 17 deletions(-) create mode 100644 src/language/validation/other/expressions/templateStrings.ts create mode 100644 src/language/validation/other/modules.ts create mode 100644 src/language/validation/other/statements/assignments.ts rename src/language/validation/{unnecessarySyntax.ts => style.ts} (100%) create mode 100644 src/language/validation/types.ts create mode 100644 tests/resources/validation/other/expressions/template strings/missing template expression/main.sdstest create mode 100644 tests/resources/validation/other/modules/declarations in pipeline files/main.sdspipe create mode 100644 tests/resources/validation/other/modules/declarations in stub files/main.sdsstub create mode 100644 tests/resources/validation/other/modules/declarations in test files/main.sdsstub create mode 100644 tests/resources/validation/other/modules/must state package/pipeline file (empty).sdspipe create mode 100644 tests/resources/validation/other/modules/must state package/pipeline file (only annotations).sdspipe create mode 100644 tests/resources/validation/other/modules/must state package/pipeline file (only imports).sdspipe create mode 100644 tests/resources/validation/other/modules/must state package/pipeline file (with declarations and package).sdspipe create mode 100644 tests/resources/validation/other/modules/must state package/pipeline file (with declarations but no package).sdspipe create mode 100644 tests/resources/validation/other/modules/must state package/stub file (empty).sdsstub create mode 100644 tests/resources/validation/other/modules/must state package/stub file (only annotations).sdsstub create mode 100644 tests/resources/validation/other/modules/must state package/stub file (only imports).sdsstub create mode 100644 tests/resources/validation/other/modules/must state package/stub file (with declarations and package).sdsstub create mode 100644 tests/resources/validation/other/modules/must state package/stub file (with declarations but no package).sdsstub create mode 100644 tests/resources/validation/other/statements/assignments/yield forbidden in pipeline/main.sdstest rename tests/resources/validation/{unnecessary syntax => style}/unnecessary assignment/main.sdstest (93%) rename tests/resources/validation/{unnecessary syntax => style}/unnecessary body in class/main.sdstest (78%) rename tests/resources/validation/{unnecessary syntax => style}/unnecessary body in enum/main.sdstest (69%) rename tests/resources/validation/{unnecessary syntax => style}/unnecessary parameter list in annotation/main.sdstest (69%) rename tests/resources/validation/{unnecessary syntax => style}/unnecessary parameter list in enum variant/main.sdstest (68%) rename tests/resources/validation/{unnecessary syntax => style}/unnecessary result list in function/main.sdstest (67%) rename tests/resources/validation/{unnecessary syntax => style}/unnecessary result list in segment/main.sdstest (70%) rename tests/resources/validation/{unnecessary syntax => style}/unnecessary type parameter list in class/main.sdstest (67%) rename tests/resources/validation/{unnecessary syntax => style}/unnecessary type parameter list in enum variant/main.sdstest (68%) rename tests/resources/validation/{unnecessary syntax => style}/unnecessary type parameter list in function/main.sdstest (67%) rename tests/resources/validation/{unnecessary syntax => style}/unnecessary union type/main.sdstest (86%) create mode 100644 tests/resources/validation/types/type hints/missing for attribute/main.sdstest create mode 100644 tests/resources/validation/types/type hints/missing for parameter/main.sdstest create mode 100644 tests/resources/validation/types/type hints/missing for result/main.sdstest diff --git a/src/language/validation/names.ts b/src/language/validation/names.ts index bc58baf49..0084a3fff 100644 --- a/src/language/validation/names.ts +++ b/src/language/validation/names.ts @@ -1,8 +1,8 @@ import { SdsDeclaration } from '../generated/ast.js'; import { ValidationAcceptor } from 'langium'; -export const CODE_NAMES_BLOCK_LAMBDA_PREFIX = 'names/block-lambda-prefix'; -export const CODE_NAMES_CASING = 'names/casing'; +export const CODE_NAME_BLOCK_LAMBDA_PREFIX = 'name/block-lambda-prefix'; +export const CODE_NAME_CASING = 'name/casing'; export const nameMustNotStartWithBlockLambdaPrefix = (node: SdsDeclaration, accept: ValidationAcceptor) => { const name = node.name ?? ''; @@ -14,7 +14,7 @@ export const nameMustNotStartWithBlockLambdaPrefix = (node: SdsDeclaration, acce { node, property: 'name', - code: CODE_NAMES_BLOCK_LAMBDA_PREFIX, + code: CODE_NAME_BLOCK_LAMBDA_PREFIX, }, ); } @@ -43,7 +43,7 @@ export const nameShouldHaveCorrectCasing = (node: SdsDeclaration, accept: Valida accept('warning', 'All segments of the qualified name of a package should be lowerCamelCase.', { node, property: 'name', - code: CODE_NAMES_CASING, + code: CODE_NAME_CASING, }); } return; @@ -95,6 +95,6 @@ const acceptCasingWarning = ( accept('warning', `Names of ${nodeName} should be ${expectedCasing}.`, { node, property: 'name', - code: CODE_NAMES_CASING, + code: CODE_NAME_CASING, }); }; diff --git a/src/language/validation/other/expressions/templateStrings.ts b/src/language/validation/other/expressions/templateStrings.ts new file mode 100644 index 000000000..8f713b70e --- /dev/null +++ b/src/language/validation/other/expressions/templateStrings.ts @@ -0,0 +1,21 @@ +import { isSdsTemplateStringPart, SdsTemplateString } from '../../../generated/ast.js'; +import { ValidationAcceptor } from 'langium'; + +export const CODE_TEMPLATE_STRING_MISSING_TEMPLATE_EXPRESSION = 'template-string/missing-template-expression'; + +export const templateStringMustHaveExpressionBetweenTwoStringParts = ( + node: SdsTemplateString, + accept: ValidationAcceptor, +): void => { + for (let i = 0; i < node.expressions.length - 1; i++) { + const first = node.expressions[i]; + const second = node.expressions[i + 1]; + + if (isSdsTemplateStringPart(first) && isSdsTemplateStringPart(second)) { + accept('error', 'There must be an expression between two string parts.', { + node: second, + code: CODE_TEMPLATE_STRING_MISSING_TEMPLATE_EXPRESSION, + }); + } + } +}; diff --git a/src/language/validation/other/modules.ts b/src/language/validation/other/modules.ts new file mode 100644 index 000000000..5975e305f --- /dev/null +++ b/src/language/validation/other/modules.ts @@ -0,0 +1,48 @@ +import { ValidationAcceptor } from 'langium'; +import { isSdsDeclaration, isSdsPipeline, isSdsSegment, SdsModule } from '../../generated/ast.js'; +import { isInPipelineFile, isInStubFile } from '../../constants/fileExtensions.js'; + +export const CODE_MODULE_MISSING_PACKAGE = 'module/missing-package'; + +export const CODE_MODULE_FORBIDDEN_IN_PIPELINE_FILE = 'module/forbidden-in-pipeline-file'; + +export const CODE_MODULE_FORBIDDEN_IN_STUB_FILE = 'module/forbidden-in-stub-file'; + +export const moduleWithDeclarationsMustStatePackage = (node: SdsModule, accept: ValidationAcceptor): void => { + if (!node.name) { + const declarations = node.members.filter(isSdsDeclaration); + if (declarations.length > 0) { + accept('error', 'A module with declarations must state its package.', { + node: declarations[0], + property: 'name', + code: CODE_MODULE_MISSING_PACKAGE, + }); + } + } +}; + +export const moduleDeclarationsMustMatchFileKind = (node: SdsModule, accept: ValidationAcceptor): void => { + const declarations = node.members.filter(isSdsDeclaration); + + if (isInPipelineFile(node)) { + for (const declaration of declarations) { + if (!isSdsPipeline(declaration) && !isSdsSegment(declaration)) { + accept('error', 'A pipeline file must only declare pipelines and segments.', { + node: declaration, + property: 'name', + code: CODE_MODULE_FORBIDDEN_IN_PIPELINE_FILE, + }); + } + } + } else if (isInStubFile(node)) { + for (const declaration of declarations) { + if (isSdsPipeline(declaration) || isSdsSegment(declaration)) { + accept('error', 'A stub file must not declare pipelines or segments.', { + node: declaration, + property: 'name', + code: CODE_MODULE_FORBIDDEN_IN_STUB_FILE, + }); + } + } + } +}; diff --git a/src/language/validation/other/statements/assignments.ts b/src/language/validation/other/statements/assignments.ts new file mode 100644 index 000000000..1ca08db0a --- /dev/null +++ b/src/language/validation/other/statements/assignments.ts @@ -0,0 +1,15 @@ +import { isSdsPipeline, SdsYield } from '../../../generated/ast.js'; +import { getContainerOfType, ValidationAcceptor } from 'langium'; + +export const CODE_ASSIGMENT_YIELD_FORBIDDEN_IN_PIPELINE = 'assignment/yield-forbidden-in-pipeline'; + +export const yieldMustNotBeUsedInPipeline = (node: SdsYield, accept: ValidationAcceptor): void => { + const containingPipeline = getContainerOfType(node, isSdsPipeline); + + if (containingPipeline) { + accept('error', 'Yield must not be used in a pipeline.', { + node, + code: CODE_ASSIGMENT_YIELD_FORBIDDEN_IN_PIPELINE, + }); + } +}; diff --git a/src/language/validation/safe-ds-validator.ts b/src/language/validation/safe-ds-validator.ts index 9dc834ab7..e4afd988b 100644 --- a/src/language/validation/safe-ds-validator.ts +++ b/src/language/validation/safe-ds-validator.ts @@ -14,7 +14,11 @@ import { functionTypeParameterListShouldNotBeEmpty, segmentResultListShouldNotBeEmpty, unionTypeShouldNotHaveASingularTypeArgument, -} from './unnecessarySyntax.js'; +} 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'; /** * Register custom validation checks. @@ -25,13 +29,19 @@ export const registerValidationChecks = function (services: SafeDsServices) { const checks: ValidationChecks = { SdsAssignment: [assignmentShouldHaveMoreThanWildcardsAsAssignees], SdsAnnotation: [annotationParameterListShouldNotBeEmpty], + SdsAttribute: [attributeMustHaveTypeHint], SdsClass: [classBodyShouldNotBeEmpty, classTypeParameterListShouldNotBeEmpty], SdsDeclaration: [nameMustNotStartWithBlockLambdaPrefix, nameShouldHaveCorrectCasing], SdsEnum: [enumBodyShouldNotBeEmpty], SdsEnumVariant: [enumVariantParameterListShouldNotBeEmpty, enumVariantTypeParameterListShouldNotBeEmpty], SdsFunction: [functionResultListShouldNotBeEmpty, functionTypeParameterListShouldNotBeEmpty], + SdsModule: [moduleDeclarationsMustMatchFileKind, moduleWithDeclarationsMustStatePackage], + SdsParameter: [parameterMustHaveTypeHint], + SdsResult: [resultMustHaveTypeHint], SdsSegment: [segmentResultListShouldNotBeEmpty], + SdsTemplateString: [templateStringMustHaveExpressionBetweenTwoStringParts], SdsUnionType: [unionTypeShouldNotHaveASingularTypeArgument], + SdsYield: [yieldMustNotBeUsedInPipeline], }; registry.register(checks, validator); }; diff --git a/src/language/validation/unnecessarySyntax.ts b/src/language/validation/style.ts similarity index 100% rename from src/language/validation/unnecessarySyntax.ts rename to src/language/validation/style.ts diff --git a/src/language/validation/types.ts b/src/language/validation/types.ts new file mode 100644 index 000000000..f459b5d7f --- /dev/null +++ b/src/language/validation/types.ts @@ -0,0 +1,42 @@ +import { getContainerOfType, ValidationAcceptor } from 'langium'; +import { isSdsCallable, isSdsLambda, SdsAttribute, SdsParameter, SdsResult } from '../generated/ast.js'; + +export const CODE_TYPE_MISSING_TYPE_HINT = 'type/missing-type-hint'; + +// ----------------------------------------------------------------------------- +// Missing type hints +// ----------------------------------------------------------------------------- + +export const attributeMustHaveTypeHint = (node: SdsAttribute, accept: ValidationAcceptor): void => { + if (!node.type) { + accept('error', 'An attribute must have a type hint.', { + node, + property: 'name', + code: CODE_TYPE_MISSING_TYPE_HINT, + }); + } +}; + +export const parameterMustHaveTypeHint = (node: SdsParameter, accept: ValidationAcceptor): void => { + if (!node.type) { + const containingCallable = getContainerOfType(node, isSdsCallable); + + if (!isSdsLambda(containingCallable)) { + accept('error', 'A parameter must have a type hint.', { + node, + property: 'name', + code: CODE_TYPE_MISSING_TYPE_HINT, + }); + } + } +}; + +export const resultMustHaveTypeHint = (node: SdsResult, accept: ValidationAcceptor): void => { + if (!node.type) { + accept('error', 'A result must have a type hint.', { + node, + property: 'name', + code: CODE_TYPE_MISSING_TYPE_HINT, + }); + } +}; diff --git a/tests/resources/validation/other/expressions/template strings/missing template expression/main.sdstest b/tests/resources/validation/other/expressions/template strings/missing template expression/main.sdstest new file mode 100644 index 000000000..4e394d564 --- /dev/null +++ b/tests/resources/validation/other/expressions/template strings/missing template expression/main.sdstest @@ -0,0 +1,11 @@ +package tests.validation.other.expressions.templateStrings.missingTemplateExpression + +pipeline test { + // $TEST$ error "There must be an expression between two string parts." + // $TEST$ error "There must be an expression between two string parts." + "start {{ »}} inner {{« »}} end"«; + + // $TEST$ no error "There must be an expression between two string parts." + // $TEST$ no error "There must be an expression between two string parts." + "start {{ 1 »}} inner {{« 1 »}} end"«; +} diff --git a/tests/resources/validation/other/modules/declarations in pipeline files/main.sdspipe b/tests/resources/validation/other/modules/declarations in pipeline files/main.sdspipe new file mode 100644 index 000000000..522c1778b --- /dev/null +++ b/tests/resources/validation/other/modules/declarations in pipeline files/main.sdspipe @@ -0,0 +1,33 @@ +package tests.validation.other.modules.declarationsInPipelineFiles + +// $TEST$ error "A pipeline file must only declare pipelines and segments." +annotation »MyAnnotation« +// $TEST$ error "A pipeline file must only declare pipelines and segments." +class »MyClass« { + + // $TEST$ no error "A pipeline file must only declare pipelines and segments." + attr »a«: Int + + // $TEST$ no error "A pipeline file must only declare pipelines and segments." + class »MyNestedClass« + + // $TEST$ no error "A pipeline file must only declare pipelines and segments." + enum »MyEnum« + + // $TEST$ no error "A pipeline file must only declare pipelines and segments." + fun »myFunction«() +} +// $TEST$ error "A pipeline file must only declare pipelines and segments." +enum »MyEnum« { + // $TEST$ no error "A pipeline file must only declare pipelines and segments." + »MyEnumInstance« +} +// $TEST$ error "A pipeline file must only declare pipelines and segments." +fun »myFunction«() +// $TEST$ error "A pipeline file must only declare pipelines and segments." +schema »MySchema« {} + +// $TEST$ no error "A pipeline file must only declare pipelines and segments." +pipeline »myPipeline« {} +// $TEST$ no error "A pipeline file must only declare pipelines and segments." +segment »mySegment«() {} diff --git a/tests/resources/validation/other/modules/declarations in stub files/main.sdsstub b/tests/resources/validation/other/modules/declarations in stub files/main.sdsstub new file mode 100644 index 000000000..e563a88da --- /dev/null +++ b/tests/resources/validation/other/modules/declarations in stub files/main.sdsstub @@ -0,0 +1,33 @@ +package tests.validation.other.modules.declarationsInStubFiles + +// $TEST$ error "A stub file must not declare pipelines or segments." +pipeline »myPipeline« {} +// $TEST$ error "A stub file must not declare pipelines or segments." +segment »mySegment«() {} + +// $TEST$ no error "A pipeline file must only declare pipelines and segments." +annotation »MyAnnotation« +// $TEST$ no error "A pipeline file must only declare pipelines and segments." +class »MyClass« { + + // $TEST$ no error "A pipeline file must only declare pipelines and segments." + attr »a«: Int + + // $TEST$ no error "A pipeline file must only declare pipelines and segments." + class »MyNestedClass« + + // $TEST$ no error "A pipeline file must only declare pipelines and segments." + enum »MyEnum« + + // $TEST$ no error "A pipeline file must only declare pipelines and segments." + fun »myFunction«() +} +// $TEST$ no error "A pipeline file must only declare pipelines and segments." +enum »MyEnum« { + // $TEST$ no error "A pipeline file must only declare pipelines and segments." + »MyEnumInstance« +} +// $TEST$ no error "A pipeline file must only declare pipelines and segments." +fun »myFunction«() +// $TEST$ no error "A pipeline file must only declare pipelines and segments." +schema »MySchema« {} diff --git a/tests/resources/validation/other/modules/declarations in test files/main.sdsstub b/tests/resources/validation/other/modules/declarations in test files/main.sdsstub new file mode 100644 index 000000000..d5fe1da76 --- /dev/null +++ b/tests/resources/validation/other/modules/declarations in test files/main.sdsstub @@ -0,0 +1,33 @@ +package tests.validation.other.modules.declarationsInTestFiles + +// $TEST$ no error "A pipeline file must only declare pipelines and segments." +annotation »MyAnnotation« +// $TEST$ no error "A pipeline file must only declare pipelines and segments." +class »MyClass« { + + // $TEST$ no error "A pipeline file must only declare pipelines and segments." + attr »a«: Int + + // $TEST$ no error "A pipeline file must only declare pipelines and segments." + class »MyNestedClass« + + // $TEST$ no error "A pipeline file must only declare pipelines and segments." + enum »MyEnum« + + // $TEST$ no error "A pipeline file must only declare pipelines and segments." + fun »myFunction«() +} +// $TEST$ no error "A pipeline file must only declare pipelines and segments." +enum »MyEnum« { + // $TEST$ no error "A pipeline file must only declare pipelines and segments." + »MyEnumInstance« +} +// $TEST$ no error "A pipeline file must only declare pipelines and segments." +fun »myFunction«() +// $TEST$ no error "A pipeline file must only declare pipelines and segments." +schema »MySchema« {} + +// $TEST$ no error "A pipeline file must only declare pipelines and segments." +pipeline »myPipeline« {} +// $TEST$ no error "A pipeline file must only declare pipelines and segments." +segment »mySegment«() {} diff --git a/tests/resources/validation/other/modules/must state package/pipeline file (empty).sdspipe b/tests/resources/validation/other/modules/must state package/pipeline file (empty).sdspipe new file mode 100644 index 000000000..27af28cb3 --- /dev/null +++ b/tests/resources/validation/other/modules/must state package/pipeline file (empty).sdspipe @@ -0,0 +1 @@ +// $TEST$ no error "A module with declarations must state its package." diff --git a/tests/resources/validation/other/modules/must state package/pipeline file (only annotations).sdspipe b/tests/resources/validation/other/modules/must state package/pipeline file (only annotations).sdspipe new file mode 100644 index 000000000..d78842d9c --- /dev/null +++ b/tests/resources/validation/other/modules/must state package/pipeline file (only annotations).sdspipe @@ -0,0 +1,3 @@ +// $TEST$ no error "A module with declarations must state its package." + +@AnnotationCall diff --git a/tests/resources/validation/other/modules/must state package/pipeline file (only imports).sdspipe b/tests/resources/validation/other/modules/must state package/pipeline file (only imports).sdspipe new file mode 100644 index 000000000..cb93ed6cf --- /dev/null +++ b/tests/resources/validation/other/modules/must state package/pipeline file (only imports).sdspipe @@ -0,0 +1,3 @@ +// $TEST$ no error "A module with declarations must state its package." + +import myPackage diff --git a/tests/resources/validation/other/modules/must state package/pipeline file (with declarations and package).sdspipe b/tests/resources/validation/other/modules/must state package/pipeline file (with declarations and package).sdspipe new file mode 100644 index 000000000..6f4bf0ff8 --- /dev/null +++ b/tests/resources/validation/other/modules/must state package/pipeline file (with declarations and package).sdspipe @@ -0,0 +1,7 @@ +package tests.validation.other.modules.mustStatePackage + +// $TEST$ no error "A module with declarations must state its package." +segment »s«() {} + +// $TEST$ no error "A module with declarations must state its package." +segment »t«() {} diff --git a/tests/resources/validation/other/modules/must state package/pipeline file (with declarations but no package).sdspipe b/tests/resources/validation/other/modules/must state package/pipeline file (with declarations but no package).sdspipe new file mode 100644 index 000000000..a55723f47 --- /dev/null +++ b/tests/resources/validation/other/modules/must state package/pipeline file (with declarations but no package).sdspipe @@ -0,0 +1,5 @@ +// $TEST$ error "A module with declarations must state its package." +segment »s«() {} + +// $TEST$ no error "A module with declarations must state its package." +segment »t«() {} diff --git a/tests/resources/validation/other/modules/must state package/stub file (empty).sdsstub b/tests/resources/validation/other/modules/must state package/stub file (empty).sdsstub new file mode 100644 index 000000000..27af28cb3 --- /dev/null +++ b/tests/resources/validation/other/modules/must state package/stub file (empty).sdsstub @@ -0,0 +1 @@ +// $TEST$ no error "A module with declarations must state its package." diff --git a/tests/resources/validation/other/modules/must state package/stub file (only annotations).sdsstub b/tests/resources/validation/other/modules/must state package/stub file (only annotations).sdsstub new file mode 100644 index 000000000..d78842d9c --- /dev/null +++ b/tests/resources/validation/other/modules/must state package/stub file (only annotations).sdsstub @@ -0,0 +1,3 @@ +// $TEST$ no error "A module with declarations must state its package." + +@AnnotationCall diff --git a/tests/resources/validation/other/modules/must state package/stub file (only imports).sdsstub b/tests/resources/validation/other/modules/must state package/stub file (only imports).sdsstub new file mode 100644 index 000000000..cb93ed6cf --- /dev/null +++ b/tests/resources/validation/other/modules/must state package/stub file (only imports).sdsstub @@ -0,0 +1,3 @@ +// $TEST$ no error "A module with declarations must state its package." + +import myPackage diff --git a/tests/resources/validation/other/modules/must state package/stub file (with declarations and package).sdsstub b/tests/resources/validation/other/modules/must state package/stub file (with declarations and package).sdsstub new file mode 100644 index 000000000..0a9fbaa54 --- /dev/null +++ b/tests/resources/validation/other/modules/must state package/stub file (with declarations and package).sdsstub @@ -0,0 +1,7 @@ +package tests.validation.other.modules.mustStatePackage + +// $TEST$ no error "A module with declarations must state its package." +class »C« + +// $TEST$ no error "A module with declarations must state its package." +class »D« diff --git a/tests/resources/validation/other/modules/must state package/stub file (with declarations but no package).sdsstub b/tests/resources/validation/other/modules/must state package/stub file (with declarations but no package).sdsstub new file mode 100644 index 000000000..ca0e6e427 --- /dev/null +++ b/tests/resources/validation/other/modules/must state package/stub file (with declarations but no package).sdsstub @@ -0,0 +1,5 @@ +// $TEST$ error "A module with declarations must state its package." +class »C« + +// $TEST$ no error "A module with declarations must state its package." +class »D« diff --git a/tests/resources/validation/other/statements/assignments/yield forbidden in pipeline/main.sdstest b/tests/resources/validation/other/statements/assignments/yield forbidden in pipeline/main.sdstest new file mode 100644 index 000000000..95bc46e87 --- /dev/null +++ b/tests/resources/validation/other/statements/assignments/yield forbidden in pipeline/main.sdstest @@ -0,0 +1,16 @@ +package tests.validation.other.statements.assignments.yieldForbiddenInPipeline + +segment s() { + // $TEST$ no error "Yield must not be used in a pipeline." + »yield a« = 1; +} + +pipeline p { + // $TEST$ error "Yield must not be used in a pipeline." + »yield a« = 1; + + () { + // $TEST$ no error "Yield must not be used in a pipeline." + »yield a« = 1; + }; +} diff --git a/tests/resources/validation/unnecessary syntax/unnecessary assignment/main.sdstest b/tests/resources/validation/style/unnecessary assignment/main.sdstest similarity index 93% rename from tests/resources/validation/unnecessary syntax/unnecessary assignment/main.sdstest rename to tests/resources/validation/style/unnecessary assignment/main.sdstest index 6a658ee17..59097760f 100644 --- a/tests/resources/validation/unnecessary syntax/unnecessary assignment/main.sdstest +++ b/tests/resources/validation/style/unnecessary assignment/main.sdstest @@ -1,4 +1,4 @@ -package tests.validation.unnecessarySyntax.unnecessaryAssignment +package tests.validation.style.unnecessaryAssignment fun f() -> (a: Int, b: Int) diff --git a/tests/resources/validation/unnecessary syntax/unnecessary body in class/main.sdstest b/tests/resources/validation/style/unnecessary body in class/main.sdstest similarity index 78% rename from tests/resources/validation/unnecessary syntax/unnecessary body in class/main.sdstest rename to tests/resources/validation/style/unnecessary body in class/main.sdstest index c2d3d12bf..24001d565 100644 --- a/tests/resources/validation/unnecessary syntax/unnecessary body in class/main.sdstest +++ b/tests/resources/validation/style/unnecessary body in class/main.sdstest @@ -1,4 +1,4 @@ -package tests.validation.unnecessarySyntax.unnecessaryBodyInClass +package tests.validation.style.unnecessaryBodyInClass // $TEST$ info "This body can be removed." class MyClass1 »{}« diff --git a/tests/resources/validation/unnecessary syntax/unnecessary body in enum/main.sdstest b/tests/resources/validation/style/unnecessary body in enum/main.sdstest similarity index 69% rename from tests/resources/validation/unnecessary syntax/unnecessary body in enum/main.sdstest rename to tests/resources/validation/style/unnecessary body in enum/main.sdstest index 0928c4d66..91b9bf82b 100644 --- a/tests/resources/validation/unnecessary syntax/unnecessary body in enum/main.sdstest +++ b/tests/resources/validation/style/unnecessary body in enum/main.sdstest @@ -1,4 +1,4 @@ -package tests.validation.unnecessarySyntax.unnecessaryBodyInEnum +package tests.validation.style.unnecessaryBodyInEnum // $TEST$ info "This body can be removed." enum MyEnum1 »{}« diff --git a/tests/resources/validation/unnecessary syntax/unnecessary parameter list in annotation/main.sdstest b/tests/resources/validation/style/unnecessary parameter list in annotation/main.sdstest similarity index 69% rename from tests/resources/validation/unnecessary syntax/unnecessary parameter list in annotation/main.sdstest rename to tests/resources/validation/style/unnecessary parameter list in annotation/main.sdstest index 17ed4fa67..9cdeefb3a 100644 --- a/tests/resources/validation/unnecessary syntax/unnecessary parameter list in annotation/main.sdstest +++ b/tests/resources/validation/style/unnecessary parameter list in annotation/main.sdstest @@ -1,4 +1,4 @@ -package tests.validation.unnecessarySyntax.unnecessaryParameterListInAnnotation +package tests.validation.style.unnecessaryParameterListInAnnotation // $TEST$ info "This parameter list can be removed." annotation MyAnnotation1»()« diff --git a/tests/resources/validation/unnecessary syntax/unnecessary parameter list in enum variant/main.sdstest b/tests/resources/validation/style/unnecessary parameter list in enum variant/main.sdstest similarity index 68% rename from tests/resources/validation/unnecessary syntax/unnecessary parameter list in enum variant/main.sdstest rename to tests/resources/validation/style/unnecessary parameter list in enum variant/main.sdstest index aabe2174a..90c689b0a 100644 --- a/tests/resources/validation/unnecessary syntax/unnecessary parameter list in enum variant/main.sdstest +++ b/tests/resources/validation/style/unnecessary parameter list in enum variant/main.sdstest @@ -1,4 +1,4 @@ -package tests.validation.unnecessarySyntax.unnecessaryParameterListInEnumVariant +package tests.validation.style.unnecessaryParameterListInEnumVariant // $TEST$ info "This parameter list can be removed." annotation MyAnnotation1»()« diff --git a/tests/resources/validation/unnecessary syntax/unnecessary result list in function/main.sdstest b/tests/resources/validation/style/unnecessary result list in function/main.sdstest similarity index 67% rename from tests/resources/validation/unnecessary syntax/unnecessary result list in function/main.sdstest rename to tests/resources/validation/style/unnecessary result list in function/main.sdstest index 529dd5c79..edb55960a 100644 --- a/tests/resources/validation/unnecessary syntax/unnecessary result list in function/main.sdstest +++ b/tests/resources/validation/style/unnecessary result list in function/main.sdstest @@ -1,4 +1,4 @@ -package tests.validation.unnecessarySyntax.unnecessaryResultListInFunction +package tests.validation.style.unnecessaryResultListInFunction // $TEST$ info "This result list can be removed." fun myFun1() »-> ()« diff --git a/tests/resources/validation/unnecessary syntax/unnecessary result list in segment/main.sdstest b/tests/resources/validation/style/unnecessary result list in segment/main.sdstest similarity index 70% rename from tests/resources/validation/unnecessary syntax/unnecessary result list in segment/main.sdstest rename to tests/resources/validation/style/unnecessary result list in segment/main.sdstest index 952176453..baea207ec 100644 --- a/tests/resources/validation/unnecessary syntax/unnecessary result list in segment/main.sdstest +++ b/tests/resources/validation/style/unnecessary result list in segment/main.sdstest @@ -1,4 +1,4 @@ -package tests.validation.unnecessarySyntax.unnecessaryResultListInSegment +package tests.validation.style.unnecessaryResultListInSegment // $TEST$ info "This result list can be removed." segment mySegment1() »-> ()« {} diff --git a/tests/resources/validation/unnecessary syntax/unnecessary type parameter list in class/main.sdstest b/tests/resources/validation/style/unnecessary type parameter list in class/main.sdstest similarity index 67% rename from tests/resources/validation/unnecessary syntax/unnecessary type parameter list in class/main.sdstest rename to tests/resources/validation/style/unnecessary type parameter list in class/main.sdstest index 9db0108ba..8d3f68dba 100644 --- a/tests/resources/validation/unnecessary syntax/unnecessary type parameter list in class/main.sdstest +++ b/tests/resources/validation/style/unnecessary type parameter list in class/main.sdstest @@ -1,4 +1,4 @@ -package tests.validation.unnecessarySyntax.unnecessaryTypeParameterListInClass +package tests.validation.style.unnecessaryTypeParameterListInClass // $TEST$ info "This type parameter list can be removed." class MyClass1»<>« diff --git a/tests/resources/validation/unnecessary syntax/unnecessary type parameter list in enum variant/main.sdstest b/tests/resources/validation/style/unnecessary type parameter list in enum variant/main.sdstest similarity index 68% rename from tests/resources/validation/unnecessary syntax/unnecessary type parameter list in enum variant/main.sdstest rename to tests/resources/validation/style/unnecessary type parameter list in enum variant/main.sdstest index 3f8c1fad5..53f24223e 100644 --- a/tests/resources/validation/unnecessary syntax/unnecessary type parameter list in enum variant/main.sdstest +++ b/tests/resources/validation/style/unnecessary type parameter list in enum variant/main.sdstest @@ -1,4 +1,4 @@ -package tests.validation.unnecessarySyntax.unnecessaryTypeParameterListInEnumVariant +package tests.validation.style.unnecessaryTypeParameterListInEnumVariant enum MyEnum { // $TEST$ info "This type parameter list can be removed." diff --git a/tests/resources/validation/unnecessary syntax/unnecessary type parameter list in function/main.sdstest b/tests/resources/validation/style/unnecessary type parameter list in function/main.sdstest similarity index 67% rename from tests/resources/validation/unnecessary syntax/unnecessary type parameter list in function/main.sdstest rename to tests/resources/validation/style/unnecessary type parameter list in function/main.sdstest index 93f75c7ad..8c67cca99 100644 --- a/tests/resources/validation/unnecessary syntax/unnecessary type parameter list in function/main.sdstest +++ b/tests/resources/validation/style/unnecessary type parameter list in function/main.sdstest @@ -1,4 +1,4 @@ -package tests.validation.unnecessarySyntax.unnecessaryTypeParameterListInFunction +package tests.validation.style.unnecessaryTypeParameterListInFunction // $TEST$ info "This type parameter list can be removed." fun myFunction1»<>«() diff --git a/tests/resources/validation/unnecessary syntax/unnecessary union type/main.sdstest b/tests/resources/validation/style/unnecessary union type/main.sdstest similarity index 86% rename from tests/resources/validation/unnecessary syntax/unnecessary union type/main.sdstest rename to tests/resources/validation/style/unnecessary union type/main.sdstest index c6cc3b533..451142b8c 100644 --- a/tests/resources/validation/unnecessary syntax/unnecessary union type/main.sdstest +++ b/tests/resources/validation/style/unnecessary union type/main.sdstest @@ -1,4 +1,4 @@ -package tests.validation.unnecessarySyntax.unnecessaryUnionType +package tests.validation.style.unnecessaryUnionType // $TEST$ no info "This can be replaced by the singular type argument of the union type." segment mySegment1( diff --git a/tests/resources/validation/types/type hints/missing for attribute/main.sdstest b/tests/resources/validation/types/type hints/missing for attribute/main.sdstest new file mode 100644 index 000000000..06b9c856b --- /dev/null +++ b/tests/resources/validation/types/type hints/missing for attribute/main.sdstest @@ -0,0 +1,9 @@ +package tests.validation.types.typeHints.missingForAttribute + +class MyClass { + // $TEST$ error "An attribute must have a type hint." + attr »myAttribute1« + + // $TEST$ no error "An attribute must have a type hint." + attr »myAttribute2«: Int +} diff --git a/tests/resources/validation/types/type hints/missing for parameter/main.sdstest b/tests/resources/validation/types/type hints/missing for parameter/main.sdstest new file mode 100644 index 000000000..f72506525 --- /dev/null +++ b/tests/resources/validation/types/type hints/missing for parameter/main.sdstest @@ -0,0 +1,39 @@ +package tests.validation.types.typeHints.missingForParameter + +// $TEST$ error "A parameter must have a type hint." +// $TEST$ no error "A parameter must have a type hint." +annotation MyAnnotation(»a«, »b«: Int) + +// $TEST$ error "A parameter must have a type hint." +// $TEST$ no error "A parameter must have a type hint." +class MyClass(»a«, »b«: Int) { + // $TEST$ error "A parameter must have a type hint." + // $TEST$ no error "A parameter must have a type hint." + class MyClass(»a«, »b«: Int) {} + + // $TEST$ error "A parameter must have a type hint." + // $TEST$ no error "A parameter must have a type hint." + fun myFunction(»a«, »b«: Int) +} + +// $TEST$ error "A parameter must have a type hint." +// $TEST$ no error "A parameter must have a type hint." +fun myFunction(»a«, »b«: Int) + +pipeline myPipeline { + // $TEST$ no error "A parameter must have a type hint." + (»a«) -> a; + + // $TEST$ no error "A parameter must have a type hint." + (»a«) {}; +} + +// $TEST$ error "A parameter must have a type hint." +// $TEST$ no error "A parameter must have a type hint." +segment mySegment1(»a«, »b«: Int) {} + +// $TEST$ error "A parameter must have a type hint." +// $TEST$ no error "A parameter must have a type hint." +segment mySegment2( + f: (»a«, »b«: Int) -> () +) {} diff --git a/tests/resources/validation/types/type hints/missing for result/main.sdstest b/tests/resources/validation/types/type hints/missing for result/main.sdstest new file mode 100644 index 000000000..29e4df16e --- /dev/null +++ b/tests/resources/validation/types/type hints/missing for result/main.sdstest @@ -0,0 +1,21 @@ +package tests.validation.types.typeHints.missingForResult + +class MyClass { + // $TEST$ error "A result must have a type hint." + // $TEST$ no error "A result must have a type hint." + fun myFunction() -> (»a«, »b«: Int) +} + +// $TEST$ error "A result must have a type hint." +// $TEST$ no error "A result must have a type hint." +fun myFunction() -> (»a«, »b«: Int) + +// $TEST$ error "A result must have a type hint." +// $TEST$ no error "A result must have a type hint." +segment mySegment1() -> (»a«, »b«: Int) {} + +// $TEST$ error "A result must have a type hint." +// $TEST$ no error "A result must have a type hint." +segment mySegment2( + f: () -> (»a«, »b«: Int) +) {}