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

Add better-boolean-variable-names #2446

Open
wants to merge 31 commits into
base: main
Choose a base branch
from

Conversation

axetroy
Copy link
Contributor

@axetroy axetroy commented Sep 8, 2024

Close #2441

Perhaps prefer-readable-boolean-variable-names is a better name?

@axetroy axetroy changed the title Add better-boolean-var-names Add better-boolean-variable-names Sep 8, 2024
@axetroy axetroy marked this pull request as draft September 8, 2024 08:21
@axetroy axetroy force-pushed the better-boolean-var-name branch 3 times, most recently from f1bc082 to bc3134e Compare September 8, 2024 08:59
@axetroy
Copy link
Contributor Author

axetroy commented Sep 8, 2024

@fregante Found the issue in the codebase, can I fix it directly in this PR, or in separate PR?

/home/runner/work/eslint-plugin-unicorn/eslint-plugin-unicorn/rules/expiring-todo-comments.js
Error:   181:9  error  Prefer readable Boolean variable names  unicorn/better-boolean-variable-names

/home/runner/work/eslint-plugin-unicorn/eslint-plugin-unicorn/rules/explicit-length-check.js
Error:   170:8  error  Prefer readable Boolean variable names  unicorn/better-boolean-variable-names

/home/runner/work/eslint-plugin-unicorn/eslint-plugin-unicorn/rules/filename-case.js
Error:   169:8  error  Prefer readable Boolean variable names  unicorn/better-boolean-variable-names

/home/runner/work/eslint-plugin-unicorn/eslint-plugin-unicorn/rules/no-for-loop.js
Error:   340:10  error  Prefer readable Boolean variable names  unicorn/better-boolean-variable-names
Error:   355:10  error  Prefer readable Boolean variable names  unicorn/better-boolean-variable-names

/home/runner/work/eslint-plugin-unicorn/eslint-plugin-unicorn/rules/no-keyword-prefix.js
Error:   60:8  error  Prefer readable Boolean variable names  unicorn/better-boolean-variable-names
Error:   71:8  error  Prefer readable Boolean variable names  unicorn/better-boolean-variable-names

/home/runner/work/eslint-plugin-unicorn/eslint-plugin-unicorn/rules/no-process-exit.js
Error:   15:8  error  Prefer readable Boolean variable names  unicorn/better-boolean-variable-names
Error:   24:6  error  Prefer readable Boolean variable names  unicorn/better-boolean-variable-names

/home/runner/work/eslint-plugin-unicorn/eslint-plugin-unicorn/rules/prefer-default-parameters.js
Error:   100:8  error  Prefer readable Boolean variable names  unicorn/better-boolean-variable-names

/home/runner/work/eslint-plugin-unicorn/eslint-plugin-unicorn/rules/prefer-spread.js
Error:   59:8  error  Prefer readable Boolean variable names  unicorn/better-boolean-variable-names

/home/runner/work/eslint-plugin-unicorn/eslint-plugin-unicorn/rules/prefer-ternary.js
Error:    40:8   error  Prefer readable Boolean variable names  unicorn/better-boolean-variable-names
Error:   137:10  error  Prefer readable Boolean variable names  unicorn/better-boolean-variable-names
Error:   217:9   error  Prefer readable Boolean variable names  unicorn/better-boolean-variable-names

/home/runner/work/eslint-plugin-unicorn/eslint-plugin-unicorn/test/utils/snapshot-rule-tester.mjs
Error:   144:9  error  Prefer readable Boolean variable names  unicorn/better-boolean-variable-names

✖ 15 problems (15 errors, 0 warnings)

Error: Process completed with exit code 1.

@axetroy axetroy marked this pull request as ready for review September 8, 2024 10:16
@axetroy axetroy force-pushed the better-boolean-var-name branch 2 times, most recently from d5882a4 to c0b0b0d Compare September 8, 2024 11:02
@fregante
Copy link
Collaborator

fregante commented Sep 8, 2024

Note that I’m not a maintainer, I just help triage the issues and have lots of opinions. 😅 I’ll leave that to @fisker

@axetroy axetroy force-pushed the better-boolean-var-name branch 2 times, most recently from bed94be to 63f8643 Compare September 8, 2024 11:27
@axetroy
Copy link
Contributor Author

axetroy commented Sep 8, 2024

@fregante OK, can you give me some advice, should I check the function name?

eg.

function completed(): boolean {}

const isCompleted = completed();

After fix:

function isCompleted1(): boolean {}

const isCompleted = isCompleted1();

Applying this rule to functions seems to cause naming problems

@fregante
Copy link
Collaborator

fregante commented Sep 8, 2024

Heh, good point.

What should be called isCompleted? The function or the constant? Both make sense.

In your (corner) case it’s only an issue because you’re “caching” the value. Generally Sindre has preferred appending an underscore when the exact name is unavailable, like function_ and arguments_. So the constant would be isCompleted_ or e.g. isCompletedLocal. I don’t have an exact solution to this.

By the way I think it would hasCompleted or isComplete

<!-- end auto-generated rule header -->
<!-- Do not manually modify this header. Run: `npm run fix:eslint-docs` -->

