fix(javascript): preserve parens for type casting for sub-item (#4648)

master
Ika 2018-06-11 19:50:53 +08:00 committed by GitHub
parent 61d35dd636
commit 5646573ad7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 10 deletions

View File

@ -5,19 +5,39 @@ const assert = require("assert");
const util = require("../common/util");
const comments = require("./comments");
function hasClosureCompilerTypeCastComment(text, node, locEnd) {
function hasClosureCompilerTypeCastComment(text, path, locStart, locEnd) {
// https://github.com/google/closure-compiler/wiki/Annotating-Types#type-casts
// Syntax example: var x = /** @type {string} */ (fruit);
const n = path.getValue();
return (
node.comments &&
node.comments.some(
comment =>
comment.leading &&
comments.isBlockComment(comment) &&
comment.value.match(/^\*\s*@type\s*{[^}]+}\s*$/) &&
util.getNextNonSpaceNonCommentCharacter(text, comment, locEnd) === "("
)
util.getNextNonSpaceNonCommentCharacter(text, n, locEnd) === ")" &&
(hasTypeCastComment(n) || hasAncestorTypeCastComment(0))
);
// for sub-item: /** @type {array} */ (numberOrString).map(x => x);
function hasAncestorTypeCastComment(index) {
const ancestor = path.getParentNode(index);
return ancestor &&
util.getNextNonSpaceNonCommentCharacter(text, ancestor, locEnd) !== ")" &&
/^[\s(]*$/.test(text.slice(locStart(ancestor), locStart(n)))
? hasTypeCastComment(ancestor) || hasAncestorTypeCastComment(index + 1)
: false;
}
function hasTypeCastComment(node) {
return (
node.comments &&
node.comments.some(
comment =>
comment.leading &&
comments.isBlockComment(comment) &&
comment.value.match(/^\*\s*@type\s*{[^}]+}\s*$/) &&
util.getNextNonSpaceNonCommentCharacter(text, comment, locEnd) === "("
)
);
}
}
function needsParens(path, options) {
@ -46,7 +66,8 @@ function needsParens(path, options) {
if (
hasClosureCompilerTypeCastComment(
options.originalText,
node,
path,
options.locStart,
options.locEnd
)
) {

View File

@ -151,6 +151,10 @@ functionCall(1 + /** @type {string} */ (value), /** @type {!Foo} */ ({}));
function returnValue() {
return /** @type {!Array.<string>} */ (['hello', 'you']);
}
var newArray = /** @type {array} */ (numberOrString).map(x => x);
var newArray = /** @type {array} */ ((numberOrString)).map(x => x);
var newArray = /** @type {array} */ ((numberOrString).map(x => x));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// test to make sure comments are attached correctly
let inlineComment = /* some comment */ someReallyLongFunctionCall(
@ -171,6 +175,10 @@ function returnValue() {
return /** @type {!Array.<string>} */ (["hello", "you"]);
}
var newArray = /** @type {array} */ (numberOrString).map(x => x);
var newArray = /** @type {array} */ (numberOrString).map(x => x);
var newArray = /** @type {array} */ (numberOrString.map(x => x));
`;
exports[`dangling.js 1`] = `

View File

@ -14,3 +14,7 @@ functionCall(1 + /** @type {string} */ (value), /** @type {!Foo} */ ({}));
function returnValue() {
return /** @type {!Array.<string>} */ (['hello', 'you']);
}
var newArray = /** @type {array} */ (numberOrString).map(x => x);
var newArray = /** @type {array} */ ((numberOrString)).map(x => x);
var newArray = /** @type {array} */ ((numberOrString).map(x => x));