ronantakizawa/codereview-bench huggingface dataset:
Repository: prettier/prettier
File: src/utils/get-string-width.js (JavaScript)

Code before:
  "\u{23CF}", // ⏏
  "\u{2640}", // ♀
  "\u{2642}", // ♂
  "\u{26A7}", // ⚧
  "\u{2716}", // ✖
  "\u{267E}", // ♾
  "\u{203C}", // ‼
  "\u{2049}", // ⁉
  "\u{2695}", // ⚕
  "\u{267B}", // ♻
  "\u{269C}", // ⚜
  "\u{2611}", // ☑
  "\u{2714}", // ✔
  "\u{2733}", // ✳
  "\u{2734}", // ✴
  "\u{2747}", // ❇
  "\u{00A9}", // ©
  "\u{00A9}", // ©
  "\u{00AE}", // ®
  "\u{2122}", // ™
  "\u{2139}", // ℹ
  "\u{25FC}", // ◼
  "\u{25FB}", // ◻
  "\u{25AA}", // ▪
  "\u{25AB}", // ▫
]);

export default getStringWidth;


Review comment (refactor):
https://github.com/prettier/prettier/actions/runs/17189754713/job/48763756908?pr=17813#step:4:340

Since bundled package contains multiple copies of this function, maybe we can reduce file size by changing  this array to a string?  

```diff
- new Set(["\u{0000}", "\u{0001}", ...])
+ new Set("\u{0000}\u{0001}...")
```

If you feel array is more readable, you can also extract to a file with name ends  with `.evaluate.js` and generate the string from array `export default [].join("")`.

Code after:
import emojiRegex from "emoji-regex";
import {
  // @ts-expect-error -- Private
  _isFullWidth as isFullWidth,
  // @ts-expect-error -- Private
  _isWide as isWide,
} from "get-east-asian-width";
import narrowEmojis from "./narrow-emojis.evaluate.js";

const notAsciiRegex = /[^\x20-\x7F]/u;
const narrowEmojisSet = new Set(narrowEmojis);

// Similar to https://github.com/sindresorhus/string-width
// We don't strip ansi, always treat ambiguous width characters as having narrow width.
/**
 * @param {string} text
 * @returns {number}
 */
function getStringWidth(text) {
  if (!text) {
    return 0;
  }

  // shortcut to avoid needless string `RegExp`s, replacements, and allocations
  if (!notAsciiRegex.test(text)) {
    return text.length;
  }

  text = text.replace(emojiRegex(), (match) =>
    narrowEmojisSet.has(match) ? " " : "  ",
  );
  let width = 0;

  // Use `Intl.Segmenter` when we drop support for Node.js v14
  // https://github.com/prettier/prettier/pull/14793#discussion_r1185840038
  // https://github.com/sindresorhus/string-width/pull/47
  for (const character of text) {
    const codePoint = character.codePointAt(0);

    // Ignore control characters
    if (codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f)) {
      continue;
    }

    // Ignore combining characters
    if (codePoint >= 0x300 && codePoint <= 0x36f) {
      continue;
    }

    // Ignore Variation Selectors
    if (codePoint >= 0xfe00 && codePoint <= 0xfe0f) {
      continue;
    }

    width += isFullWidth(codePoint) || isWide(codePoint) ? 2 : 1;
  }

  return width;
}

export default getStringWidth;
Repository: prettier/prettier
File: src/language-js/print/call-arguments.js (JavaScript)

