-
Notifications
You must be signed in to change notification settings - Fork 290
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add codemod to transform string refs to arrow-functions
- Loading branch information
Showing
12 changed files
with
299 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
transforms/__testfixtures__/string-refs/literal-with-owner.input.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import * as React from "react"; | ||
|
||
class ParentComponent extends React.Component { | ||
render() { | ||
return ( | ||
<div ref="P" id="P"> | ||
<div ref="P_P1" id="P_P1"> | ||
<span ref="P_P1_C1" id="P_P1_C1" /> | ||
<span ref="P_P1_C2" id="P_P1_C2" /> | ||
</div> | ||
<div ref="P_OneOff" id="P_OneOff" /> | ||
</div> | ||
); | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
transforms/__testfixtures__/string-refs/literal-with-owner.output.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import * as React from "react"; | ||
|
||
class ParentComponent extends React.Component { | ||
render() { | ||
return ( | ||
<div ref={current => { | ||
this.refs['P'] = current; | ||
}} id="P"> | ||
<div ref={current => { | ||
this.refs['P_P1'] = current; | ||
}} id="P_P1"> | ||
<span ref={current => { | ||
this.refs['P_P1_C1'] = current; | ||
}} id="P_P1_C1" /> | ||
<span ref={current => { | ||
this.refs['P_P1_C2'] = current; | ||
}} id="P_P1_C2" /> | ||
</div> | ||
<div ref={current => { | ||
this.refs['P_OneOff'] = current; | ||
}} id="P_OneOff" /> | ||
</div> | ||
); | ||
} | ||
} |
3 changes: 3 additions & 0 deletions
3
transforms/__testfixtures__/string-refs/literal-without-owner.input.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import * as React from "react"; | ||
|
||
<div ref="bad" />; |
5 changes: 5 additions & 0 deletions
5
transforms/__testfixtures__/string-refs/literal-without-owner.output.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import * as React from "react"; | ||
|
||
<div ref={current => { | ||
this.refs['bad'] = current; | ||
}} />; |
19 changes: 19 additions & 0 deletions
19
transforms/__testfixtures__/string-refs/typescript/literal-with-owner.input.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import * as React from "react"; | ||
|
||
class ParentComponent extends React.Component { | ||
// Actual code probably has more accurate types. | ||
// Codemod might cause TypeScript errors but these are good errors since they reveal unsound code. | ||
refs: Record<string, any>; | ||
|
||
render() { | ||
return ( | ||
<div ref="P" id="P"> | ||
<div ref="P_P1" id="P_P1"> | ||
<span ref="P_P1_C1" id="P_P1_C1" /> | ||
<span ref="P_P1_C2" id="P_P1_C2" /> | ||
</div> | ||
<div ref="P_OneOff" id="P_OneOff" /> | ||
</div> | ||
); | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
transforms/__testfixtures__/string-refs/typescript/literal-with-owner.output.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import * as React from "react"; | ||
|
||
class ParentComponent extends React.Component { | ||
// Actual code probably has more accurate types. | ||
// Codemod might cause TypeScript errors but these are good errors since they reveal unsound code. | ||
refs: Record<string, any>; | ||
|
||
render() { | ||
return ( | ||
<div ref={current => { | ||
this.refs['P'] = current; | ||
}} id="P"> | ||
<div ref={current => { | ||
this.refs['P_P1'] = current; | ||
}} id="P_P1"> | ||
<span ref={current => { | ||
this.refs['P_P1_C1'] = current; | ||
}} id="P_P1_C1" /> | ||
<span ref={current => { | ||
this.refs['P_P1_C2'] = current; | ||
}} id="P_P1_C2" /> | ||
</div> | ||
<div ref={current => { | ||
this.refs['P_OneOff'] = current; | ||
}} id="P_OneOff" /> | ||
</div> | ||
); | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
transforms/__testfixtures__/string-refs/value-with-owner.input.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import * as React from "react"; | ||
|
||
class ParentComponent extends React.Component { | ||
render() { | ||
const refName = "P"; | ||
// Giving up. Would need to implement scope tracking. | ||
return <div ref={refName} id="P"></div>; | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
transforms/__testfixtures__/string-refs/value-with-owner.output.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import * as React from "react"; | ||
|
||
class ParentComponent extends React.Component { | ||
render() { | ||
const refName = "P"; | ||
// Giving up. Would need to implement scope tracking. | ||
return <div ref={refName} id="P"></div>; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/** | ||
* Copyright 2015-present, Facebook, Inc. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
*/ | ||
|
||
"use strict"; | ||
|
||
const flowTests = [ | ||
"literal-with-owner", | ||
"literal-without-owner", | ||
"value-with-owner", | ||
]; | ||
|
||
const typescriptTests = ["literal-with-owner"]; | ||
|
||
const defineTest = require("jscodeshift/dist/testUtils").defineTest; | ||
|
||
describe("string-refs", () => { | ||
describe("flow", () => { | ||
flowTests.forEach((test) => | ||
defineTest(__dirname, "string-refs", null, `string-refs/${test}`, { | ||
parser: "flow", | ||
}) | ||
); | ||
}); | ||
|
||
describe("typescript", () => { | ||
typescriptTests.forEach((test) => | ||
defineTest( | ||
__dirname, | ||
"string-refs", | ||
null, | ||
`string-refs/typescript/${test}`, | ||
{ parser: "tsx" } | ||
) | ||
); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/** | ||
* Copyright 2015-present, Facebook, Inc. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
*/ | ||
|
||
"use strict"; | ||
|
||
export default (file, api, options) => { | ||
const j = api.jscodeshift; | ||
|
||
const printOptions = options.printOptions || { | ||
quote: "single", | ||
trailingComma: true, | ||
}; | ||
|
||
const root = j(file.source); | ||
|
||
let hasModifications = false; | ||
|
||
root | ||
.find(j.JSXAttribute, (node) => { | ||
return node.name.name === "ref"; | ||
}) | ||
.forEach((jsxAttributePath) => { | ||
const valuePath = jsxAttributePath.get("value"); | ||
if ( | ||
// Flow parser | ||
valuePath.value.type === "Literal" || | ||
// TSX parser | ||
valuePath.value.type === "StringLiteral" | ||
) { | ||
hasModifications = true; | ||
// This might shadow existing variables. | ||
// But this should be safe since we control what identifiers we're reading in this block. | ||
// It will trigger ESLint's `no-shadow` though. | ||
// Babel has a helper to get a identifier that doesn't shadow existing vars. | ||
// Maybe JSCodeShift has such a helper as well? | ||
const currentIdentifierName = "current"; | ||
valuePath.replace( | ||
// {(current) => { this.refs[valuePath.node.value] = current }} | ||
j.jsxExpressionContainer( | ||
j.arrowFunctionExpression( | ||
[j.identifier(currentIdentifierName)], | ||
j.blockStatement([ | ||
j.expressionStatement( | ||
j.assignmentExpression( | ||
"=", | ||
j.memberExpression( | ||
j.memberExpression( | ||
j.thisExpression(), | ||
j.identifier("refs") | ||
), | ||
j.literal(valuePath.node.value) | ||
), | ||
j.identifier(currentIdentifierName) | ||
) | ||
), | ||
]) | ||
) | ||
) | ||
); | ||
} | ||
}); | ||
|
||
return hasModifications ? root.toSource(printOptions) : file.source; | ||
}; |