From 11c81b32f8a279dcc59239150cdea3fe4f75cf42 Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Sun, 5 May 2024 11:37:29 +0200 Subject: [PATCH] feat: suggest adding assignment if statement does nothing (#1156) Closes #1142 ### Summary of Changes Suggest adding an assignment if the user likely forgot it. --- .../validation/other/statements/statements.ts | 28 +++++++++++++++---- .../has no effect/main.sdsdev | 26 ++++++++--------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/packages/safe-ds-lang/src/language/validation/other/statements/statements.ts b/packages/safe-ds-lang/src/language/validation/other/statements/statements.ts index 689bb8bf7..438b1483f 100644 --- a/packages/safe-ds-lang/src/language/validation/other/statements/statements.ts +++ b/packages/safe-ds-lang/src/language/validation/other/statements/statements.ts @@ -1,18 +1,34 @@ -import { SdsStatement } from '../../../generated/ast.js'; +import { isSdsExpressionStatement, SdsStatement } from '../../../generated/ast.js'; import { ValidationAcceptor } from 'langium'; import { SafeDsServices } from '../../../safe-ds-module.js'; +import { NamedTupleType } from '../../../typing/model.js'; export const CODE_STATEMENT_HAS_NO_EFFECT = 'statement/has-no-effect'; export const statementMustDoSomething = (services: SafeDsServices) => { const purityComputer = services.purity.PurityComputer; + const typeComputer = services.typing.TypeComputer; return (node: SdsStatement, accept: ValidationAcceptor): void => { - if (!purityComputer.statementDoesSomething(node)) { - accept('warning', 'This statement does nothing.', { - node, - code: CODE_STATEMENT_HAS_NO_EFFECT, - }); + if (purityComputer.statementDoesSomething(node)) { + return; } + + // Special warning message if an assignment is probably missing + if (isSdsExpressionStatement(node)) { + const expressionType = typeComputer.computeType(node.expression); + if (!(expressionType instanceof NamedTupleType) || expressionType.length > 0) { + accept('warning', 'This statement does nothing. Did you forget the assignment?', { + node, + code: CODE_STATEMENT_HAS_NO_EFFECT, + }); + return; + } + } + + accept('warning', 'This statement does nothing.', { + node, + code: CODE_STATEMENT_HAS_NO_EFFECT, + }); }; }; diff --git a/packages/safe-ds-lang/tests/resources/validation/other/statements/expression statements/has no effect/main.sdsdev b/packages/safe-ds-lang/tests/resources/validation/other/statements/expression statements/has no effect/main.sdsdev index 5dcf20fe1..39d35aa38 100644 --- a/packages/safe-ds-lang/tests/resources/validation/other/statements/expression statements/has no effect/main.sdsdev +++ b/packages/safe-ds-lang/tests/resources/validation/other/statements/expression statements/has no effect/main.sdsdev @@ -4,17 +4,17 @@ package tests.validation.other.statements.expressionStatements.hasNoEffect fun impureFunction() @Pure -fun pureFunction() -> a: Int +fun pureFunctionWithResults() -> a: Int class MyClass() { @Impure([ImpurityReason.Other]) fun impureFunction() - @Pure fun pureFunction() + @Pure fun pureFunctionWithoutResults() } segment pureSegment() { - val a = pureFunction(); + val a = pureFunctionWithResults(); } segment impureSegment() { @@ -30,12 +30,12 @@ segment recursiveB() { } segment mySegment() { - // $TEST$ warning "This statement does nothing." + // $TEST$ warning "This statement does nothing. Did you forget the assignment?" »1 + 2;« + // $TEST$ warning "This statement does nothing. Did you forget the assignment?" + »pureFunctionWithResults();« // $TEST$ warning "This statement does nothing." - »pureFunction();« - // $TEST$ warning "This statement does nothing." - »MyClass().pureFunction();« + »MyClass().pureFunctionWithoutResults();« // $TEST$ no warning "This statement does nothing." »impureFunction();« @@ -43,12 +43,12 @@ segment mySegment() { »MyClass().impureFunction();« () { - // $TEST$ warning "This statement does nothing." + // $TEST$ warning "This statement does nothing. Did you forget the assignment?" »1 + 2;« + // $TEST$ warning "This statement does nothing. Did you forget the assignment?" + »pureFunctionWithResults();« // $TEST$ warning "This statement does nothing." - »pureFunction();« - // $TEST$ warning "This statement does nothing." - »MyClass().pureFunction();« + »MyClass().pureFunctionWithoutResults();« // $TEST$ no warning "This statement does nothing." »impureFunction();« @@ -64,8 +64,8 @@ segment mySegment() { // $TEST$ warning "This statement does nothing." »(() { - pureFunction(); - MyClass().pureFunction(); + pureFunctionWithResults(); + MyClass().pureFunctionWithoutResults(); })();« // $TEST$ no warning "This statement does nothing."