Skip to content

Commit

Permalink
Decaff helper jscodemods. (#5732)
Browse files Browse the repository at this point in the history
* Added a file that removes comments that start with #.

* Added .eslintrc to silence ts errors in codemods.

* Convert switch (false) to if-else.

* Add disable-eslint no-empty by default after empty catch.

* Reserve comments when converting switch-case.

* Added new codemods to bulk-decaffeinate.

* Preserve comments.

* Ignored lint rules for test fixtures.

* Move comments between arrow and block to the top.

* Merged tests into one file.

* Turned off no-undef for test fixtures.

* No-cond-assign

* Added jscodemods to decaff config.

* Fixed typo.

* Make CI test codemods

* Added test-no-return.

* Revert "Added test-no-return."

This reverts commit d610829.

* fix arrow-comment


Co-authored-by: Ben Kucera <14625260+Bkucera@users.noreply.github.com>
Co-authored-by: Zach Bloomquist <github@chary.us>
  • Loading branch information
3 people committed Dec 6, 2019
1 parent 4a2636d commit 994ab32
Show file tree
Hide file tree
Showing 21 changed files with 338 additions and 0 deletions.
5 changes: 5 additions & 0 deletions bulk-decaffeinate.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,10 @@ module.exports = {
path.resolve('node_modules', 'jscodemods', 'decaffeinate', 'fix-multi-assign-class-export.js'),
path.resolve('node_modules', 'jscodemods', 'decaffeinate', 'fix-implicit-return-assignment.js'),
path.resolve('node_modules', 'jscodemods', 'decaffeinate', 'fix-existential-conditional-assignment.js'),
'./scripts/decaff/remove-comment-sharp.js',
'./scripts/decaff/switch-false.js',
'./scripts/decaff/empty-catch.js',
'./scripts/decaff/no-cond-assign.js',
'./scripts/decaff/arrow-comment.js',
],
}
2 changes: 2 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@ jobs:
- run: npm run test-mocha-snapshot
# make sure packages with TypeScript can be transpiled to JS
- run: npm run all build-js
# test codemods
- run: npm run test-jscodeshift
# run unit tests from individual packages
- run: npm run all test -- --package cli
- run: npm run all test -- --package electron
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"stop-only-all": "npm run stop-only -- --folder packages",
"test": "echo '⚠️ This root monorepo is only for local development and new contributions. There are no tests.'",
"test-debug-package": "node ./scripts/test-debug-package.js",
"test-jscodeshift": "jest ./scripts/decaff",
"test-mocha": "mocha --reporter spec scripts/spec.js",
"test-mocha-snapshot": "mocha scripts/mocha-snapshot-spec.js",
"test-s3-api": "node -r ./packages/coffee/register -r ./packages/ts/register scripts/binary/s3-api-demo.ts",
Expand Down Expand Up @@ -133,6 +134,7 @@
"husky": "2.4.1",
"inquirer": "3.3.0",
"inquirer-confirm": "2.0.3",
"jest": "24.9.0",
"js-codemod": "cpojer/js-codemod#29dafed",
"jscodemods": "cypress-io/jscodemods#01b546e",
"jscodeshift": "0.6.3",
Expand Down
3 changes: 3 additions & 0 deletions scripts/decaff/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"parser": "espree"
}
11 changes: 11 additions & 0 deletions scripts/decaff/__testfixtures__/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"parser": "espree",
"rules": {
"no-empty": "off",
"no-undef": "off",
"no-cond-assign": "off",
"semi": "off",
"brace-style": "off",
"no-case-declarations": "off"
}
}
10 changes: 10 additions & 0 deletions scripts/decaff/__testfixtures__/arrow-comment.input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Original comment
const func = (a, b) =>
// Multiline comment
// is here
{
a.works()
b.check.thisOut()
}

func()
10 changes: 10 additions & 0 deletions scripts/decaff/__testfixtures__/arrow-comment.output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Original comment
// Multiline comment
// is here
const func = (a, b) =>
{
a.works()
b.check.thisOut()
};

func()
7 changes: 7 additions & 0 deletions scripts/decaff/__testfixtures__/empty-catch.input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
try {
// do something
} catch (e) {}

try {
// do something
} finally {}
7 changes: 7 additions & 0 deletions scripts/decaff/__testfixtures__/empty-catch.output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
try {
// do something
} catch (e) {} // eslint-disable-line no-empty

try {
// do something
} finally {}
6 changes: 6 additions & 0 deletions scripts/decaff/__testfixtures__/no-cond-assign.input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
let a

// Comment
if (a = c()) {
a.fix()
}
8 changes: 8 additions & 0 deletions scripts/decaff/__testfixtures__/no-cond-assign.output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
let a

