function collectUnusedVariables(scope, unusedVars) {
			const variables = scope.variables;
			const childScopes = scope.childScopes;
			let i, l;

			if (scope.type !== "global" || config.vars === "all") {
				for (i = 0, l = variables.length; i < l; ++i) {
					const variable = variables[i];

					// skip a variable of class itself name in the class scope
					if (
						scope.type === "class" &&
						scope.block.id === variable.identifiers[0]
					) {
						continue;
					}

					// 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;
							}
						}

						// 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)
								) {
									context.report({
										node: def.name,
										messageId: "usedIgnoredVar",
										data: getUsedIgnoredMessageData(
											variable,
											"catch-clause",
										),
									});
								}

								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)
							) {
								if (
									config.reportUsedIgnorePattern &&
									isUsedVariable(variable)
								) {
									context.report({
										node: def.name,
										messageId: "usedIgnoredVar",
										data: getUsedIgnoredMessageData(
											variable,
											"parameter",
										),
									});
								}

								continue;
							}

							// if "args" option is "after-used", skip used variables
							if (
								config.args === "after-used" &&
								astUtils.isFunction(def.name.parent) &&
								!isAfterLastUsedArg(variable)
							) {
								continue;
							}
						} else {
							// skip ignored variables
							if (
								config.varsIgnorePattern &&
								config.varsIgnorePattern.test(def.name.name)
							) {
								if (
									config.reportUsedIgnorePattern &&
									isUsedVariable(variable)
								) {
									context.report({
										node: def.name,
										messageId: "usedIgnoredVar",
										data: getUsedIgnoredMessageData(
											variable,
											"variable",
										),
									});
								}

								continue;
							}
						}
					}

					if (
						!isUsedVariable(variable) &&
						!isExported(variable) &&
						!hasRestSpreadSibling(variable)
					) {
						unusedVars.push(variable);
					}
				}
			}

			for (i = 0, l = childScopes.length; i < l; ++i) {
				collectUnusedVariables(childScopes[i], unusedVars);
			}

			return unusedVars;
		}
Gets an array of variables without read references.
@param {Scope} scope an eslint-scope Scope object.
@param {Variable[]} unusedVars an array that saving result.
@returns {Variable[]} unused variables of the scope and descendant scopes.
@private