Repository: eslint/eslint
File: tools/check-rule-examples.js (JavaScript)

Code before:
                    ecmaVersionErrorMessage = `"ecmaVersion" must be one of ${[...VALID_ECMA_VERSIONS].join(", ")}.`;
                }

                if (ecmaVersionErrorMessage) {
                    problems.push({
                        fatal: false,
                        severity: 2,
                        message: ecmaVersionErrorMessage,
                        line: codeBlockToken.map[0] - 1,
                        column: 1
                    });
                }
            }

            const { ast, error } = tryParseForPlayground(code, languageOptions);

            if (ast) {
                let hasRuleConfigComment = false;

                for (const comment of ast.comments) {

                    if (comment.type === "Block" && /^\s*eslint-env(?!\S)/u.test(comment.value)) {
                        problems.push({
                            fatal: false,
                            severity: 2,
                            message: "/* eslint-env */ comments are no longer supported. Remove the comment.",
                            line: codeBlockToken.map[0] + 1 + comment.loc.start.line,
                            column: comment.loc.start.column + 1
                        });
                    }

                    if (comment.type !== "Block" || !/^\s*eslint(?!\S)/u.test(comment.value)) {
                        continue;
                    }
                    const { value } = commentParser.parseDirective(comment.value);
                    const parseResult = commentParser.parseJSONLikeConfig(value);
                    const parseError = parseResult.error;

                    if (parseError) {
                        problems.push({
                            fatal: true,
                            severity: 2,
                            message: parseError.message,
                            line: comment.loc.start.line + codeBlockToken.map[0] + 1,
                            column: comment.loc.start.column + 1
                        });
                    } else if (Object.hasOwn(parseResult.config, title)) {
                        if (hasRuleConfigComment) {
                            problems.push({
                                fatal: false,
                                severity: 2,

Review comment (bug):
I see why it makes sense to check for fatal messages before adding a non-fatal message, but currently it's still possible to get fatal and non-fatal messages mixed up for the same example because the `fatal` flag is not really cared about anywhere. For instance:

````md
:::incorrect

```ts
?foo
```

:::
````

This will produce the output:

````console
  3:4  error  Nonstandard language tag 'ts': use one of 'javascript', 'js' or 'jsx'
  4:1  error  Unexpected lint error found: Parsing error: Unexpected token ?

✖ 2 problems (2 errors, 0 warnings)
````

Where only the second problem is fatal. So if we want to avoid showing non-fatal problems when there are fatal ones maybe it would be better to keep two separate lists for non-fatal and fatal problems respectively, and in the end return only one of the lists from the `findProblems` call.

Alternatively, we could say that we don't care about the fatal status and just report all lint messages that apply without checking for the `fatal` flag. This is basically what the existing implementation is doing.

Code after:
                problems.push({
                    fatal: true,
                    severity: 2,
                    message: `Configuration error: ${error.message}`,
                    line: codeBlockToken.map[0] - 1,
                    column: 1
                });

                return;
            }

            // for removed rules, leave only parsing errors
            if (isRuleRemoved) {
                lintMessages = lintMessages.filter(lintMessage => lintMessage.fatal);
            } else {

                if (type === "incorrect") {
                    const { length } = lintMessages;

                    // filter out errors reported by the rule as they are expected in incorrect examples
                    lintMessages = lintMessages.filter(lintMessage =>
                        lintMessage.ruleId !== title ||
                        lintMessage.fatal ||
                        lintMessage.message.includes(`Inline configuration for rule "${title}" is invalid`));

                    if (lintMessages.length === length && !lintMessages.some(lintMessage => lintMessage.fatal)) {
                        problems.push({
                            fatal: false,
                            severity: 2,
                            message: "Incorrect examples should have at least one error reported by the rule.",
                            line: codeBlockToken.map[0] + 2,
                            column: 1
                        });
                    }
                }
            }

            problems.push(...lintMessages.map(lintMessage => ({
                ...lintMessage,
                message: `Unexpected lint error found: ${lintMessage.message}`,
                line: codeBlockToken.map[0] + 1 + lintMessage.line
            })));

            const sourceCode = linter.getSourceCode();

            if (sourceCode) {
                const { ast } = sourceCode;
                let hasRuleConfigComment = false;

                for (const comment of ast.comments) {