Code before:
    } else if (isNextLineEmpty(arg, options)) {
      anyArgEmptyLine = true;
      argDoc = [argDoc, ",", hardline, hardline];
    } else {
      argDoc = [argDoc, ",", line];
    }

    printedArguments.push(argDoc);
  });

  const maybeTrailingComma =
    // Angular does not allow trailing comma
    !options.parser.startsWith("__ng_") &&
    // Dynamic imports cannot have trailing commas
    node.type !== "ImportExpression" &&
    node.type !== "TSImportType" &&
    shouldPrintComma(options, "all")
      ? ","
      : "";

  // Don't break simple import with long module name
  if (
    (node.type === "TSImportType" || node.type === "ImportExpression") &&
    args.length === 1 &&
    ((((node.type === "TSImportType" && args[0].type === "TSLiteralType") ||
      (node.type === "ImportExpression" && args[0].type === "Literal")) &&
      isStringLiteral(args[0].literal)) ||
      // TODO: Remove this when update Babel to v8
      isStringLiteral(args[0])) &&
    !hasComment(args[0])
  ) {
    return group(["(", ...printedArguments, ifBreak(maybeTrailingComma), ")"]);
  }

  function allArgsBrokenOut() {
    return group(
      ["(", indent([line, ...printedArguments]), maybeTrailingComma, line, ")"],
      { shouldBreak: true },
    );
  }

  if (
    anyArgEmptyLine ||
    (path.parent.type !== "Decorator" && isFunctionCompositionArgs(args))
  ) {
    return allArgsBrokenOut();
  }

  if (shouldExpandFirstArg(args)) {
    const tailArgs = printedArguments.slice(1);
    if (tailArgs.some(willBreak)) {

Review comment (suggestion):
I'm surprised that this works, babel uses `StringLiteral` instead of `Literal`.

Code after:
    } else if (isNextLineEmpty(arg, options)) {
      anyArgEmptyLine = true;
      argDoc = [argDoc, ",", hardline, hardline];
    } else {
      argDoc = [argDoc, ",", line];
    }

    printedArguments.push(argDoc);
  });

  // Don't break simple import with long module name
  if (
    (node.type === "TSImportType" || node.type === "ImportExpression") &&
    args.length === 1 &&
    !hasComment(args[0])
  ) {
    let source = args[0];

    // TODO: remove this once https://github.com/typescript-eslint/typescript-eslint/issues/11583 get fixed
    if (node.type === "TSImportType" && source.type === "TSLiteralType") {
      source = source.literal;
    }

    if (isStringLiteral(source)) {
      return group(["(", printedArguments, ")"]);
    }
  }

  const maybeTrailingComma =
    // Angular does not allow trailing comma
    !options.parser.startsWith("__ng_") &&
    // Dynamic imports cannot have trailing commas
    node.type !== "ImportExpression" &&
    node.type !== "TSImportType" &&
    shouldPrintComma(options, "all")
      ? ","
      : "";

  function allArgsBrokenOut() {
    return group(
      ["(", indent([line, ...printedArguments]), maybeTrailingComma, line, ")"],
      { shouldBreak: true },
    );
  }

  if (
    anyArgEmptyLine ||
    (path.parent.type !== "Decorator" && isFunctionCompositionArgs(args))
  ) {
    return allArgsBrokenOut();
  }
Repository: prettier/prettier
File: src/language-js/print/semicolon.js (JavaScript)

Code before:

  if (pathNeedsParens(path, options)) {
    return true;
  }

  if (!hasNakedLeftSide(node)) {
    return false;
  }

  return path.call(
    () => expressionNeedsASIProtection(path, options),
    ...getLeftSidePathName(node),
  );
}

function isSingleJsxExpressionStatementInMarkdown({ node, parent }, options) {
  return (
    (options.parentParser === "markdown" || options.parentParser === "mdx") &&
    node.type === "ExpressionStatement" &&
    isJsxElement(node.expression) &&
    parent.type === "Program" &&
    parent.body.length === 1
  );
}

function isSingleHTMLEventBindingExpressionStatement(
  { node, parent },
  options,
) {
  return (
    options.parser === "__html_event_binding" &&
    node.type === "ExpressionStatement" &&
    parent.type === "Program" &&
    parent.body.length === 1
  );
}

function isSingleVueEventBindingExpressionStatement({ node, parent }, options) {
  return (
    (options.parser === "__vue_event_binding" ||
      options.parser === "__vue_ts_event_binding") &&
    node.type === "ExpressionStatement" &&
    parent.type === "Program" &&
    parent.body.length === 1
  );
}

