Repository: prettier/prettier (JavaScript)
Date: 2017-02-12 03:40:43+00:00
Task type: Bug Fix

Issue:
Comments between ) and { on if/then/else is not stable
```js
async function f() {
  if (untrackedChoice === 0) /* Cancel */ {
    return null;
  } else if (untrackedChoice === 1) /* Add */ {
    await repository.addAll(Array.from(untrackedChanges.keys()));
    shouldAmend = true;
  } else if (untrackedChoice === 2) /* Allow Untracked */ {
    allowUntracked = true;
  }
}
```

turns into

```js
async function f() {
  if (untrackedChoice === 0)
    /* Cancel */ {
      return null;
    }
  else if (untrackedChoice === 1)
    /* Add */ {
      await repository.addAll(Array.from(untrackedChanges.keys()));
      shouldAmend = true;
    }
  else if (untrackedChoice === 2)
    /* Allow Untracked */ {
      allowUntracked = true;
    }
}
```

https://jlongster.github.io/prettier/#%7B%22content%22%3A%22async%20function%20f()%20%7B%5Cn%20%20if%20(untrackedChoice%20%3D%3D%3D%200)%20%2F*%20Cancel%20*%2F%20%7B%5Cn%20%20%20%20return%20null%3B%5Cn%20%20%7D%20else%20if%20(untrackedChoice%20%3D%3D%3D%201)%20%2F*%20Add%20*%2F%20%7B%5Cn%20%20%20%20await%20repository.addAll(Array.from(untrackedChanges.keys()))%3B%5Cn%20%20%20%20shouldAmend%20%3D%20true%3B%5Cn%20%20%7D%20else%20if%20(untrackedChoice%20%3D%3D%3D%202)%20%2F*%20Allow%20Untracked%20*%2F%20%7B%5Cn%20%20%20%20allowUntracked%20%3D%20true%3B%5Cn%20%20%7D%5Cn%7D%22%2C%22options%22%3A%7B%22printWidth%22%3A80%2C%22tabWidth%22%3A2%2C%22singleQuote%22%3Atrue%2C%22trailingComma%22%3Atrue%2C%22bracketSpacing%22%3Atrue%2C%22doc%22%3Afalse%7D%7D

which then turns into

```js
async function f() {
  if (untrackedChoice === 0) {
    /* Cancel */ return null;
  } else if (untrackedChoice === 1) {
    /* Add */ await repository.addAll(Array.from(untrackedChanges.keys()));
    shouldAmend = true;
  } else if (untrackedChoice === 2) {
    /* Allow Untracked */ allowUntracked = true;
  }
}
```

https://jlongster.github.io/prettier/#%7B%22content%22%3A%22async%20function%20f()%20%7B%5Cn%20%20if%20(untrackedChoice%20%3D%3D%3D%200)%5Cn%20%20%20%20%2F*%20Cancel%20*%2F%20%7B%5Cn%20%20%20%20%20%20return%20null%3B%5Cn%20%20%20%20%7D%5Cn%20%20else%20if%20(untrackedChoice%20%3D%3D%3D%201)%5Cn%20%20%20%20%2F*%20Add%20*%2F%20%7B%5Cn%20%20%20%20%20%20await%20repository.addAll(Array.from(untrackedChanges.keys()))%3B%5Cn%20%20%20%20%20%20shouldAmend%20%3D%20true%3B%5Cn%20%20%20%20%7D%5Cn%20%20else%20if%20(untrackedChoice%20%3D%3D%3D%202)%5Cn%20%20%20%20%2F*%20Allow%20Untracked%20*%2F%20%7B%5Cn%20%20%20%20%20%20allowUntracked%20%3D%20true%3B%5Cn%20%20%20%20%7D%5Cn%7D%5Cn%22%2C%22options%22%3A%7B%22printWidth%22%3A80%2C%22tabWidth%22%3A2%2C%22singleQuote%22%3Atrue%2C%22trailingComma%22%3Atrue%2C%22bracketSpacing%22%3Atrue%2C%22doc%22%3Afalse%7D%7D

But... seriously, why would you put comments there!?


Issue discussion:

Solution patch:
diff --git a/src/comments.js b/src/comments.js
index d97dae762510..6109ce834a52 100644
--- a/src/comments.js
+++ b/src/comments.js
@@ -170,12 +170,14 @@ function attach(comments, ast, text) {
         addDanglingComment(ast, comment);
       }
     } else {
-      // Otherwise, text exists both before and after the comment on
-      // the same line. If there is both a preceding and following
-      // node, use a tie-breaking algorithm to determine if it should
-      // be attached to the next or previous node. In the last case,
-      // simply attach the right node;
-      if (precedingNode && followingNode) {
+      if (handleIfStatementComments(enclosingNode, followingNode, comment)) {
+        // We're good
+      } else if (precedingNode && followingNode) {
+        // Otherwise, text exists both before and after the comment on
+        // the same line. If there is both a preceding and following
+        // node, use a tie-breaking algorithm to determine if it should
+        // be attached to the next or previous node. In the last case,
+        // simply attach the right node;
         const tieCount = tiesToBreak.length;
         if (tieCount > 0) {
           var lastTie = tiesToBreak[tieCount - 1];


Test patch:
diff --git a/tests/if_comments/__snapshots__/jsfmt.spec.js.snap b/tests/if_comments/__snapshots__/jsfmt.spec.js.snap
new file mode 100644
index 000000000000..569510378650
--- /dev/null
+++ b/tests/if_comments/__snapshots__/jsfmt.spec.js.snap
@@ -0,0 +1,73 @@
+exports[`test if_comments.js 1`] = `
+"async function f() {
+  if (untrackedChoice === 0) /* Cancel */ {
+    return null;
+  } else if (untrackedChoice === 1) /* Add */ {
+    await repository.addAll(Array.from(untrackedChanges.keys()));
+    shouldAmend = true;
+  } else if (untrackedChoice === 2) /* Allow Untracked */ {
+    allowUntracked = true;
+  }
+}
+
+async function f() {
+  if (untrackedChoice === 0)
+    /* Cancel */ {
+      return null;
+    }
+  else if (untrackedChoice === 1)
+    /* Add */ {
+      await repository.addAll(Array.from(untrackedChanges.keys()));
+      shouldAmend = true;
+    }
+  else if (untrackedChoice === 2)
+    /* Allow Untracked */ {
+      allowUntracked = true;
+    }
+}
+
+async function f() {
+  if (untrackedChoice === 0) {
+    /* Cancel */ return null;
+  } else if (untrackedChoice === 1) {
+    /* Add */ await repository.addAll(Array.from(untrackedChanges.keys()));
+    shouldAmend = true;
+  } else if (untrackedChoice === 2) {
+    /* Allow Untracked */ allowUntracked = true;
+  }
+}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+async function f() {
+  if (untrackedChoice === 0) {
+    /* Cancel */ return null;
+  } else if (untrackedChoice === 1) {
+    /* Add */ await repository.addAll(Array.from(untrackedChanges.keys()));
+    shouldAmend = true;
+  } else if (untrackedChoice === 2) {
+    /* Allow Untracked */ allowUntracked = true;
+  }
+}
+
+async function f() {
+  if (untrackedChoice === 0) {
+    /* Cancel */ return null;
+  } else if (untrackedChoice === 1) {
+    /* Add */ await repository.addAll(Array.from(untrackedChanges.keys()));
+    shouldAmend = true;
+  } else if (untrackedChoice === 2) {
+    /* Allow Untracked */ allowUntracked = true;
+  }
+}
+
+async function f() {
+  if (untrackedChoice === 0) {
+    /* Cancel */ return null;
+  } else if (untrackedChoice === 1) {
+    /* Add */ await repository.addAll(Array.from(untrackedChanges.keys()));
+    shouldAmend = true;
+  } else if (untrackedChoice === 2) {
+    /* Allow Untracked */ allowUntracked = true;
+  }
+}
+"
+`;
diff --git a/tests/if_comments/if_comments.js b/tests/if_comments/if_comments.js
new file mode 100644
index 000000000000..2b35529999a2
--- /dev/null
+++ b/tests/if_comments/if_comments.js
@@ -0,0 +1,37 @@
+async function f() {
+  if (untrackedChoice === 0) /* Cancel */ {
+    return null;
+  } else if (untrackedChoice === 1) /* Add */ {
+    await repository.addAll(Array.from(untrackedChanges.keys()));
+    shouldAmend = true;
+  } else if (untrackedChoice === 2) /* Allow Untracked */ {
+    allowUntracked = true;
+  }
+}
+
+async function f() {
+  if (untrackedChoice === 0)
+    /* Cancel */ {
+      return null;
+    }
+  else if (untrackedChoice === 1)
+    /* Add */ {
+      await repository.addAll(Array.from(untrackedChanges.keys()));
+      shouldAmend = true;
+    }
+  else if (untrackedChoice === 2)
+    /* Allow Untracked */ {
+      allowUntracked = true;
+    }
+}
+
+async function f() {
+  if (untrackedChoice === 0) {
+    /* Cancel */ return null;
+  } else if (untrackedChoice === 1) {
+    /* Add */ await repository.addAll(Array.from(untrackedChanges.keys()));
+    shouldAmend = true;
+  } else if (untrackedChoice === 2) {
+    /* Allow Untracked */ allowUntracked = true;
+  }
+}
diff --git a/tests/if_comments/jsfmt.spec.js b/tests/if_comments/jsfmt.spec.js
new file mode 100644
index 000000000000..989047bccc52
--- /dev/null
+++ b/tests/if_comments/jsfmt.spec.js
@@ -0,0 +1,1 @@
+run_spec(__dirname);