Skip to content

Commit

Permalink
fix(javascript): preserve parens for type casting for sub-item (#4648)
Browse files Browse the repository at this point in the history
  • Loading branch information
ikatyang committed Jun 11, 2018
1 parent 61d35dd commit 5646573
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 10 deletions.
41 changes: 31 additions & 10 deletions src/language-js/needs-parens.js
Expand Up @@ -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) {
Expand Down Expand Up @@ -46,7 +66,8 @@ function needsParens(path, options) {
if (
hasClosureCompilerTypeCastComment(
options.originalText,
node,
path,
options.locStart,
options.locEnd
)
) {
Expand Down
8 changes: 8 additions & 0 deletions tests/comments/__snapshots__/jsfmt.spec.js.snap
Expand Up @@ -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(
Expand All @@ -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`] = `
Expand Down
4 changes: 4 additions & 0 deletions tests/comments/closure-compiler-type-cast.js
Expand Up @@ -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));

0 comments on commit 5646573

Please sign in to comment.