ronantakizawa/codereview-bench huggingface dataset:
Repository: discordjs/discord.js
File: packages/builders/src/interactions/modals/Modal.ts (TypeScript)

Code before:
	 * Sets the custom id of this modal.
	 *
	 * @param customId - The custom id to use
	 */
	public setCustomId(customId: string) {
		this.data.custom_id = customId;
		return this;
	}
	
	/**
	 * Adds label components to this modal.
	 *
	 * @param components - The components to add
	 */
	public addLabelComponents(
		...components: RestOrArray<
			APILabelComponent | LabelBuilder | ((builder: LabelBuilder) => LabelBuilder)
		>
	) {
		const normalized = normalizeArray(components);
		const resolved = normalized.map((row) => resolveBuilder(row, LabelBuilder));

		this.data.components.push(...resolved);

		return this;
	}

	/**
	 * Sets the labels for this modal.
	 *
	 * @param components - The components to set
	 */
	public setLabelComponents(
		...components: RestOrArray<
			APILabelComponent | LabelBuilder | ((builder: LabelBuilder) => LabelBuilder)
		>
	) {
		const normalized = normalizeArray(components);
		this.spliceLabelComponents(0, this.data.components.length, ...normalized);

		return this;
	}

	/**
	 * Removes, replaces, or inserts labels for this modal.
	 *
	 * @remarks
	 * This method behaves similarly
	 * to {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/splice | Array.prototype.splice()}.
	 * The maximum amount of labels that can be added is 5.
	 *

Review comment (suggestion):
This and the splice don't make sense this way. The current {set/splice}ActionRows should be renamed to just {set/splice}Components and accept both types.

Code after:
		this.data.custom_id = customId;
		return this;
	}

	/**
	 * Adds label components to this modal.
	 *
	 * @param components - The components to add
	 */
	public addLabelComponents(
		...components: RestOrArray<APILabelComponent | LabelBuilder | ((builder: LabelBuilder) => LabelBuilder)>
	) {
		const normalized = normalizeArray(components);
		const resolved = normalized.map((label) => resolveBuilder(label, LabelBuilder));

		this.data.components.push(...resolved);

		return this;
	}

	/**
	 * Sets the labels for this modal.
	 *
	 * @param components - The components to set
	 */
	public setLabelComponents(
		...components: RestOrArray<APILabelComponent | LabelBuilder | ((builder: LabelBuilder) => LabelBuilder)>
	) {
		const normalized = normalizeArray(components);
		this.spliceLabelComponents(0, this.data.components.length, ...normalized);

		return this;
	}

	/**
	 * Removes, replaces, or inserts labels for this modal.
	 *
	 * @remarks
	 * This method behaves similarly
	 * to {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/splice | Array.prototype.splice()}.
	 * The maximum amount of labels that can be added is 5.
	 *
	 * It's useful for modifying and adjusting order of the already-existing labels of a modal.
	 * @example
	 * Remove the first label:
	 * ```ts
	 * modal.spliceLabelComponents(0, 1);
	 * ```
	 * @example
	 * Remove the first n labels:
	 * ```ts
Repository: discordjs/discord.js
File: packages/builders/src/interactions/modals/Modal.ts (TypeScript)

Code before:

/**
 * A builder that creates API-compatible JSON data for modals.
 */
export class ModalBuilder implements JSONEncodable<APIModalInteractionResponseCallbackData> {
	/**
	 * The API data associated with this modal.
	 */
	private readonly data: ModalBuilderData;

	/**
	 * The components within this modal.
	 */
	public get components(): readonly LabelBuilder[] {
		return this.data.components;
	}

	/**
	 * Creates a new modal.
	 *
	 * @param data - The API data to create this modal with
	 */
	public constructor(
		data: Partial<
			Omit<APIModalInteractionResponseCallbackData, 'components'> & { components: APILabelComponent[] }
		> = {},
	) {
		const { components = [], ...rest } = data;

		this.data = {
			...structuredClone(rest),
			components: components.map((component) => createComponentBuilder(component)),
		};
	}

	/**
	 * Sets the title of this modal.
	 *
	 * @param title - The title to use
	 */
	public setTitle(title: string) {
		this.data.title = title;
		return this;
	}

