UNPKG

@adguard/aglint

Version:

Universal adblock filter list linter.

91 lines (88 loc) 3.72 kB
/* * AGLint v3.0.0 (build date: Wed, 21 May 2025 13:24:14 GMT) * (c) 2025 AdGuard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/AGLint#readme */ import { RuleCategory, CommentRuleType } from '@adguard/agtree'; import { SEVERITY } from '../severity.js'; import { IF_DIRECTIVE, ENDIF_DIRECTIVE, ELSE_DIRECTIVE } from '../../common/constants.js'; /** * Rule that checks if all if directives are closed */ const IfClosed = { meta: { severity: SEVERITY.error, }, events: { onStartFilterList: (context) => { // Each rule ONLY sees its own storage. At the beginning of the filter list, // we just initialize the storage. context.storage.openIfs = []; }, onRule: (context) => { // Get actually iterated adblock rule const rule = context.getActualAdblockRuleAst(); // Check adblock rule category and type if (rule.category !== RuleCategory.Comment || rule.type !== CommentRuleType.PreProcessorCommentRule) { return; } const directive = rule.name.value; switch (directive) { case IF_DIRECTIVE: // Collect open "if" context.storage.openIfs.push(rule); break; case ELSE_DIRECTIVE: // '!#else' can only be used alone without any parameters if (rule.params) { context.report({ message: `Invalid usage of preprocessor directive: "${ELSE_DIRECTIVE}"`, node: rule, }); } // Check if there is an open "!#if" before "!#else" if (context.storage.openIfs.length === 0) { context.report({ // eslint-disable-next-line max-len message: `Using an "${ELSE_DIRECTIVE}" directive without an opening "${IF_DIRECTIVE}" directive`, node: rule, }); } // otherwise do nothing break; case ENDIF_DIRECTIVE: // '!#endif' can only be used alone without any parameters if (rule.params) { context.report({ message: `Invalid usage of preprocessor directive: "${ENDIF_DIRECTIVE}"`, node: rule, }); } if (context.storage.openIfs.length === 0) { context.report({ // eslint-disable-next-line max-len message: `Using an "${ENDIF_DIRECTIVE}" directive without an opening "${IF_DIRECTIVE}" directive`, node: rule, }); } else { // Mark "if" as closed (simply delete it from collection) context.storage.openIfs.pop(); } break; } }, onEndFilterList: (context) => { // If there are any collected "if"s, that means they aren't closed, so a problem must be reported for them for (const rule of context.storage.openIfs) { context.report({ message: `Unclosed "${IF_DIRECTIVE}" directive`, node: rule, }); } }, }, }; export { IfClosed };