Merge branch 'main' into next

This commit is contained in:
fisker Cheung committed 2022-01-14 15:51:35 +08:00
commit c0fafdce78
14 files changed
+472 -270

No files matched your search

+17
View File
@@ -0,0 +1,17 @@
#### Print comments for parenthesized TS keyword types with `babel-ts` parser (#12070 by @sosukesuzuki)
<!-- prettier-ignore -->
```ts
// Input
let foo: (
// comment
never
);
// Prettier stable
Error: Comment "comment" was not printed. Please report this error!
// Prettier main
let foo: // comment
never;
```
+61 -42
View File
@@ -26,11 +26,13 @@ class Node {
if (nodes !== this[key]) {
this[key] = cloneAndUpdateNodes(nodes, this);
if (key === "attrs") {
setNonEnumerableProperties(this, {
attrMap: Object.fromEntries(
setNonEnumerableProperty(
this,
"attrMap",
Object.fromEntries(
this[key].map((attr) => [attr.fullName, attr.value])
),
});
)
);
}
}
}
@@ -45,7 +47,8 @@ class Node {
const mappedNodes = mapNodesIfChanged(nodes, (node) => node.map(fn));
if (newNode !== nodes) {
if (!newNode) {
newNode = new Node();
// @ts-expect-error
newNode = new Node({ parent: this.parent });
}
newNode._setNodes(NODES_KEY, mappedNodes);
}
@@ -58,15 +61,6 @@ class Node {
newNode[key] = this[key];
}
}
// @ts-expect-error
const { index, siblings, prev, next, parent } = this;
setNonEnumerableProperties(newNode, {
index,
siblings,
prev,
next,
parent,
});
}
return fn(newNode || this);
@@ -85,10 +79,37 @@ class Node {
}
/**
* @param {Object} [overrides]
* @param {Node} [target]
* @param {Object} [node]
*/
clone(overrides) {
return new Node(overrides ? { ...this, ...overrides } : this);
insertChildBefore(target, node) {
const newNode = new Node({ ...node, parent: this });
// @ts-expect-error
this.children.splice(this.children.indexOf(target), 0, newNode);
}
/**
* @param {Node} [child]
*/
removeChild(child) {
// @ts-expect-error
this.children.splice(this.children.indexOf(child), 1);
}
/**
* @param {Node} [target]
* @param {Object} [node]
*/
replaceChild(target, node) {
const newNode = new Node({ ...node, parent: this });
// @ts-expect-error
this.children[this.children.indexOf(target)] = newNode;
}
clone() {
return new Node(this);
}
/**
@@ -108,6 +129,24 @@ class Node {
return isNonEmptyArray(this.children) ? getLast(this.children) : null;
}
get prev() {
// @ts-expect-error
if (!this.parent) {
return null;
}
// @ts-expect-error
return this.parent.children[this.parent.children.indexOf(this) - 1];
}
get next() {
// @ts-expect-error
if (!this.parent) {
return null;
}
// @ts-expect-error
return this.parent.children[this.parent.children.indexOf(this) + 1];
}
// for element and attribute
get rawName() {
// @ts-expect-error
@@ -128,38 +167,18 @@ function mapNodesIfChanged(nodes, fn) {
function cloneAndUpdateNodes(nodes, parent) {
const siblings = nodes.map((node) =>
node instanceof Node ? node.clone() : new Node(node)
node instanceof Node ? node.clone() : new Node({ ...node, parent })
);
let prev = null;
let current = siblings[0];
let next = siblings[1] || null;
for (let index = 0; index < siblings.length; index++) {
setNonEnumerableProperties(current, {
index,
siblings,
prev,
next,
parent,
});
prev = current;
current = next;
next = siblings[index + 2] || null;
for (const sibling of siblings) {
sibling.parent = parent;
}
return siblings;
}
function setNonEnumerableProperties(obj, props) {
const descriptors = Object.fromEntries(
Object.entries(props).map(([key, value]) => [
key,
{ value, enumerable: false },
])
);
Object.defineProperties(obj, descriptors);
function setNonEnumerableProperty(obj, key, value) {
Object.defineProperty(obj, key, { value, enumerable: false });
}
module.exports = {
+1
View File
@@ -8,6 +8,7 @@ const ignoredProperties = new Set([
"endSourceSpan",
"nameSpan",
"valueSpan",
"parent",
]);
function clean(ast, newNode) {
+8 -5
View File
@@ -334,13 +334,16 @@ function _parse(text, options, parserOptions, shouldParseFrontMatter = true) {
parserOptions,
false
);
// @ts-expect-error
subAst.sourceSpan = new ParseSourceSpan(
startSpan,
// @ts-expect-error
getLast(subAst.children).sourceSpan.end
);
// @ts-expect-error
const firstText = subAst.children[0];
if (firstText.length === offset) {
/* istanbul ignore next */
/* istanbul ignore next */ // @ts-expect-error
subAst.children.shift();
} else {
firstText.sourceSpan = new ParseSourceSpan(
@@ -352,19 +355,19 @@ function _parse(text, options, parserOptions, shouldParseFrontMatter = true) {
return subAst;
};
return ast.map((node) => {
ast.walk((node) => {
if (node.type === "comment") {
const ieConditionalComment = parseIeConditionalComment(
node,
parseSubHtml
);
if (ieConditionalComment) {
return ieConditionalComment;
node.parent.replaceChild(node, ieConditionalComment);
}
}
return node;
});
return ast;
}
/**
+173 -217
View File
@@ -3,7 +3,6 @@
const {
ParseSourceSpan,
} = require("angular-html-parser/lib/compiler/src/parse_util");
const getLast = require("../utils/get-last.js");
const {
htmlTrim,
getLeadingAndTrailingHtmlWhitespace,
@@ -31,11 +30,10 @@ const PREPROCESS_PIPELINE = [
];
function preprocess(ast, options) {
const res = ast.map((node) => node);
for (const fn of PREPROCESS_PIPELINE) {
fn(res, options);
fn(ast, options);
}
return res;
return ast;
}
function removeIgnorableFirstLf(ast /*, options */) {
@@ -47,12 +45,12 @@ function removeIgnorableFirstLf(ast /*, options */) {
node.children[0].type === "text" &&
node.children[0].value[0] === "\n"
) {
const [text, ...rest] = node.children;
node.setChildren(
text.value.length === 1
? rest
: [text.clone({ value: text.value.slice(1) }), ...rest]
);
const text = node.children[0];
if (text.value.length === 1) {
node.removeChild(text);
} else {
text.value = text.value.slice(1);
}
}
});
}
@@ -73,47 +71,32 @@ function mergeIfConditionalStartEndCommentIntoElementOpeningTag(
node.firstChild.sourceSpan.start.offset === node.startSourceSpan.end.offset;
ast.walk((node) => {
if (node.children) {
const isTargetResults = node.children.map(isTarget);
if (isTargetResults.some(Boolean)) {
const newChildren = [];
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
if (isTargetResults[i + 1]) {
// ieConditionalStartComment
continue;
}
if (isTargetResults[i]) {
const ieConditionalStartComment = child.prev;
const ieConditionalEndComment = child.firstChild;
const startSourceSpan = new ParseSourceSpan(
ieConditionalStartComment.sourceSpan.start,
ieConditionalEndComment.sourceSpan.end
);
const sourceSpan = new ParseSourceSpan(
startSourceSpan.start,
child.sourceSpan.end
);
newChildren.push(
child.clone({
condition: ieConditionalStartComment.condition,
sourceSpan,
startSourceSpan,
children: child.children.slice(1),
})
);
continue;
}
newChildren.push(child);
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
if (!isTarget(child)) {
continue;
}
node.setChildren(newChildren);
const ieConditionalStartComment = child.prev;
const ieConditionalEndComment = child.firstChild;
// ieConditionalStartComment
node.removeChild(ieConditionalStartComment);
i--; // because a node was removed
const startSourceSpan = new ParseSourceSpan(
ieConditionalStartComment.sourceSpan.start,
ieConditionalEndComment.sourceSpan.end
);
const sourceSpan = new ParseSourceSpan(
startSourceSpan.start,
child.sourceSpan.end
);
child.condition = ieConditionalStartComment.condition;
child.sourceSpan = sourceSpan;
child.startSourceSpan = startSourceSpan;
child.removeChild(ieConditionalEndComment);
}
}
});
@@ -122,42 +105,31 @@ function mergeIfConditionalStartEndCommentIntoElementOpeningTag(
function mergeNodeIntoText(ast, shouldMerge, getValue) {
ast.walk((node) => {
if (node.children) {
const shouldMergeResults = node.children.map(shouldMerge);
if (shouldMergeResults.some(Boolean)) {
const newChildren = [];
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
if (child.type !== "text" && !shouldMergeResults[i]) {
newChildren.push(child);
continue;
}
const newChild =
child.type === "text"
? child
: child.clone({ type: "text", value: getValue(child) });
if (
newChildren.length === 0 ||
getLast(newChildren).type !== "text"
) {
newChildren.push(newChild);
continue;
}
const lastChild = newChildren.pop();
newChildren.push(
lastChild.clone({
value: lastChild.value + newChild.value,
sourceSpan: new ParseSourceSpan(
lastChild.sourceSpan.start,
newChild.sourceSpan.end
),
})
);
if (child.type !== "text" && !shouldMerge(child)) {
continue;
}
node.setChildren(newChildren);
if (child.type !== "text") {
child.type = "text";
child.value = getValue(child);
}
const prevChild = child.prev;
if (!prevChild || prevChild.type !== "text") {
continue;
}
prevChild.value += child.value;
prevChild.sourceSpan = new ParseSourceSpan(
prevChild.sourceSpan.start,
child.sourceSpan.end
);
node.removeChild(child);
i--; // because a node was removed
}
}
});
@@ -190,36 +162,29 @@ function mergeSimpleElementIntoText(ast /*, options */) {
node.next.type === "text";
ast.walk((node) => {
if (node.children) {
const isSimpleElementResults = node.children.map(isSimpleElement);
if (isSimpleElementResults.some(Boolean)) {
const newChildren = [];
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
if (isSimpleElementResults[i]) {
const lastChild = newChildren.pop();
const nextChild = node.children[++i];
const { isTrailingSpaceSensitive, hasTrailingSpaces } = nextChild;
newChildren.push(
lastChild.clone({
value:
lastChild.value +
`<${child.rawName}>` +
child.firstChild.value +
`</${child.rawName}>` +
nextChild.value,
sourceSpan: new ParseSourceSpan(
lastChild.sourceSpan.start,
nextChild.sourceSpan.end
),
isTrailingSpaceSensitive,
hasTrailingSpaces,
})
);
} else {
newChildren.push(child);
}
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
if (!isSimpleElement(child)) {
continue;
}
node.setChildren(newChildren);
const prevChild = child.prev;
const nextChild = child.next;
prevChild.value +=
`<${child.rawName}>` +
child.firstChild.value +
`</${child.rawName}>` +
nextChild.value;
prevChild.sourceSpan = new ParseSourceSpan(
prevChild.sourceSpan.start,
nextChild.sourceSpan.end
);
prevChild.isTrailingSpaceSensitive = nextChild.isTrailingSpaceSensitive;
prevChild.hasTrailingSpaces = nextChild.hasTrailingSpaces;
node.removeChild(child);
i--; // because a node was removed
node.removeChild(nextChild);
}
}
});
@@ -236,11 +201,8 @@ function extractInterpolation(ast, options) {
return;
}
const newChildren = [];
for (const child of node.children) {
if (child.type !== "text") {
newChildren.push(child);
continue;
}
@@ -257,7 +219,7 @@ function extractInterpolation(ast, options) {
if (i % 2 === 0) {
endSourceSpan = startSourceSpan.moveBy(value.length);
if (value.length > 0) {
newChildren.push({
node.insertChildBefore(child, {
type: "text",
value,
sourceSpan: new ParseSourceSpan(startSourceSpan, endSourceSpan),
@@ -267,7 +229,7 @@ function extractInterpolation(ast, options) {
}
endSourceSpan = startSourceSpan.moveBy(value.length + 4); // `{{` + `}}`
newChildren.push({
node.insertChildBefore(child, {
type: "interpolation",
sourceSpan: new ParseSourceSpan(startSourceSpan, endSourceSpan),
children:
@@ -285,9 +247,9 @@ function extractInterpolation(ast, options) {
],
});
}
}
node.setChildren(newChildren);
node.removeChild(child);
}
});
}
@@ -298,7 +260,6 @@ function extractInterpolation(ast, options) {
* - add `isWhitespaceSensitive`, `isIndentationSensitive` field for text nodes
* - remove insensitive whitespaces
*/
const WHITESPACE_NODE = { type: "whitespace" };
function extractWhitespaces(ast /*, options*/) {
ast.walk((node) => {
if (!node.children) {
@@ -319,94 +280,91 @@ function extractWhitespaces(ast /*, options*/) {
const isWhitespaceSensitive = isWhitespaceSensitiveNode(node);
const isIndentationSensitive = isIndentationSensitiveNode(node);
node.setChildren(
node.children
// extract whitespace nodes
.flatMap((child) => {
if (child.type !== "text" || isWhitespaceSensitive) {
return child;
if (!isWhitespaceSensitive) {
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
if (child.type !== "text") {
continue;
}
const { leadingWhitespace, text, trailingWhitespace } =
getLeadingAndTrailingHtmlWhitespace(child.value);
const prevChild = child.prev;
const nextChild = child.next;
if (!text) {
node.removeChild(child);
i--; // because a node was removed
if (leadingWhitespace || trailingWhitespace) {
if (prevChild) {
prevChild.hasTrailingSpaces = true;
}
if (nextChild) {
nextChild.hasLeadingSpaces = true;
}
}
const localChildren = [];
const { leadingWhitespace, text, trailingWhitespace } =
getLeadingAndTrailingHtmlWhitespace(child.value);
} else {
child.value = text;
child.sourceSpan = new ParseSourceSpan(
child.sourceSpan.start.moveBy(leadingWhitespace.length),
child.sourceSpan.end.moveBy(-trailingWhitespace.length)
);
if (leadingWhitespace) {
localChildren.push(WHITESPACE_NODE);
if (prevChild) {
prevChild.hasTrailingSpaces = true;
}
child.hasLeadingSpaces = true;
}
if (text) {
localChildren.push({
type: "text",
value: text,
sourceSpan: new ParseSourceSpan(
child.sourceSpan.start.moveBy(leadingWhitespace.length),
child.sourceSpan.end.moveBy(-trailingWhitespace.length)
),
});
}
if (trailingWhitespace) {
localChildren.push(WHITESPACE_NODE);
child.hasTrailingSpaces = true;
if (nextChild) {
nextChild.hasLeadingSpaces = true;
}
}
}
}
}
return localChildren;
})
// set hasLeadingSpaces/hasTrailingSpaces
.map((child, index, children) => {
if (child === WHITESPACE_NODE) {
return;
}
return {
...child,
hasLeadingSpaces: children[index - 1] === WHITESPACE_NODE,
hasTrailingSpaces: children[index + 1] === WHITESPACE_NODE,
};
})
// filter whitespace nodes
.filter(Boolean)
);
node.isWhitespaceSensitive = isWhitespaceSensitive;
node.isIndentationSensitive = isIndentationSensitive;
});
}
function addIsSelfClosing(ast /*, options */) {
ast.walk((node) =>
Object.assign(node, {
isSelfClosing:
!node.children ||
(node.type === "element" &&
(node.tagDefinition.isVoid ||
// self-closing
node.startSourceSpan === node.endSourceSpan)),
})
);
ast.walk((node) => {
node.isSelfClosing =
!node.children ||
(node.type === "element" &&
(node.tagDefinition.isVoid ||
// self-closing
node.startSourceSpan === node.endSourceSpan));
});
}
function addHasHtmComponentClosingTag(ast, options) {
ast.walk((node) =>
node.type !== "element"
? node
: Object.assign(node, {
hasHtmComponentClosingTag:
node.endSourceSpan &&
/^<\s*\/\s*\/\s*>$/.test(
options.originalText.slice(
node.endSourceSpan.start.offset,
node.endSourceSpan.end.offset
)
),
})
);
ast.walk((node) => {
if (node.type !== "element") {
return;
}
node.hasHtmComponentClosingTag =
node.endSourceSpan &&
/^<\s*\/\s*\/\s*>$/.test(
options.originalText.slice(
node.endSourceSpan.start.offset,
node.endSourceSpan.end.offset
)
);
});
}
function addCssDisplay(ast, options) {
ast.walk((node) =>
Object.assign(node, { cssDisplay: getNodeCssStyleDisplay(node, options) })
);
ast.walk((node) => {
node.cssDisplay = getNodeCssStyleDisplay(node, options);
});
}
/**
@@ -416,39 +374,37 @@ function addCssDisplay(ast, options) {
*/
function addIsSpaceSensitive(ast, options) {
ast.walk((node) => {
if (!node.children) {
const { children } = node;
if (!children) {
return;
}
if (node.children.length === 0) {
if (children.length === 0) {
node.isDanglingSpaceSensitive = isDanglingSpaceSensitiveNode(node);
return;
}
node.setChildren(
node.children
.map((child) => ({
...child,
isLeadingSpaceSensitive: isLeadingSpaceSensitiveNode(child, options),
isTrailingSpaceSensitive: isTrailingSpaceSensitiveNode(
child,
options
),
}))
.map((child, index, children) => ({
...child,
isLeadingSpaceSensitive:
index === 0
? child.isLeadingSpaceSensitive
: children[index - 1].isTrailingSpaceSensitive &&
child.isLeadingSpaceSensitive,
isTrailingSpaceSensitive:
index === children.length - 1
? child.isTrailingSpaceSensitive
: children[index + 1].isLeadingSpaceSensitive &&
child.isTrailingSpaceSensitive,
}))
);
for (const child of children) {
child.isLeadingSpaceSensitive = isLeadingSpaceSensitiveNode(
child,
options
);
child.isTrailingSpaceSensitive = isTrailingSpaceSensitiveNode(
child,
options
);
}
for (let index = 0; index < children.length; index++) {
const child = children[index];
child.isLeadingSpaceSensitive =
index === 0
? child.isLeadingSpaceSensitive
: child.prev.isTrailingSpaceSensitive &&
child.isLeadingSpaceSensitive;
child.isTrailingSpaceSensitive =
index === children.length - 1
? child.isTrailingSpaceSensitive
: child.next.isLeadingSpaceSensitive &&
child.isTrailingSpaceSensitive;
}
});
}
+2 -3
View File
@@ -113,12 +113,11 @@ function hasPrettierIgnore(node) {
return false;
}
if (typeof node.index !== "number" || node.index === 0) {
if (!node.prev) {
return false;
}
const prevNode = node.parent.children[node.index - 1];
return isPrettierIgnore(prevNode);
return isPrettierIgnore(node.prev);
}
function isPrettierIgnore(node) {
+9 -1
View File
@@ -3,6 +3,7 @@
const { getLast } = require("../../../common/util.js");
const { locStart, locEnd } = require("../../loc.js");
const { isTypeCastComment } = require("../../comments.js");
const { isTsKeywordType } = require("../../utils.js");
const visitNode = require("./visitNode.js");
const { throwErrorForInvalidNodes } = require("./typescript.js");
@@ -79,7 +80,14 @@ function postprocess(ast, options) {
}
// remove redundant TypeScript nodes
case "TSParenthesizedType": {
node.typeAnnotation.range = [locStart(node), locEnd(node)];
if (
!(
isTsKeywordType(node.typeAnnotation) ||
node.typeAnnotation.type === "TSThisType"
)
) {
node.typeAnnotation.range = [locStart(node), locEnd(node)];
}
return node.typeAnnotation;
}
case "TSTypeParameter":
+2 -1
View File
@@ -20,6 +20,7 @@ const {
shouldPrintComma,
isCallExpression,
isMemberExpression,
isTsKeywordType,
} = require("../utils.js");
const { locStart, locEnd } = require("../loc.js");
@@ -58,7 +59,7 @@ function printTypescript(path, options, print) {
return;
}
if (node.type.endsWith("Keyword")) {
if (isTsKeywordType(node)) {
return node.type.slice(2, -7).toLowerCase();
}
+5
View File
@@ -1322,6 +1322,10 @@ const markerForIfWithoutBlockAndSameLineComment = Symbol(
"ifWithoutBlockAndSameLineComment"
);
function isTsKeywordType({ type }) {
return type.startsWith("TS") && type.endsWith("Keyword");
}
module.exports = {
getFunctionParameters,
iterateFunctionParametersPath,
@@ -1387,4 +1391,5 @@ module.exports = {
getComments,
CommentCheckFlags,
markerForIfWithoutBlockAndSameLineComment,
isTsKeywordType,
};
+2 -1
View File
@@ -55,7 +55,8 @@ function getSortedChildNodes(node, options, resultArray) {
key !== "precedingNode" &&
key !== "followingNode" &&
key !== "tokens" &&
key !== "comments"
key !== "comments" &&
key !== "parent"
)
.map(([, value]) => value));
@@ -0,0 +1,125 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`conditional-types.ts format 1`] = `
====================================options=====================================
parsers: ["typescript"]
printWidth: 80
| printWidth
=====================================input======================================
export type UnwrappedResultRow<T> = {
[P in keyof T]: (
T[P] extends Req<infer a> ? (
a
) : (
T[P] extends Opt<infer b> ? (
b
) : (
// TEST
never
)
)
);
};
=====================================output=====================================
export type UnwrappedResultRow<T> = {
[P in keyof T]: T[P] extends Req<infer a>
? a
: T[P] extends Opt<infer b>
? b
: // TEST
never;
};
================================================================================
`;
exports[`keyword-types-with-parens-comments.ts format 1`] = `
====================================options=====================================
parsers: ["typescript"]
printWidth: 80
| printWidth
=====================================input======================================
let foo: (
// comment
any
);
let foo: (
// comment
null
);
let foo: (
// comment
this
);
let foo: (
// comment
number
);
let foo: (
// comment
void
);
let foo: (
// comment
boolean
);
let foo: (
// comment
bigint
);
let foo: (
// comment
symbol
);
let foo: (
// comment
string
);
let foo: (
// comment
never
);
let foo: (
// comment
object
);
let foo: (
// comment
undefined
);
let foo: (
// comment
unknown
);
=====================================output=====================================
let foo: // comment
any;
let foo: // comment
null;
let foo: // comment
this;
let foo: // comment
number;
let foo: // comment
void;
let foo: // comment
boolean;
let foo: // comment
bigint;
let foo: // comment
symbol;
let foo: // comment
string;
let foo: // comment
never;
let foo: // comment
object;
let foo: // comment
undefined;
let foo: // comment
unknown;
================================================================================
`;
@@ -0,0 +1,14 @@
export type UnwrappedResultRow<T> = {
[P in keyof T]: (
T[P] extends Req<infer a> ? (
a
) : (
T[P] extends Opt<infer b> ? (
b
) : (
// TEST
never
)
)
);
};
@@ -0,0 +1 @@
run_spec(__dirname, ["typescript"]);
@@ -0,0 +1,52 @@
let foo: (
// comment
any
);
let foo: (
// comment
null
);
let foo: (
// comment
this
);
let foo: (
// comment
number
);
let foo: (
// comment
void
);
let foo: (
// comment
boolean
);
let foo: (
// comment
bigint
);
let foo: (
// comment
symbol
);
let foo: (
// comment
string
);
let foo: (
// comment
never
);
let foo: (
// comment
object
);
let foo: (
// comment
undefined
);
let foo: (
// comment
unknown
);