ronantakizawa/codereview-bench huggingface dataset:
Repository: chartjs/Chart.js
File: src/helpers/helpers.dom.ts (TypeScript)

Code before:
import {ChartEvent} from '../types';
import {INFINITY} from './helpers.math';
import {ChartArea, Scale, type Chart} from '../../types';

/**
 * Note: typedefs are auto-exported, so use a made-up `dom` namespace where
 * necessary to avoid duplicates with `export * from './helpers`; see
 * https://github.com/microsoft/TypeScript/issues/46011
 * @typedef { import("../core/core.controller").default } dom.Chart
 * @typedef { import('../../types').ChartEvent } ChartEvent
 */

/**
 * @private
 */
export function _isDomSupported(): boolean {
  return typeof window !== 'undefined' && typeof document !== 'undefined';
}

/**
 * @private
 */
export function _getParentNode(domNode: HTMLCanvasElement): HTMLCanvasElement {
  let parent = domNode.parentNode;
  if (parent && parent.toString() === '[object ShadowRoot]') {
    parent = (parent as ShadowRoot).host;
  }
  return parent as HTMLCanvasElement;

Review comment (suggestion):
is the `type` here necesarry? Since you are already importing it from the types I would think TS already knows its a type

Code after:
import {ChartArea, Scale} from '../../types';
import Chart from '../core/core.controller';
import {ChartEvent} from '../types';
import {INFINITY} from './helpers.math';

/**
 * Note: typedefs are auto-exported, so use a made-up `dom` namespace where
 * necessary to avoid duplicates with `export * from './helpers`; see
 * https://github.com/microsoft/TypeScript/issues/46011
 * @typedef { import("../core/core.controller").default } dom.Chart
 * @typedef { import('../../types').ChartEvent } ChartEvent
 */

/**
 * @private
 */
export function _isDomSupported(): boolean {
  return typeof window !== 'undefined' && typeof document !== 'undefined';
}

/**
 * @private
 */
export function _getParentNode(domNode: HTMLCanvasElement): HTMLCanvasElement {
  let parent = domNode.parentNode;
  if (parent && parent.toString() === '[object ShadowRoot]') {
    parent = (parent as ShadowRoot).host;
  }
Repository: chartjs/Chart.js
File: src/helpers/helpers.dom.ts (TypeScript)

Code before:
    const pos = positions[i];
    result[pos] = parseFloat(styles[style + '-' + pos + suffix]) || 0;
  }
  result.width = result.left + result.right;
  result.height = result.top + result.bottom;
  return result;
}

const useOffsetPos = (x: number, y: number, target: HTMLElement | EventTarget) =>
  (x > 0 || y > 0) && (!target || !(target as HTMLElement).shadowRoot);

/**
 * @param {Event} e
 * @param {HTMLCanvasElement} canvas
 * @returns {{x: number, y: number, box: boolean}}
 */
function getCanvasPosition(
  e: Event | TouchEvent | MouseEvent,
  canvas: HTMLCanvasElement
): {
    x: number;
    y: number;
    box: boolean;
  } {
  const touches = (e as TouchEvent).touches;
  const source = touches && touches.length ? touches[0] : e;
  const {offsetX, offsetY} = source as MouseEvent;
  let box = false;
  let x, y;
  if (useOffsetPos(offsetX, offsetY, e.target)) {
    x = offsetX;
    y = offsetY;
  } else {
    const rect = canvas.getBoundingClientRect();
    x = (source as MouseEvent).clientX - rect.left;
    y = (source as MouseEvent).clientY - rect.top;
    box = true;
  }
  return {x, y, box};
}

/**
 * Gets an event's x, y coordinates, relative to the chart area
 * @param {Event|ChartEvent} evt
 * @param {dom.Chart} chart
 * @returns {{x: number, y: number}}
 */

export function getRelativePosition(
  evt: Event | ChartEvent,
  chart: Chart

Review comment (suggestion):
maybe better to cast type once
```suggestion
  const source = (touches && touches.length ? touches[0] : e) as MouseEvent;
```

Code after:
  for (let i = 0; i < 4; i++) {
    const pos = positions[i];
    result[pos] = parseFloat(styles[style + '-' + pos + suffix]) || 0;
  }
  result.width = result.left + result.right;
  result.height = result.top + result.bottom;
  return result;
}

const useOffsetPos = (x: number, y: number, target: HTMLElement | EventTarget) =>
  (x > 0 || y > 0) && (!target || !(target as HTMLElement).shadowRoot);

/**
 * @param e
 * @param canvas
 * @returns Canvas position
 */
