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

Extend fixers for prefer-string-slice #424

Merged
merged 13 commits into from Nov 29, 2019
Merged

Extend fixers for prefer-string-slice #424

merged 13 commits into from Nov 29, 2019

Conversation

voxpelli
Copy link
Contributor

Currently barely any substr() or substring() calls can be automatically fixed.

This PR makes pretty much all substring() calls fixable and makes many substr() fixable.

@voxpelli
Copy link
Contributor Author

I've realized that I need to do some more changes to this

@voxpelli
Copy link
Contributor Author

Done, now it should be a more correct auto fixer

const firstArgument = argumentNodes[0] ? sourceCode.getText(argumentNodes[0]) : undefined;
const secondArgument = argumentNodes[1] ? sourceCode.getText(argumentNodes[1]) : undefined;

let slice;
Copy link
Collaborator

Choose a reason for hiding this comment

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

this can be an array and concat with .slice( and )

Copy link
Collaborator

Choose a reason for hiding this comment

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

rename to sliceArguments

Copy link
Collaborator

Choose a reason for hiding this comment

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

could you rename this variable? more specific

@fisker
Copy link
Collaborator

fisker commented Oct 29, 2019

some NaN tests?

@voxpelli
Copy link
Contributor Author

Fixed most of your feedback @fisker, thanks!

some NaN tests?

Could you give me an example of what kind of NaN tests you're thinking of?

Copy link
Collaborator

@futpib futpib left a comment

Choose a reason for hiding this comment

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

I initially did not aim to include advanced fixing due to subtle differences in index handling between the methods. Sorry I can't review this properly and check this myself, but I hope if this PR is merged, it handles edge cases properly (or good arguments are provided for why it should not and it is documented that it does not):

substring:

If indexStart is greater than indexEnd, then the effect of substring() is as if the two arguments were swapped

substr:

If start is a positive number, the index starts counting at the start of the string. Its value is capped at str.length.
If start is a negative number, the index starts counting from the end of the string. Its value is capped at -str.length.
If length is undefined, substr() extracts characters to the end of the string.

.. and maybe some others.

@voxpelli
Copy link
Contributor Author

If indexStart is greater than indexEnd, then the effect of substring() is as if the two arguments were swapped

This handled wherever it can be handled and in cases where it can't be handled, no fix is provided.

If start is a positive number, the index starts counting at the start of the string. Its value is capped at str.length.
If start is a negative number, the index starts counting from the end of the string. Its value is capped at -str.length.
If length is undefined, substr() extracts characters to the end of the string.

This is very similar to .slice() except that .slice() has an end index instead of a length. Adding the startvalue, whenever possible, to the length solves that and is something I've done. When that isn't possible no fix is provided.

@fisker
Copy link
Collaborator

fisker commented Oct 29, 2019

Could you give me an example of what kind of NaN tests you're thinking of?

sorry, I thought too much, not really needed

fisker added a commit to fisker/eslint-plugin-unicorn that referenced this pull request Oct 29, 2019
@fisker
Copy link
Collaborator

fisker commented Oct 29, 2019

@voxpelli I just send a PR to your fork, I did't change any your logic, should be more readable https://github.com/voxpelli/eslint-plugin-unicorn/pull/1

@voxpelli
Copy link
Contributor Author

@fisker I actually prefer my version, but I wouldn't want it to block a merger of this, so whoever merges it can pick :)

@voxpelli
Copy link
Contributor Author

voxpelli commented Nov 2, 2019

@fisker How do we best proceed?

}

