Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix closure compiler type casts (#5947)
* Fix closure compiler type casts This fixes casts when they are followed by a closing parenthesis, eg: ```js foo( /** @type {!Array} */(arrOrString).length ); ``` The old code would see the `CallExpresion`'s closing `)` and assume the typecast belonged to the `MemberExpression`, not the `arrOrString` `Identifier`. This would be easier to accomplish if every AST would tell us if the expression were parenthesized. If they did, we could check that the node were parenthesized and either it or an ancestor has a typecast, stopping when we find an ancestor is itself parenthesized. * More tests, and changelog * Fix while loop * Update changelog * Update CHANGELOG.unreleased.md * Use babel's parenthesized information * Cleanup call
- Loading branch information
1 parent
ed15b6d
commit c085aeb
Showing
6 changed files
with
175 additions
and
123 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
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
132 changes: 132 additions & 0 deletions
132
tests/comments_closure_typecast/__snapshots__/jsfmt.spec.js.snap
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,132 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`closure-compiler-type-cast.js 1`] = ` | ||
====================================options===================================== | ||
parsers: ["babel"] | ||
printWidth: 80 | ||
| printWidth | ||
=====================================input====================================== | ||
// test to make sure comments are attached correctly | ||
let inlineComment = /* some comment */ ( | ||
someReallyLongFunctionCall(withLots, ofArguments)); | ||
let object = { | ||
key: /* some comment */ (someReallyLongFunctionCall(withLots, ofArguments)) | ||
}; | ||
// preserve parens only for type casts | ||
let assignment = /** @type {string} */ (getValue()); | ||
let value = /** @type {string} */ (this.members[0]).functionCall(); | ||
functionCall(1 + /** @type {string} */ (value), /** @type {!Foo} */ ({})); | ||
function returnValue() { | ||
return /** @type {!Array.<string>} */ (['hello', 'you']); | ||
} | ||
// Only numberOrString is typecast | ||
var newArray = /** @type {array} */ (numberOrString).map(x => x); | ||
var newArray = /** @type {array} */ ((numberOrString)).map(x => x); | ||
var newArray = test(/** @type {array} */ (numberOrString).map(x => x)); | ||
var newArray = test(/** @type {array} */ ((numberOrString)).map(x => x)); | ||
// The numberOrString.map CallExpression is typecast | ||
var newArray = /** @type {array} */ (numberOrString.map(x => x)); | ||
var newArray = /** @type {array} */ ((numberOrString).map(x => x)); | ||
var newArray = test(/** @type {array} */ (numberOrString.map(x => x))); | ||
var newArray = test(/** @type {array} */ ((numberOrString).map(x => x))); | ||
test(/** @type {number} */(num) + 1); | ||
test(/** @type {!Array} */(arrOrString).length + 1); | ||
test(/** @type {!Array} */((arrOrString)).length + 1); | ||
const data = functionCall( | ||
arg1, | ||
arg2, | ||
/** @type {{height: number, width: number}} */ (arg3)); | ||
// Invalid type casts | ||
const v = /** @type {} */ (value); | ||
const v = /** @type {}} */ (value); | ||
const v = /** @type } */ (value); | ||
const v = /** @type { */ (value); | ||
const v = /** @type {{} */ (value); | ||
const style = /** @type {{ | ||
width: number, | ||
height: number, | ||
marginTop: number, | ||
marginLeft: number, | ||
marginRight: number, | ||
marginBottom: number, | ||
}} */ ({ | ||
width, | ||
height, | ||
...margins, | ||
}); | ||
=====================================output===================================== | ||
// test to make sure comments are attached correctly | ||
let inlineComment = /* some comment */ someReallyLongFunctionCall( | ||
withLots, | ||
ofArguments | ||
); | ||
let object = { | ||
key: /* some comment */ someReallyLongFunctionCall(withLots, ofArguments) | ||
}; | ||
// preserve parens only for type casts | ||
let assignment = /** @type {string} */ (getValue()); | ||
let value = /** @type {string} */ (this.members[0]).functionCall(); | ||
functionCall(1 + /** @type {string} */ (value), /** @type {!Foo} */ ({})); | ||
function returnValue() { | ||
return /** @type {!Array.<string>} */ (["hello", "you"]); | ||
} | ||
// Only numberOrString is typecast | ||
var newArray = /** @type {array} */ (numberOrString).map(x => x); | ||
var newArray = /** @type {array} */ (numberOrString).map(x => x); | ||
var newArray = test(/** @type {array} */ (numberOrString).map(x => x)); | ||
var newArray = test(/** @type {array} */ (numberOrString).map(x => x)); | ||
// The numberOrString.map CallExpression is typecast | ||
var newArray = /** @type {array} */ (numberOrString.map(x => x)); | ||
var newArray = /** @type {array} */ (numberOrString.map(x => x)); | ||
var newArray = test(/** @type {array} */ (numberOrString.map(x => x))); | ||
var newArray = test(/** @type {array} */ (numberOrString.map(x => x))); | ||
test(/** @type {number} */ (num) + 1); | ||
test(/** @type {!Array} */ (arrOrString).length + 1); | ||
test(/** @type {!Array} */ (arrOrString).length + 1); | ||
const data = functionCall( | ||
arg1, | ||
arg2, | ||
/** @type {{height: number, width: number}} */ (arg3) | ||
); | ||
// Invalid type casts | ||
const v = /** @type {} */ value; | ||
const v = /** @type {}} */ value; | ||
const v = /** @type } */ value; | ||
const v = /** @type { */ value; | ||
const v = /** @type {{} */ value; | ||
const style = /** @type {{ | ||
width: number, | ||
height: number, | ||
marginTop: number, | ||
marginLeft: number, | ||
marginRight: number, | ||
marginBottom: number, | ||
}} */ ({ | ||
width, | ||
height, | ||
...margins | ||
}); | ||
================================================================================ | ||
`; |
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 |
---|---|---|
@@ -0,0 +1 @@ | ||
run_spec(__dirname, ["babel"]); |