Add getters to path object (#13448)

Co-authored-by: fisker Cheung <lionkay@gmail.com>
This commit is contained in:
Georgii Dolzhykovandfisker Cheung authored and GitHub committed 2022-09-09 21:28:14 +08:00
1 parent e2337dce26
commit 299503f9be
2 files changed
+93 -66

No files matched your search

+70 -21
View File
@@ -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);
+23 -45
View File
@@ -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 = {