function createIndividualDirectivesRemoval(
	directives,
	parentDirective,
	sourceCode,
) {
	/*
	 * Get the list of the rules text without any surrounding whitespace. In order to preserve the original
	 * formatting, we don't want to change that whitespace.
	 *
	 *     // eslint-disable-line rule-one , rule-two , rule-three -- comment
	 *                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	 */
	const listText = parentDirective.value.trim();

	// Calculate where it starts in the source code text
	const listStart = sourceCode.text.indexOf(
		listText,
		sourceCode.getRange(parentDirective.node)[0],
	);

	/*
	 * We can assume that `listText` contains multiple elements.
	 * Otherwise, this function wouldn't be called - if there is
	 * only one rule in the list, then the whole comment must be removed.
	 */

	return directives.map(directive => {
		const { ruleId } = directive;

		const regex = new RegExp(
			String.raw`(?:^|\s*,\s*)(?<quote>['"]?)${escapeRegExp(ruleId)}\k<quote>(?:\s*,\s*|$)`,
			"u",
		);
		const match = regex.exec(listText);
		const matchedText = match[0];
		const matchStart = listStart + match.index;
		const matchEnd = matchStart + matchedText.length;

		const firstIndexOfComma = matchedText.indexOf(",");
		const lastIndexOfComma = matchedText.lastIndexOf(",");

		let removalStart, removalEnd;

		if (firstIndexOfComma !== lastIndexOfComma) {
			/*
			 * Since there are two commas, this must one of the elements in the middle of the list.
			 * Matched range starts where the previous rule name ends, and ends where the next rule name starts.
			 *
			 *     // eslint-disable-line rule-one , rule-two , rule-three -- comment
			 *                                    ^^^^^^^^^^^^^^
			 *
			 * We want to remove only the content between the two commas, and also one of the commas.
			 *
			 *     // eslint-disable-line rule-one , rule-two , rule-three -- comment
			 *                                     ^^^^^^^^^^^
			 */
			removalStart = matchStart + firstIndexOfComma;
			removalEnd = matchStart + lastIndexOfComma;
		} else {
			/*
			 * This is either the first element or the last element.
			 *
			 * If this is the first element, matched range starts where the first rule name starts
			 * and ends where the second rule name starts. This is exactly the range we want
			 * to remove so that the second rule name will start where the first one was starting
			 * and thus preserve the original formatting.
			 *
			 *     // eslint-disable-line rule-one , rule-two , rule-three -- comment
			 *                            ^^^^^^^^^^^
			 *
			 * Similarly, if this is the last element, we've already matched the range we want to
			 * remove. The previous rule name will end where the last one was ending, relative
			 * to the content on the right side.
			 *
			 *     // eslint-disable-line rule-one , rule-two , rule-three -- comment
			 *                                               ^^^^^^^^^^^^^
			 */
			removalStart = matchStart;
			removalEnd = matchEnd;
		}

		return {
			description: `'${ruleId}'`,
			fix: {
				range: [removalStart, removalEnd],
				text: "",
			},
			unprocessedDirective: directive.unprocessedDirective,
		};
	});
}
Creates removal details for a set of directives within the same comment.
@param {Directive[]} directives Unused directives to be removed.
@param {{node: Token, value: string}} parentDirective Data about the backing directive.
@param {SourceCode} sourceCode The source code object for the file being linted.
@returns {{ description, fix, unprocessedDirective }[]} Details for later creation of output Problems.