	/**
	 * Sets the custom id of this modal.
	 *
	 * @param customId - The custom id to use
	 */
	public setCustomId(customId: string) {

Review comment (bug):
this omit looks wrong, while I understand action rows are deprecated we shouldn't juggle types like this

Code after:
 * A builder that creates API-compatible JSON data for modals.
 */
export class ModalBuilder implements JSONEncodable<APIModalInteractionResponseCallbackData> {
	/**
	 * The API data associated with this modal.
	 */
	private readonly data: ModalBuilderData;

	/**
	 * The components within this modal.
	 */
	public get components(): readonly (ActionRowBuilder | LabelBuilder)[] {
		return this.data.components;
	}

	/**
	 * Creates a new modal.
	 *
	 * @param data - The API data to create this modal with
	 */
	public constructor(data: Partial<APIModalInteractionResponseCallbackData> = {}) {
		const { components = [], ...rest } = data;

		this.data = {
			...structuredClone(rest),
			components: components.map((component) => createComponentBuilder(component)),
		};
	}

	/**
	 * Sets the title of this modal.
	 *
	 * @param title - The title to use
	 */
	public setTitle(title: string) {
		this.data.title = title;
		return this;
	}

	/**
	 * Sets the custom id of this modal.
	 *
	 * @param customId - The custom id to use
	 */
	public setCustomId(customId: string) {
		this.data.custom_id = customId;
		return this;
	}

	/**
	 * Adds label components to this modal.
Repository: discordjs/discord.js
File: packages/builders/src/interactions/modals/Modal.ts (TypeScript)

Code before:
	 * @example
	 * Remove the first label:
	 * ```ts
	 * modal.spliceLabelComponents(0, 1);
	 * ```
	 * @example
	 * Remove the first n labels:
	 * ```ts
	 * const n = 4;
	 * modal.spliceLabelComponents(0, n);
	 * ```
	 * @example
	 * Remove the last label:
	 * ```ts
	 * modal.spliceLabelComponents(-1, 1);
	 * ```
	 * @param index - The index to start at
	 * @param deleteCount - The number of labels to remove
	 * @param rows - The replacing label objects
	 */
	public spliceLabelComponents(
		index: number,
		deleteCount: number,
		...rows: (APILabelComponent | LabelBuilder | ((builder: LabelBuilder) => LabelBuilder))[]
	): this {
		const resolved = rows.map((row) => resolveBuilder(row, LabelBuilder));
		this.data.components.splice(index, deleteCount, ...resolved);

		return this;
	}

	/**
	 * Serializes this builder to API-compatible JSON data.
	 *
	 * Note that by disabling validation, there is no guarantee that the resulting object will be valid.
	 *
	 * @param validationOverride - Force validation to run/not run regardless of your global preference
	 */
	public toJSON(validationOverride?: boolean): APIModalInteractionResponseCallbackData {
		const { components, ...rest } = this.data;

		const data = {
			...structuredClone(rest),
			components: components.map((component) => component.toJSON(validationOverride)),
		};

		validate(modalPredicate, data, validationOverride);

		return data as APIModalInteractionResponseCallbackData;
	}
}

Review comment (suggestion):
```suggestion
		const resolved = labels.map((label) => resolveBuilder(label, LabelBuilder));
```

Code after:
	 * @example
	 * Remove the first label:
	 * ```ts
	 * modal.spliceLabelComponents(0, 1);
	 * ```
	 * @example
	 * Remove the first n labels:
	 * ```ts
	 * const n = 4;
	 * modal.spliceLabelComponents(0, n);
	 * ```
	 * @example
	 * Remove the last label:
	 * ```ts
	 * modal.spliceLabelComponents(-1, 1);
	 * ```
	 * @param index - The index to start at
	 * @param deleteCount - The number of labels to remove
	 * @param labels - The replacing label objects
	 */
	public spliceLabelComponents(
		index: number,
		deleteCount: number,
		...labels: (APILabelComponent | LabelBuilder | ((builder: LabelBuilder) => LabelBuilder))[]
	): this {
		const resolved = labels.map((label) => resolveBuilder(label, LabelBuilder));
		this.data.components.splice(index, deleteCount, ...resolved);

		return this;
	}

	/**
	 * Serializes this builder to API-compatible JSON data.
	 *
	 * Note that by disabling validation, there is no guarantee that the resulting object will be valid.
	 *
	 * @param validationOverride - Force validation to run/not run regardless of your global preference
	 */
	public toJSON(validationOverride?: boolean): APIModalInteractionResponseCallbackData {
		const { components, ...rest } = this.data;

		const data = {
			...structuredClone(rest),
			components: components.map((component) => component.toJSON(validationOverride)),
		};

		validate(modalPredicate, data, validationOverride);

		return data as APIModalInteractionResponseCallbackData;
	}
}
Repository: discordjs/discord.js
File: packages/discord.js/src/util/InviteFlagsBitField.js (JavaScript)

Code before:
/* eslint-disable jsdoc/check-values */
'use strict';

const { InviteFlags } = require('discord-api-types/v10');
const { BitField } = require('./BitField.js');

/**
 * Data structure that makes it easy to interact with an {@link GuildInvite#flags} bit field.
 *
 * @extends {BitField}
 */
class InviteFlagsBitField extends BitField {
  /**
   * Numeric invite flags.
   *
   * @type {InviteFlags}
   * @memberof InviteFlagsBitField
   */
  static Flags = InviteFlags;
}

/**
 * @name InviteFlagsBitField
 * @kind constructor
 * @memberof InviteFlagsBitField
 * @param {BitFieldResolvable} [bits=0] Bit(s) to read from
 */

exports.InviteFlagsBitField = InviteFlagsBitField;


Review comment (suggestion):
```suggestion
 * Data structure that makes it easy to interact with a {@link GuildInvite#flags} bit field.
```


Code after:
/* eslint-disable jsdoc/check-values */
'use strict';

const { InviteFlags } = require('discord-api-types/v10');
const { BitField } = require('./BitField.js');

/**
 * Data structure that makes it easy to interact with a {@link GuildInvite#flags} bit field.
 *
 * @extends {BitField}
 */
class InviteFlagsBitField extends BitField {
  /**
   * Numeric invite flags.
   *
   * @type {InviteFlags}
   * @memberof InviteFlagsBitField
   */
  static Flags = InviteFlags;
}

/**
 * @name InviteFlagsBitField
 * @kind constructor
 * @memberof InviteFlagsBitField
 * @param {BitFieldResolvable} [bits=0] Bit(s) to read from
 */

exports.InviteFlagsBitField = InviteFlagsBitField;
Repository: discordjs/discord.js
File: packages/rest/src/lib/utils/types.ts (TypeScript)

Code before:
}

