Repository: eslint/eslint
File: lib/rules/utils/ast-utils.js (JavaScript)

Code before:
	 *                 while (d)
	 *                     if (e)
	 *                         while(f)
	 *                             foo();
	 *            }
	 *     else
	 *         bar();
	 * @param {ASTNode} node `BlockStatement` body with exactly one statement directly inside. The statement can have its own nested statements.
	 * @param {SourceCode} sourceCode The source code
	 * @returns {boolean} `true` if the braces are necessary - removing them (replacing the given `BlockStatement` body with its single statement content)
	 * would change the semantics of the code or produce a syntax error.
	 */
	areBracesNecessary(node, sourceCode) {
		/**
		 * Determines if the given node is a lexical declaration (let, const, using, await using, function, or class)
		 * @param {ASTNode} nodeToCheck The node to check
		 * @returns {boolean} True if the node is a lexical declaration
		 * @private
		 */
		function isLexicalDeclaration(nodeToCheck) {
			if (nodeToCheck.type === "VariableDeclaration") {
				return (
					nodeToCheck.kind === "const" ||
					nodeToCheck.kind === "let" ||
					nodeToCheck.kind === "using" ||
					nodeToCheck.kind === "await using"
				);
			}

			return (
				nodeToCheck.type === "FunctionDeclaration" ||
				nodeToCheck.type === "ClassDeclaration"
			);
		}

		/**
		 * Checks if the given token is an `else` token or not.
		 * @param {Token} token The token to check.
		 * @returns {boolean} `true` if the token is an `else` token.
		 */
		function isElseKeywordToken(token) {
			return token.value === "else" && token.type === "Keyword";
		}

		/**
		 * Determines whether the given node has an `else` keyword token as the first token after.
		 * @param {ASTNode} nodeToCheck The node to check.
		 * @returns {boolean} `true` if the node is followed by an `else` keyword token.
		 */
		function isFollowedByElseKeyword(nodeToCheck) {
			const nextToken = sourceCode.getTokenAfter(nodeToCheck);

Review comment (suggestion):
Not a blocker but can we move these to a set like `const DECLARATION_KINDS = new Set(["const", "let","using", "await using"]);` and then assert on `DECLARATION_KINDS.has(nodeToCheck.kind)`

Code after:
	 *     else
	 *         bar();
	 *
	 *     if (a)
	 *         while (b)
	 *             while (c) {
	 *                 while (d)
	 *                     if (e)
	 *                         while(f)
	 *                             foo();
	 *            }
	 *     else
	 *         bar();
	 * @param {ASTNode} node `BlockStatement` body with exactly one statement directly inside. The statement can have its own nested statements.
	 * @param {SourceCode} sourceCode The source code
	 * @returns {boolean} `true` if the braces are necessary - removing them (replacing the given `BlockStatement` body with its single statement content)
	 * would change the semantics of the code or produce a syntax error.
	 */
	areBracesNecessary(node, sourceCode) {
		/**
		 * Determines if the given node is a lexical declaration (let, const, using, await using, function, or class)
		 * @param {ASTNode} nodeToCheck The node to check
		 * @returns {boolean} True if the node is a lexical declaration
		 * @private
		 */
		function isLexicalDeclaration(nodeToCheck) {
			if (nodeToCheck.type === "VariableDeclaration") {
				return LEXICAL_DECLARATION_KINDS.has(nodeToCheck.kind);
			}

			return (
				nodeToCheck.type === "FunctionDeclaration" ||
				nodeToCheck.type === "ClassDeclaration"
			);
		}

		/**
		 * Checks if the given token is an `else` token or not.
		 * @param {Token} token The token to check.
		 * @returns {boolean} `true` if the token is an `else` token.
		 */
		function isElseKeywordToken(token) {
			return token.value === "else" && token.type === "Keyword";
		}

		/**
		 * Determines whether the given node has an `else` keyword token as the first token after.
		 * @param {ASTNode} nodeToCheck The node to check.
		 * @returns {boolean} `true` if the node is followed by an `else` keyword token.
		 */
		function isFollowedByElseKeyword(nodeToCheck) {