ronantakizawa/codereview-bench huggingface dataset:
Repository: pola-rs/polars
File: crates/polars-core/src/chunked_array/logical/decimal.rs (Rust)

Code before:
    /// Converts self to a physical representation with the given precision and
    /// scale, returning the given sentinel value instead for values which don't
    /// fit in the given precision and scale. This can be useful for comparisons.
    pub fn into_phys_with_prec_scale_or_sentinel(
        &self,
        prec: usize,
        scale: usize,
        sentinel: i128,
    ) -> Int128Chunked {
        if self.precision() <= prec && self.scale() == scale {
            return self.phys.clone();
        }

        let old_s = self.scale();
        unary_elementwise(&self.phys, |x| {
            Some(dec128_rescale(x?, old_s, prec, scale).unwrap_or(sentinel))
        })
    }

    pub fn prod_reduce(&self) -> Scalar {
        let prec = DEC128_MAX_PREC;
        let scale = self.scale();

        let mut prod = i128_to_dec128(1, prec, scale).unwrap();
        for arr in self.phys.downcast_iter() {
            for v in arr.into_iter().flatten() {
                if let Some(p) = dec128_mul(prod, *v, prec, scale) {
                    prod = p;
                } else {
                    return Scalar::null(DataType::Decimal(prec, scale));
                }
            }
        }

        Scalar::new(
            DataType::Decimal(prec, scale),
            AnyValue::Decimal(prod, prec, scale),
        )
    }
}


Review comment (suggestion):
```suggestion
            for v in arr.non_null_values_iter() {
```

Code after:
    /// Converts self to a physical representation with the given precision and
    /// scale, returning the given sentinel value instead for values which don't
    /// fit in the given precision and scale. This can be useful for comparisons.
    pub fn into_phys_with_prec_scale_or_sentinel(
        &self,
        prec: usize,
        scale: usize,
        sentinel: i128,
    ) -> Int128Chunked {
        if self.precision() <= prec && self.scale() == scale {
            return self.phys.clone();
        }

        let old_s = self.scale();
        unary_elementwise(&self.phys, |x| {
            Some(dec128_rescale(x?, old_s, prec, scale).unwrap_or(sentinel))
        })
    }

    pub fn prod_reduce(&self) -> Scalar {
        let prec = DEC128_MAX_PREC;
        let scale = self.scale();

        let mut prod = i128_to_dec128(1, prec, scale).unwrap();
        for arr in self.phys.downcast_iter() {
            for v in arr.non_null_values_iter() {
                if let Some(p) = dec128_mul(prod, v, prec, scale) {
                    prod = p;
                } else {
                    return Scalar::null(DataType::Decimal(prec, scale));
                }
            }
        }

        Scalar::new(
            DataType::Decimal(prec, scale),
            AnyValue::Decimal(prod, prec, scale),
        )
    }
}
Repository: prettier/prettier
File: src/language-handlebars/printer-glimmer.js (JavaScript)

Code before:

  if (
    a.loc.start.line === b.loc.start.line &&
    a.loc.start.column < b.loc.start.column
  ) {
    return -1;
  }

  if (
    a.loc.start.line === b.loc.start.line &&
    a.loc.start.column === b.loc.start.column
  ) {
    return 0;
  }

  return 1;
}

function printStartingTag(path, print) {
  const node = path.getValue();

  const types = ["attributes", "modifiers", "comments"].filter((property) =>
    isNonEmptyArray(node[property])
  );
  const attributes = types
    .reduce((acc, type) => [...acc, ...node[type]], [])
    .sort(sortByLoc);

  for (const attributeType of types) {
    path.each((attributePath) => {
      const index = attributes.indexOf(attributePath.getValue());
      attributes.splice(index, 1, [line, print()]);
    }, attributeType);
  }

  if (isNonEmptyArray(node.blockParams)) {
    attributes.push(line, printBlockParams(node));
  }

  return ["<", node.tag, indent(attributes), printStartingTagEndMarker(node)];
}

