JavaScript: fix edge cases in type cast comment detection regex (#5793)

Fix edge cases involving {...} ([record @type](http://usejsdoc.org/tags-type.html)) and newlines in prettier's detection code for type cast comments
This commit is contained in:
Yang Su authored and Ika committed 2019-01-30 15:24:34 +08:00
1 parent 847a78e8e9
commit 47da0804a9
4 files changed
+122 -1

No files matched your search

+17
View File
@@ -67,3 +67,20 @@ Examples:
<!-- Output (Prettier master) -->
Prix·:·32·€
```
- JavaScript: fix record type cast comment detection ([#5793] by [@yangsu])
Previously, type cast comments with record types were ignored and prettier
stripped the subsequent parens. Prettier master handles these cases correctly.
<!-- prettier-ignore -->
```js
// Input
const v = /** @type {{key: number}} */ (value);
// Output (Prettier stable)
const v = /** @type {{key: number}} */ value;
// Output (Prettier master)
const v = /** @type {{key: number}} */ (value);
```
+27 -1
View File
@@ -34,11 +34,37 @@ function hasClosureCompilerTypeCastComment(text, path, locStart, locEnd) {
comment =>
comment.leading &&
comments.isBlockComment(comment) &&
comment.value.match(/^\*\s*@type\s*{[^}]+}\s*$/) &&
isTypeCastComment(comment.value) &&
util.getNextNonSpaceNonCommentCharacter(text, comment, locEnd) === "("
)
);
}
function isTypeCastComment(comment) {
const trimmed = comment.trim();
if (!/^\*\s*@type\s*\{[^]+\}$/.test(trimmed)) {
return false;
}
let isCompletelyClosed = false;
let unpairedBracketCount = 0;
for (const char of trimmed) {
if (char === "{") {
if (isCompletelyClosed) {
return false;
}
unpairedBracketCount++;
} else if (char === "}") {
if (unpairedBracketCount === 0) {
return false;
}
unpairedBracketCount--;
if (unpairedBracketCount === 0) {
isCompletelyClosed = true;
}
}
}
return unpairedBracketCount === 0;
}
}
function needsParens(path, options) {
@@ -350,6 +350,32 @@ var newArray = /** @type {array} */ (numberOrString).map(x => x);
var newArray = /** @type {array} */ ((numberOrString)).map(x => x);
var newArray = /** @type {array} */ ((numberOrString).map(x => x));
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(
@@ -374,6 +400,32 @@ var newArray = /** @type {array} */ (numberOrString).map(x => x);
var newArray = /** @type {array} */ (numberOrString).map(x => x);
var newArray = /** @type {array} */ (numberOrString.map(x => x));
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
});
================================================================================
`;
@@ -18,3 +18,29 @@ function returnValue() {
var newArray = /** @type {array} */ (numberOrString).map(x => x);
var newArray = /** @type {array} */ ((numberOrString)).map(x => x);
var newArray = /** @type {array} */ ((numberOrString).map(x => x));
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,
});