8000 feat(eslint-plugin): add no-uncalled-signals rule by scj7t4 · Pull Request #2383 · angular-eslint/angular-eslint · GitHub
[go: up one dir, main page]

Skip to content

feat(eslint-plugin): add no-uncalled-signals rule #2383

New issue

Have a question about this project? Sign up for a free GitHub account to open an 8000 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

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

scj7t4
Copy link
@scj7t4 scj7t4 commented Apr 20, 2025

Checks that signals used in logical expressions are invoked. For #2302

Thanks for your work on the project! This is my first attempt at a typescript eslint plugin, so feedback is very appreciated on what I messed up :)

@scj7t4 scj7t4 force-pushed the add-signal-logic-rule branch from fc8bd24 to 41eaa68 Compare April 20, 2025 17:19
Copy link
Member
@JamesHenry JamesHenry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeScript has always referred to this as uncalled function checks: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#uncalled-function-checks

So maybe no-uncalled-signals is a better name (given it doesn't check any other kind of "misuse")?

@JamesHenry
Copy link
Member

WDYT about the name @reduckted?

@reduckted
Copy link
Contributor

I think no-uncalled-signals is a good name. It aligns with the TypeScript concept, and also describes what ithe rule actually checks - that signals are called.
👍

@scj7t4 scj7t4 force-pushed the add-signal-logic-rule branch 2 times, most recently from 6826326 to 74db158 Compare May 10, 2025 17:23
@scj7t4
Copy link
Author
scj7t4 commented May 10, 2025

Thanks for the feedback! I've reverted the package.json files and changed the name of the rule to no-uncalled-signals

@scj7t4 scj7t4 changed the title feat(no-misused-signals): check use of signals in logical expressions feat(no-uncalled-signals): check use of signals in logical expressions (Formerly no-misused-signals) May 10, 2025
@scj7t4 scj7t4 force-pushed the add-signal-logic-rule branch from 74db158 to fd51cce Compare May 10, 2025 21:41
@JamesHenry JamesHenry changed the title feat(no-uncalled-signals): check use of signals in logical expressions (Formerly no-misused-signals) feat(no-uncalled-signals): check use of signals in logical expressions May 11, 2025
@JamesHenry JamesHenry changed the title feat(no-uncalled-signals): check use of signals in logical expressions feat(eslint-plugin): add no-uncalled-signals rule May 11, 2025
Copy link
8000
nx-cloud bot commented May 11, 2025

View your CI Pipeline Execution ↗ for commit 3cae292.

Command Status Duration Result
nx run-many -t build,typecheck,check-rule-docs,... ❌ Failed 1m 26s View ↗
nx run-many -t test ❌ Failed 36s View ↗
nx-cloud record -- pnpm nx sync:check ✅ Succeeded 2s View ↗
nx-cloud record -- pnpm format-check ✅ Succeeded 5s View ↗
nx run-many -t build ✅ Succeeded 14s View ↗

☁️ Nx Cloud last updated this comment at 2025-05-13 10:08:02 UTC

@JamesHenry
Copy link
Member

@scj7t4 Thanks please see the CI failures they tell you what to do to fix them

description:
"Warns user about unintentionally doing logic on the signal, rather than the signal's value",
},
hasSuggestions: true,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rule is marked with hasSuggestions: true but doesn't implement any suggestions in the context.report() call. To properly support suggestions, either:

  1. Add a suggest property to the report object with appropriate fixes:

    context.report({
      node,
      messageId: 'noUncalledSignals',
      suggest: [
        {
          messageId: 'addCallParentheses',
          fix: (fixer) => fixer.replaceText(node, `${node.name}()`)
        }
      ]
    });
  2. Or remove the hasSuggestions: true property if no suggestions will be provided.

This would make the rule's behavior consistent with its metadata.

Spotted by Diamond

Is this helpful? React 👍 or 👎 to let us know.

@scj7t4 scj7t4 marked this pull request as draft May 12, 2025 00:57
Checks that signals used in logical expressions are invoked. For angular-eslint#2302
@scj7t4 scj7t4 force-pushed the add-signal-logic-rule branch from f2adafb to 33e6dfc Compare May 12, 2025 01:23
@scj7t4 scj7t4 marked this pull request as ready for review May 12, 2025 01:26
@scj7t4
Copy link
Author
scj7t4 commented May 12, 2025

@scj7t4 Thanks please see the CI failures they tell you what to do to fix them

Should be fixed

@reduckted
Copy link
Contributor

@scj7t4 You'll need to run these two commands to update some generated files:

pnpm update-rule-lists
pnpm update-rule-configs
pnpm update-rule-docs

export type MessageIds = 'noUncalledSignals';
export const RULE_NAME = 'no-uncalled-signals';

const KNOWN_SIGNAL_TYPES: ReadonlySet<string> = new Set([
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is duplicated from the prefer-signals rule. You might want to move it into a common place (maybe ./utils/signals.ts) so that both rules can share it.

ESLintUtils.getParserServices(context);

return {
'*.test[type=Identifier], *.test Identifier'(node: TSESTree.Identifier) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice use of *.test. 👍

There are some cases that it doesn't find though:

const v = aSignal || true;
const v = aSignal ?? true;

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm struggling a bit with this one. If I add the matcher:

[type=LogicalExpression] Identifier

I can find these cases. However, then I can't find a variation of the first matcher (or my new matcher) that will not match for both in some cases. Is it okay to have a rule report the same finding 2 times?

I've pushed the new version with the extra matcher.

const identifierType = type.getSymbol()?.name;

if (identifierType && KNOWN_SIGNAL_TYPES.has(identifierType)) {
context.report({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the most likely change to fix this problem will be to call the signal, it might be worth including a suggestion that adds () after the identifier. It won't auto-fix it, but it will provide a quick way for users to apply the code change to get rid of this problem.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, it's the exact thing graphite suggested above #2383 (comment)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a suggestion and adjusted the tests to verify the suggestion.

@scj7t4 scj7t4 marked this pull request as draft May 14, 2025 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0