function printChildren(path, options, print) {
  const node = path.getValue();
  const isEmpty = node.children.every((node) => isWhitespaceNode(node));
  if (options.htmlWhitespaceSensitivity === "ignore" && isEmpty) {
    return "";
  }

  return path.map((childPath, childIndex) => {
    const printedChild = print();

Review comment (suggestion):
```suggestion
    .flatMap((type) => node[type])
```

Code after:
function printStartingTag(path, print) {
  const node = path.getValue();

  const types = ["attributes", "modifiers", "comments"].filter((property) =>
    isNonEmptyArray(node[property])
  );
  const attributes = types.flatMap((type) => node[type]).sort(sortByLoc);

  for (const attributeType of types) {
    path.each((attributePath) => {
      const index = attributes.indexOf(attributePath.getValue());
      attributes.splice(index, 1, [line, print()]);
    }, attributeType);
  }

  if (isNonEmptyArray(node.blockParams)) {
    attributes.push(line, printBlockParams(node));
  }

  return ["<", node.tag, indent(attributes), printStartingTagEndMarker(node)];
}

function printChildren(path, options, print) {
  const node = path.getValue();
  const isEmpty = node.children.every((node) => isWhitespaceNode(node));
  if (options.htmlWhitespaceSensitivity === "ignore" && isEmpty) {
    return "";
  }

  return path.map((childPath, childIndex) => {
    const printedChild = print();

    if (childIndex === 0 && options.htmlWhitespaceSensitivity === "ignore") {
      return [softline, printedChild];
    }

    return printedChild;
  }, "children");
}

function printStartingTagEndMarker(node) {
  if (isVoid(node)) {
    return ifBreak([softline, "/>"], [" />", softline]);
  }

  return ifBreak([softline, ">"], ">");
}

/* MustacheStatement print helpers */

function printOpeningMustache(node) {
Repository: prettier/prettier
File: src/language-handlebars/printer-glimmer.js (JavaScript)

Code before:
  return options.originalText.slice(
    node.children.at(0).loc.start.offset,
    node.children.at(-1).loc.end.offset,
  );
}

function embed(path, options) {
  const { node } = path;

  if (node.type === "ElementNode") {
    const parser = getCssParser(node, options);

    // For now, we only support embedding CSS language (via `<style>` tags)
    if (!parser) {
      return;
    }

    return async (textToDoc, print) => {
      const content = getNodeContent(node, options);
      let isEmpty = /^\s*$/.test(content);
      let doc = "";
      if (!isEmpty) {
        doc = await textToDoc(content, {
          parser,
          __embeddedInHtml: true,
        });
        isEmpty = doc === "";
      }

      const startingTag = group(printStartingTag(path, print));
      const endingTag = ["</", node.tag, ">"];

      return group([
        startingTag,
        isEmpty ? "" : breakParent,
        indent([softline, doc]),
        softline,
        endingTag,
      ]);
    };
  }
}

const printer = {
  print,
  massageAstNode: clean,
  hasPrettierIgnore,
  getVisitorKeys,
  embed,
};


Review comment (suggestion):
I think we should check `TextNode` instead, `<style>` should not printed here.

Code after:
const PATH_EXPRESSION_FORBIDDEN_CHARACTERS = new Set(
  "!\"#%&'()*+,./;<=>@[\\]^`{|}~",
);
const PATH_EXPRESSION_FORBIDDEN_IN_FIRST_PART = new Set([
  "true",
  "false",
  "null",
  "undefined",
]);
const isPathExpressionPartNeedBrackets = (part, index) => {
  if (index === 0 && part.startsWith("@")) {
    return false;
  }

  return (
    (index !== 0 && PATH_EXPRESSION_FORBIDDEN_IN_FIRST_PART.has(part)) ||
    /\s/u.test(part) ||
    /^\d/u.test(part) ||
    Array.prototype.some.call(part, (character) =>
      PATH_EXPRESSION_FORBIDDEN_CHARACTERS.has(character),
    )
  );
};
function printPathExpression(node) {
  // check if node is a legacy path expression and leave it alone
  if (node.tail.length === 0 && node.original.includes("/")) {
    return node.original;
  }

  const parts = [node.head.original, ...node.tail];

  return parts
    .map((part, index) =>
      isPathExpressionPartNeedBrackets(part, index) ? `[${part}]` : part,
    )
    .join(".");
}

const printer = {
  print,
  massageAstNode: clean,
  hasPrettierIgnore,
  getVisitorKeys,
  embed,
};

export default printer;
Repository: prettier/prettier
File: src/utils/ast-utils.js (JavaScript)

Code before:

/**
 * @param {Node} node
 * @param {{getVisitorKeys: GetVisitorKeys, filter?: Predicate}} options
 */
function* getDescendants(node, options) {
  const queue = [node];
  for (let index = 0; index < queue.length; index++) {
    const node = queue[index];

    for (const child of getChildren(node, options)) {
      yield child;
      queue.push(child);
    }
  }
}

/**
 * @param {Node} node
 * @param {{getVisitorKeys: GetVisitorKeys}} options
 */
function isLeaf(node, options) {
  for (const _ of getChildren(node, options)) {
    return false;
  }
  return true;
}

/**
 * @param {Node} node
 * @param {{getVisitorKeys: GetVisitorKeys, predicate: Predicate}} options
 */
function hasDescendant(node, { getVisitorKeys, predicate }) {
  for (const descendant of getDescendants(node, { getVisitorKeys })) {
    if (predicate(descendant)) {
      return true;
    }
  }

  return false;
}

export { getChildren, getDescendants, hasDescendant, isLeaf };


Review comment (suggestion):
```suggestion
  return getChildren(node, options).next().done;
```

Code after:

/**
 * @param {Node} node
 * @param {{getVisitorKeys: GetVisitorKeys, filter?: Predicate}} options
 */
function* getDescendants(node, options) {
  const queue = [node];
  for (let index = 0; index < queue.length; index++) {
    const node = queue[index];

    for (const child of getChildren(node, options)) {
      yield child;
      queue.push(child);
    }
  }
}

/**
 * @param {Node} node
 * @param {{getVisitorKeys: GetVisitorKeys}} options
 */
function isLeaf(node, options) {
  return getChildren(node, options).next().done;
}

/**
 * @param {Node} node
 * @param {{getVisitorKeys: GetVisitorKeys, predicate: Predicate}} options
 */
function hasDescendant(node, { getVisitorKeys, predicate }) {
  for (const descendant of getDescendants(node, { getVisitorKeys })) {
    if (predicate(descendant)) {
      return true;
    }
  }

  return false;
}

export { getChildren, getDescendants, hasDescendant, isLeaf };
Repository: prettier/prettier
File: src/language-js/utils/index.js (JavaScript)

Code before:
  "TSLiteralType",
  "TSTemplateLiteralType",
]);
/**
 * @param {Node} node
 * @returns {boolean}
 */
function isSimpleType(node) {
  return (
    isTsKeywordType(node) ||
    isFlowKeywordType(node) ||
    isSimpleTypeAnnotation(node) ||
    ((node.type === "GenericTypeAnnotation" ||
      node.type === "TSTypeReference") &&
      !node.typeParameters)
  );
}

/**
 * @param {CallExpression} node
 * @returns {boolean}
 */
function isUnitTestSetUp(node) {
  return (
    node.callee.type === "Identifier" &&
    node.arguments.length === 1 &&
    (node.callee.name === "beforeEach" ||
      node.callee.name === "beforeAll" ||
      node.callee.name === "afterEach" ||
      node.callee.name === "afterAll")
  );
}

const testCallCalleePatterns = [
  "it",
  "it.only",
  "it.skip",
  "describe",
  "describe.only",
  "describe.skip",
  "test",
  "test.only",
  "test.skip",
  "test.step",
  "test.describe",
  "test.describe.only",
  "test.describe.parallel",
  "test.describe.parallel.only",
  "test.describe.serial",
  "test.describe.serial.only",
  "skip",

Review comment (suggestion):
`node.arguments` already checked in `isTestCall`, let's remove it, since we are not checking `node.type` here either.

Code after:
  "TSLiteralType",
  "TSTemplateLiteralType",
]);
/**
 * @param {Node} node
 * @returns {boolean}
 */
