Repository: jlongster/prettier (js)

Issue:
Comment between if/else is formatted strangely
```js
if(x) {
}
// comment
else {
}
```

output:

```js
if (x) {
} else
  // comment
  {
  }
```

Pull request description:
Make comments between if & else to look good
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

Patch:
diff --git a/src/comments.js b/src/comments.js
index e05c7f50f..1309a1889 100644
--- a/src/comments.js
+++ b/src/comments.js
@@ -152,7 +152,9 @@ function attach(comments, ast, text) {
       // If a comment exists on its own line, prefer a leading comment.
       // We also need to check if it's the first line of the file.
 
-      if (followingNode) {
+      if (handleIfStatementComments(enclosingNode, followingNode, comment)) {
+        // We're good
+      } else if (followingNode) {
         // Always a leading comment.
         addLeadingComment(followingNode, comment);
       } else if (precedingNode) {
@@ -278,6 +280,52 @@ function addTrailingComment(node, comment) {
   addCommentHelper(node, comment);
 }
 
+function addBlockStatementFirstComment(node, comment) {
+  if (node.body.length === 0) {
+    addDanglingComment(node, comment);
+  } else {
+    addLeadingComment(node.body[0], comment);
+  }
+}
+
+// There are often comments before the else clause of if statements like
+//
+//   if (1) { ... }
+//   // comment
+//   else { ... }
+//
+// They are being attached as leading comments of the BlockExpression which
+// is not well printed. What we want is to instead move the comment inside
+// of the block and make it leadingComment of the first element of the block
+// or dangling comment of the block if there is nothing inside
+//
+//   if (1) { ... }
+//   else {
+//     // comment
+//     ...  
+//   }
+function handleIfStatementComments(enclosingNode, followingNode, comment) {
+  if (!enclosingNode || enclosingNode.type !== "IfStatement" || !followingNode) {
+    return false;
+  }
+
+  if (followingNode.type === "BlockStatement") {
+    addBlockStatementFirstComment(followingNode, comment);
+    return true;
+  }
+
+  if (followingNode.type === "IfStatement") {
+    if (followingNode.consequent.type === "BlockStatement") {
+      addBlockStatementFirstComment(followingNode.consequent, comment);
+    } else {
+      addLeadingComment(followingNode.consequent, comment);
+    }
+    return true;
+  }
+
+  return false;
+}
+
 function printComment(commentPath) {
   const comment = commentPath.getValue();
 


Test patch:
diff --git a/tests/comments/__snapshots__/jsfmt.spec.js.snap b/tests/comments/__snapshots__/jsfmt.spec.js.snap
index ca8c8260c..d4f993d89 100644
--- a/tests/comments/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/comments/__snapshots__/jsfmt.spec.js.snap
@@ -70,6 +70,94 @@ declare class Foo extends Qux<string> {/* dangling */}
 "
 `;
 
+exports[`test if.js 1`] = `
+"if (1)
+// comment
+{
+  false
+}
+// comment
+else if (2)
+  true
+// multi
+// ple
+// lines
+else if (3)
+  // existing comment
+  true
+// okay?
+else if (4) {
+  // empty with existing comment
+}
+// comment
+else {
+}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+if (1) {
+  // comment
+  false;
+} else if (2)
+  // comment
+  true;
+else if (3)
+  // multi
+  // ple
+  // lines
+  // existing comment
+  true;
+else if (4) {
+  // okay?
+  // empty with existing comment
+} else {
+  // comment
+}
+"
+`;
+
+exports[`test if.js 2`] = `
+"if (1)
+// comment
+{
+  false
+}
+// comment
+else if (2)
+  true
+// multi
+// ple
+// lines
+else if (3)
+  // existing comment
+  true
+// okay?
+else if (4) {
+  // empty with existing comment
+}
+// comment
+else {
+}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+if (1) {
+  // comment
+  false;
+} else if (2)
+  // comment
+  true;
+else if (3)
+  // multi
+  // ple
+  // lines
+  // existing comment
+  true;
+else if (4) {
+  // okay?
+  // empty with existing comment
+} else {
+  // comment
+}
+"
+`;
+
 exports[`test issues.js 1`] = `
 "// Does not need to break as it fits in 80 columns
 this.call(a, /* comment */ b);
@@ -284,10 +372,9 @@ if (1) {
 
 // Comments trigger invalid JavaScript in-between else if
 if (1) {
-} else
+} else {
   // Comment
-  {
-  }
+}
 
 // The comment makes the line break in a weird way
 const result = asyncExecute(\"non_existing_command\", /* args */ []);
@@ -514,10 +601,9 @@ if (1) {
 
 // Comments trigger invalid JavaScript in-between else if
 if (1) {
-} else
+} else {
   // Comment
-  {
-  }
+}
 
 // The comment makes the line break in a weird way
 const result = asyncExecute(\"non_existing_command\", /* args */ []);
diff --git a/tests/comments/if.js b/tests/comments/if.js
new file mode 100644
index 000000000..a542793bd
--- /dev/null
+++ b/tests/comments/if.js
@@ -0,0 +1,21 @@
+if (1)
+// comment
+{
+  false
+}
+// comment
+else if (2)
+  true
+// multi
+// ple
+// lines
+else if (3)
+  // existing comment
+  true
+// okay?
+else if (4) {
+  // empty with existing comment
+}
+// comment
+else {
+}