if (node.type === 'UnaryExpression' && node.operator === '-') {
return 0 - getNumericValue(node.argument);
Copy link
Collaborator

Choose a reason for hiding this comment

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

this 0 should remove

Copy link
Collaborator

Choose a reason for hiding this comment

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

also, do we really want recury this? just number and negative number should enough

Copy link
Owner

Choose a reason for hiding this comment

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

this 0 should remove

It's usually useful to explain why if it's not immediately obvious.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why should the 0 be removed?

Copy link
Collaborator

@fisker fisker Nov 15, 2019

Choose a reason for hiding this comment

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

sorry, I was not explaining clear, this is negative number, right?

0 - 1 is the same as -1

am I missing something?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a positive number Literal wrapped in a UnaryExpression with a - operator, so the 0 - part is to convert the positive number into its correct negative value. I do think I have added tests for that?

Copy link
Collaborator

@fisker fisker Nov 15, 2019

Choose a reason for hiding this comment

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

I know that -1 is parsed as UnaryExpressionand operator:- and argument:1

so return 0 - node.argument equals to return - node.argument.

I am getting confused, am I wrong?

rules/prefer-string-slice.js Show resolved Hide resolved
const firstArgument = argumentNodes[0] ? sourceCode.getText(argumentNodes[0]) : undefined;
const secondArgument = argumentNodes[1] ? sourceCode.getText(argumentNodes[1]) : undefined;

let slice;
Copy link
Collaborator

Choose a reason for hiding this comment

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

rename to sliceArguments

} else if (argumentNodes.length === 1) {
slice = [firstArgument];
} else if (argumentNodes.length === 2) {
if (firstArgument === '0') {
Copy link
Collaborator

@fisker fisker Nov 2, 2019

Choose a reason for hiding this comment

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

should be literal zero, we don't want handle "0", utils should have a function do this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The text representation of an argument node can only ever be === '0' if it's a literal zero, no?

Copy link
Collaborator

@fisker fisker Nov 15, 2019

Choose a reason for hiding this comment

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

sorry, my comment is based on const firstArgument = argumentNodes[0](I changed it in my refactoring, but forgot it's not changed here), why we need sourceCode.getText? Isn't argumentNodes[0] easier to use?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As almost every branch used the value of firstArgument I decided to calculate them in shared space to make the code more easy to read and more DRY.

As firstArgument then was already calculated I considered firstArgument === '0' to be preferable over isLiteralNumber(argumentNodes[0]) && argumentNodes[0].value === 0 as it's shorter and simpler.

Copy link
Collaborator

@fisker fisker Nov 15, 2019

Choose a reason for hiding this comment

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

thanks for explaining this, this make sense now, but I think it makes the logic little hard to understand. you want use those functions?

const isLiteralValue = require('./utils/is-literal-value');

const isLiteralZero = node => isLiteralValue(node, 0);

rules/prefer-string-slice.js Outdated Show resolved Hide resolved
rules/prefer-string-slice.js Show resolved Hide resolved
rules/prefer-string-slice.js Outdated Show resolved Hide resolved
@sindresorhus sindresorhus changed the title Extend fixers for prefer-string-slice Extend fixers for prefer-string-slice Nov 12, 2019
}

if (node.type === 'UnaryExpression' && node.operator === '-') {
return 0 - getNumericValue(node.argument);
Copy link
Owner

Choose a reason for hiding this comment

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

this 0 should remove

It's usually useful to explain why if it's not immediately obvious.

Copy link
Contributor Author

@voxpelli voxpelli left a comment

Choose a reason for hiding this comment

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

Adapted to some of the feedback + asked for clarification where I'm not sure regarding the feedback.

} else if (argumentNodes.length === 1) {
slice = [firstArgument];
} else if (argumentNodes.length === 2) {
if (firstArgument === '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.

The text representation of an argument node can only ever be === '0' if it's a literal zero, no?

rules/prefer-string-slice.js Show resolved Hide resolved
}

if (node.type === 'UnaryExpression' && node.operator === '-') {
return 0 - getNumericValue(node.argument);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why should the 0 be removed?

rules/prefer-string-slice.js Show resolved Hide resolved
Copy link
Collaborator

@fisker fisker left a comment

Choose a reason for hiding this comment

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

@sindresorhus sindresorhus merged commit 567c970 into sindresorhus:master Nov 29, 2019
@sindresorhus
Copy link
Owner

Thanks for working on this, @voxpelli 👌

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.

None yet

4 participants