function isSimpleType(node) {
  return (
    isTsKeywordType(node) ||
    isFlowKeywordType(node) ||
    isSimpleTypeAnnotation(node) ||
    ((node.type === "GenericTypeAnnotation" ||
      node.type === "TSTypeReference") &&
      !node.typeParameters)
  );
}

/**
 * @param {*} node
 * @returns {boolean}
 */
function isUnitTestSetupIdentifier(node) {
  return (
    node.type === "Identifier" &&
    (node.name === "beforeEach" ||
      node.name === "beforeAll" ||
      node.name === "afterEach" ||
      node.name === "afterAll")
  );
}

const testCallCalleePatterns = [
  "it",
  "it.only",
  "it.skip",
  "describe",
  "describe.only",
  "describe.skip",
  "test",
  "test.only",
  "test.skip",
  "test.step",
  "test.describe",
  "test.describe.only",
  "test.describe.parallel",
  "test.describe.parallel.only",
  "test.describe.serial",
  "test.describe.serial.only",
  "skip",
  "xit",
Repository: prettier/prettier
File: src/language-js/embed/utils.js (JavaScript)

Code before:
      node.key.type === "Identifier" &&
      node.key.name === "template" &&
      name === "value",
    ...angularComponentObjectExpressionPredicates,
  );
}