export {
  isSingleHTMLEventBindingExpressionStatement,
  isSingleJsxExpressionStatementInMarkdown,
  isSingleVueEventBindingExpressionStatement,

Review comment (suggestion):
```suggestion
function isSingleHtmlEventHandlerExpressionStatement(
```

Code after:

  if (pathNeedsParens(path, options)) {
    return true;
  }

  if (!hasNakedLeftSide(node)) {
    return false;
  }

  return path.call(
    () => expressionNeedsASIProtection(path, options),
    ...getLeftSidePathName(node),
  );
}

const isSingleExpressionStatement = ({ node, parent }) =>
  node.type === "ExpressionStatement" &&
  parent.type === "Program" &&
  parent.body.length === 1;

function isSingleJsxExpressionStatementInMarkdown(path, options) {
  return (
    (options.parentParser === "markdown" || options.parentParser === "mdx") &&
    isSingleExpressionStatement(path) &&
    isJsxElement(path.node.expression)
  );
}

function isSingleHtmlEventHandlerExpressionStatement(path, options) {
  return (
    options.__isHtmlInlineEventHandler && isSingleExpressionStatement(path)
  );
}

function isSingleVueEventBindingExpressionStatement(path, options) {
  return (
    (options.parser === "__vue_event_binding" ||
      options.parser === "__vue_ts_event_binding") &&
    isSingleExpressionStatement(path)
  );
}

export {
  isSingleHtmlEventHandlerExpressionStatement,
  isSingleJsxExpressionStatementInMarkdown,
  isSingleVueEventBindingExpressionStatement,
  shouldPrintLeadingSemicolon,
};
Repository: prettier/prettier
File: src/language-js/parse/babel.js (JavaScript)

Code before:
const babelFlow = createBabelParser({
  optionsCombinations: [
    appendPlugins(["jsx", ["flow", { all: true }], "flowComments"]),
  ],
});
const babelEstree = createBabelParser({
  optionsCombinations: babelParserOptionsCombinations.map((options) =>
    appendPlugins(["estree"], options),
  ),
});

export { babel, babelFlow as "babel-flow", babelTs as "babel-ts" };

/** @internal */
// eslint-disable-next-line simple-import-sort/exports
export {
  babelExpression as __js_expression,
  babelTSExpression as __ts_expression,
  /** for vue filter */
  babelExpression as __vue_expression,
  /** for vue filter written in TS */
  babelTSExpression as __vue_ts_expression,
  /** for vue event binding to handle semicolon */
  babel as __vue_event_binding,
  /** for html event binding to handle semicolon */
  babel as __html_event_binding,
  /** for vue event binding written in TS to handle semicolon */
  babelTs as __vue_ts_event_binding,
  /** verify that we can print this AST */
  babelEstree as __babel_estree,
};


Review comment (suggestion):
```suggestion
  babel as __html_event_handler,
```

Code after:
const babelFlow = createBabelParser({
  optionsCombinations: [
    appendPlugins(["jsx", ["flow", { all: true }], "flowComments"]),
  ],
});
const babelEstree = createBabelParser({
  optionsCombinations: babelParserOptionsCombinations.map((options) =>
    appendPlugins(["estree"], options),
  ),
});

export { babel, babelFlow as "babel-flow", babelTs as "babel-ts" };

/** @internal */
// eslint-disable-next-line simple-import-sort/exports
export {
  babelExpression as __js_expression,
  babelTSExpression as __ts_expression,
  /** for vue filter */
  babelExpression as __vue_expression,
  /** for vue filter written in TS */
  babelTSExpression as __vue_ts_expression,
  /** for vue event binding to handle semicolon */
  babel as __vue_event_binding,
  /** for vue event binding written in TS to handle semicolon */
  babelTs as __vue_ts_event_binding,
  /** verify that we can print this AST */
  babelEstree as __babel_estree,
};
Repository: prettier/prettier
File: src/utils/front-matter/clean.js (JavaScript)