When it is clear that an expression is a Boolean value, the variable name should start with `is`/`was`/`has`/`can`/`should` to improve readability.
Copy link
Collaborator

@fregante fregante Sep 8, 2024

Choose a reason for hiding this comment

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

Also: will am are have were got does


```js
const gotModifyRights = isGotPreviewRights() && isGotDownloadRights(); // ❌
const isGotModifyRights = isGotPreviewRights() && isGotDownloadRights(); // ✅
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why? I think got is right.

const gotMilk = true

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here is the response from AI:

The word "got" is generally not suitable as a prefix for Boolean variables because it does not conform to the conventions for naming Boolean variables. Boolean variable names typically use verbs or adverbs to clearly express their Boolean value, such as "is," "has," "can," etc.

Using "got" as a prefix may result in variable names that are not sufficiently clear, thereby reducing the readability and maintainability of the code. Therefore, it is recommended to avoid using "got" as a prefix for Boolean variables.

Better choices include the following prefixes:

  • is: isUserLoggedIn
  • has: hasAdminPrivileges
  • can: canEditProfile
  • should: shouldDisplayNotification
  • will: willSendEmail
  • needs: needsPasswordReset

These prefixes can more clearly express the meaning of Boolean variables.

'unicorn/prefer-readable-boolean-variable-names': [
'error',
{
prefixes: ['will', 'allows']
Copy link
Collaborator

@fregante fregante Sep 8, 2024

Choose a reason for hiding this comment

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

This gives me doubts about this rule. Having to configure your own verbs is a smell to me. allows should be valid by default… maybe? Or should it be doesAllowDeletion? What situations are we missing?

I don’t really want1 a rule that bugs you for names that are fine and that might be difficult to get right.

Footnotes

  1. meaning: if we add this rule to the recommended and then we get complaints, adding it would be a net loss.

Copy link
Contributor Author

@axetroy axetroy Sep 9, 2024

Choose a reason for hiding this comment

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

How about we add more prefixes to covering most scenarios? eg.

["is","was","has","had","will","would","can","could","should","shall","does","needs","must","includes","enables","supports"]

These prefixes are treated as valid names, but only a few suggested fixes are provided.

Comment on lines 24 to 44
```js
const completed = Boolean('true'); // ❌
const isCompleted = Boolean('true'); // ✅
```

```js
const completed = new Boolean('true'); // ❌
const isCompleted = new Boolean('true'); // ✅
```
Copy link
Owner

Choose a reason for hiding this comment

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

I would drop these. No one would code like this.

Comment on lines 13 to 21
/**
Capitalize the first letter of a string

@param {string} str
@returns {string}
*/
function capitalize(string_) {
return string_.charAt(0).toUpperCase() + string_.slice(1);
}
Copy link
Owner

Choose a reason for hiding this comment

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

I think this should be un utils.

Also:

Suggested change
/**
Capitalize the first letter of a string
@param {string} str
@returns {string}
*/
function capitalize(string_) {
return string_.charAt(0).toUpperCase() + string_.slice(1);
}
/**
Capitalize the first letter of a string.
@param {string} string
@returns {string}
*/
function capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}

@param {import('estree').Expression} node
@param {number} [deep] - The current recursion depth. Users do not need to pass this parameter.
*/
function isBooleanExpression(context, node, deep = 0) {
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
function isBooleanExpression(context, node, deep = 0) {
function isBooleanExpression(context, node, depth = 0) {

/**
Replace the string between start and end with replacement.

@param {string} str
Copy link
Owner

Choose a reason for hiding this comment

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

Does not match actual parameter.

function isExportedVariable(identifier) {
return (
identifier
&& identifier.parent?.type === 'VariableDeclarator'
Copy link
Owner

Choose a reason for hiding this comment

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

Use tab-indentation.

* ```js
* export const foo = 1
* ```
*
Copy link
Owner

Choose a reason for hiding this comment

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

Don't prefix comment lines with *

@@ -0,0 +1,162 @@
# Prefer readable Boolean variable names
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
# Prefer readable Boolean variable names
# Prefer readable boolean variable names

<!-- end auto-generated rule header -->
<!-- Do not manually modify this header. Run: `npm run fix:eslint-docs` -->

When it is clear that an expression is a Boolean value, the variable name should start with `is`/`was`/`has`/`can`/`should` to improve readability.
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
When it is clear that an expression is a Boolean value, the variable name should start with `is`/`was`/`has`/`can`/`should` to improve readability.
Boolean variable names should start with `is`/`was`/`has`/`can`/`should` for clarity and readability.


```js
{
'unicorn/prefer-readable-boolean-variable-names': [
Copy link
Owner

Choose a reason for hiding this comment

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

Tab-indentation.

@param {number} [depth] - The current recursion depth. Users do not need to pass this parameter.
@returns {boolean}
*/
function isBooleanExpression(context, node, depth = 0) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I know there is a method isBooleanNode, but it is not comprehensive enough, and it cannot track the type of Identifier.

function isBooleanNode(node) {
if (
isLogicNot(node)
|| isLogicNotArgument(node)
|| isBooleanCall(node)
|| isBooleanCallArgument(node)

So, I need more advice, should I use the same method.

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.

Rule proposal: better-boolean-var-name
3 participants