{"action":"created","issue":{"url":"https://api.github.com/repos/lob/eslint-plugin-lob/issues/2","repository_url":"https://api.github.com/repos/lob/eslint-plugin-lob","labels_url":"https://api.github.com/repos/lob/eslint-plugin-lob/issues/2/labels{/name}","comments_url":"https://api.github.com/repos/lob/eslint-plugin-lob/issues/2/comments","events_url":"https://api.github.com/repos/lob/eslint-plugin-lob/issues/2/events","html_url":"https://github.com/lob/eslint-plugin-lob/pull/2","id":133167948,"number":2,"title":"feat(newline-after-mocha): add the newline-after-mocha rule","user":{"login":"robinjoseph08","id":2454505,"avatar_url":"https://avatars.githubusercontent.com/u/2454505?v=3","gravatar_id":"","url":"https://api.github.com/users/robinjoseph08","html_url":"https://github.com/robinjoseph08","followers_url":"https://api.github.com/users/robinjoseph08/followers","following_url":"https://api.github.com/users/robinjoseph08/following{/other_user}","gists_url":"https://api.github.com/users/robinjoseph08/gists{/gist_id}","starred_url":"https://api.github.com/users/robinjoseph08/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/robinjoseph08/subscriptions","organizations_url":"https://api.github.com/users/robinjoseph08/orgs","repos_url":"https://api.github.com/users/robinjoseph08/repos","events_url":"https://api.github.com/users/robinjoseph08/events{/privacy}","received_events_url":"https://api.github.com/users/robinjoseph08/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":{"login":"mgartner","id":1128750,"avatar_url":"https://avatars.githubusercontent.com/u/1128750?v=3","gravatar_id":"","url":"https://api.github.com/users/mgartner","html_url":"https://github.com/mgartner","followers_url":"https://api.github.com/users/mgartner/followers","following_url":"https://api.github.com/users/mgartner/following{/other_user}","gists_url":"https://api.github.com/users/mgartner/gists{/gist_id}","starred_url":"https://api.github.com/users/mgartner/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mgartner/subscriptions","organizations_url":"https://api.github.com/users/mgartner/orgs","repos_url":"https://api.github.com/users/mgartner/repos","events_url":"https://api.github.com/users/mgartner/events{/privacy}","received_events_url":"https://api.github.com/users/mgartner/received_events","type":"User","site_admin":false},"milestone":null,"comments":0,"created_at":"2016-02-12T06:29:31Z","updated_at":"2016-02-12T21:42:00Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/lob/eslint-plugin-lob/pulls/2","html_url":"https://github.com/lob/eslint-plugin-lob/pull/2","diff_url":"https://github.com/lob/eslint-plugin-lob/pull/2.diff","patch_url":"https://github.com/lob/eslint-plugin-lob/pull/2.patch"},"body":"### What\r\n\r\nAdds the `newlint-after-mocha` rule that enforces new lines in between mocha blocks (`describe`, `it`, `beforeEach`, etc). This is based off of the default [`newline-after-var` rule](https://github.com/eslint/eslint/blob/master/lib/rules/newline-after-var.js) That makes this valid (without `padded-describes`):\r\n\r\n```js\r\ndescribe('controller', () => {\r\n  beforeEach(() => {\r\n  });\r\n\r\n  it('test1', () => {\r\n  });\r\n\r\n  it('test2', () => {\r\n  });\r\n});\r\n```\r\n\r\nAnd this invalid:\r\n\r\n```js\r\ndescribe('controller', () => {\r\n  beforeEach(() => {\r\n  });\r\n  it('test1', () => {\r\n  });\r\n  it('test2', () => {\r\n  });\r\n});\r\n```\r\n\r\n### Details\r\n\r\nThe reason most of the logic is centered around the `statement` (which is `node.parent`) instead of `node` is because every mocha call (`it('', () => {});`) is structured as an `ExpressionStatement` with a nested `CallExpression`, so two `it` blocks next to each other looks like this:\r\n\r\n```\r\nProgram\r\n├── ExpressionStatement\r\n│   └── CallExpression\r\n└── ExpressionStatement\r\n    └── CallExpression\r\n```\r\n\r\nSo by registering the rule function under `CallExpression` (which is necessary because the info about the name of the function is on the `CallExpression`), to know if it's the last call (since you don't want to enforce the new line rule if it's the last call), you need to see if the `ExpressionStatement` is the last child of `Program`.\r\n\r\nThe actual logic of the rule takes the last token of the statement (usually the semi-colon) and the first token after the statement (usually the next `it`) and makes sure the next token is at least 2 lines greater than the last token. And the tests cover all of our normal cases so I think it all works fine.\r\n\r\nHopefully that makes sense. If not, I can explain it further IRL.\r\n\r\n@mgartner "},"comment":{"url":"https://api.github.com/repos/lob/eslint-plugin-lob/issues/comments/183498231","html_url":"https://github.com/lob/eslint-plugin-lob/pull/2#issuecomment-183498231","issue_url":"https://api.github.com/repos/lob/eslint-plugin-lob/issues/2","id":183498231,"user":{"login":"mgartner","id":1128750,"avatar_url":"https://avatars.githubusercontent.com/u/1128750?v=3","gravatar_id":"","url":"https://api.github.com/users/mgartner","html_url":"https://github.com/mgartner","followers_url":"https://api.github.com/users/mgartner/followers","following_url":"https://api.github.com/users/mgartner/following{/other_user}","gists_url":"https://api.github.com/users/mgartner/gists{/gist_id}","starred_url":"https://api.github.com/users/mgartner/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mgartner/subscriptions","organizations_url":"https://api.github.com/users/mgartner/orgs","repos_url":"https://api.github.com/users/mgartner/repos","events_url":"https://api.github.com/users/mgartner/events{/privacy}","received_events_url":"https://api.github.com/users/mgartner/received_events","type":"User","site_admin":false},"created_at":"2016-02-12T21:42:00Z","updated_at":"2016-02-12T21:42:00Z","body":"Awesome! LGTM"}}