Skip to content

Fix missing comments in assignment pattern#704

Merged
vjeux merged 9 commits intoprettier:masterfrom
yamafaktory:699-fix-missing-comments-assignment-pattern
Feb 20, 2017
Merged

Fix missing comments in assignment pattern#704
vjeux merged 9 commits intoprettier:masterfrom
yamafaktory:699-fix-missing-comments-assignment-pattern

Conversation

@yamafaktory
Copy link
Copy Markdown
Contributor

This PR should fix #699.

"
`;

exports[`test dangling_array.js 1`] = `
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oops.. will fix that!

src/comments.js Outdated
} else {
if (handleIfStatementComments(enclosingNode, followingNode, comment)) {
// We're good
} else if (handleAssignmentPatternComments(enclosingNode, comment)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you put

if (
  handleIfStatement... ||
  handleAssignment... ||
)

like we do above?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Of course!

src/comments.js Outdated
return false;
}

function handleAssignmentPatternComments(enclosingNode, comment) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't think that this is the right fix. Can you figure out where the comment is attached without this logic and find out why this node didn't print its comment?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I did investigate a bit. For the following case, this line is involved https://github.com/jlongster/prettier/blob/master/src/comments.js#L192. Then addCommentHelper enforcescomment.printed = false which strips the comment. If set to true then this is working again:

const { c = 1 /* comment */ } = d;

I don't think you want to alter such a primitive function, that's why I used this handleAssignmentPatternComments function.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

But, funny thing, switching to comment.printed = true doesn't break any tests 😮! Then, I just need to figure out how to print the comment for:

const {a /* comment */ = 1 } = b

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

comment.printed shouldn't have any affect on the output; it's used to do a sanity check afterwards to make sure we printed all the comments. I don't know why it would affect the output.

Copy link
Copy Markdown
Contributor Author

@yamafaktory yamafaktory Feb 15, 2017

Choose a reason for hiding this comment

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

Good to know, thanks! But this definitely has an impact... Your thoughts on the handleAssignmentPatternComments function, is that a wrong approach?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's not the wrong approach if we have to do it, but I'd also like to know why we have to. If like you say it triggers that branch and attaches it as a trailing comment to the identifier, it should be printed.

Search the code for comment.printed; it's only ever set the true and false. Nothing ever branched on it, so can you look into why something is changed and why the comment isn't printed in the first place?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I saw it. I'm going to investigate, thanks!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@jlongster + @vjeux I think I've identified what's causing the issue. For example, with something like:

const {a /* comment */ = 1 } = b

The comment is stripped and we get the error message for non-printed comments. This is coming from https://github.com/jlongster/prettier/blob/master/src/comments.js#L487 where the right-hand side of the boolean (types.getFieldValue(value, "comments")) is always null or undefined. As a consequence, on line 490, printed is returned and the comment is sadly omitted...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oh, and I forgot to mention that in this case there is a trailing comment (I can trace it here https://github.com/jlongster/prettier/blob/master/src/comments.js#L193).

@jlongster
Copy link
Copy Markdown
Member

I discovered the problem. The problem is that the { a = 1 } code is compiled into an ObjectProperty with shorthand: true, which indicates that we should only print the value node. For normal shorthand objects like { a } it wouldn't matter if we printed the key or value, but we print the value because the destructuring assignment above exists on the value prop as a AssignmentPattern. Here's the important parts of the AST:

Node {
  type: 'ObjectProperty',
  start: 7,
  end: 26,
  loc:
   SourceLocation {
     start: Position { line: 1, column: 7 },
     end: Position { line: 1, column: 26 } },
  method: false,
  shorthand: true,
  computed: false,
  key:
   Node {
     type: 'Identifier',
     start: 7,
     end: 8,
     loc: SourceLocation { start: [Object], end: [Object], identifierName: 'a' },
     name: 'a',
     leadingComments: null,
     trailingComments: [ [Object] ],
     comments: [ [Object] ] },
  value:
   Node {
     type: 'AssignmentPattern',
     start: 7,
     end: 26,
     loc: SourceLocation { start: [Object], end: [Object] },
     left:
      Node {
        type: 'Identifier',
        start: 7,
        end: 8,
        loc: [Object],
        name: 'a',
        __clone: [Function: __clone] },
     right:

The problem is that the comment is attached to the identifier in the key node, as you can see in the comments array. But the identifier in the AssignmentPattern is what's actually printed.

Not sure what the best solution is yet, but that's the problem.

@yamafaktory
Copy link
Copy Markdown
Contributor Author

@jlongster I tried to implement a different logic, i.e. solving the root issue by handling these comments attached to the key node. Not sure if this is a better way to do it, and by the way, this currently only solves the non-printed comment warning (still need to print those comments in the end).

@vjeux
Copy link
Copy Markdown
Contributor

vjeux commented Feb 20, 2017

@@ -179,7 +179,8 @@ function attach(comments, ast, text) {
         addDanglingComment(ast, comment);
       }
     } else {
-      if (handleIfStatementComments(enclosingNode, followingNode, comment)) {
+      if (handleIfStatementComments(enclosingNode, followingNode, comment) ||
+          handleObjectProperty(enclosingNode, precedingNode, comment)) {
         // We're good
       } else if (precedingNode && followingNode) {
         // Otherwise, text exists both before and after the comment on
@@ -395,6 +396,17 @@ function handleConditionalExpressionComments(
   return false;
 }

+function handleObjectProperty(enclosingNode, precedingNode, comment) {
+  if (enclosingNode.type === "ObjectProperty" &&
+      enclosingNode.shorthand &&
+      enclosingNode.key === precedingNode &&
+      enclosingNode.value.type === "AssignmentPattern") {
+    addTrailingComment(enclosingNode.value.left, comment);
+    return true;
+  }
+  return false;
+}
+

What do you think about relocating the comment the same way we move a bunch of others?

const {/* missing */ a /* missing comment */ = 1} = b

outputs

const { /* missing */ a /* missing comment */ = 1 } = b;

@yamafaktory
Copy link
Copy Markdown
Contributor Author

This looks good to me!

@yamafaktory
Copy link
Copy Markdown
Contributor Author

yamafaktory commented Feb 20, 2017

@vjeux Actually you've implemented something close to what I initially did 😛 fc998c9. And we need to check for type === "Property" when using Flow. But sadly this is breaking other tests, I have to investigate.

src/comments.js Outdated

if (
locStart(child) - locStart(comment) <= 0 &&
locEnd(comment) - locEnd(child) <= 0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you revert all the changes you've triggered by running prettier on that file? :)

return path.needsParens() ? concat(["(", lines, ")"]) : lines;
}

function shouldPrintComma(options, level) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think you messed up your rebase :x

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oops, let me clean that!

@vjeux vjeux merged commit d613f92 into prettier:master Feb 20, 2017
@vjeux
Copy link
Copy Markdown
Contributor

vjeux commented Feb 20, 2017

Yay, thanks!

@yamafaktory
Copy link
Copy Markdown
Contributor Author

@vjeux Now this should be cleaned up and all the tests should pass!

@yamafaktory
Copy link
Copy Markdown
Contributor Author

@vjeux Wow, you're fast! Thanks 👍

@vjeux
Copy link
Copy Markdown
Contributor

vjeux commented Feb 20, 2017

I'm pretty excited about this PR :)

@yamafaktory yamafaktory deleted the 699-fix-missing-comments-assignment-pattern branch February 25, 2017 18:30
@lock lock bot added the locked-due-to-inactivity Please open a new issue and fill out the template instead of commenting. label Jan 21, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Jan 21, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

locked-due-to-inactivity Please open a new issue and fill out the template instead of commenting.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unprinted comment in object destructuring

3 participants