Decaff helper jscodemods. (#5732)

* 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 d610829e957e38a6d56c19ba2219681e3f6c65ec.

* fix arrow-comment


Co-authored-by: Ben Kucera <14625260+Bkucera@users.noreply.github.com>
Co-authored-by: Zach Bloomquist <github@chary.us>
This commit is contained in:
Kukhyeon Heo
2019-12-07 07:43:20 +09:00
committed by Zach Bloomquist
parent 4a2636ddd3
commit 994ab326a0
21 changed files with 338 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
{
"parser": "espree"
}

View File

@@ -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"
}
}

View File

@@ -0,0 +1,10 @@
// Original comment
const func = (a, b) =>
// Multiline comment
// is here
{
a.works()
b.check.thisOut()
}
func()

View File

@@ -0,0 +1,10 @@
// Original comment
// Multiline comment
// is here
const func = (a, b) =>
{
a.works()
b.check.thisOut()
};
func()

View File

@@ -0,0 +1,7 @@
try {
// do something
} catch (e) {}
try {
// do something
} finally {}

View File

@@ -0,0 +1,7 @@
try {
// do something
} catch (e) {} // eslint-disable-line no-empty
try {
// do something
} finally {}

View File

@@ -0,0 +1,6 @@
let a
// Comment
if (a = c()) {
a.fix()
}

View File

@@ -0,0 +1,8 @@
let a
// Comment
a = c();
if (a) {
a.fix()
}

View File

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

View File

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

View File

@@ -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()

View File

@@ -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()

View File

@@ -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')

View File

@@ -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()
}

View File

@@ -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')
}

View File

@@ -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()
}

View File

@@ -0,0 +1,4 @@
// This file doesn't use AST because it makes things too complicated.
module.exports = (fileInfo) => {
return fileInfo.source.replace(/\/\/#/g, '//')
}

View File

@@ -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
}