Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove unused MemberExpression root identifiers (#158)
In our codebase, I noticed that we had the following pattern that was not getting properly cleaned up: ```js const shapePropType = PropTypes.shape({ foo: PropTypes.string, }); const ComponentA = () => <div />; ComponentA.propTypes = { foo: shapePropType.isRequired, }; ``` The notable thing here is that inside the propTypes assignment, a MemberExpression is used instead of just an identifier. However, in our visitor for collecting nested identifiers, we special-cased Identifiers that have a MemberExpression parent to not be collected. This was to prevent the `bar` portion of `foo.bar` from being collected. However, in this case, we actually want the `foo` part of `foo.bar` to be collected for possible additional cleanup, so we need to add a little more logic to make this happen. To solve this, I added a function that takes a path and traverses up the tree until it finds the first non-MemberExpression, and then traverses down the left side of that tree until it finds the root identifier. This should be the `foo` in `foo.bar.baz`, for instance. It seems likely that there is a better more built-in Babel way to do this, but I was unable to find anything to point me in that direction so I rolled my own.
- Loading branch information
Showing
7 changed files
with
200 additions
and
2 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
var createReactClass = require('create-react-class'); | ||
|
||
var PropTypes = require('prop-types'); | ||
|
||
createReactClass({}); |
39 changes: 39 additions & 0 deletions
39
test/fixtures/variable-assignment-member-expressions/actual.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,39 @@ | ||
const shapePropType = PropTypes.shape({ | ||
foo: PropTypes.string, | ||
}); | ||
|
||
const ComponentA = () => <div />; | ||
ComponentA.propTypes = { | ||
foo: shapePropType.isRequired, | ||
}; | ||
|
||
const somePropTypes = { | ||
foo: PropTypes.string, | ||
bar: PropTypes.number, | ||
}; | ||
|
||
const ComponentB = () => <div />; | ||
ComponentB.propTypes = { | ||
foo: somePropTypes.foo.isRequired, | ||
}; | ||
|
||
const somePropTypesC = { | ||
foo: PropTypes.string, | ||
bar: PropTypes.number, | ||
}; | ||
|
||
const ComponentC = () => <div />; | ||
ComponentC.propTypes = { | ||
foo: somePropTypesC['foo'].isRequired, | ||
}; | ||
|
||
const somePropTypesD = { | ||
foo: PropTypes.string, | ||
bar: PropTypes.number, | ||
}; | ||
|
||
const ComponentD = () => <div />; | ||
const foo = { bar: 'foo' }; | ||
ComponentD.propTypes = { | ||
[foo.bar]: somePropTypesD['foo'].isRequired, | ||
}; |
21 changes: 21 additions & 0 deletions
21
test/fixtures/variable-assignment-member-expressions/expected-remove-es5.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,21 @@ | ||
"use strict"; | ||
|
||
var ComponentA = function ComponentA() { | ||
return React.createElement("div", null); | ||
}; | ||
|
||
var ComponentB = function ComponentB() { | ||
return React.createElement("div", null); | ||
}; | ||
|
||
var ComponentC = function ComponentC() { | ||
return React.createElement("div", null); | ||
}; | ||
|
||
var ComponentD = function ComponentD() { | ||
return React.createElement("div", null); | ||
}; | ||
|
||
var foo = { | ||
bar: 'foo' | ||
}; |
11 changes: 11 additions & 0 deletions
11
test/fixtures/variable-assignment-member-expressions/expected-remove-es6.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,11 @@ | ||
const ComponentA = () => <div />; | ||
|
||
const ComponentB = () => <div />; | ||
|
||
const ComponentC = () => <div />; | ||
|
||
const ComponentD = () => <div />; | ||
|
||
const foo = { | ||
bar: 'foo' | ||
}; |
50 changes: 50 additions & 0 deletions
50
test/fixtures/variable-assignment-member-expressions/expected-wrap-es5.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,50 @@ | ||
"use strict"; | ||
|
||
var shapePropType = process.env.NODE_ENV !== "production" ? PropTypes.shape({ | ||
foo: PropTypes.string | ||
}) : {};; | ||
|
||
var ComponentA = function ComponentA() { | ||
return React.createElement("div", null); | ||
}; | ||
|
||
ComponentA.propTypes = process.env.NODE_ENV !== "production" ? { | ||
foo: shapePropType.isRequired | ||
} : {}; | ||
var somePropTypes = process.env.NODE_ENV !== "production" ? { | ||
foo: PropTypes.string, | ||
bar: PropTypes.number | ||
} : {};; | ||
|
||
var ComponentB = function ComponentB() { | ||
return React.createElement("div", null); | ||
}; | ||
|
||
ComponentB.propTypes = process.env.NODE_ENV !== "production" ? { | ||
foo: somePropTypes.foo.isRequired | ||
} : {}; | ||
var somePropTypesC = process.env.NODE_ENV !== "production" ? { | ||
foo: PropTypes.string, | ||
bar: PropTypes.number | ||
} : {};; | ||
|
||
var ComponentC = function ComponentC() { | ||
return React.createElement("div", null); | ||
}; | ||
|
||
ComponentC.propTypes = process.env.NODE_ENV !== "production" ? { | ||
foo: somePropTypesC['foo'].isRequired | ||
} : {}; | ||
var somePropTypesD = process.env.NODE_ENV !== "production" ? { | ||
foo: PropTypes.string, | ||
bar: PropTypes.number | ||
} : {};; | ||
|
||
var ComponentD = function ComponentD() { | ||
return React.createElement("div", null); | ||
}; | ||
|
||
var foo = { | ||
bar: 'foo' | ||
}; | ||
ComponentD.propTypes = process.env.NODE_ENV !== "production" ? babelHelpers.defineProperty({}, foo.bar, somePropTypesD['foo'].isRequired) : {}; |
42 changes: 42 additions & 0 deletions
42
test/fixtures/variable-assignment-member-expressions/expected-wrap-es6.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,42 @@ | ||
const shapePropType = process.env.NODE_ENV !== "production" ? PropTypes.shape({ | ||
foo: PropTypes.string | ||
}) : {};; | ||
|
||
const ComponentA = () => <div />; | ||
|
||
ComponentA.propTypes = process.env.NODE_ENV !== "production" ? { | ||
foo: shapePropType.isRequired | ||
} : {}; | ||
const somePropTypes = process.env.NODE_ENV !== "production" ? { | ||
foo: PropTypes.string, | ||
bar: PropTypes.number | ||
} : {};; | ||
|
||
const ComponentB = () => <div />; | ||
|
||
ComponentB.propTypes = process.env.NODE_ENV !== "production" ? { | ||
foo: somePropTypes.foo.isRequired | ||
} : {}; | ||
const somePropTypesC = process.env.NODE_ENV !== "production" ? { | ||
foo: PropTypes.string, | ||
bar: PropTypes.number | ||
} : {};; | ||
|
||
const ComponentC = () => <div />; | ||
|
||
ComponentC.propTypes = process.env.NODE_ENV !== "production" ? { | ||
foo: somePropTypesC['foo'].isRequired | ||
} : {}; | ||
const somePropTypesD = process.env.NODE_ENV !== "production" ? { | ||
foo: PropTypes.string, | ||
bar: PropTypes.number | ||
} : {};; | ||
|
||
const ComponentD = () => <div />; | ||
|
||
const foo = { | ||
bar: 'foo' | ||
}; | ||
ComponentD.propTypes = process.env.NODE_ENV !== "production" ? { | ||
[foo.bar]: somePropTypesD['foo'].isRequired | ||
} : {}; |