Add getters to path object (#13448)
Co-authored-by: fisker Cheung <lionkay@gmail.com>
This commit is contained in:
1 parent
e2337dce26
commit
299503f9be
2 files changed
+93
-66
No files matched your search
+70
-21
@@ -1,35 +1,73 @@
|
||||
import getLast from "../utils/get-last.js";
|
||||
|
||||
function getNodeHelper(path, count) {
|
||||
const stackIndex = getNodeStackIndexHelper(path.stack, count);
|
||||
return stackIndex === -1 ? null : path.stack[stackIndex];
|
||||
}
|
||||
|
||||
function getNodeStackIndexHelper(stack, count) {
|
||||
for (let i = stack.length - 1; i >= 0; i -= 2) {
|
||||
const value = stack[i];
|
||||
if (value && !Array.isArray(value) && --count < 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
import { getPenultimate } from "./util.js";
|
||||
|
||||
class AstPath {
|
||||
constructor(value) {
|
||||
this.stack = [value];
|
||||
}
|
||||
|
||||
get key() {
|
||||
const { stack, siblings } = this;
|
||||
return stack[stack.length - (siblings === null ? 4 : 2)] ?? null;
|
||||
}
|
||||
|
||||
get index() {
|
||||
return this.siblings === null ? null : getPenultimate(this.stack);
|
||||
}
|
||||
|
||||
get node() {
|
||||
return getLast(this.stack);
|
||||
}
|
||||
|
||||
get parent() {
|
||||
return this.getNode(1);
|
||||
}
|
||||
|
||||
get grandparent() {
|
||||
return this.getNode(2);
|
||||
}
|
||||
|
||||
get isInArray() {
|
||||
return this.siblings !== null;
|
||||
}
|
||||
|
||||
get siblings() {
|
||||
const { stack } = this;
|
||||
const maybeArray = stack[stack.length - 3];
|
||||
return Array.isArray(maybeArray) ? maybeArray : null;
|
||||
}
|
||||
|
||||
get next() {
|
||||
return this.siblings[this.index + 1];
|
||||
}
|
||||
|
||||
get previous() {
|
||||
return this.siblings[this.index - 1];
|
||||
}
|
||||
|
||||
get isFirst() {
|
||||
return this.index === 0;
|
||||
}
|
||||
|
||||
get isLast() {
|
||||
const { siblings, index } = this;
|
||||
return siblings !== null && index === siblings.length - 1;
|
||||
}
|
||||
|
||||
get isRoot() {
|
||||
return this.stack.length === 1;
|
||||
}
|
||||
|
||||
// The name of the current property is always the penultimate element of
|
||||
// this.stack, and always a String.
|
||||
// this.stack, and always a string/number/symbol.
|
||||
getName() {
|
||||
const { stack } = this;
|
||||
const { length } = stack;
|
||||
if (length > 1) {
|
||||
return stack[length - 2];
|
||||
}
|
||||
// Since the name is always a string, null is a safe sentinel value to
|
||||
// return if we do not know the name of the (root) value.
|
||||
// Since the name is a string/number/symbol, null is a safe sentinel value
|
||||
// to return if we do not know the name of the (root) value.
|
||||
/* istanbul ignore next */
|
||||
return null;
|
||||
}
|
||||
@@ -41,11 +79,22 @@ class AstPath {
|
||||
}
|
||||
|
||||
getNode(count = 0) {
|
||||
return getNodeHelper(this, count);
|
||||
const stackIndex = this.#getNodeStackIndex(count);
|
||||
return stackIndex === -1 ? null : this.stack[stackIndex];
|
||||
}
|
||||
|
||||
getParentNode(count = 0) {
|
||||
return getNodeHelper(this, count + 1);
|
||||
return this.getNode(count + 1);
|
||||
}
|
||||
|
||||
#getNodeStackIndex(count) {
|
||||
const { stack } = this;
|
||||
for (let i = stack.length - 1; i >= 0; i -= 2) {
|
||||
if (!Array.isArray(stack[i]) && --count < 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Temporarily push properties named by string arguments given after the
|
||||
@@ -70,7 +119,7 @@ class AstPath {
|
||||
}
|
||||
|
||||
callParent(callback, count = 0) {
|
||||
const stackIndex = getNodeStackIndexHelper(this.stack, count + 1);
|
||||
const stackIndex = this.#getNodeStackIndex(count + 1);
|
||||
const parentValues = this.stack.splice(stackIndex + 1);
|
||||
try {
|
||||
return callback(this);
|
||||
|
||||
@@ -55,7 +55,7 @@ const SIBLING_NODE_TYPES = new Set([
|
||||
]);
|
||||
|
||||
function genericPrint(path, options, print) {
|
||||
const node = path.getValue();
|
||||
const { node } = path;
|
||||
|
||||
if (shouldRemainTheSameContent(path)) {
|
||||
return splitText(
|
||||
@@ -137,13 +137,11 @@ function genericPrint(path, options, print) {
|
||||
return escapedValue;
|
||||
}
|
||||
case "whitespace": {
|
||||
const parentNode = path.getParentNode();
|
||||
const index = parentNode.children.indexOf(node);
|
||||
const nextNode = parentNode.children[index + 1];
|
||||
const { next } = path;
|
||||
|
||||
const proseWrap =
|
||||
// leading char that may cause different syntax
|
||||
nextNode && /^>|^(?:[*+-]|#{1,6}|\d+[).])$/.test(nextNode.value)
|
||||
next && /^>|^(?:[*+-]|#{1,6}|\d+[).])$/.test(next.value)
|
||||
? "never"
|
||||
: options.proseWrap;
|
||||
|
||||
@@ -154,21 +152,14 @@ function genericPrint(path, options, print) {
|
||||
if (isAutolink(node.children[0])) {
|
||||
style = options.originalText[node.position.start.offset];
|
||||
} else {
|
||||
const parentNode = path.getParentNode();
|
||||
const index = parentNode.children.indexOf(node);
|
||||
const prevNode = parentNode.children[index - 1];
|
||||
const nextNode = parentNode.children[index + 1];
|
||||
const { previous, next } = path;
|
||||
const hasPrevOrNextWord = // `1*2*3` is considered emphasis but `1_2_3` is not
|
||||
(prevNode &&
|
||||
prevNode.type === "sentence" &&
|
||||
prevNode.children.length > 0 &&
|
||||
getLast(prevNode.children).type === "word" &&
|
||||
!getLast(prevNode.children).hasTrailingPunctuation) ||
|
||||
(nextNode &&
|
||||
nextNode.type === "sentence" &&
|
||||
nextNode.children.length > 0 &&
|
||||
nextNode.children[0].type === "word" &&
|
||||
!nextNode.children[0].hasLeadingPunctuation);
|
||||
(previous?.type === "sentence" &&
|
||||
getLast(previous.children)?.type === "word" &&
|
||||
!getLast(previous.children).hasTrailingPunctuation) ||
|
||||
(next?.type === "sentence" &&
|
||||
next.children[0]?.type === "word" &&
|
||||
!next.children[0].hasLeadingPunctuation);
|
||||
style =
|
||||
hasPrevOrNextWord || getAncestorNode(path, "emphasis") ? "*" : "_";
|
||||
}
|
||||
@@ -269,9 +260,9 @@ function genericPrint(path, options, print) {
|
||||
];
|
||||
}
|
||||
case "html": {
|
||||
const parentNode = path.getParentNode();
|
||||
const { parent } = path;
|
||||
const value =
|
||||
parentNode.type === "root" && getLast(parentNode.children) === node
|
||||
parent.type === "root" && getLast(parent.children) === node
|
||||
? node.value.trimEnd()
|
||||
: node.value;
|
||||
const isHtmlComment = /^<!--.*-->$/s.test(value);
|
||||
@@ -283,10 +274,7 @@ function genericPrint(path, options, print) {
|
||||
);
|
||||
}
|
||||
case "list": {
|
||||
const nthSiblingIndex = getNthListSiblingIndex(
|
||||
node,
|
||||
path.getParentNode()
|
||||
);
|
||||
const nthSiblingIndex = getNthListSiblingIndex(node, path.parent);
|
||||
|
||||
const isGitDiffFriendlyOrderedList = hasGitDiffFriendlyOrderedList(
|
||||
node,
|
||||
@@ -296,7 +284,7 @@ function genericPrint(path, options, print) {
|
||||
return printChildren(path, options, print, {
|
||||
processor: (childPath, index) => {
|
||||
const prefix = getPrefix();
|
||||
const childNode = childPath.getValue();
|
||||
const childNode = childPath.node;
|
||||
|
||||
if (
|
||||
childNode.children.length === 2 &&
|
||||
@@ -392,7 +380,6 @@ function genericPrint(path, options, print) {
|
||||
case "footnoteReference":
|
||||
return ["[^", node.identifier, "]"];
|
||||
case "footnoteDefinition": {
|
||||
const nextNode = path.getParentNode().children[path.getName() + 1];
|
||||
const shouldInlineFootnote =
|
||||
node.children.length === 1 &&
|
||||
node.children[0].type === "paragraph" &&
|
||||
@@ -414,9 +401,7 @@ function genericPrint(path, options, print) {
|
||||
index === 0 ? group([softline, print()]) : print(),
|
||||
})
|
||||
),
|
||||
nextNode && nextNode.type === "footnoteDefinition"
|
||||
? softline
|
||||
: "",
|
||||
path.next?.type === "footnoteDefinition" ? softline : "",
|
||||
]),
|
||||
];
|
||||
}
|
||||
@@ -464,13 +449,13 @@ function genericPrint(path, options, print) {
|
||||
}
|
||||
|
||||
function printListItem(path, options, print, listPrefix) {
|
||||
const node = path.getValue();
|
||||
const { node } = path;
|
||||
const prefix = node.checked === null ? "" : node.checked ? "[x] " : "[ ] ";
|
||||
return [
|
||||
prefix,
|
||||
printChildren(path, options, print, {
|
||||
processor: (childPath, index) => {
|
||||
if (index === 0 && childPath.getValue().type !== "list") {
|
||||
if (index === 0 && childPath.node.type !== "list") {
|
||||
return align(" ".repeat(prefix.length), print());
|
||||
}
|
||||
|
||||
@@ -560,7 +545,7 @@ function printLine(path, value, options) {
|
||||
}
|
||||
|
||||
function printTable(path, options, print) {
|
||||
const node = path.getValue();
|
||||
const { node } = path;
|
||||
|
||||
const columnMaxWidths = [];
|
||||
// { [rowIndex: number]: { [columnIndex: number]: {text: string, width: number} } }
|
||||
@@ -644,7 +629,7 @@ function printRoot(path, options, print) {
|
||||
/** @type {IgnorePosition | null} */
|
||||
let ignoreStart = null;
|
||||
|
||||
const { children } = path.getValue();
|
||||
const { children } = path.node;
|
||||
for (const [index, childNode] of children.entries()) {
|
||||
switch (isPrettierIgnore(childNode)) {
|
||||
case "start":
|
||||
@@ -702,13 +687,13 @@ function printChildren(path, options, print, events = {}) {
|
||||
const { postprocessor } = events;
|
||||
const processor = events.processor || (() => print());
|
||||
|
||||
const node = path.getValue();
|
||||
const { node } = path;
|
||||
const parts = [];
|
||||
|
||||
let lastChildNode;
|
||||
|
||||
path.each((childPath, index) => {
|
||||
const childNode = childPath.getValue();
|
||||
const childNode = childPath.node;
|
||||
|
||||
const result = processor(childPath, index);
|
||||
if (result !== false) {
|
||||
@@ -833,7 +818,7 @@ function shouldPrePrintDoubleHardline(node, data) {
|
||||
}
|
||||
|
||||
function shouldPrePrintTripleHardline(node, data) {
|
||||
const isPrevNodeList = data.prevNode && data.prevNode.type === "list";
|
||||
const isPrevNodeList = data.prevNode?.type === "list";
|
||||
const isIndentedCode = node.type === "code" && node.isIndented;
|
||||
|
||||
return isPrevNodeList && isIndentedCode;
|
||||
@@ -904,14 +889,7 @@ function clamp(value, min, max) {
|
||||
}
|
||||
|
||||
function hasPrettierIgnore(path) {
|
||||
const index = Number(path.getName());
|
||||
|
||||
if (index === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const prevNode = path.getParentNode().children[index - 1];
|
||||
return isPrettierIgnore(prevNode) === "next";
|
||||
return path.index > 0 && isPrettierIgnore(path.previous) === "next";
|
||||
}
|
||||
|
||||
const printer = {
|
||||
|
||||
Reference in new issue
Block a user