* Hug template literals inside of JSXExpressionContainer
We already hug a bunch of things inside of `{}`. It seems that it's a good idea to do it for template literals as well. I don't think I've seen anyone actually indent them.
Fixes#1090
* Inline jsx elements with single template literal expression
If there is a single expression and a single template literal, then a lot of people in the jsx-style world inline it. I've also myself used this for markdown and printed it that way. So we probably should print it that way.
Note that I'm checking for children.length === 1, this means that if there's any whitespace, this is not going to be true and will not enter this case. So it WON'T reformat
```js
<style>
{`
color: red;
`}
</style>
```
into
```js
<style>{`
color: red;
`}</style>
```
which is great. You have to opt-in to the second style in order to get it.
Fixes#1090
I'm unclear whether anyone was ever confused by this but the eslint page is kind of compelling
```js
// The intent is not clear
var x = a => 1 ? 2 : 3;
// Did the author mean this
var x = function (a) { return 1 ? 2 : 3 };
// Or this
var x = a <= 1 ? 2 : 3;
```
Adding a parenthesis makes it valid with `{"allowParens": true}` rule. Note that if this option is not enabled, the code would not pass lint in the first place.
I've tried a lot of places where to fix this and this is the only one that gives correct results. This is likely not exhaustive but works for that use case. It's been reported twice in issues and I've seen it happen a few other times so we probably want to get it fixed.
Fixes#922Fixes#797
This one sucks.
The range of the `test` of `if (a /* comment */) {}` is only `a` and doesn't include the comment nor parenthesis. This means that we have no way to know if the comment is placed before or after the `)` unless you look at the actual source and strip all the whitespace/comments characters to see if it's a `)`...
This happened on the babel source code twice and many times in the fb codebase. I think we need to fix it unfortunately :(
Fixes#867
We need to call the `skipToLineEnd` which skips `,` after an inline comment. So we have to put it inside of the while loop as you can have many comments, a comma and then many more comments.
Fixes#964
.#1136 accidentally removed all the empty lines between statements inside of switch cases. I just brough back the logic and made sure to only use it for everything but the last line.
* Add exceptions for html escape usage in href and src attributes.
* Add new test cases.
* Remove useless spaces.
* Do not escape if the parser does not do so.
* Implement a different heuristic for keeping along with the parser.
* Update tests.
* Forgot passing options as param.
* Experimental alternative implementation.
* Remove other function.
* Push test after merge.
* Update getJsXRawValue in order to return the unprocessed raw value.
Latest Babylon version includes a fix that allow us to directly
inject the unprocessed raw value available in the `extra.rawValue`
property of the node. A last transformation is applied by replacing
double quotes to `"` entities.
* Drop unused htmlEscapeInsideDoubleQuote function.
* Move getJSXRawValue function logic to the its only call, drop it.
A simple check is performed to determine if the parser is babylon or
flow via `n.value.extra`. Thus, the corresponding raw value is
extracted. If we are converting a string from single quotes to
double quotes, we need to make sure that double quotes are converted
to ".
* Remove ambiguous comment.
* Add Babylon parser.
* Update test cases accordingly, revert regression introduced previously.
* Extract custom tests from tests/flow/
Approach:
1. Remove all .js files in tests/flow except .snap.js files.
2. Copy over all .js files from tests/ in the flow repo.
3. Go through the diff looking for deletions.
- It was easy to see which deletions were due to changes in the tests
due to updates in the flow repo.
- For the rest of the deletions, I used `git blame` to verify that
they had been added by us since the flow tests were copied over.
This makes tests/flow/ simply a copy of the tests from the flow repo,
making it easier to sync with the upstream flow tests in the future.
* Add a script for syncing the flow tests
* Sync the flow tests
We break on `class` before `extends` but didn't for `interface`. Now we do in the same way. Also TIL that `interface` was an actual keyword in JavaScript :P
* Verify parsers against same snapshot
- Reworked run_spec, now accepts 3th optional array argument for
additional parsers to verify against
- Merged duplicate run_spec configs
- Removed duplicate snapshot data
* Formatted run_spec.js with prettier
* Fixed node4 incompatibility
If you write your code in a functional way where you have an arrow function for each argument, it looks better for them to be inline. I can't imagine any case where it would be used in a different way if we limit to a single argument.
Fixes#1065
We started using the same logic for union and intersection but then added a special case for `a & {}`. It turns out that they should be handled completely differently in practice.
The heuristic i'm using is if you go from object to non-object or vis-versa, then inline, otherwise go to the next line and indent (like &&).
Fixes#864Fixes#1017
This is very common for stateful react functional components. It also matches last object expansion. I think that we should only do that for a single argument in function definitions though, unlike the last for function calls.
Fixes#1019
* Revert "Remove mutation in `printBinaryishExpressions` (#1067)"
This reverts commit e7312ad7b2.
* Revert "Make it clear what parser was used in each snapshot (#1068)"
This reverts commit 4f7ae4815b.
The root cause is that we're calling `printComments` with an empty string, meaning that the leading/trailing comments are not correctly inserted at the right location.
So, the way to fix it is to call `p => concat(parts)` but because we're mutating the array in place, it doesn't work. We need to mutate it and create a copy. But, the root call is actually checking the shape of the parts array which our code is now breaking...
```js
// Don't include the initial expression in the indentation
// level. The first item is guaranteed to be the first
// left-most expression.
parts.length > 0 ? parts[0] : "",
```
The consequence is that binary expressions are no longer indented if the first expression has a comment (but now it places the comment properly!), which seems like a good trade-off.
I'm not sure if we should merge this one or instead refactor this code such that it doesn't rely on mutation and looking at the shape of the printed tree. `printMemberChain` is a good thing to reference for inspiration.
Fixes#946
Right now it's only doing one test for begin/end, but in the issue #1037, we have two nodes that have the same start but different end. The current implementation incorrectly sorts them and the identifier ends up being before the container and therefore the comment search doesn't recurse into it.
Fixes#1037
ast-types was missing a type, I sent a PR on ast-type ( https://github.com/benjamn/ast-types/pull/211 ) which was merged and released (thanks @benjamn for being super quick!). So I'm upgrading ast-types and add the test in this PR.
Fixes#1007
While looking at an instability on the React codebase ( ba1299acc2 (diff-2550aa3d377452ae29361f5e53c51c10) ), I realized that we don't let them break which makes the code look weird.
So I added the ability for them to break :)
We already had a special case for it for a group of 2 elements but now that we are also going in this codepath for 3 if we merge, then we need to do the same here.
Fixes#930
* Add some typescript tests
* fix: Remove extraneous colon in type parameter constraint
* style: Add missing newline at EOF in TS tests
* feat: Pretty print typescript object type annotations
* feat: Pretty print TSFunctionType
* fix: Type annotations was missing on class properties
* Add a new batch of tests
* Bump typescript-eslint-parser
* Add a new batch of tests and fix a syntax error in previous
* Bump typescript-eslint-parser
* Group first arg for inline functions
* Group first arg. Unless there are comments.
* Group first arg. Allow second arg to be empty object/array.
This implementation has a side effect of disallowing empty objects/arrays in the should group last arg heuristic.
* Add handleImportDeclarationComments function.
* Fix indent.
* Update test cases accordingly.
* Implement better heuristic for adding comments.
* Make the test case more exhaustive.
* Refactor condition in printStatementSequence, add new helper function.
* Add new test cases.
* Move logic in SwitchCase case.
* Revert unrelated changes, remove unecessary variables.
* Use util.getLast helper function.
* Move variables out of the loop.
* Simplify code.
* Fix mapping with mutated path.
* Implement checking for not printing the parens in this case.
* Add test case.
* Remove parent type checking.
* Fix test accordingly.
* Refactor to a better heuristic.
* Add new test cases.
* Fix implementation.
* Fix unnecessary function call.
* Add new test cases 🚀.
* Use isObjectTypePropertyAFunction and create isTypeAnnotationAFunction.
* Add missing space.
* Add new test cases.
Printing the first line of a binary expression next to the `=` leads to weird cases where the first expression is parenthesised and doens't read well with chained conditionals as they don't align well. This makes it behave the same was as `if` tests.
Fixes#863
This was intended for object expressions. I tried to remove it for ObjectTypeAnnotation but it changes a ton of stuff as it's used all over the place in many different contexts. We should clean it up but in a later PR :)
Fixes part of #975
In practice, trying to allow calls to be inlined is causing a lot of code to look very weird and unstable as seen by the four issues this is fixing. It also requires us to add a conditional group and do hackery around it.
Fixes#959Fixes#760Fixes#615Fixes#625
* WIP immediate feedback
* typescript parser is drop-in replacement for flow parser
* Add new TypeScript Parser snapshots where drop-in replacement possible
* Snapshot updates after rebasing
* Remove unnecessary stripping of properties on TypeScript parser AST
* Remove annotated issues
* Move TS dependencies to dev for now
* Implement new logic for wrapping binary op in arrowFunctionExpression.
* Add new test cases.
* Reuse new helper function in order to fix#917.
* Add new test case.
* Extend heuristic to dive deeper into mixed types.
* Add new test.
* Enhance logic to cover more cases.
* Add new test cases.
* Disable Flow as it gets BindExpression as an unexpected token.
* Simplify getCombinedDeepest function.
* Add missing case.
* Extract all conditions in switch cases to one top level condition.
* Refactor implementation to make it cleaner and also handle ExpressionStatement.
* Update related test cases.
* Add new test case.
* Make condition less expensive.
* Clean up unecessary conditions, simplify condition involving startsWithOpenCurlyBrace.
* Update and add new test cases for better coverage.
* Remove unecessary condition, refactor canBeFirstInStatement to drop some useless parens.
* Update test cases accordingly 🚀.
* Add new handleOnlyComments function.
* Update tests.
* Update test as the printer forces a trailing newline if there were any contents.
* Implement a different heuristic.
* Update tests.
* Add directives checking in handleOnlyComments function.
* Add directives checking in handleOnlyComments function (amend to retrigger CI).
* Remove duplicate.
* Add new helper function to convert comments as blocks in ExportNamedDeclaration.
* Add new test.
* Switch to a leading position.
* Update test accordingly.
The comments infra has been architected with trailing operators and fails for leading `|`. Instead of having leading comments, we can put trailing comments on the previous one and use the same technique as assignment to deal with the indentation.
Fixes#849
This happens very frequently that naming a test makes the entire line go > 80 columns and requires to indent everything which takes a lot more space. We've had this being reported multiple times and it also affects a lot of tests inside of fb.
Fixes#159
(Note, this is built on-top of #841 but github doesn't handle stacked pull requests well...)
This is a leftover from the recast prototype, it hasn't been touched since then. I have never seen anyone not put the label on the same line.
Fixes#859
This is a neat trick from the React codebase. It helps highlight the fact that this is an assignment and not a comparison which is subtle to realize.
Fixes#861
In #605 I restricted it to binary operations as I didn't know how it would affect boolean operations but it turns out the same technique solves problems that people are reporting. So doesn't make sense to restrict it.
Fixes#824
It turns out that my fix was not correct. We should not add parenthesis for FunctionDeclaration instead of checking if the function expression is named.
Fixes#819
In #596, I fixed a bunch of jsx expression comment edge cases and happened to add a softline there. But it turns out that it's not needed and is actually harmful :)
Fixes#712
Since this is extremely rare, I just took the easy way out and if you are adding a comment inside the "as" node, I just move it outside. We could be more fancy but that works.
Fixes#620
This has come up a couple times on the issue tracker on the react-native-web discussion about Twitter internals. It seems like there's a concensus that people don't break long require calls and they'd rather have it go > 80 columns.
Fixes#303Fixes#752
I'm not really sure what a general rule is for those, but starting with LogicalExpressions should be good. Outside of identifiers, function calls and logical expressions, there aren't a lot of things you'd put there in real code anyway.
Fixes#822
Instead of trying to figure out a complicated way to preserve their correct position, it's easier to just migrate those comments before the class.
Fixes#693Fixes#694
Printing a merged group indented was actually not the right fix. The right fix was to print them in a single line. It used to have this behavior when I was mutating the first group but now that I don't anymore I need to reproduce this condition.
Fixes#823
We need to add parenthesis around function expressions if they are named otherwise the name leak, but if the function is not named then it's just superfluous.
The conditional change is due to a bad use of switch case where it would fall through the next one. We don't want parenthesis there.
* Add new handleFunctionDeclarationComments function.
* Add dangling comments printing for function params.
* Add new test case.
* Update tests.
* Refactor handleFunctionDeclarationComments to only addDanglingComment when no params.
* Remove unecessary helper function, only attach dangling comments when no params.
* Reset flow tests, no more regression.
It seems like precedence for this combination of operators is very unclear to people (myself included) and consistently adding parenthesis there would be good.
Fixes#773
The idea is that if you reach the end of the `}` inside of a template literal, we have to flush the trailing comma, otherwise it would generate invalid code. We also need the same special case for JSX.
I don't like adding yet another type of document but it seems like the most elegant way to solve the problem.
Fixes#623
* Add handleTemplateLiteralComment helper function.
* Fix handleTemplateLiteralComment function.
* Extend handleTemplateLiteralComment to deal with trailing comments 🚀.
* Add test.
* Make handle comments function naming more consistent, fix merge conflicts.
* Update tests.
* Add better comment injection in Template Literal.
* Pass options to attach function.
* Update tests to match new implementation.
* Fix let -> var in findExpressionIndexForComment for NodeJS v4.
* Reorder after merge conflicts.
* Drop old tests for dangling arrays.
* Replace redundant conditional by a boolean 🚀.
* Refactor implementation.
I originally wanted to expand it but I think that it may not be a good decision because it's very common for them to be empty and you want it to take as little space as possible.
I tried to remove all those conditions but I think that there are valid places where we always want to expand like empty if/for/while loops.
Fixes#778
In addition to Observable, $ or _, we should also add `this` to the list of things that are likely factory and not objects you want to apply things on directly.
I added a way to make the function call break on its own line when it doesn't fit in one line and indent. But I think that only having the indentation is enough, having the call on its own line feels weird.
Fixes#777
Previously we would blindly put leading comments of the next expression, but we didn't account for a real trailing comment. By checking if the leadingNode is on the same line, we can correctly put it there when needed
Fixes#685
* Add handleAssignmentPatternComments helper function.
* Add new tests 🎉.
* Remove unecessary arg in function.
* Reorder it.
* Experimental fix for key comments in the printComments function.
* Pull master and switch to @vjeux implementation.
* Fix bad rebase.
* Add additional checking for enclosingNode in handleObjectProperty function.
There is an off by one error which made the algorithm not work all the time. In many cases, it actually is the opposite, so whenever you save, it adds/removes that line. I noticed it during the --debug-check run on our codebase but didn't investigate.
Fixes#723
This has come up many times in the past and while going through the fb codebase, there are a few instances where we group array elements logically using empty lines and it's a shame that they are gone.
I've started the discussion around it but I think that it was a mistake. It feels weird to add parenthesis on object values sometimes but not others. I think that it's best to let prettier do its work on staying under 80 columns based on the rules we added.
We inline function definitions but we shouldn't inline new expressions,
835befebf5 introduced both call expressions and new expressions. Call expressions have been removed but looks like new haven't.
This was surprisingly easy to write!
Technically, it doesn't ignore the next line but the next expression or block but I'm guessing that people are already used to `// eslint-disable-next-line` so it's going to be an easier learning curve.
Fixes#120
* Extend ReturnStatement case to better handle comments in argument 🎉.
* Update test.
* Add missing space between return and left parenthese.
* Fix current tests and add new tests.
* Do not break one-liner returns.
* Revert specific test.
* Patch from #683.
In #563 it looked odd that there was no space before `//`, it turns out that we don't automatically go to the new line for dangling comments. I think that we just should no matter what, so this is what this diff does.
Fixes#563
* Inject source text into printAstToDoc function.
* Add getNodeSource helper function.
* Fix Flow drawback with missing DeclareTypeAlias by checking the node source.
* Add new test.
* Fix getNodeSource helper function.
* Revert text injection.
* Refactor DeclareTypeAlias printing.
* Drop expensive getNodeSource helper function 🗑️.
* Refactor declareTypeAlias case in printer.
* Update tests.
* Implement the same logic for DeclareInterface.
* Update the tests.
* Fix missing semicolons and typo.
* Put Flow specific node detection code into own helper function 🚀.
* Refactor isFlowNodeStartingWithDeclare helper function.
* Simplify isFlowNodeStartingWithDeclare helper function.
* Rename test spec.
* Update tests.
When there is a comment right before the first `.`, we want to force break such that the comment is printed on its own line.
Note: this needs to be based on-top of #667 as it always indent the first `.`
Fixes#613
* Add prettier indentation for UnionTypeAnnotation in ObjectTypeAnnotation.
* Update tests accordingly.
* Fix indentation.
* Update a bunch of tests 🚀.
* Switch to a more consistent indentation.
* Fix tests to match new indentation 🚀.
The reason why trailing comments on a line work with commas is because of a special `lineSuffix` document that delays printing the content until a \n is printed. But `lineSuffix` only worked for pure string. By making it work with arbitrary documents we can fix trailing commas with trailing comments.
Fixes#538
Before, we would always concatenate the first `.call()` if the identifier started with a capital letter, but we do want to break if the content of the call doesn't fit in one line.
Fixes#639
Because the group was too high up, the comment would be taken into consideration to determine the size and it would break and add parenthesis. Adding a group where we actually want the ifBreak seems to be passing all the existing tests and fixes this edge case.
Fixes#655
We already preserve blank lines inside of classes but not objects. It's still very common to have objects that represent classes (React.createClass) and having the same behavior there seems like a good idea. It does make the snapshot tests look better!
Fixes#554
I've been trying to come up with a heuristic to stop putting small elements on a new line and I just realized that all the cases I found out only involved a single binary expression. If there's only a single operation, we can just put them on the same line (if it fits) and it's not going to look weird.
We do the same thing for MemberExpression where we only break if there are more than one ".".
Fixes#583Fixes#503
* Do not indent binary expressions inside of if
The reason why the indent has been added is to support the
```js
var x = a ||
b;
```
use case where we need a level of indentation. But inside of a `if` it just looks strange
```js
if (
a ||
b
) {
```
because the parent already indented the first line.
Fixes#567
* Tweak logic to make more explicit
We want to preserve an empty line before the last comment. It is added as a trailing comment of the node and adding the same logic to detect if the next line is empty is working.
Fixes#566
* Remove last trailing line for directives-only files
There are two hardlines that are added that do not need to.
- The first one is when there's an empty line afterwards, we want to remove it. The solution I opted for to fix this one is to trimRight the originalText so that globally it's never going to return yes for the isNextLineEmpty.
- The second one is at the end of Program, but we already printed it inside of the directive itself, so we can just add a condition to make sure it's only printed when there's a body or a comment, but not a directive.
Fixes#527
* Add comment
If you removed it before #561, it would trigger an exception in the globalPreceding branch. But now that we don't have this hack anymore, it works fine.
Fixes#543
Babylon has a two top level nodes: File and Program whereas flow just has Program. This causes two things two happen that prevents comments from being displayed:
1) Because there's a single node, none of following/preceding/enclosing exist. We ran into a TOOD case that we now need to fill. We just need to attach comments to the only node we have: the ast.
2) Both the raw comments and the computed comments are set on the `.comments` field of the object, however, it is being reset after calling `attach`, so we lose the computed comments :( The fix is to use a local variable and delete the comments before calling `attach`.
Since we don't print EmptyStatement, we don't want to attach comments to them. I've tried actually printing the EmptyStatement but it messes up a ton of other things.
I made sure that MemberExpressions where printed correctly but didn't do the same for CallExpression. Now it is! It is a bit less straightforward because the comments for the root CallExpression have already been printed, so we need to extract the first call out.
(This is the last place where we drop comments on the test suite, we can start enabling throwing when comments are dropped!)
* Add parentheses if node is StringLiteral surrounded by ExpressionStatement :tools:.
* Add new test.
* Update tests to run against Babylon, plus no regression case.
* Split actual test and no regression test in two files.
* Disable Flow till facebook/flow#3234 is merged.
The original motivation for this change is trying to fix#560 where the comment was attached to the JSXText node instead of the JSXExpressionContainer because it used the globalPrecedingNode. In general, I don't think that it is very safe to attach a comment to a random node just because it happened to be before.
I tried to delete the globalPrecedingNode codepath and I think that it actually improves the results. I'll add inline comments in the pull request to explain the various changes.
Fixes#560
This reverts commit 7148184d65.
There are four types of literals where escapes were normalized:
1. Strings ('\xAb' and "\xAb")
2. Regexes (/\xAb/)
3. Untagged template literals (`\xAb`)
4. Tagged template literals (tag`\xAb`)
However, changing the case of the escapes alters the runtime behavior of
in two of the above cases.
```js
/\xAb/.source === '\\xAb' // true
String.raw`\xAb` === '\\xAb' // true
```
So for regexes and tagged template literals the escapes must not be
changed. Instead of enforcing lowercase escapes in only 50% of the
different cases, it was decided not to bother with escapes at all.
Closes#562.
While trying to figure out how to handle both MemberExpression comments and IfStatement comments, I ended up doing this one as well... Sorry @yamafaktory :(
The logic is a bit annoying but works.
Fixes#487
There are currently three issues related to suboptimal rendering of MemberExpression chains. The previous implementation was trying to flatten only a single group at the same time, but it didn't work well because we didn't have the full context to be able to make decisions.
In this implementation, I'm going through the entire chain at the same time and group it into logical units and make decisions based on this. It solves all the problems I can think of and if we need to tweak it in the future, it should be easy.
Fixes#268Fixes#212Fixes#21
If there's a break inside of a call, we want to force it in the group, otherwise it may get the indentation wrong. See the real-world use case in #513Fixes#513
It turns that our hasNextLine logic needs to be tuned to skip all the trailing comments. The code is not pretty but it does the job. It looks like it fixes a bunch of things in the test cases :)
I made sure that nested inline comments are NOT valid JavaScript
```js
/* /* a */ */
Uncaught SyntaxError: Unexpected token *
```
so it is okay to do a dumb search for */ when you are in a comment
* Print \x and \u escapes in strings and regexes lowercase
Theoretically, we would want to do this for escapes int identifiers as
well. However, neither flow nor babylon preserves escapes in
identifiers. For example, `\u0061.\u{0061}` cannot be distinguished from
`a.a`. Nobody uses such escapes in real code anyway. It could also be
considered a feature that such escapes are converted to real unicode
characters.
* Update snapshots
* Normalize escapes in template literals
* Update snapshots
* [Failing test] Comments in call expression
```js
foo(
// Hi
)
```
prints
```js
foo
// Hi();
```
* add one more failing case
* Don't group last args that has comments attached
* Update snapshot
It turns out that the range is not inclusive. It incorrectly included a \n after and would expand way more objects than we intended to.
I found it while running prettier on the codebase.
I'll make 0.14.1 for this.
* Print numbers in a uniform way
- Still preserve the radix (binary, octal, hexadecimal or decimal) used
in the original source code.
- Still preserve scientific notation.
- Add 0 to fractions. `.1` -> `0.1`
- Remove trailing dots from integers. `1.` -> `1`
- Always print the radix letters lowercase. `0b`, `0o`, `0x`
- Always print scientific notation lowercase. `1e1`
- Always print hexadecimal digits uppercase. `0x123ABCDEF`
- Remove unneeded plus in scientific notation. `1e+1` -> `1e1`
- Remove unneeded zeroes in scientific notation. `1e-001` -> `1e-1`
- Preserve leading zeroes in non-decimal radix. This can be useful when
working in binary, and having both `0b111000` and `0b000111` for
example.
* Always print numbers lowercase
* Remove trailing dot in scientific notation
* Update snapshots
Another attempt at solving the issue where objects are not expanded the way people expect. If there's any new line in the original source, it's going to expand it. This gives more control to the user in how the objects should be formatted.
Fixes#74
It turns out that in an unlikely turn of event, the inner group can be inline and not print the opening paren but the outer group breaks and outputs the closing paren which generates invalid JavaScript.
I tried removing the group altogether and no tests failed, so I'm assuming the group wasn't needed in the first place. If it was, we should add tests to cover this.
Fixes#501
* Proper support for dangling comments
In one code path, the dangling comment case is not properly handled. So I added the dangling comment, but it turns out that we only print manually in two node types: Program and BlockStatement. I made the generic printComment function print it everywhere but those two nodes. I tried to get rid of those special cases but unfortunately we need them there otherwise they are not printed at the right place.
Fixes#20
* Output dangling comments in specific places
The logic was already working, it was just special-cased to the first comment of the file! Presumably because the new line detection logic used to be broken ;)
I manually checked the first 10 snapshots and they are all legit, so I assume that all of them are.
Fixes#356
We don't call the generic print on the BinaryExpression itself, so we need to manually print those comments. It's going to be useful for my work on the MemberExpression :)
It's actually not needed to use conditionalGroup as we can use ifBreak for it. I was able to do it just for cleanup and found out that it also fixed two of the bugs we have with comments. That's great :p
Fixes#485Fixes#486
Conditionals are very common in JSX and it is unfortunate that they take up so much vertical space in the current prettier.
This pull request does a few tweaks:
- It hugs ConditionalExpression (ternary) and LogicalExpression (&&) inside of `{}` in a jsx child, not an attribute
- It doesn't output parenthesis if your parent is a LogicalExpression (&&)
Fixes#317
Mobx is the only popular JavaScript library that I know about which uses decorators. They put things on the same line so we should follow their conventions.
The logic implemented here is the following: if there is one decorator, it's on the same line. If there is more than one, they are each on their own line.
Fixes#325
This was introduced by #314 where `line` should have been `softline`. By the way, I was going to propose renaming `line` to `line_or_space` and `softline` to `line_or_nothing` which should make it more explicit what is going on.
Fixes#461
* new_tests
* move_all_clobbered_tests
* remove all the tests that no longer exist
* re-run flow tests
* Move all the flow tests to tests/flow and prettier to tests/
* Move prettier tests to their own folders
* Add jsfmt files
* run prettier snapshot tests
Given the discussion on #296, it seems like there's debate between spaces around `{}` but no one puts spaces around `[]`. So changing the behavior to respect this.
The original intent of it was for `if then else` and `try catch` as they aren't likely to be empty, but it accidentally caught function bodys, which have many valid reasons to be empty. Let's special case those out.
This one is really weird
```js
if (() => {} ? 1 : 0) {}
```
parses fine but
```js
if (() => {
} ? 1 : 0) {}
```
is a syntax error. Let's always add a parenthesis.
Note that no one is every going to write this in practice, this is really useless :p
We actually need this `;` for EmptyStatement, otherwise it applies to the next block of code. (Creating a label with an empty statement is completely useless, but it triggers a lot in the fuzz testing tool)
Fixes#376
We avoid adding a `;` for a variable declaration in for loop but this is only meant if the var declaration is inside of the `()` part of the for loop. Not if the body part.
Fixes#385
* Add tests for quotes
* Update test snapshots
* Output strings with the minimum amount of escaped quotes
* Update test snapshots
* Move tests/prettier/quotes.js into tests/quotes/strings.js
* Update test snapshots
- During the first iteration, we printed the unescaped values which let to printing invalid JavaScript characters and bad things like invisible characters.
- During the second iteration, we escaped everything, which generated valid JavaScript but you lost your emojis and chinese/cyrillic characters
In this iteration, which I hope will be the last one, we maintain the string exactly as encoded and only swap quotes. The swap quotes implementation is a bit convoluted but I think it works.
The previous API was inconsistent. The new one is
```js
--parser flow
--parser babylon
{parser: 'flow'}
{parser: 'babylon'}
```
if we ever want to add new parsers in the future it'll allow that more easily.
I put a console.log in parser.js in both functions and tested that the test suite worked both with and without the change in run_spec. I also tested that both the previous and new command line options are working.
At some point in the future we'll likely want to get rid of the old api but might as well keep supporting it so we don't break anyone for now.
It's annoying that there's a bug inside of the flow parser, I raised it internally. While this is getting fixed, we can workaround it. This now makes babylon properly escape JSXText.
I thought I didn't need to check the length but forgot that the rest argument is not in the list for class declaration. Now it doesn't crash anymore and there's a test...
The current output of
```js
[...a, ...b]
```
is
```js
[...a, , ...b]
```
because flow parses it as
```
ArrayExpression(SpreadExpression, null, SpreadExpression)
```
This is a bug in the flow parser. Until it gets fixed, we can workaround it by deleting the `null` after a `SpreadExpression`.
* Remove +1 from newline detection
All the changes are related to spurious `;`. Sometimes the logic is more correct, sometimes less. Since `;` are going to be removed after the first save, I don't think it matters that much.
* Handle inconsistent `end` node locations when looking for newlines
I copy and pasted the code for arrays which doesn't have this problem. Would be nice to come up with an abstraction for a list of stuff separated by commas. It happens a lot of time and right now it's duplicated everywhere.
Fixes#255
According to @mroch, "Flow is using CESU-8, not UTF-8. http://www.unicode.org/reports/tr26/ ". While this is being fixed in flow, we can easily work around it inside of prettier. The downside of this approach is that we can't convert those strings to single or double quotes anymore.
```js
for (;;);
function f() {}
```
The `;` was dropped meaning that the line right after was executed within the for loop which is not correct.
I tried to return `;` but it looks like
```js
for (;;)
;
```
which looks super weird so I ended up printing `{}` which looks like
```js
for (;;) {}
```
The current implementation with `JSON.stringify()` is clever but unfortunately generates incorrect JavaScript. Using `jsesc` seems like a better and safer option. https://github.com/mathiasbynens/jsesc It doesn't have any dependencies and is pretty small.
I opted for escaping all the non ascii characters, so we don't display emojis anymore. I don't think that the world is ready yet for having random unicode characters inside of source files, there still are so many parts of the toolchain that breaks with them. If we want to revert back on this decision, there's a `minimal` option on jsesc which only escapes values that need to in order to generate valid JavaScript file (assuming the encoding of the file is set to utf8).
Also, while working on React Native, we've seen that there is an optimization inside of jsc for js files that are all ascii: it doesn't do a copy for the conversion to ucs16.
Fixes#163
There's a handful of files inside of Nuclide that throw exceptions because an assertion is raised.
```
{ AssertionError: ']' === '`'
at fixTemplateLiteral (/Users/vjeux/random/prettier/src/util.js:105:10)
at Object.util.fixFaultyLocations (/Users/vjeux/random/prettier/src/util.js:45:5)
at getSortedChildNodes (/Users/vjeux/random/prettier/src/comments.js:25:8)
at getSortedChildNodes (/Users/vjeux/random/prettier/src/comments.js:61:5)
at decorateComment (/Users/vjeux/random/prettier/src/comments.js:71:20)
at decorateComment (/Users/vjeux/random/prettier/src/comments.js:85:7)
at decorateComment (/Users/vjeux/random/prettier/src/comments.js:85:7)
at decorateComment (/Users/vjeux/random/prettier/src/comments.js:85:7)
at decorateComment (/Users/vjeux/random/prettier/src/comments.js:85:7)
at /Users/vjeux/random/prettier/src/comments.js:129:5
```
When trying https://github.com/facebook/nuclide/blob/master/pkg/nuclide-task-runner/lib/main.js#L174
It throws in the fixTemplateLiteral method.
That method was added to fix https://github.com/benjamn/recast/issues/216 more than a year ago
```js
var x = {
y: () => Relay.QL`
query {
${foo},
field,
}
`
};
```
I've checked (and added a test) and it now parses and prints correctly without that method. So it should be safe to remove.
Babylon has a bug where it doesn't escape DirectiveLiteral properly. Except for `'use strict';`, this never happens in real world code, so let's put strings in a array in order to workaround this bug and have the same output on both parsers.
https://github.com/babel/babylon/issues/289
DeclareInterface (flow) and InterfaceDeclaration (babylon) are the same type so should behave the same way. I am using the same `declare` trick where I only add it if you are inside of a `declare module` block.
The search for an empty line incorrectly does +1 which happens to be skipping a `\n`, but in case of windows line endings it skips the `\r` but sees a `\n` afterwards and incorrectly assumes that it is a empty line.
This doesn't change the behavior of doing +1 when there's not a line ending. Making it correct actually triggers a bunch of changes, where half of them are better and half of them regressions. So I'm going to send another pull request to fix that case.
When looking into adding a test, I realized that the logic was inside of bin/prettier.js and therefore only applying to the cli. Moving it to index.js and adding a test so that it's more robust :)
If there you are opting in for double quote but there's a string with a double quote in it, it's better to swap to a single quote to avoid having too many `\`. Note that if there are both single and double quotes in the string, we should use the default string instead.
Fixes#139
- This brings in the flow test suite that contains a ton of JavaScript parsing edge cases
- This creates snapshot tests using the pretty printer for all of them
- If uncomment `RUN_AST_TESTS` line in `tests/run_specs.js`, it checks ast(pretty_print(x)) == ast(x). Right now, "178 failed, 197 passed, 375 of 377 total". So half of the tests are not passing, most of them are crashes and many of the rest are subtle issues.