Code before:
import isFrontMatter from "./is-front-matter.js";

function clean(original, cloned) {
  if (
    isFrontMatter(original) &&
    (original.language === "yaml" || original.language === "toml")
  ) {
    delete cloned.end;
    delete cloned.raw;
    delete cloned.value;
  }
}

export default clean;


Review comment (refactor):
We can extract this part as `isEmbedFrontMatter`, and use it in other languages too.

Code after:
import { isEmbedFrontMatter } from "./embed.js";

function clean(original, cloned) {
  if (isEmbedFrontMatter({ node: original })) {
    delete cloned.end;
    delete cloned.raw;
    delete cloned.value;
  }

  return cloned;
}

export default clean;
Repository: prettier/prettier
File: src/language-html/embed.js (JavaScript)

Code before:
            textToDocOptions.parser = isVueSfcWithTypescriptScript(
              path,
              options,
            )
              ? "__vue_ts_expression"
              : "__vue_expression";
          } else {
            textToDocOptions.parser = "__js_expression";
          }

          return [
            indent([line, await textToDoc(node.value, textToDocOptions)]),
            node.parent.next &&
            needsToBorrowPrevClosingTagEndMarker(node.parent.next)
              ? " "
              : line,
          ];
        };
      }
      break;

    case "attribute":
      return printAttribute(path, options);

    case "front-matter":
      return (textToDoc) => printEmbedFrontMatter(textToDoc, path);

    case "angularControlFlowBlockParameters":
      if (!embeddedAngularControlFlowBlocks.has(path.parent.name)) {
        return;
      }

      return printAngularControlFlowBlockParameters;

    case "angularLetDeclarationInitializer":
      return (textToDoc) =>
        formatAttributeValue(node.value, textToDoc, {
          parser: "__ng_binding",
          __isInHtmlAttribute: false,
        });
  }
}

export default embed;


Review comment (suggestion):
```suggestion
      return printEmbedFrontMatter;
```

Code after:
          const textToDocOptions = {
            __isInHtmlInterpolation: true, // to avoid unexpected `}}`
            __embeddedInHtml: true,
          };
          if (options.parser === "angular") {
            textToDocOptions.parser = "__ng_interpolation";
          } else if (options.parser === "vue") {
            textToDocOptions.parser = isVueSfcWithTypescriptScript(
              path,
              options,
            )
              ? "__vue_ts_expression"
              : "__vue_expression";
          } else {
            textToDocOptions.parser = "__js_expression";
          }

          return [
            indent([line, await textToDoc(node.value, textToDocOptions)]),
            node.parent.next &&
            needsToBorrowPrevClosingTagEndMarker(node.parent.next)
              ? " "
              : line,
          ];
        };
      }
      break;

    case "attribute":
      return printAttribute(path, options);

    case "angularControlFlowBlockParameters":
      if (!embeddedAngularControlFlowBlocks.has(path.parent.name)) {
        return;
      }

      return printAngularControlFlowBlockParameters;

    case "angularLetDeclarationInitializer":
      return (textToDoc) =>
        formatAttributeValue(node.value, textToDoc, {
          parser: "__ng_binding",
          __isInHtmlAttribute: false,
        });
  }
}

export default embed;
Repository: prettier/prettier
File: src/language-css/embed.js (JavaScript)

Code before:
import { hardline } from "../document/builders.js";
import {
  isFrontMatter,
  printEmbedFrontMatter,
} from "../utils/front-matter/index.js";

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

  if (isFrontMatter(node)) {
    return async (textToDoc, print) => {
      const doc = await printEmbedFrontMatter(textToDoc, print, path);
      return doc ? [doc, hardline] : undefined;
    };
  }
}

// `front-matter` only available on `css-root`
embed.getVisitorKeys = (node) =>
  node.type === "css-root" ? ["frontMatter"] : [];

export default embed;


Review comment (suggestion):
```suggestion
    return async (...args) => {
      const doc = await printEmbedFrontMatter(...args);
      return doc ? [doc, hardline] : undefined;
    };
```

