Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: disable "unused" warning for placeholders whose name starts with an underscore #1155

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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();
};
}