function getCanvasPosition(
  e: Event | TouchEvent | MouseEvent,
  canvas: HTMLCanvasElement
): {
    x: number;
    y: number;
    box: boolean;
  } {
  const touches = (e as TouchEvent).touches;
  const source = (touches && touches.length ? touches[0] : e) as MouseEvent;
  const {offsetX, offsetY} = source as MouseEvent;
  let box = false;
  let x, y;
  if (useOffsetPos(offsetX, offsetY, e.target)) {
    x = offsetX;
    y = offsetY;
  } else {
    const rect = canvas.getBoundingClientRect();
    x = source.clientX - rect.left;
    y = source.clientY - rect.top;
    box = true;
  }
  return {x, y, box};
}

/**
 * Gets an event's x, y coordinates, relative to the chart area
 * @param event
 * @param chart
 * @returns x and y coordinates of the event
 */

export function getRelativePosition(
  event: Event | ChartEvent | TouchEvent | MouseEvent,
Repository: chartjs/Chart.js
File: src/helpers/helpers.dom.ts (TypeScript)

Code before:
    x: number;
    y: number;
    box: boolean;
  } {
  const touches = (e as TouchEvent).touches;
  const source = (touches && touches.length ? touches[0] : e) as MouseEvent;
  const {offsetX, offsetY} = source as MouseEvent;
  let box = false;
  let x, y;
  if (useOffsetPos(offsetX, offsetY, e.target)) {
    x = offsetX;
    y = offsetY;
  } else {
    const rect = canvas.getBoundingClientRect();
    x = source.clientX - rect.left;
    y = source.clientY - rect.top;
    box = true;
  }
  return {x, y, box};
}

/**
 * Gets an event's x, y coordinates, relative to the chart area
 * @param {Event|ChartEvent} evt
 * @param {Chart} chart
 * @returns {{x: number, y: number}}
 */

