diff --git a/src/language/validation/other/imports.ts b/src/language/validation/other/imports.ts new file mode 100644 index 000000000..30f9a07c4 --- /dev/null +++ b/src/language/validation/other/imports.ts @@ -0,0 +1,30 @@ +import { ValidationAcceptor } from 'langium'; +import { SdsImport } from '../../generated/ast.js'; +import { SafeDsServices } from '../../safe-ds-module.js'; +import { isEmpty } from 'radash'; + +export const CODE_IMPORT_MISSING_PACKAGE = 'import/missing-package'; +export const CODE_IMPORT_EMPTY_PACKAGE = 'import/empty-package'; + +export const importPackageMustExist = + (services: SafeDsServices) => + (node: SdsImport, accept: ValidationAcceptor): void => { + if (!services.workspace.PackageManager.hasPackage(node.package)) { + accept('error', `The package '${node.package}' does not exist.`, { + node, + property: 'package', + }); + } + }; + +export const importPackageShouldNotBeEmpty = + (services: SafeDsServices) => + (node: SdsImport, accept: ValidationAcceptor): void => { + const declarationsInPackage = services.workspace.PackageManager.getDeclarationsInPackage(node.package); + if (isEmpty(declarationsInPackage)) { + accept('warning', `The package '${node.package}' is empty.`, { + node, + property: 'package', + }); + } + }; diff --git a/src/language/validation/other/modules.ts b/src/language/validation/other/modules.ts index 19f03143f..061f40f3a 100644 --- a/src/language/validation/other/modules.ts +++ b/src/language/validation/other/modules.ts @@ -3,9 +3,7 @@ import { isSdsDeclaration, isSdsPipeline, isSdsSegment, SdsModule } from '../../ import { isInPipelineFile, isInStubFile } from '../../helpers/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 => { diff --git a/src/language/validation/safe-ds-validator.ts b/src/language/validation/safe-ds-validator.ts index f6d837666..d0845efd8 100644 --- a/src/language/validation/safe-ds-validator.ts +++ b/src/language/validation/safe-ds-validator.ts @@ -72,6 +72,7 @@ import { lambdaParametersMustNotBeAnnotated, } from './other/declarations/annotationCalls.js'; import { memberAccessMustBeNullSafeIfReceiverIsNullable } from './other/expressions/memberAccesses.js'; +import { importPackageMustExist, importPackageShouldNotBeEmpty } from './other/imports.js'; /** * Register custom validation checks. @@ -118,6 +119,7 @@ export const registerValidationChecks = function (services: SafeDsServices) { SdsEnumVariant: [enumVariantMustContainUniqueNames, enumVariantParameterListShouldNotBeEmpty], SdsExpressionLambda: [expressionLambdaMustContainUniqueNames], SdsFunction: [functionMustContainUniqueNames, functionResultListShouldNotBeEmpty], + SdsImport: [importPackageMustExist(services), importPackageShouldNotBeEmpty(services)], SdsIndexedAccess: [indexedAccessesShouldBeUsedWithCaution], SdsLambda: [lambdaParametersMustNotBeAnnotated, lambdaParameterMustNotHaveConstModifier], SdsMemberAccess: [ diff --git a/tests/resources/validation/other/imports/empty.sdstest b/tests/resources/validation/other/imports/empty.sdstest new file mode 100644 index 000000000..fee4a826e --- /dev/null +++ b/tests/resources/validation/other/imports/empty.sdstest @@ -0,0 +1 @@ +package tests.other.imports.empty diff --git a/tests/resources/validation/other/imports/main with issues.sdstest b/tests/resources/validation/other/imports/main with issues.sdstest new file mode 100644 index 000000000..bb2154698 --- /dev/null +++ b/tests/resources/validation/other/imports/main with issues.sdstest @@ -0,0 +1,15 @@ +package tests.other.imports + +// $TEST$ error "The package 'tests.other.imports.missing' does not exist." +from »tests.other.imports.missing« import * +// $TEST$ error ""The package 'tests.other.imports.missing' does not exist." +from »tests.other.imports.missing« import C +// $TEST$ error ""The package 'tests.other.imports.missing' does not exist." +from »tests.other.imports.missing« import C as D + +// $TEST$ warning "The package 'tests.other.imports.empty' is empty." +from »tests.other.imports.empty« import * +// $TEST$ warning "The package 'tests.other.imports.empty' is empty." +from »tests.other.imports.empty« import C +// $TEST$ warning "The package 'tests.other.imports.empty' is empty." +from »tests.other.imports.empty« import C as D diff --git a/tests/resources/validation/other/imports/main without issues.sdstest b/tests/resources/validation/other/imports/main without issues.sdstest new file mode 100644 index 000000000..193d07a8b --- /dev/null +++ b/tests/resources/validation/other/imports/main without issues.sdstest @@ -0,0 +1,8 @@ +package tests.other.imports + +// $TEST$ no error r"The package '\.*' does not exist\." +// $TEST$ no warning r"The package '\.*' is empty\." + +from tests.other.imports.nonEmpty import * +from tests.other.imports.nonEmpty import C +from tests.other.imports.nonEmpty import C as D diff --git a/tests/resources/validation/other/imports/non empty.sdstest b/tests/resources/validation/other/imports/non empty.sdstest new file mode 100644 index 000000000..036c7412c --- /dev/null +++ b/tests/resources/validation/other/imports/non empty.sdstest @@ -0,0 +1,3 @@ +package tests.other.imports.nonEmpty + +class C