export interface AuthData {
	/**
	 * The authorization prefix to use for this request, useful if you use this with bearer tokens
	 *
	 * @defaultValue `REST.options.authPrefix`
	 */
	prefix?: 'Bearer' | 'Bot';
	/**
	 * The authorization token to use for this request
	 */
	token: string;
}

/**
 * Represents possible data to be given to an endpoint
 */
export interface RequestData {
	/**
	 * Whether to append JSON data to form data instead of `payload_json` when sending files
	 */
	appendToFormData?: boolean;
	/**
	 * Alternate authorization data to use for this request only, or `false` to disable the Authorization header.
	 * When making a request to a ropute that includes a token (such as interactions or webhooks), set to `false`
	 * to avoid accidentally unsetting the instance token if a 401 is encountered.
	 *
	 * @defaultValue `true`
	 */
	auth?: AuthData | boolean | undefined;
	/**
	 * The body to send to this request.
	 * If providing as BodyInit, set `passThroughBody: true`
	 */
	body?: BodyInit | unknown;
	/**
	 * The {@link https://undici.nodejs.org/#/docs/api/Agent | Agent} to use for the request.
	 */
	dispatcher?: Agent;
	/**
	 * Files to be attached to this request
	 */
	files?: RawFile[] | undefined;
	/**
	 * Additional headers to add to this request
	 */
	headers?: Record<string, string>;
	/**
	 * Whether to pass-through the body property directly to `fetch()`.
	 * <warn>This only applies when files is NOT present</warn>

Review comment (suggestion):
```suggestion
	 * When making a request to a route that includes a token (such as interactions or webhooks), set to `false`
```

Code after:
}

export interface AuthData {
	/**
	 * The authorization prefix to use for this request, useful if you use this with bearer tokens
	 *
	 * @defaultValue `REST.options.authPrefix`
	 */
	prefix?: 'Bearer' | 'Bot';
	/**
	 * The authorization token to use for this request
	 */
	token: string;
}

/**
 * Represents possible data to be given to an endpoint
 */