// Comment
a = c();

if (a) {
a.fix()
}
6 changes: 6 additions & 0 deletions scripts/decaff/__testfixtures__/remove-comment-sharp.input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//# Testing this
// eslint-disable-next-line
console.log('it works') //# Test

// This # should not be removed.
/*# it's not wrong */
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Testing this
// eslint-disable-next-line
console.log('it works') // Test

// This # should not be removed.
/*# it's not wrong */
33 changes: 33 additions & 0 deletions scripts/decaff/__testfixtures__/switch-false.input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
function f () {
switch (false) {
// Comment should be reserved
case !a.subject(a):
let x = 30

b.doSomething(x)
break
// Multi line comment
// should be reserved
case c.isGood:
c.checkThisOut()
findThings()
break
case isBad:
c.neverCheck()
break
case !isAwesome:
a.subject(a)
break
case hi:
// This should be reserved, too
return 3
case you:
// This comment is preserved
break
default:
b.goToNext()
break
}
}

f()
25 changes: 25 additions & 0 deletions scripts/decaff/__testfixtures__/switch-false.output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
function f () {
if (a.subject(a)) {
// Comment should be reserved
let x = 30;

b.doSomething(x)
} else if (!c.isGood) {
// Multi line comment
// should be reserved
c.checkThisOut();
findThings()
} else if (!isBad) {
c.neverCheck();
} else if (isAwesome) {
a.subject(a);
} else if (!hi) {
// This should be reserved, too
return 3
} else if (!you) // This comment is preserved
{} else {
b.goToNext();
}
}

f()
10 changes: 10 additions & 0 deletions scripts/decaff/__tests__/decaff.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* global jest */

jest.autoMockOff()
const defineTest = require('jscodeshift/dist/testUtils').defineTest

