function runRules(
	sourceCode,
	configuredRules,
	ruleMapper,
	parserName,
	language,
	languageOptions,
	settings,
	filename,
	applyDefaultOptions,
	disableFixes,
	cwd,
	physicalFilename,
	ruleFilter,
	stats,
	slots,
) {
	const visitor = new SourceCodeVisitor();

	/*
	 * Create a frozen object with the ruleContext properties and methods that are shared by all rules.
	 * All rule contexts will inherit from this object. This avoids the performance penalty of copying all the
	 * properties once for each rule.
	 */
	const fileContext = new FileContext({
		cwd,
		filename,
		physicalFilename: physicalFilename || filename,
		sourceCode,
		parserOptions: {
			...languageOptions.parserOptions,
		},
		parserPath: parserName,
		languageOptions,
		settings,
	});

	const lintingProblems = [];
	const steps = sourceCode.traverse();

	Object.keys(configuredRules).forEach(ruleId => {
		const severity = Config.getRuleNumericSeverity(configuredRules[ruleId]);

		// not load disabled rules
		if (severity === 0) {
			return;
		}

		if (ruleFilter && !ruleFilter({ ruleId, severity })) {
			return;
		}

		const rule = ruleMapper(ruleId);

		if (!rule) {
			lintingProblems.push(createLintingProblem({ ruleId, language }));
			return;
		}

		const messageIds = rule.meta && rule.meta.messages;
		let reportTranslator = null;
		const ruleContext = fileContext.extend({
			id: ruleId,
			options: getRuleOptions(
				configuredRules[ruleId],
				applyDefaultOptions ? rule.meta?.defaultOptions : void 0,
			),
			report(...args) {
				/*
				 * Create a report translator lazily.
				 * In a vast majority of cases, any given rule reports zero errors on a given
				 * piece of code. Creating a translator lazily avoids the performance cost of
				 * creating a new translator function for each rule that usually doesn't get
				 * called.
				 *
				 * Using lazy report translators improves end-to-end performance by about 3%
				 * with Node 8.4.0.
				 */
				if (reportTranslator === null) {
					reportTranslator = createReportTranslator({
						ruleId,
						severity,
						sourceCode,
						messageIds,
						disableFixes,
						language,
					});
				}
				const problem = reportTranslator(...args);

				if (problem.fix && !(rule.meta && rule.meta.fixable)) {
					throw new Error(
						'Fixable rules must set the `meta.fixable` property to "code" or "whitespace".',
					);
				}
				if (
					problem.suggestions &&
					!(rule.meta && rule.meta.hasSuggestions === true)
				) {
					if (
						rule.meta &&
						rule.meta.docs &&
						typeof rule.meta.docs.suggestion !== "undefined"
					) {
						// Encourage migration from the former property name.
						throw new Error(
							"Rules with suggestions must set the `meta.hasSuggestions` property to `true`. `meta.docs.suggestion` is ignored by ESLint.",
						);
					}
					throw new Error(
						"Rules with suggestions must set the `meta.hasSuggestions` property to `true`.",
					);
				}
				lintingProblems.push(problem);
			},
		});

		const ruleListenersReturn =
			timing.enabled || stats
				? timing.time(
						ruleId,
						createRuleListeners,
						stats,
					)(rule, ruleContext)
				: createRuleListeners(rule, ruleContext);

		const ruleListeners = stats
			? ruleListenersReturn.result
			: ruleListenersReturn;

		if (stats) {
			storeTime(
				ruleListenersReturn.tdiff,
				{ type: "rules", key: ruleId },
				slots,
			);
		}

		/**
		 * Include `ruleId` in error logs
		 * @param {Function} ruleListener A rule method that listens for a node.
		 * @returns {Function} ruleListener wrapped in error handler
		 */
		function addRuleErrorHandler(ruleListener) {
			return function ruleErrorHandler(...listenerArgs) {
				try {
					const ruleListenerReturn = ruleListener(...listenerArgs);

					const ruleListenerResult = stats
						? ruleListenerReturn.result
						: ruleListenerReturn;

					if (stats) {
						storeTime(
							ruleListenerReturn.tdiff,
							{ type: "rules", key: ruleId },
							slots,
						);
					}

					return ruleListenerResult;
				} catch (e) {
					e.ruleId = ruleId;
					throw e;
				}
			};
		}

		if (typeof ruleListeners === "undefined" || ruleListeners === null) {
			throw new Error(
				`The create() function for rule '${ruleId}' did not return an object.`,
			);
		}

		// add all the selectors from the rule as listeners
		Object.keys(ruleListeners).forEach(selector => {
			const ruleListener =
				timing.enabled || stats
					? timing.time(ruleId, ruleListeners[selector], stats)
					: ruleListeners[selector];

			visitor.add(selector, addRuleErrorHandler(ruleListener));
		});
	});

	const traverser = SourceCodeTraverser.getInstance(language);

	traverser.traverseSync(sourceCode, visitor, { steps });

	return lintingProblems;
}
Runs the given rules on the given SourceCode object
@param {SourceCode} sourceCode A SourceCode object for the given text
@param {Object} configuredRules The rules configuration
@param {function(string): RuleDefinition} ruleMapper A mapper function from rule names to rules
@param {string | undefined} parserName The name of the parser in the config
@param {Language} language The language object used for parsing.
@param {LanguageOptions} languageOptions The options for parsing the code.
@param {Object} settings The settings that were enabled in the config
@param {string} filename The reported filename of the code
@param {boolean} applyDefaultOptions If true, apply rules' meta.defaultOptions in computing their config options.
@param {boolean} disableFixes If true, it doesn't make `fix` properties.
@param {string | undefined} cwd cwd of the cli
@param {string} physicalFilename The full path of the file on disk without any code block information
@param {Function} ruleFilter A predicate function to filter which rules should be executed.
@param {boolean} stats If true, stats are collected appended to the result
@param {WeakMap<Linter, LinterInternalSlots>} slots InternalSlotsMap of linter
@returns {LintMessage[]} An array of reported problems
@throws {Error} If traversal into a node fails.