export interface RequestData {
	/**
	 * Whether to append JSON data to form data instead of `payload_json` when sending files
	 */
	appendToFormData?: boolean;
	/**
	 * Alternate authorization data to use for this request only, or `false` to disable the Authorization header.
	 * When making a request to a route that includes a token (such as interactions or webhooks), set to `false`
	 * to avoid accidentally unsetting the instance token if a 401 is encountered.
	 *
	 * @defaultValue `true`
	 */
	auth?: AuthData | boolean | undefined;
	/**
	 * The body to send to this request.
	 * If providing as BodyInit, set `passThroughBody: true`
	 */
	body?: BodyInit | unknown;
	/**
	 * The {@link https://undici.nodejs.org/#/docs/api/Agent | Agent} to use for the request.
	 */
	dispatcher?: Agent;
	/**
	 * Files to be attached to this request
	 */
	files?: RawFile[] | undefined;
	/**
	 * Additional headers to add to this request
	 */
	headers?: Record<string, string>;
	/**
	 * Whether to pass-through the body property directly to `fetch()`.
	 * <warn>This only applies when files is NOT present</warn>
Repository: discordjs/discord.js
File: packages/rest/src/lib/utils/utils.ts (TypeScript)

Code before:
	if (typeof offset === 'number') {
		return Math.max(0, offset);
	}

	const result = offset(route);
	return Math.max(0, result);
}

/**
 * Normalizes the retry backoff used to add delay to retrying 5xx and aborted requests.
 * Applies a Math.max(0, N) to prevent negative backoffs, also deals with callbacks.
 *
 * @internal
 */
export function normalizeRetryBackoff(
	retryBackoff: GetRetryBackoffFunction | number,
	route: string,
	statusCode: number | null,
	retryCount: number,
	requestBody: unknown,
): number | null {
	if (typeof retryBackoff === 'number') {
		let backoff = Math.max(0, retryBackoff);
		for (let exponent = 0; exponent < retryCount; exponent++) {
			backoff += backoff;
		}

		return backoff;
	}

	// No need to Math.max as we'll only set the sleep timer if the value is > 0 (and not equal)
	return retryBackoff(route, statusCode, retryCount, requestBody);
}

/**
 * Normalizes the timeout for aborting requests. Applies a Math.max(0, N) to prevent negative timeouts,
 * also deals with callbacks.
 *
 * @internal
 */
export function normalizeTimeout(timeout: GetTimeoutFunction | number, route: string, requestBody: unknown): number {
	if (typeof timeout === 'number') {
		return Math.max(0, timeout);
	}

	const result = timeout(route, requestBody);
	return Math.max(0, result);
}


Review comment (bug):
If my math doesn't fail today, this should be equivalent:
```suggestion
		backoff += backoff * retryCount;
```

Code after:
	if (typeof offset === 'number') {
		return Math.max(0, offset);
	}

	const result = offset(route);
	return Math.max(0, result);
}

/**
 * Normalizes the retry backoff used to add delay to retrying 5xx and aborted requests.
 * Applies a Math.max(0, N) to prevent negative backoffs, also deals with callbacks.
 *
 * @internal
 */
export function normalizeRetryBackoff(
	retryBackoff: GetRetryBackoffFunction | number,
	route: string,
	statusCode: number | null,
	retryCount: number,
	requestBody: unknown,
): number | null {
	if (typeof retryBackoff === 'number') {
		return Math.max(0, retryBackoff) * (1 << retryCount);
	}

	// No need to Math.max as we'll only set the sleep timer if the value is > 0 (and not equal)
	return retryBackoff(route, statusCode, retryCount, requestBody);
}

/**
 * Normalizes the timeout for aborting requests. Applies a Math.max(0, N) to prevent negative timeouts,
 * also deals with callbacks.
 *
 * @internal
 */
export function normalizeTimeout(timeout: GetTimeoutFunction | number, route: string, requestBody: unknown): number {
	if (typeof timeout === 'number') {
		return Math.max(0, timeout);
	}

	const result = timeout(route, requestBody);
	return Math.max(0, result);
}
Repository: discordjs/discord.js
File: packages/discord.js/src/structures/ModalSubmitFields.js (JavaScript)

Code before:
'use strict';

const { Collection } = require('@discordjs/collection');
const { ComponentType } = require('discord-api-types/v10');
const { DiscordjsTypeError, ErrorCodes } = require('../errors/index.js');

/**
 * Represents the serialized fields from a modal submit interaction
 */
class ModalSubmitFields {
  constructor(components) {
    /**
     * The components within the modal
     *
     * @type {<ActionRowModalData | LabelModalData>[]}
     */
    this.components = components;

    /**
     * The extracted fields from the modal
     *
     * @type {Collection<string, ModalData>}
     */
    this.fields = components.reduce((accumulator, next) => {
      // NOTE: for legacy support of action rows in modals, which has `components`
      if ('components' in next) {
        for (const component of next.components) accumulator.set(component.customId, component);
      }

      // For label component
      if ('component' in next) {
        accumulator.set(next.component.customId, next.component);
      }

      return accumulator;
    }, new Collection());
  }