export function getRelativePosition(
  evt: Event | ChartEvent,
  chart: Chart
): { x: number; y: number } {
  if ('native' in evt) {
    return evt;
  }

  const {canvas, currentDevicePixelRatio} = chart;
  const style = getComputedStyle(canvas);
  const borderBox = style.boxSizing === 'border-box';
  const paddings = getPositionedStyle(style, 'padding');
  const borders = getPositionedStyle(style, 'border', 'width');
  const {x, y, box} = getCanvasPosition(evt, canvas);
  const xOffset = paddings.left + (box && borders.left);
  const yOffset = paddings.top + (box && borders.top);

  let {width, height} = chart;
  if (borderBox) {
    width -= paddings.width + borders.width;
    height -= paddings.height + borders.height;
  }
  return {

Review comment (suggestion):
now we should remove all type annotations from jsdoc (so it becomes tsdoc)

Code after:
): {
    x: number;
    y: number;
    box: boolean;
  } {
  const touches = (e as TouchEvent).touches;
  const source = (touches && touches.length ? touches[0] : e) as MouseEvent;
  const {offsetX, offsetY} = source as MouseEvent;
  let box = false;
  let x, y;
  if (useOffsetPos(offsetX, offsetY, e.target)) {
    x = offsetX;
    y = offsetY;
  } else {
    const rect = canvas.getBoundingClientRect();
    x = source.clientX - rect.left;
    y = source.clientY - rect.top;
    box = true;
  }
  return {x, y, box};
}

/**
 * Gets an event's x, y coordinates, relative to the chart area
 * @param event
 * @param chart
 * @returns x and y coordinates of the event
 */

export function getRelativePosition(
  event: Event | ChartEvent | TouchEvent | MouseEvent,
  chart: Chart
): { x: number; y: number } {
  if ('native' in event) {
    return event;
  }

  const {canvas, currentDevicePixelRatio} = chart;
  const style = getComputedStyle(canvas);
  const borderBox = style.boxSizing === 'border-box';
  const paddings = getPositionedStyle(style, 'padding');
  const borders = getPositionedStyle(style, 'border', 'width');
  const {x, y, box} = getCanvasPosition(event, canvas);
  const xOffset = paddings.left + (box && borders.left);
  const yOffset = paddings.top + (box && borders.top);

  let {width, height} = chart;
  if (borderBox) {
    width -= paddings.width + borders.width;
    height -= paddings.height + borders.height;
  }
Repository: chartjs/Chart.js
File: src/helpers/helpers.dom.ts (TypeScript)

Code before:
import {ChartArea, Scale} from '../../types';
import Chart from '../core/core.controller';
import {ChartEvent} from '../types';
import {INFINITY} from './helpers.math';
/**
 * Note: typedefs are auto-exported, so use a made-up `dom` namespace where
 * necessary to avoid duplicates with `export * from './helpers`; see
 * https://github.com/microsoft/TypeScript/issues/46011
 * @typedef { import("../core/core.controller").default } dom.Chart
 * @typedef { import('../../types').ChartEvent } ChartEvent
 */

/**
 * @private
 */
export function _isDomSupported(): boolean {
  return typeof window !== 'undefined' && typeof document !== 'undefined';
}

/**
 * @private
 */
export function _getParentNode(domNode: HTMLCanvasElement): HTMLCanvasElement {
  let parent = domNode.parentNode;
  if (parent && parent.toString() === '[object ShadowRoot]') {
    parent = (parent as ShadowRoot).host;
  }

Review comment (suggestion):
(nit) IMO its good practice (and is used in this repository) to have an empty line between the imports and other code/comments. So I'd keep this line

Code after:
import {ChartArea, Scale} from '../../types';
import Chart from '../core/core.controller';
import {ChartEvent} from '../types';
import {INFINITY} from './helpers.math';

/**
 * Note: typedefs are auto-exported, so use a made-up `dom` namespace where
 * necessary to avoid duplicates with `export * from './helpers`; see
 * https://github.com/microsoft/TypeScript/issues/46011
 * @typedef { import("../core/core.controller").default } dom.Chart
 * @typedef { import('../../types').ChartEvent } ChartEvent
 */

/**
 * @private
 */
export function _isDomSupported(): boolean {
  return typeof window !== 'undefined' && typeof document !== 'undefined';
}

/**
 * @private
 */
export function _getParentNode(domNode: HTMLCanvasElement): HTMLCanvasElement {
  let parent = domNode.parentNode;
  if (parent && parent.toString() === '[object ShadowRoot]') {
    parent = (parent as ShadowRoot).host;
Repository: chartjs/Chart.js
File: src/helpers/helpers.options.ts (TypeScript)

Code before:
import defaults from '../core/core.defaults';
import {isArray, isObject, toDimension, valueOrDefault} from './helpers.core';
import {toFontString} from './helpers.canvas';
import {ArcBorderRadius, FontSpec} from '../../types';
import {ChartArea, TRBL, TRBLCorners} from '../../types/geometric';

const LINE_HEIGHT = new RegExp(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);
const FONT_STYLE = new RegExp(/^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/);

/**
 * @alias Chart.helpers.options
 * @namespace
 */
/**
 * Converts the given line height `value` in pixels for a specific font `size`.
 * @param value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em').
 * @param size - The font size (in pixels) used to resolve relative `value`.
 * @returns The effective line height in pixels (size * 1.2 if value is invalid).
 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
 * @since 2.7.0
 */
export function toLineHeight(value: number | string, size: number): number {
  const matches = ('' + value).match(LINE_HEIGHT);
  if (!matches || matches[1] === 'normal') {
    return size * 1.2;
  }

  value = +matches[2];

  switch (matches[3]) {

Review comment (suggestion):
```suggestion
import type {ArcBorderRadius, FontSpec} from '../../types';
import type {ChartArea, TRBL, TRBLCorners} from '../../types/geometric';
```

Code after:
import defaults from '../core/core.defaults';
import {isArray, isObject, toDimension, valueOrDefault} from './helpers.core';
import {Point, toFontString} from './helpers.canvas';
import type {ChartArea, FontSpec} from '../../types';
import type {TRBL, TRBLCorners} from '../../types/geometric';

const LINE_HEIGHT = /^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/;
const FONT_STYLE = /^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/;

/**
 * @alias Chart.helpers.options
 * @namespace
 */
/**
 * Converts the given line height `value` in pixels for a specific font `size`.
 * @param value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em').
 * @param size - The font size (in pixels) used to resolve relative `value`.
 * @returns The effective line height in pixels (size * 1.2 if value is invalid).
 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
 * @since 2.7.0
 */
export function toLineHeight(value: number | string, size: number): number {
  const matches = ('' + value).match(LINE_HEIGHT);
  if (!matches || matches[1] === 'normal') {
    return size * 1.2;
  }

  value = +matches[2];

  switch (matches[3]) {
Repository: chartjs/Chart.js
File: src/helpers/helpers.options.ts (TypeScript)

Code before:
import defaults from '../core/core.defaults';
import {isArray, isObject, toDimension, valueOrDefault} from './helpers.core';
import {Point, toFontString} from './helpers.canvas';
import type {ChartArea, FontSpec} from '../../types';
import type {TRBL, TRBLCorners} from '../../types/geometric';

const LINE_HEIGHT = new RegExp(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);
const FONT_STYLE = new RegExp(/^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/);

/**
 * @alias Chart.helpers.options
 * @namespace
 */
/**
 * Converts the given line height `value` in pixels for a specific font `size`.
 * @param value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em').
 * @param size - The font size (in pixels) used to resolve relative `value`.
 * @returns The effective line height in pixels (size * 1.2 if value is invalid).
 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
 * @since 2.7.0
 */
export function toLineHeight(value: number | string, size: number): number {
  const matches = ('' + value).match(LINE_HEIGHT);
  if (!matches || matches[1] === 'normal') {
    return size * 1.2;
  }

  value = +matches[2];

  switch (matches[3]) {
    case 'px':
      return value;
    case '%':

Review comment (suggestion):
nit

```suggestion
const LINE_HEIGHT = /^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/;
const FONT_STYLE = /^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/;
```

Code after:
import defaults from '../core/core.defaults';
import {isArray, isObject, toDimension, valueOrDefault} from './helpers.core';
import {Point, toFontString} from './helpers.canvas';
import type {ChartArea, FontSpec} from '../../types';
import type {TRBL, TRBLCorners} from '../../types/geometric';

const LINE_HEIGHT = /^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/;
const FONT_STYLE = /^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/;

/**
 * @alias Chart.helpers.options
 * @namespace
 */
/**
 * Converts the given line height `value` in pixels for a specific font `size`.
 * @param value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em').
 * @param size - The font size (in pixels) used to resolve relative `value`.
 * @returns The effective line height in pixels (size * 1.2 if value is invalid).
 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
 * @since 2.7.0
 */
export function toLineHeight(value: number | string, size: number): number {
  const matches = ('' + value).match(LINE_HEIGHT);
  if (!matches || matches[1] === 'normal') {
    return size * 1.2;
  }

  value = +matches[2];

  switch (matches[3]) {
    case 'px':
      return value;
    case '%':
Repository: chartjs/Chart.js
File: src/helpers/helpers.options.ts (TypeScript)

Code before:
 * @returns The effective line height in pixels (size * 1.2 if value is invalid).
 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
 * @since 2.7.0
 */
export function toLineHeight(value: number | string, size: number): number {
  const matches = ('' + value).match(LINE_HEIGHT);
  if (!matches || matches[1] === 'normal') {
    return size * 1.2;
  }

  value = +matches[2];

  switch (matches[3]) {
    case 'px':
      return value;
    case '%':
      value /= 100;
      break;
    default:
      break;
  }

  return size * value;
}

const numberOrZero = (v: number) => +v || 0;

/**
 * @param value
 * @param props
 */
export function _readValueToProps<K extends string>(value: number | Record<K, number>, props: K[]): Record<K, number>;
export function _readValueToProps<K extends string, T extends string>(value: number | Record<K & T, number>, props: Record<T, K>): Record<T, number>;
export function _readValueToProps(value: number | Record<string, number>, props: string[] | Record<string, string>) {
  const ret = {};
  const objProps = isObject(props);
  const keys = objProps ? Object.keys(props) : props;
  const read = isObject(value)
    ? objProps
      ? prop => valueOrDefault(value[prop], value[props[prop]])
      : prop => value[prop]
    : () => value;

  for (const prop of keys) {
    ret[prop] = numberOrZero(read(prop));
  }
  return ret;
}

/**
 * Converts the given value into a TRBL object.

Review comment (suggestion):
```suggestion
const numberOrZero = (v: unknown) => +v || 0;
```

Code after:
 * @returns The effective line height in pixels (size * 1.2 if value is invalid).
 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
 * @since 2.7.0
 */
export function toLineHeight(value: number | string, size: number): number {
  const matches = ('' + value).match(LINE_HEIGHT);
  if (!matches || matches[1] === 'normal') {
    return size * 1.2;
  }

  value = +matches[2];

  switch (matches[3]) {
    case 'px':
      return value;
    case '%':
      value /= 100;
      break;
    default:
      break;
  }

  return size * value;
}

const numberOrZero = (v: unknown) => +v || 0;

/**
 * @param value
 * @param props
 */
export function _readValueToProps<K extends string>(value: number | Record<K, number>, props: K[]): Record<K, number>;
export function _readValueToProps<K extends string, T extends string>(value: number | Record<K & T, number>, props: Record<T, K>): Record<T, number>;
export function _readValueToProps(value: number | Record<string, number>, props: string[] | Record<string, string>) {
  const ret = {};
  const objProps = isObject(props);
  const keys = objProps ? Object.keys(props) : props;
  const read = isObject(value)
    ? objProps
      ? prop => valueOrDefault(value[prop], value[props[prop]])
      : prop => value[prop]
    : () => value;

  for (const prop of keys) {
    ret[prop] = numberOrZero(read(prop));
  }
  return ret;
}

/**
 * Converts the given value into a TRBL object.
Repository: chartjs/Chart.js
File: test/fixtures/core.scale/tick-backdrop.js (JavaScript)

Code before:
            crossAlign: 'far',
          },
          grid,
          title
        },
        right: {
          type: 'linear',
          position: 'right',
          ticks: {
            display: true,
            showLabelBackdrop: true,
            backdropColor: 'gray',
            backdropPadding: 5,
          },
          grid,
          title
        },
      }
    }
  },
  options: {
    canvas: {
      height: 256,
      width: 256
    },
    spriteText: false,
  }
};


Review comment (bug):
This is likely the cause of test failures. We should always `spriteText: true` to account for browser differences

Code after:
            crossAlign: 'far',
          },
          grid,
          title
        },
        right: {
          type: 'linear',
          position: 'right',
          ticks: {
            display: true,
            showLabelBackdrop: true,
            backdropColor: 'gray',
            backdropPadding: 5,
          },
          grid,
          title
        },
      }
    }
  },
  options: {
    canvas: {
      height: 256,
      width: 256
    },
    spriteText: true,
  }
};
Repository: chartjs/Chart.js
File: src/elements/element.arc.ts (TypeScript)

Code before:
import Element from '../core/core.element';
import {_angleBetween, getAngleFromPoint, TAU, HALF_PI, valueOrDefault} from '../helpers/index';
import {PI, _isBetween, _limitValue} from '../helpers/helpers.math';
import {_readValueToProps} from '../helpers/helpers.options';
import {type ArcOptions, type Point} from '../../types';


function clipArc(ctx: CanvasRenderingContext2D, element: ArcElement, endAngle: number) {
  const {startAngle, pixelMargin, x, y, outerRadius, innerRadius} = element;
  let angleMargin = pixelMargin / outerRadius;

  // Draw an inner border by clipping the arc and drawing a double-width border
  // Enlarge the clipping arc by 0.33 pixels to eliminate glitches between borders
  ctx.beginPath();
  ctx.arc(x, y, outerRadius, startAngle - angleMargin, endAngle + angleMargin);
  if (innerRadius > pixelMargin) {
    angleMargin = pixelMargin / innerRadius;
    ctx.arc(x, y, innerRadius, endAngle + angleMargin, startAngle - angleMargin, true);
  } else {
    ctx.arc(x, y, pixelMargin, endAngle + HALF_PI, startAngle - HALF_PI);
  }
  ctx.closePath();
  ctx.clip();
}

function toRadiusCorners(value) {
  return _readValueToProps(value, ['outerStart', 'outerEnd', 'innerStart', 'innerEnd']);
}

/**

Review comment (suggestion):
nit
```suggestion
import type {ArcOptions, Point} from '../../types';
```

Code after:
import Element from '../core/core.element';
import {_angleBetween, getAngleFromPoint, TAU, HALF_PI, valueOrDefault} from '../helpers/index';
import {PI, _isBetween, _limitValue} from '../helpers/helpers.math';
import {_readValueToProps} from '../helpers/helpers.options';
import type {ArcOptions, Point} from '../../types';


function clipArc(ctx: CanvasRenderingContext2D, element: ArcElement, endAngle: number) {
  const {startAngle, pixelMargin, x, y, outerRadius, innerRadius} = element;
  let angleMargin = pixelMargin / outerRadius;

  // Draw an inner border by clipping the arc and drawing a double-width border
  // Enlarge the clipping arc by 0.33 pixels to eliminate glitches between borders
  ctx.beginPath();
  ctx.arc(x, y, outerRadius, startAngle - angleMargin, endAngle + angleMargin);
  if (innerRadius > pixelMargin) {
    angleMargin = pixelMargin / innerRadius;
    ctx.arc(x, y, innerRadius, endAngle + angleMargin, startAngle - angleMargin, true);
  } else {
    ctx.arc(x, y, pixelMargin, endAngle + HALF_PI, startAngle - HALF_PI);
  }
  ctx.closePath();
  ctx.clip();
}

function toRadiusCorners(value) {
  return _readValueToProps(value, ['outerStart', 'outerEnd', 'innerStart', 'innerEnd']);
}

/**