function hasLeadingBlockCommentWithName(node, languageName) {
  // This checks for a leading comment that is exactly `/* GraphQL */`
  // In order to be in line with other implementations of this comment tag
  // we will not trim the comment value and we will expect exactly one space on
  // either side of the GraphQL string
  // Also see ./clean.js
  return hasComment(
    node,
    CommentCheckFlags.Block | CommentCheckFlags.Leading,
    ({ value }) => value === ` ${languageName} `,
  );
}
function hasLanguageComment({ node, parent }, languageName) {
  return (
    hasLeadingBlockCommentWithName(node, languageName) ||
    (isAsConstExpression(parent) &&
      hasLeadingBlockCommentWithName(parent, languageName)) ||
    (parent.type === "ExpressionStatement" &&
      node.type === "TemplateLiteral" &&
      hasLeadingBlockCommentWithName(parent, languageName))
  );
}

function isAsConstExpression(node) {
  return (
    node.type === "AsConstExpression" ||
    (node.type === "TSAsExpression" &&
      node.typeAnnotation.type === "TSTypeReference" &&
      node.typeAnnotation.typeName.type === "Identifier" &&
      node.typeAnnotation.typeName.name === "const")
  );
}

export {
  hasLanguageComment,
  isAngularComponentStyles,
  isAngularComponentTemplate,
  isAsConstExpression,
};


Review comment (suggestion):
```suggestion
    (parent.type === "ExpressionStatement" &&
      hasLeadingBlockCommentWithName(parent, languageName))
```

Code after:
      node.key.type === "Identifier" &&
      node.key.name === "template" &&
      name === "value",
    ...angularComponentObjectExpressionPredicates,
  );
}

function hasLeadingBlockCommentWithName(node, languageName) {
  // This checks for a leading comment that is exactly `/* GraphQL */`
  // In order to be in line with other implementations of this comment tag
  // we will not trim the comment value and we will expect exactly one space on
  // either side of the GraphQL string
  // Also see ./clean.js
  return hasComment(
    node,
    CommentCheckFlags.Block | CommentCheckFlags.Leading,
    ({ value }) => value === ` ${languageName} `,
  );
}
function hasLanguageComment({ node, parent }, languageName) {
  return (
    hasLeadingBlockCommentWithName(node, languageName) ||
    (isAsConstExpression(parent) &&
      hasLeadingBlockCommentWithName(parent, languageName)) ||
    (parent.type === "ExpressionStatement" &&
      hasLeadingBlockCommentWithName(parent, languageName))
  );
}

function isAsConstExpression(node) {
  return (
    node.type === "AsConstExpression" ||
    (node.type === "TSAsExpression" &&
      node.typeAnnotation.type === "TSTypeReference" &&
      node.typeAnnotation.typeName.type === "Identifier" &&
      node.typeAnnotation.typeName.name === "const")
  );
}

export {
  hasLanguageComment,
  isAngularComponentStyles,
  isAngularComponentTemplate,
  isAsConstExpression,
};
Repository: prettier/prettier
File: src/language-js/print/call-arguments.js (JavaScript)

Code before:
  shouldPrintComma,
} from "../utils/index.js";
import { isConciselyPrintedArray } from "./array.js";

