Skip to content

Commit 3ba8698

Browse files
authored
feat: mark unused internal/private segments as unnecessary (#710)
Closes #682 ### Summary of Changes Show a warning if internal/private segments are unused and mark them as unnecessary.
1 parent 9d342e4 commit 3ba8698

File tree

4 files changed

+62
-7
lines changed

4 files changed

+62
-7
lines changed

packages/safe-ds-lang/src/language/validation/other/declarations/segments.ts

+34-6
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@ import { DiagnosticTag } from 'vscode-languageserver';
66

77
export const CODE_SEGMENT_DUPLICATE_YIELD = 'segment/duplicate-yield';
88
export const CODE_SEGMENT_UNASSIGNED_RESULT = 'segment/unassigned-result';
9+
export const CODE_SEGMENT_UNUSED = 'segment/unused';
910
export const CODE_SEGMENT_UNUSED_PARAMETER = 'segment/unused-parameter';
1011

11-
export const segmentResultMustBeAssignedExactlyOnce =
12-
(services: SafeDsServices) => (node: SdsSegment, accept: ValidationAcceptor) => {
12+
export const segmentResultMustBeAssignedExactlyOnce = (services: SafeDsServices) => {
13+
const nodeMapper = services.helpers.NodeMapper;
14+
15+
return (node: SdsSegment, accept: ValidationAcceptor) => {
1316
const results = getResults(node.resultList);
1417
for (const result of results) {
15-
const yields = services.helpers.NodeMapper.resultToYields(result);
18+
const yields = nodeMapper.resultToYields(result);
1619
if (yields.isEmpty()) {
1720
accept('error', 'Nothing is assigned to this result.', {
1821
node: result,
@@ -32,11 +35,35 @@ export const segmentResultMustBeAssignedExactlyOnce =
3235
}
3336
}
3437
};
38+
};
39+
40+
export const segmentShouldBeUsed = (services: SafeDsServices) => {
41+
const referenceProvider = services.references.References;
42+
43+
return (node: SdsSegment, accept: ValidationAcceptor) => {
44+
// Don't show this warning for public segments
45+
if (node.visibility === undefined) {
46+
return;
47+
}
48+
49+
const references = referenceProvider.findReferences(node, {});
50+
if (references.isEmpty()) {
51+
accept('warning', 'This segment is unused and can be removed.', {
52+
node,
53+
property: 'name',
54+
code: CODE_SEGMENT_UNUSED,
55+
tags: [DiagnosticTag.Unnecessary],
56+
});
57+
}
58+
};
59+
};
60+
61+
export const segmentParameterShouldBeUsed = (services: SafeDsServices) => {
62+
const nodeMapper = services.helpers.NodeMapper;
3563

36-
export const segmentParameterShouldBeUsed =
37-
(services: SafeDsServices) => (node: SdsSegment, accept: ValidationAcceptor) => {
64+
return (node: SdsSegment, accept: ValidationAcceptor) => {
3865
for (const parameter of getParameters(node)) {
39-
const usages = services.helpers.NodeMapper.parameterToReferences(parameter);
66+
const usages = nodeMapper.parameterToReferences(parameter);
4067

4168
if (usages.isEmpty()) {
4269
accept('warning', 'This parameter is unused and can be removed.', {
@@ -48,3 +75,4 @@ export const segmentParameterShouldBeUsed =
4875
}
4976
}
5077
};
78+
};

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

+6-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,11 @@ import {
9393
referenceTargetShouldNotExperimental,
9494
} from './builtins/experimental.js';
9595
import { placeholderShouldBeUsed, placeholdersMustNotBeAnAlias } from './other/declarations/placeholders.js';
96-
import { segmentParameterShouldBeUsed, segmentResultMustBeAssignedExactlyOnce } from './other/declarations/segments.js';
96+
import {
97+
segmentParameterShouldBeUsed,
98+
segmentResultMustBeAssignedExactlyOnce,
99+
segmentShouldBeUsed,
100+
} from './other/declarations/segments.js';
97101
import {
98102
lambdaMustBeAssignedToTypedParameter,
99103
lambdaParameterMustNotHaveConstModifier,
@@ -282,6 +286,7 @@ export const registerValidationChecks = function (services: SafeDsServices) {
282286
segmentParameterShouldBeUsed(services),
283287
segmentResultMustBeAssignedExactlyOnce(services),
284288
segmentResultListShouldNotBeEmpty,
289+
segmentShouldBeUsed(services),
285290
],
286291
SdsTemplateString: [templateStringMustHaveExpressionBetweenTwoStringParts],
287292
SdsTypeParameter: [typeParameterMustHaveSufficientContext],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package tests.validation.other.declarations.segments.unused
2+
3+
// $TEST$ warning "This segment is unused and can be removed."
4+
private segment »myUnusedPrivateSegment«() {}
5+
6+
// $TEST$ no warning "This segment is unused and can be removed."
7+
private segment »myUsedPrivateSegment«() {}
8+
9+
// $TEST$ warning "This segment is unused and can be removed."
10+
internal segment »myUnusedInternalSegment«() {}
11+
12+
// $TEST$ no warning "This segment is unused and can be removed."
13+
internal segment »myUsedInternalSegment«() {}
14+
15+
pipeline myPipeline1 {
16+
myUsedPrivateSegment();
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package tests.validation.other.declarations.segments.unused
2+
3+
pipeline myPipeline2 {
4+
myUsedInternalSegment();
5+
}

0 commit comments

Comments
 (0)