Repository: eslint/eslint
File: lib/rules/no-unused-vars.js (JavaScript)

Code before:
                    // explicit global variables don't have definitions.
                    const def = variable.defs[0];

                    if (def) {
                        const type = def.type;
                        const refUsedInArrayPatterns = variable.references.some(ref => ref.identifier.parent.type === "ArrayPattern");

                        // skip elements of array destructuring patterns
                        if (
                            (
                                def.name.parent.type === "ArrayPattern" ||
                                refUsedInArrayPatterns
                            ) &&
                            config.destructuredArrayIgnorePattern &&
                            config.destructuredArrayIgnorePattern.test(def.name.name)
                        ) {
                            if (config.reportUsedIgnorePattern && isUsedVariable(variable)) {
                                usedIgnoredVars.push(variable);
                            }

                            continue;
                        }

                        // skip catch variables
                        if (type === "CatchClause") {
                            if (config.caughtErrors === "none") {
                                continue;
                            }

                            // skip ignored parameters
                            if (config.caughtErrorsIgnorePattern && config.caughtErrorsIgnorePattern.test(def.name.name)) {
                                if (config.reportUsedIgnorePattern && isUsedVariable(variable)) {
                                    usedIgnoredVars.push(variable);
                                }

                                continue;
                            }
                        } else if (type === "Parameter") {

                            // skip any setter argument
                            if ((def.node.parent.type === "Property" || def.node.parent.type === "MethodDefinition") && def.node.parent.kind === "set") {
                                continue;
                            }

                            // if "args" option is "none", skip any parameter
                            if (config.args === "none") {
                                continue;
                            }

                            // skip ignored parameters
                            if (config.argsIgnorePattern && config.argsIgnorePattern.test(def.name.name)) {

Review comment (suggestion):
Instead of collecting these vars and later figuring out why they were considered as used ignored, we could just report them right away with the data we have at this point:

```suggestion
                            if (config.reportUsedIgnorePattern && isUsedVariable(variable)) {
                                context.report({
                                    node: def.name,
                                    messageId: "usedIgnoredVar",
                                    data: {
                                        varName: variable.name,
                                        additional: `. Used elements of array destructuring must not match ${config.destructuredArrayIgnorePattern}`
                                    }
                                });
                            }
```

(the same for catch arguments, params and variables).

That would fix https://github.com/eslint/eslint/pull/17662#issuecomment-1910344522 and https://github.com/eslint/eslint/pull/17662#issuecomment-1959062359.

Code after:
                    }

                    // skip function expression names
                    if (scope.functionExpressionScope) {
                        continue;
                    }

                    // skip variables marked with markVariableAsUsed()
                    if (!config.reportUsedIgnorePattern && variable.eslintUsed) {
                        continue;
                    }

                    // skip implicit "arguments" variable
                    if (scope.type === "function" && variable.name === "arguments" && variable.identifiers.length === 0) {
                        continue;
                    }

                    // explicit global variables don't have definitions.
                    const def = variable.defs[0];

                    if (def) {
                        const type = def.type;
                        const refUsedInArrayPatterns = variable.references.some(ref => ref.identifier.parent.type === "ArrayPattern");

                        // skip elements of array destructuring patterns
                        if (
                            (
                                def.name.parent.type === "ArrayPattern" ||
                                refUsedInArrayPatterns
                            ) &&
                            config.destructuredArrayIgnorePattern &&
                            config.destructuredArrayIgnorePattern.test(def.name.name)
                        ) {
                            if (config.reportUsedIgnorePattern && isUsedVariable(variable)) {
                                context.report({
                                    node: def.name,
                                    messageId: "usedIgnoredVar",
                                    data: getUsedIgnoredMessageData(variable, "array-destructure")
                                });
                            }

                            continue;
                        }

                        if (type === "ClassName") {
                            const hasStaticBlock = def.node.body.body.some(node => node.type === "StaticBlock");

                            if (config.ignoreClassWithStaticInitBlock && hasStaticBlock) {
                                continue;
                            }
                        }