function printCallArguments(path, options, print) {
  const { node } = path;

  const args = getCallArguments(node);
  if (args.length === 0) {
    return ["(", printDanglingComments(path, options), ")"];
  }

  // useEffect(() => { ... }, [foo, bar, baz])
  // useImperativeHandle(ref, () => { ... }, [foo, bar, baz])
  if (isReactHookCallWithDepsArray(args)) {
    const parts = ["("];
    for (let i = 0; i < args.length; i++) {
      parts.push(print(["arguments", i]));
      if (i !== args.length - 1) {
        parts.push(", ");
      }
    }
    parts.push(")");
    return parts;
  }

  let anyArgEmptyLine = false;
  const lastArgIndex = args.length - 1;
  const printedArguments = [];
  iterateCallArgumentsPath(path, ({ node: arg }, index) => {
    let argDoc = print();

    if (index === lastArgIndex) {
      // do nothing
    } else if (isNextLineEmpty(arg, options)) {
      anyArgEmptyLine = true;
      argDoc = [argDoc, ",", hardline, hardline];
    } else {
      argDoc = [argDoc, ",", line];
    }

    printedArguments.push(argDoc);
  });

  // Dynamic imports cannot have trailing commas
  const isDynamicImport =
    node.type === "ImportExpression" || node.callee.type === "Import";
  const maybeTrailingComma =
    !isDynamicImport && shouldPrintComma(options, "all") ? "," : "";

  function allArgsBrokenOut() {

Review comment (refactor):
This part can simplify to `join(..., path.map(...))`, but better to use `iterateCallArgumentsPath(...)`. 

Code after:
  shouldPrintComma,
} from "../utils/index.js";
import { isConciselyPrintedArray } from "./array.js";

function printCallArguments(path, options, print) {
  const { node } = path;

  const args = getCallArguments(node);
  if (args.length === 0) {
    return ["(", printDanglingComments(path, options), ")"];
  }

  const lastArgIndex = args.length - 1;

  // useEffect(() => { ... }, [foo, bar, baz])
  // useImperativeHandle(ref, () => { ... }, [foo, bar, baz])
  if (isReactHookCallWithDepsArray(args)) {
    const parts = ["("];
    iterateCallArgumentsPath(path, (path, index) => {
      parts.push(print());
      if (index !== lastArgIndex) {
        parts.push(", ");
      }
    });
    parts.push(")");
    return parts;
  }

  let anyArgEmptyLine = false;
  const printedArguments = [];
  iterateCallArgumentsPath(path, ({ node: arg }, index) => {
    let argDoc = print();

    if (index === lastArgIndex) {
      // do nothing
    } else if (isNextLineEmpty(arg, options)) {
      anyArgEmptyLine = true;
      argDoc = [argDoc, ",", hardline, hardline];
    } else {
      argDoc = [argDoc, ",", line];
    }

    printedArguments.push(argDoc);
  });

  // Dynamic imports cannot have trailing commas
  const isDynamicImport =
    node.type === "ImportExpression" || node.callee.type === "Import";
  const maybeTrailingComma =
    !isDynamicImport && shouldPrintComma(options, "all") ? "," : "";
Repository: prettier/prettier
File: src/language-js/print/type-annotation.js (JavaScript)

Code before:
}

/*
- `TSArrayType`
- `ArrayTypeAnnotation`
*/
function printArrayType(print) {
  return [print("elementType"), "[]"];
}

/*
- `TSTypeQuery`
- `TypeofTypeAnnotation`
*/
function printTypeQuery({ node }, print) {
  const argumentPropertyName =
    node.type === "TSTypeQuery" ? "exprName" : "argument";
  const typeArgsPropertyName =
    node.type === "TSTypeQuery" ? "typeParameters" : "typeArguments";
  return ["typeof ", print(argumentPropertyName), print(typeArgsPropertyName)];
}

function printTypePredicate(path, print) {
  const { node } = path;
  return [
    node.asserts ? "asserts " : node.kind ? `${node.kind} ` : "",
    print("parameterName"),
    node.typeAnnotation
      ? [" is ", printTypeAnnotationProperty(path, print)]
      : "",
  ];
}

export {
  printArrayType,
  printFunctionType,
  printIndexedAccessType,
  printInferType,
  printIntersectionType,
  printJSDocType,
  printNamedTupleMember,
  printOpaqueType,
  printRestType,
  printTypeAlias,
  printTypeAnnotation,
  printTypeAnnotationProperty,
  printTypePredicate,
  printTypeQuery,
  printUnionType,
  shouldHugType,
};

Review comment (suggestion):
Flow has replaced the `asserts` boolean flag with a `kind` field that will either by `null`, or be `"asserts"` or `"implies"`.

Code after:
}

/*
- `TSArrayType`
- `ArrayTypeAnnotation`
*/
function printArrayType(print) {
  return [print("elementType"), "[]"];
}

