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

Explicit parentheses in operations where precedence might not be clear #175

Merged
merged 3 commits into from
Aug 5, 2019

Conversation

Janther
Copy link
Contributor

@Janther Janther commented Jul 8, 2019

Ok,
So while working on Binary operations and properly printing them across the different scenarios I stumbled on this case a && b || c && d prettier JS says "ok this one is difficult for a normal developer to easily read" (and I agree) so it formats it like this (a && b) || (c && d).

So why doesn't prettier-solidity does this?
Because we have to change the AST.

I wouldn't want to add to the execution stack or have the contract use more gas just because one way of writing the code looks nicer.

So I created a personal repo where I could test these changes and I discovered that as long as the order of precedence is respected, the bytecode is the same, regardless of the parentheses.

With this green light, I proceeded to imitate all of the parentheses rules that prettier is doing for js.

The change is very localised and is easily removed if it causes problems.
I understand this one might need a bit more scrutiny.

@codecov
Copy link

codecov bot commented Jul 8, 2019

Codecov Report

Merging #175 into master will increase coverage by 0.08%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #175      +/-   ##
==========================================
+ Coverage   98.55%   98.64%   +0.08%     
==========================================
  Files          74       74              
  Lines         553      589      +36     
  Branches       84       87       +3     
==========================================
+ Hits          545      581      +36     
  Misses          8        8
Impacted Files Coverage Δ
src/parser.js 100% <100%> (ø) ⬆️
src/nodes/TupleExpression.js 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 87d2b8d...79730f0. Read the comment docs.

Copy link
Member

@fvictorio fvictorio left a comment

Choose a reason for hiding this comment

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

LGTM, and I like this approach a lot!

e %
f **
g;
(((c * d) / e) % f ** g);
Copy link
Member

Choose a reason for hiding this comment

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

I think (c * d / e) % f ** g might be a little better, but I don't know how hard that would be to do.

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 has parentheses because it's following veryVeryVeryVeryVeryLongVariableCalledB -
if you try prettier veryVeryVeryVeryVeryLongVariableCalledA + veryVeryVeryVeryVeryLongVariableCalledB - c * d / e % f ** g in javascript it will create the same parentheses.
+ and - are well known to have little precedence but modulo % is a tricky one that's why I think prettier js wraps the % between parentheses, you can check this rule in lines 43 and 44 of src/parser.js in this PR.
Anyway, we don't have to follow by the letter each rule of prettier js, I just thought it was a good place to start, we can add or remove rules according to what makes more sense. My main concern is that the parentheses suggestions have to follow the order of precedence of operators, otherwise, the bytecode will not be the same when compiled.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, I mean specifically the parentheses around c*d. I think c * d / e is better than (c * d) / e, but that's just me. Besides, if that's how prettierjs does it, I'm more than fine with following its lead.

@@ -2,6 +2,16 @@ const extract = require('extract-comments');
// https://prettier.io/docs/en/plugins.html#parsers
const parser = require('solidity-parser-antlr');

const tryHug = (node, operators) => {
Copy link
Member

Choose a reason for hiding this comment

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

Maybe we should document this function.

Copy link
Member

Choose a reason for hiding this comment

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

yeah, that's not a bad idea actually

veryVeryVeryVeryVeryLongVariableCalledA &&
veryVeryVeryVeryVeryLongVariableCalledB ||
(veryVeryVeryVeryVeryLongVariableCalledA &&
veryVeryVeryVeryVeryLongVariableCalledB) ||
Copy link
Member

Choose a reason for hiding this comment

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

interesting indentation, is that on purpose?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah, well the indentation rule here falls into the TupleExpression indentation rules instead of BinaryOperation indentation rules.
Same happens in javascript.

// Before Prettier
if (veryVeryVeryVeryVeryLongVariableCalledA && veryVeryVeryVeryVeryLongVariableCalledB || c);
// After Prettier
if (
  (veryVeryVeryVeryVeryLongVariableCalledA &&
    veryVeryVeryVeryVeryLongVariableCalledB) ||
  c
);

@@ -2,6 +2,16 @@ const extract = require('extract-comments');
// https://prettier.io/docs/en/plugins.html#parsers
const parser = require('solidity-parser-antlr');

const tryHug = (node, operators) => {
Copy link
Member

Choose a reason for hiding this comment

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

yeah, that's not a bad idea actually

@mattiaerre mattiaerre merged commit 5710581 into master Aug 5, 2019
@mattiaerre mattiaerre deleted the feature/explicit_parentheses_in_operations branch August 5, 2019 16:25
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

3 participants