Code after:
import {
  isEmbedFrontMatter,
  printEmbedFrontMatter,
} from "../utils/front-matter/index.js";

function embed(path) {
  if (isEmbedFrontMatter(path)) {
    return printEmbedFrontMatter;
  }
}

// `front-matter` only available on `css-root`
embed.getVisitorKeys = (node) =>
  node.type === "css-root" ? ["frontMatter"] : [];

export default embed;
Repository: prettier/prettier
File: src/language-css/clean.js (JavaScript)

Code before:
    delete cloned.value;
  }

  // Workaround for SCSS nested properties
  if (original.type === "selector-unknown") {
    delete cloned.value;
  }

  // Workaround for SCSS arbitrary arguments
  if (original.type === "value-comma_group") {
    const index = original.groups.findIndex(
      (node) => node.type === "value-number" && node.unit === "...",
    );

    if (index !== -1) {
      cloned.groups[index].unit = "";
      cloned.groups.splice(index + 1, 0, {
        type: "value-word",
        value: "...",
        isColor: false,
        isHex: false,
      });
    }
  }

  // We parse `@var[ foo ]` , `@var[foo]` and `var [ @foo ]` differently
  if (
    original.type === "value-comma_group" &&
    original.groups.some(
      (node) =>
        (node.type === "value-atword" &&
          (node.value.endsWith("[") || node.value.endsWith("]"))) ||
        (node.type === "value-word" &&
          (node.value.startsWith("]") || node.value.startsWith("["))),
    )
  ) {
    return {
      type: "value-atword",
      value: original.groups.map((node) => node.value).join(""),
      group: {
        open: null,
        close: null,
        groups: [],
        type: "value-paren_group",
      },
    };
  }
}

clean.ignoredProperties = ignoredProperties;


Review comment (suggestion):
```suggestion
  // We parse `@var[ foo ]` , `@var[foo]`, and `var [ @foo ]` differently
```

Yup, we use the Oxford comma.

Code after:
    delete cloned.value;
  }

  // Workaround for SCSS nested properties
  if (original.type === "selector-unknown") {
    delete cloned.value;
  }

  // Workaround for SCSS arbitrary arguments
  if (original.type === "value-comma_group") {
    const index = original.groups.findIndex(
      (node) => node.type === "value-number" && node.unit === "...",
    );

    if (index !== -1) {
      cloned.groups[index].unit = "";
      cloned.groups.splice(index + 1, 0, {
        type: "value-word",
        value: "...",
        isColor: false,
        isHex: false,
      });
    }
  }

  // We parse `@var[ foo ]`, `@var[foo]`, and `var [ @foo ]` differently
  if (
    original.type === "value-comma_group" &&
    original.groups.some(
      (node) =>
        (node.type === "value-atword" &&
          (node.value.endsWith("[") || node.value.endsWith("]"))) ||
        (node.type === "value-word" &&
          (node.value.startsWith("]") || node.value.startsWith("["))),
    )
  ) {
    return {
      type: "value-atword",
      value: original.groups.map((node) => node.value).join(""),
      group: {
        open: null,
        close: null,
        groups: [],
        type: "value-paren_group",
      },
    };
  }
}

clean.ignoredProperties = ignoredProperties;
Repository: prettier/prettier
File: src/language-handlebars/embed.js (JavaScript)

Code before:
    )
  ) {
    return;
  }

  const languageAttribute = parent.attributes.find(
    (attribute) => attribute.type === "AttrNode" && attribute.name === "lang",
  );
  if (
    languageAttribute &&
    !(
      languageAttribute.value.type === "TextNode" &&
      (languageAttribute.value.chars === "" ||
        languageAttribute.value.chars === "css")
    )
  ) {
    return;
  }

  return async (textToDoc) => {
    const doc = await textToDoc(node.chars, { parser: "css" });
    if (!doc) {
      return [];
    }

    if (options.htmlWhitespaceSensitivity === "ignore") {
      return doc;
    }

    return [hardline, doc, dedent(softline)];
  };
}