/*
- `TSTypeQuery` (TypeScript)
- `TypeofTypeAnnotation` (flow)
*/
function printTypeQuery({ node }, print) {
  const argumentPropertyName =
    node.type === "TSTypeQuery" ? "exprName" : "argument";
  const typeArgsPropertyName =
    node.type === "TSTypeQuery" ? "typeParameters" : "typeArguments";
  return ["typeof ", print(argumentPropertyName), print(typeArgsPropertyName)];
}

/*
- `TSTypePredicate` (TypeScript)
- `TypePredicate` (flow)
*/
function printTypePredicate(path, print) {
  const { node } = path;
  const prefix =
    node.type === "TSTypePredicate" && node.asserts
      ? "asserts "
      : node.type === "TypePredicate" && node.kind
        ? `${node.kind} `
        : "";
  return [
    prefix,
    print("parameterName"),
    node.typeAnnotation
      ? [" is ", printTypeAnnotationProperty(path, print)]
      : "",
  ];
}

export {
  printArrayType,
  printFunctionType,
  printIndexedAccessType,
  printInferType,
  printIntersectionType,
  printJSDocType,
  printNamedTupleMember,
Repository: prettier/prettier
File: src/language-handlebars/printer-glimmer.js (JavaScript)

Code before:
}

function printBlockParams(node) {
  return ["as |", node.blockParams.join(" "), "|"];
}

// https://handlebarsjs.com/guide/expressions.html#literal-segments
const PATH_EXPRESSION_FORBIDDEN_CHARACTERS = new Set(
  "!\"#%&'()*+,./;<=>@[\\]^`{|}~",
);
const PATH_EXPRESSION_FORBIDDEN_IN_FIRST_PART = new Set([
  "true",
  "false",
  "null",
  "undefined",
]);
const isPathExpressionPartNeedBrackets = (part, index) =>
  (index !== 0 && PATH_EXPRESSION_FORBIDDEN_IN_FIRST_PART.has(part)) ||
  /\s/.test(part) ||
  /^\d/.test(part) ||
  Array.prototype.some.call(part, (character) =>
    PATH_EXPRESSION_FORBIDDEN_CHARACTERS.has(character),
  );
function printPathExpression(node, print) {
  if (node.head.type === "AtHead") {
    return print(node.tail);
  }

  if (node.tail.length === 0 && node.original.includes("/")) {
    // check if node has data, or
    // check if node is a legacy path expression (and leave it alone)
    return node.original;
  }

  const parts = [node.head.original, ...node.tail];

  return parts
    .map((part, index) =>
      isPathExpressionPartNeedBrackets(part, index) ? `[${part}]` : part,
    )
    .join(".");
}

const printer = {
  print,
  massageAstNode: clean,
  hasPrettierIgnore,
  getVisitorKeys,
};

export default printer;

Review comment (suggestion):
```suggestion
    return join(".", [print("head"), ...node.tail]);
```

You should also add tests to confirm it work as expected.  Take https://github.com/prettier/prettier/pull/15605/files as example.

Code after:
function printBlockParams(node) {
  return ["as |", node.blockParams.join(" "), "|"];
}

// https://handlebarsjs.com/guide/expressions.html#literal-segments
const PATH_EXPRESSION_FORBIDDEN_CHARACTERS = new Set(
  "!\"#%&'()*+,./;<=>@[\\]^`{|}~",
);
const PATH_EXPRESSION_FORBIDDEN_IN_FIRST_PART = new Set([
  "true",
  "false",
  "null",
  "undefined",
]);
const isPathExpressionPartNeedBrackets = (part, index) => {
  if (index === 0 && part.startsWith("@")) {
    return false;
  }

  return (
    (index !== 0 && PATH_EXPRESSION_FORBIDDEN_IN_FIRST_PART.has(part)) ||
    /\s/.test(part) ||
    /^\d/.test(part) ||
    Array.prototype.some.call(part, (character) =>
      PATH_EXPRESSION_FORBIDDEN_CHARACTERS.has(character),
    )
  );
};
function printPathExpression(node) {
  // check if node is a legacy path expression and leave it alone
  if (node.tail.length === 0 && node.original.includes("/")) {
    return node.original;
  }

  const parts = [node.head.original, ...node.tail];

  return parts
    .map((part, index) =>
      isPathExpressionPartNeedBrackets(part, index) ? `[${part}]` : part,
    )
    .join(".");
}

const printer = {
  print,
  massageAstNode: clean,
  hasPrettierIgnore,
  getVisitorKeys,
};

export default printer;