Skip to content

Commit

Permalink
feat: disable "unused" warning for placeholders whose name starts wit…
Browse files Browse the repository at this point in the history
…h an underscore (#1155)

Closes #1154

### Summary of Changes

Don't show a warning anymore that a placeholder is unused, if its name
starts with an underscore.
  • Loading branch information
lars-reimann authored May 5, 2024
1 parent b469779 commit 25781a8
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 30 deletions.
4 changes: 3 additions & 1 deletion docs/pipeline-language/statements/assignments.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ This assignment to a placeholder has the following syntactic elements:

??? info "Name convention"

Use `#!sds lowerCamelCase` for the name of the placeholder.
Use `#!sds lowerCamelCase` for the name of the placeholder. You may prefix the name of an unused placeholder with an
underscore (`_`) to indicate that it is intentionally unused, e.g. to
[inspect its value](#inspecting-placeholder-values-in-vs-code). This disables the "unused" warning.

### References to Placeholder

Expand Down
22 changes: 21 additions & 1 deletion packages/safe-ds-lang/src/language/validation/names.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,12 @@ export const nameShouldHaveCorrectCasing = (services: SafeDsServices) => {
case SdsPipeline:
return nameShouldBeLowerCamelCase(node, 'pipelines', accept);
case SdsPlaceholder:
return nameShouldBeLowerCamelCase(node, 'placeholders', accept);
const usages = services.helpers.NodeMapper.placeholderToReferences(node as SdsPlaceholder);
if (usages.isEmpty()) {
return nameShouldBeLowerCamelCaseWithOptionalLeadingUnderscore(node, 'unused placeholders', accept);
} else {
return nameShouldBeLowerCamelCase(node, 'used placeholders', accept);
}
case SdsResult:
return nameShouldBeLowerCamelCase(node, 'results', accept);
case SdsSchema:
Expand All @@ -169,6 +174,21 @@ const isLowerCamelCase = (name: string): boolean => {
return /^[a-z][a-zA-Z0-9]*$/gu.test(name);
};

const nameShouldBeLowerCamelCaseWithOptionalLeadingUnderscore = (
node: SdsDeclaration,
nodeName: string,
accept: ValidationAcceptor,
): void => {
const name = node.name ?? '';
if (!isLowerCamelCaseWithOptionalLeadingUnderscore(name)) {
acceptCasingWarning(node, nodeName, 'lowerCamelCase with an optional leading underscore', accept);
}
};

const isLowerCamelCaseWithOptionalLeadingUnderscore = (name: string): boolean => {
return /^_?[a-z][a-zA-Z0-9]*$/gu.test(name);
};

const nameShouldBeUpperCamelCase = (node: SdsDeclaration, nodeName: string, accept: ValidationAcceptor): void => {
const name = node.name ?? '';
if (!isUpperCamelCase(name)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ export const placeholdersMustNotBeAnAlias = (node: SdsPlaceholder, accept: Valid

export const placeholderShouldBeUsed =
(services: SafeDsServices) => (node: SdsPlaceholder, accept: ValidationAcceptor) => {
// Don't a warning if the placeholder's name starts with an underscore
if (node.name.startsWith('_')) {
return;
}

// Check if the placeholder is used
const usages = services.helpers.NodeMapper.placeholderToReferences(node);
if (!usages.isEmpty()) {
return;
Expand All @@ -52,10 +58,14 @@ export const placeholderShouldBeUsed =
return;
}

accept('warning', 'This placeholder is unused and can be removed.', {
node,
property: 'name',
code: CODE_PLACEHOLDER_UNUSED,
tags: [DiagnosticTag.Unnecessary],
});
accept(
'warning',
'This placeholder is unused and can be removed. Prefix its name with an underscore to disable this warning.',
{
node,
property: 'name',
code: CODE_PLACEHOLDER_UNUSED,
tags: [DiagnosticTag.Unnecessary],
},
);
};
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
package tests.validation.names.casing

pipeline myPipeline2 {
// $TEST$ warning "Names of placeholders should be lowerCamelCase."
val »PlaceholderUppercase« = 1;
// $TEST$ no warning "Names of placeholders should be lowerCamelCase."
val »placeholderLowercase1« = 1;
// $TEST$ no warning "Names of placeholders should be lowerCamelCase."
val »`placeholderLowercase2`« = 1;
// $TEST$ warning "Names of placeholders should be lowerCamelCase."
val »_placeholderUnderscore« = 1;
// $TEST$ warning "Names of placeholders should be lowerCamelCase."
val »placeholder_snake_case« = 1;
// $TEST$ warning "Names of used placeholders should be lowerCamelCase."
val »UsedPlaceholderUppercase« = 1;
// $TEST$ no warning "Names of used placeholders should be lowerCamelCase.""
val »usedPlaceholderLowercase1« = 1;
// $TEST$ no warning "Names of used placeholders should be lowerCamelCase.""
val »`usedPlaceholderLowercase2`« = 1;
// $TEST$ warning "Names of used placeholders should be lowerCamelCase."
val »_usedPlaceholderUnderscore« = 1;
// $TEST$ warning "Names of used placeholders should be lowerCamelCase."
val »used_placeholder_snake_case« = 1;

// $TEST$ warning "Names of unused placeholders should be lowerCamelCase with an optional leading underscore."
val »UnusedPlaceholderUppercase« = UsedPlaceholderUppercase + 1;
// $TEST$ no warning "Names of unused placeholders should be lowerCamelCase. with an optional leading underscore."
val »unusedPlaceholderLowercase1« = usedPlaceholderLowercase1 + 1;
// $TEST$ no warning "Names of unused placeholders should be lowerCamelCase. with an optional leading underscore."
val »`unusedPlaceholderLowercase2`« = usedPlaceholderLowercase2 + 1;
// $TEST$ no warning "Names of unused placeholders should be lowerCamelCase with an optional leading underscore."
val »_unusedPlaceholderUnderscore« = _usedPlaceholderUnderscore + 1;
// $TEST$ warning "Names of unused placeholders should be lowerCamelCase with an optional leading underscore."
val »unused_placeholder_snake_case« = used_placeholder_snake_case + 1;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,51 @@ package tests.validation.other.declarations.placeholders.unused
fun f() -> (r1: Int, r2: Int)

segment mySegment() {
// $TEST$ warning "This placeholder is unused and can be removed."
// $TEST$ warning "This placeholder is unused and can be removed. Prefix its name with an underscore to disable this warning."
val »unused« = 1;

// $TEST$ no warning "This placeholder is unused and can be removed."
// $TEST$ no warning "This placeholder is unused and can be removed. Prefix its name with an underscore to disable this warning."
val »_unused« = 1;

// $TEST$ no warning "This placeholder is unused and can be removed. Prefix its name with an underscore to disable this warning."
val »used« = 1;
used;

// $TEST$ no warning "This placeholder is unused and can be removed."
// $TEST$ no warning "This placeholder is unused and can be removed."
// $TEST$ no warning "This placeholder is unused and can be removed. Prefix its name with an underscore to disable this warning."
// $TEST$ no warning "This placeholder is unused and can be removed. Prefix its name with an underscore to disable this warning."
val »last1«, val »last2« = f();
}

pipeline myPipeline1 {
// $TEST$ warning "This placeholder is unused and can be removed."
// $TEST$ warning "This placeholder is unused and can be removed. Prefix its name with an underscore to disable this warning."
val »unused« = 1;

// $TEST$ no warning "This placeholder is unused and can be removed."
// $TEST$ no warning "This placeholder is unused and can be removed. Prefix its name with an underscore to disable this warning."
val »_unused« = 1;

// $TEST$ no warning "This placeholder is unused and can be removed. Prefix its name with an underscore to disable this warning."
val »used« = 1;
used;

// $TEST$ no warning "This placeholder is unused and can be removed."
// $TEST$ no warning "This placeholder is unused and can be removed."
// $TEST$ no warning "This placeholder is unused and can be removed. Prefix its name with an underscore to disable this warning."
// $TEST$ no warning "This placeholder is unused and can be removed. Prefix its name with an underscore to disable this warning."
val »last1«, val »last2« = f();
}

pipeline myPipeline2 {
() {
// $TEST$ warning "This placeholder is unused and can be removed."
// $TEST$ warning "This placeholder is unused and can be removed. Prefix its name with an underscore to disable this warning."
val »unused« = 1;

// $TEST$ no warning "This placeholder is unused and can be removed."
// $TEST$ no warning "This placeholder is unused and can be removed. Prefix its name with an underscore to disable this warning."
val »_unused« = 1;

// $TEST$ no warning "This placeholder is unused and can be removed. Prefix its name with an underscore to disable this warning."
val »used« = 1;
used;

// $TEST$ no warning "This placeholder is unused and can be removed."
// $TEST$ no warning "This placeholder is unused and can be removed."
// $TEST$ no warning "This placeholder is unused and can be removed. Prefix its name with an underscore to disable this warning."
// $TEST$ no warning "This placeholder is unused and can be removed. Prefix its name with an underscore to disable this warning."
val »last1«, val »last2« = f();
};
}

0 comments on commit 25781a8

Please sign in to comment.