export default embed;


Review comment (bug):
Can you try remove L39 to see if there are tests fails? I think it prevent empty css been printed. But it should checked here without calling the textToDoc.

Code after:
    return;
  }

  const languageAttribute = parent.attributes.find(
    (attribute) => attribute.type === "AttrNode" && attribute.name === "lang",
  );
  if (
    languageAttribute &&
    !(
      languageAttribute.value.type === "TextNode" &&
      (languageAttribute.value.chars === "" ||
        languageAttribute.value.chars === "css")
    )
  ) {
    return;
  }

  return async (textToDoc) => {
    const context = node.chars;
    if (!context.trim()) {
      return "";
    }
    const doc = await textToDoc(context, { parser: "css" });
    return doc;
  };
}

export default embed;
Repository: prettier/prettier
File: src/language-css/utils/index.js (JavaScript)

Code before:
  );

  return (
    atRuleAncestorNode &&
    atRuleNames.includes(atRuleAncestorNode.name.toLowerCase())
  );
}

function insideURLFunctionInImportAtRuleNode(path) {
  const { node } = path;
  return (
    node.groups[0]?.value === "url" &&
    node.groups.length === 2 &&
    path.findAncestor((node) => node.type === "css-atrule")?.name === "import"
  );
}

function isURLFunctionNode(node) {
  return node.type === "value-func" && node.value.toLowerCase() === "url";
}

function isVarFunctionNode(node) {
  return node.type === "value-func" && node.value.toLowerCase() === "var";
}

function isMathOrCustomFunctionNode(node) {
  return (
    node.type === "value-func" &&
    (node.value.toLowerCase() === "var" ||
      node.value.toLowerCase() === "calc" ||
      node.value.toLowerCase() === "min" ||
      node.value.toLowerCase() === "max" ||
      node.value.toLowerCase() === "clamp" ||
      node.value.startsWith("--"))
  );
}

function isDetachedRulesetDeclarationNode(node) {
  const { selector } = node;
  // If a Less file ends up being parsed with the SCSS parser, Less
  // variable declarations will be parsed as atrules with names ending
  // with a colon, so keep the original case then.
  /* c8 ignore next 3 */
  if (!selector) {
    return false;
  }

  return (
    (typeof selector === "string" && /^@.+:.*$/u.test(selector)) ||
    (selector.value && /^@.+:.*$/u.test(selector.value))
  );

Review comment (refactor):
```js
function isPossibleFontSize(node) {
```

Please move this function to where it's used.

Code after:
  );

  return (
    atRuleAncestorNode &&
    atRuleNames.includes(atRuleAncestorNode.name.toLowerCase())
  );
}

function insideURLFunctionInImportAtRuleNode(path) {
  const { node } = path;
  return (
    node.groups[0]?.value === "url" &&
    node.groups.length === 2 &&
    path.findAncestor((node) => node.type === "css-atrule")?.name === "import"
  );
}

function isURLFunctionNode(node) {
  return node.type === "value-func" && node.value.toLowerCase() === "url";
}

function isVarFunctionNode(node) {
  return node.type === "value-func" && node.value.toLowerCase() === "var";
}

function isDetachedRulesetDeclarationNode(node) {
  const { selector } = node;
  // If a Less file ends up being parsed with the SCSS parser, Less
  // variable declarations will be parsed as atrules with names ending
  // with a colon, so keep the original case then.
  /* c8 ignore next 3 */
  if (!selector) {
    return false;
  }

  return (
    (typeof selector === "string" && /^@.+:.*$/u.test(selector)) ||
    (selector.value && /^@.+:.*$/u.test(selector.value))
  );
}

function isForKeywordNode(node) {
  return (
    node.type === "value-word" &&
    ["from", "through", "end"].includes(node.value)
  );
}

function isIfElseKeywordNode(node) {
  return (
    node.type === "value-word" && ["and", "or", "not"].includes(node.value)