defineTest(__dirname, 'switch-false')
defineTest(__dirname, 'empty-catch')
defineTest(__dirname, 'remove-comment-sharp')
defineTest(__dirname, 'arrow-comment')
defineTest(__dirname, 'no-cond-assign')
28 changes: 28 additions & 0 deletions scripts/decaff/arrow-comment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module.exports = (fileInfo, api) => {
const j = api.jscodeshift

return j(fileInfo.source)
.find(j.VariableDeclaration, {
declarations: [{
type: 'VariableDeclarator',
init: {
type: 'ArrowFunctionExpression',
body: {
type: 'BlockStatement',
},
},
}],
})
.replaceWith((nodePath) => {
const { node } = nodePath
const comments = node.declarations[0].init.body.comments

if (comments && comments.length > 0) {
node.comments = [...node.comments, ...comments]
node.declarations[0].init.body.comments = null
}

return node
})
.toSource()
}
28 changes: 28 additions & 0 deletions scripts/decaff/empty-catch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module.exports = (fileInfo, api) => {
const j = api.jscodeshift

const source = j(fileInfo.source)
.find(j.TryStatement)
.replaceWith((nodePath) => {
const { node } = nodePath

// Add trailing eslint-disable-line for empty catch block
if (node.handler && node.handler.body.body.length === 0) {
node.handler.body.comments = [
{
type: 'Line',
value: ' eslint-disable-line no-empty',
leading: false,
trailing: true,
},
]
}

return node
})
.toSource()

// Generated source above creates {}// eslint-disable-line block.
// So, add a space with replace
return source.replace(/\{\}\/\/ eslint-disable-line/g, '{} // eslint-disable-line')
}
29 changes: 29 additions & 0 deletions scripts/decaff/no-cond-assign.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module.exports = (fileInfo, api) => {
const j = api.jscodeshift

return j(fileInfo.source)
.find(j.IfStatement, {
test: {
type: 'AssignmentExpression',
},
})
.replaceWith((nodePath) => {
const { node } = nodePath

const assign = j.expressionStatement(node.test)

assign.comments = node.comments

const ifStatement = j.ifStatement(
node.test.left,
node.consequent,
node.alternate
)

return [
assign,
ifStatement,
]
})
.toSource()
}
4 changes: 4 additions & 0 deletions scripts/decaff/remove-comment-sharp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// This file doesn't use AST because it makes things too complicated.
module.exports = (fileInfo) => {
return fileInfo.source.replace(/\/\/#/g, '//')
}
98 changes: 98 additions & 0 deletions scripts/decaff/switch-false.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
module.exports = (fileInfo, api) => {
const j = api.jscodeshift

return j(fileInfo.source)
.find(j.SwitchStatement, {
discriminant: {
type: 'Literal',
value: false,
},
})
.replaceWith((nodePath) => {
const { node } = nodePath

const cases = node.cases.map((c) => {
const { test, consequent, comments } = c

return {
test: generateTest(j, test),
content: generateContent(j, consequent),
comments,
}
})

const ifStatement = generateIfStatement(j, cases)

ifStatement.comments = node.comments

return ifStatement
})
.toSource()
}

function generateTest (j, test) {
if (test) {
if (test.type === 'UnaryExpression') {
return test.argument
}

return j.unaryExpression('!', test)
}

return null
}

function generateContent (j, consequent) {
if (consequent.length === 1 && consequent[0].type === 'BreakStatement') {
const block = j.blockStatement([])

block.comments = consequent[0].comments

return block
}

return j.blockStatement(consequent.filter((c) => c.type !== 'BreakStatement'))
}

function generateIfStatement (j, cases) {
const nonDefaultCases = cases.filter((c) => c.test !== null)
const defaultCase = cases.filter((c) => c.test === null)[0]

let ifStatement = null

if (defaultCase) {
const content = addComment(defaultCase.content, defaultCase.comments)

ifStatement = content
}

nonDefaultCases.reverse().forEach((c) => {
const content = addComment(c.content, c.comments)

ifStatement = j.ifStatement(
c.test,
content,
ifStatement
)
})

return ifStatement
}

function addComment (content, comments) {
if (content.body.length > 0) {
content.body[0].comments = [...(comments || []), ...(content.body[0].comments || [])]
} else {
const newComments = (comments || []).map((co) => {
return {
...co,
leading: false,
trailing: false,
}
})

content.comments = [...newComments, ...(content.comments || [])]
}

return content
}

4 comments on commit 994ab32

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 994ab32 Dec 6, 2019

Choose a reason for hiding this comment

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

Circle has built the linux x64 version of the Test Runner.

You can install this pre-release platform-specific build using instructions at https://on.cypress.io/installing-cypress#Install-pre-release-version.

You will need to use custom CYPRESS_INSTALL_BINARY url and install Cypress using an url instead of the version.

export CYPRESS_INSTALL_BINARY=https://cdn.cypress.io/beta/binary/3.8.0/linux-x64/circle-develop-994ab326a0ed42589f0205a366a508d9da72bfb7-210398/cypress.zip
npm install https://cdn.cypress.io/beta/npm/3.8.0/circle-develop-994ab326a0ed42589f0205a366a508d9da72bfb7-210392/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 994ab32 Dec 6, 2019

Choose a reason for hiding this comment

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

AppVeyor has built the win32 x64 version of the Test Runner.

You can install this pre-release platform-specific build using instructions at https://on.cypress.io/installing-cypress#Install-pre-release-version.

You will need to use custom CYPRESS_INSTALL_BINARY url and install Cypress using an url instead of the version.

set CYPRESS_INSTALL_BINARY=https://cdn.cypress.io/beta/binary/3.8.0/win32-x64/appveyor-develop-994ab326a0ed42589f0205a366a508d9da72bfb7-29375398/cypress.zip
npm install https://cdn.cypress.io/beta/binary/3.8.0/win32-x64/appveyor-develop-994ab326a0ed42589f0205a366a508d9da72bfb7-29375398/cypress.zip

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 994ab32 Dec 6, 2019

Choose a reason for hiding this comment

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

AppVeyor has built the win32 ia32 version of the Test Runner.

You can install this pre-release platform-specific build using instructions at https://on.cypress.io/installing-cypress#Install-pre-release-version.

You will need to use custom CYPRESS_INSTALL_BINARY url and install Cypress using an url instead of the version.

set CYPRESS_INSTALL_BINARY=https://cdn.cypress.io/beta/binary/3.8.0/win32-ia32/appveyor-develop-994ab326a0ed42589f0205a366a508d9da72bfb7-29375398/cypress.zip
npm install https://cdn.cypress.io/beta/binary/3.8.0/win32-ia32/appveyor-develop-994ab326a0ed42589f0205a366a508d9da72bfb7-29375398/cypress.zip

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 994ab32 Dec 6, 2019

Choose a reason for hiding this comment

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

Circle has built the darwin x64 version of the Test Runner.

You can install this pre-release platform-specific build using instructions at https://on.cypress.io/installing-cypress#Install-pre-release-version.

You will need to use custom CYPRESS_INSTALL_BINARY url and install Cypress using an url instead of the version.

export CYPRESS_INSTALL_BINARY=https://cdn.cypress.io/beta/binary/3.8.0/darwin-x64/circle-develop-994ab326a0ed42589f0205a366a508d9da72bfb7-210405/cypress.zip
npm install https://cdn.cypress.io/beta/npm/3.8.0/circle-develop-994ab326a0ed42589f0205a366a508d9da72bfb7-210403/cypress.tgz

Please sign in to comment.