  /**
   * Gets a field given a custom id from a component

Review comment (suggestion):
```suggestion
     * @type {Array<ActionRowModalData|LabelModalData>[]}
```

Code after:
'use strict';

const { Collection } = require('@discordjs/collection');
const { ComponentType } = require('discord-api-types/v10');
const { DiscordjsTypeError, ErrorCodes } = require('../errors/index.js');

/**
 * Represents the serialized fields from a modal submit interaction
 */
class ModalSubmitFields {
  constructor(components) {
    /**
     * The components within the modal
     *
     * @type {Array<ActionRowModalData | LabelModalData>}
     */
    this.components = components;

    /**
     * The extracted fields from the modal
     *
     * @type {Collection<string, ModalData>}
     */
    this.fields = components.reduce((accumulator, next) => {
      // NOTE: for legacy support of action rows in modals, which has `components`
      if ('components' in next) {
        for (const component of next.components) accumulator.set(component.customId, component);
      }

      // For label component
      if ('component' in next) {
        accumulator.set(next.component.customId, next.component);
      }

      return accumulator;
    }, new Collection());
  }

  /**
   * Gets a field given a custom id from a component
Repository: discordjs/discord.js
File: packages/builders/src/components/fileUpload/FileUpload.ts (TypeScript)

Code before:
import { validate } from '../../util/validation.js';
import { ComponentBuilder } from '../Component.js';
import { fileUploadPredicate } from './Assertions.js';

/**
 * A builder that creates API-compatible JSON data for file uploads.
 */
export class FileUploadBuilder extends ComponentBuilder<APIFileUploadComponent> {
	/**
	 * @internal
	 */
	protected readonly data: Partial<APIFileUploadComponent>;

	/**
	 * Creates a new file upload.
	 *
	 * @param data - The API data to create this file upload with
	 * @example
	 * Creating a file upload from an API data object:
	 * ```ts
	 * const fileUpload = new FileUploadBuilder({
	 * 	custom_id: "file_upload",
	 *  min_values: 2,
	 * });
	 * ```
	 * @example
	 * Creating a file upload using setters and API data:
	 * ```ts
	 * const fileUpload = new FileUploadBuilder({
	 * 	custom_id: "file_upload",
	 *  min_values: 2,
	 * }).setRequired();
	 * ```
	 */
	public constructor(data: Partial<APIFileUploadComponent> = {}) {
		super();
		this.data = { ...structuredClone(data), type: ComponentType.FileUpload };
	}

	/**
	 * Sets the custom id for this file upload.
	 *
	 * @param customId - The custom id to use
	 */
	public setCustomId(customId: string) {
		this.data.custom_id = customId;
		return this;
	}

	/**
	 * Sets the minimum number of file uploads required.

Review comment (suggestion):
This example actually isn't valid because `max_values` defaults to 1. min_values must always be <= max_values.

Code after:
import { validate } from '../../util/validation.js';
import { ComponentBuilder } from '../Component.js';
import { fileUploadPredicate } from './Assertions.js';

/**
 * A builder that creates API-compatible JSON data for file uploads.
 */
export class FileUploadBuilder extends ComponentBuilder<APIFileUploadComponent> {
	/**
	 * @internal
	 */
	protected readonly data: Partial<APIFileUploadComponent>;

	/**
	 * Creates a new file upload.
	 *
	 * @param data - The API data to create this file upload with
	 * @example
	 * Creating a file upload from an API data object:
	 * ```ts
	 * const fileUpload = new FileUploadBuilder({
	 * 	custom_id: "file_upload",
	 *  min_values: 2,
	 *  max_values: 5,
	 * });
	 * ```
	 * @example
	 * Creating a file upload using setters and API data:
	 * ```ts
	 * const fileUpload = new FileUploadBuilder({
	 * 	custom_id: "file_upload",
	 *  min_values: 2,
	 *  max_values: 5,
	 * }).setRequired();
	 * ```
	 */
	public constructor(data: Partial<APIFileUploadComponent> = {}) {
		super();
		this.data = { ...structuredClone(data), type: ComponentType.FileUpload };
	}

	/**
	 * Sets the custom id for this file upload.
	 *
	 * @param customId - The custom id to use
	 */
	public setCustomId(customId: string) {
		this.data.custom_id = customId;
		return this;
	}