Skip to content

Commit 18641de

Browse files
authored
feat: validate package of imports (#627)
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
1 parent 077daff commit 18641de

File tree

7 files changed

+59
-2
lines changed

7 files changed

+59
-2
lines changed
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { ValidationAcceptor } from 'langium';
2+
import { SdsImport } from '../../generated/ast.js';
3+
import { SafeDsServices } from '../../safe-ds-module.js';
4+
import { isEmpty } from 'radash';
5+
6+
export const CODE_IMPORT_MISSING_PACKAGE = 'import/missing-package';
7+
export const CODE_IMPORT_EMPTY_PACKAGE = 'import/empty-package';
8+
9+
export const importPackageMustExist =
10+
(services: SafeDsServices) =>
11+
(node: SdsImport, accept: ValidationAcceptor): void => {
12+
if (!services.workspace.PackageManager.hasPackage(node.package)) {
13+
accept('error', `The package '${node.package}' does not exist.`, {
14+
node,
15+
property: 'package',
16+
});
17+
}
18+
};
19+
20+
export const importPackageShouldNotBeEmpty =
21+
(services: SafeDsServices) =>
22+
(node: SdsImport, accept: ValidationAcceptor): void => {
23+
const declarationsInPackage = services.workspace.PackageManager.getDeclarationsInPackage(node.package);
24+
if (isEmpty(declarationsInPackage)) {
25+
accept('warning', `The package '${node.package}' is empty.`, {
26+
node,
27+
property: 'package',
28+
});
29+
}
30+
};

src/language/validation/other/modules.ts

-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ import { isSdsDeclaration, isSdsPipeline, isSdsSegment, SdsModule } from '../../
33
import { isInPipelineFile, isInStubFile } from '../../helpers/fileExtensions.js';
44

55
export const CODE_MODULE_MISSING_PACKAGE = 'module/missing-package';
6-
76
export const CODE_MODULE_FORBIDDEN_IN_PIPELINE_FILE = 'module/forbidden-in-pipeline-file';
8-
97
export const CODE_MODULE_FORBIDDEN_IN_STUB_FILE = 'module/forbidden-in-stub-file';
108

119
export const moduleWithDeclarationsMustStatePackage = (node: SdsModule, accept: ValidationAcceptor): void => {

src/language/validation/safe-ds-validator.ts

+2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ import {
7272
lambdaParametersMustNotBeAnnotated,
7373
} from './other/declarations/annotationCalls.js';
7474
import { memberAccessMustBeNullSafeIfReceiverIsNullable } from './other/expressions/memberAccesses.js';
75+
import { importPackageMustExist, importPackageShouldNotBeEmpty } from './other/imports.js';
7576

7677
/**
7778
* Register custom validation checks.
@@ -118,6 +119,7 @@ export const registerValidationChecks = function (services: SafeDsServices) {
118119
SdsEnumVariant: [enumVariantMustContainUniqueNames, enumVariantParameterListShouldNotBeEmpty],
119120
SdsExpressionLambda: [expressionLambdaMustContainUniqueNames],
120121
SdsFunction: [functionMustContainUniqueNames, functionResultListShouldNotBeEmpty],
122+
SdsImport: [importPackageMustExist(services), importPackageShouldNotBeEmpty(services)],
121123
SdsIndexedAccess: [indexedAccessesShouldBeUsedWithCaution],
122124
SdsLambda: [lambdaParametersMustNotBeAnnotated, lambdaParameterMustNotHaveConstModifier],
123125
SdsMemberAccess: [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package tests.other.imports.empty
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package tests.other.imports
2+
3+
// $TEST$ error "The package 'tests.other.imports.missing' does not exist."
4+
from »tests.other.imports.missing« import *
5+
// $TEST$ error ""The package 'tests.other.imports.missing' does not exist."
6+
from »tests.other.imports.missing« import C
7+
// $TEST$ error ""The package 'tests.other.imports.missing' does not exist."
8+
from »tests.other.imports.missing« import C as D
9+
10+
// $TEST$ warning "The package 'tests.other.imports.empty' is empty."
11+
from »tests.other.imports.empty« import *
12+
// $TEST$ warning "The package 'tests.other.imports.empty' is empty."
13+
from »tests.other.imports.empty« import C
14+
// $TEST$ warning "The package 'tests.other.imports.empty' is empty."
15+
from »tests.other.imports.empty« import C as D
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package tests.other.imports
2+
3+
// $TEST$ no error r"The package '\.*' does not exist\."
4+
// $TEST$ no warning r"The package '\.*' is empty\."
5+
6+
from tests.other.imports.nonEmpty import *
7+
from tests.other.imports.nonEmpty import C
8+
from tests.other.imports.nonEmpty import C as D
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package tests.other.imports.nonEmpty
2+
3+
class C

0 commit comments

Comments
 (0)