Skip to content

Commit

Permalink
feat: validate package of imports (#627)
Browse files Browse the repository at this point in the history
Closes partially #543

### Summary of Changes

* Show an error if a package is imported that does not exist
* Show a warning if an empty package is imported
  • Loading branch information
lars-reimann authored Oct 10, 2023
1 parent 077daff commit 18641de
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 2 deletions.
30 changes: 30 additions & 0 deletions src/language/validation/other/imports.ts
Original file line number Diff line number Diff line change
@@ -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',
});
}
};
2 changes: 0 additions & 2 deletions src/language/validation/other/modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand Down
2 changes: 2 additions & 0 deletions src/language/validation/safe-ds-validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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: [
Expand Down
1 change: 1 addition & 0 deletions tests/resources/validation/other/imports/empty.sdstest
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package tests.other.imports.empty
15 changes: 15 additions & 0 deletions tests/resources/validation/other/imports/main with issues.sdstest
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions tests/resources/validation/other/imports/non empty.sdstest
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package tests.other.imports.nonEmpty

class C

0 comments on commit 18641de

Please sign in to comment.