You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
4.8 KiB
165 lines
4.8 KiB
/** |
|
* @author Toru Nagashima <https://github.com/mysticatea> |
|
*/ |
|
'use strict' |
|
|
|
/** |
|
* @typedef {import('eslint').Linter.LintMessage} LintMessage |
|
*/ |
|
/** |
|
* @typedef {object} GroupState |
|
* @property {Set<string>} GroupState.disableAllKeys |
|
* @property {Map<string, string[]>} GroupState.disableRuleKeys |
|
*/ |
|
|
|
module.exports = { |
|
/** @param {string} code */ |
|
preprocess(code) { |
|
return [code] |
|
}, |
|
|
|
/** |
|
* @param {LintMessage[][]} messages |
|
* @returns {LintMessage[]} |
|
*/ |
|
postprocess(messages) { |
|
const state = { |
|
/** @type {GroupState} */ |
|
block: { |
|
disableAllKeys: new Set(), |
|
disableRuleKeys: new Map() |
|
}, |
|
/** @type {GroupState} */ |
|
line: { |
|
disableAllKeys: new Set(), |
|
disableRuleKeys: new Map() |
|
} |
|
} |
|
/** @type {string[]} */ |
|
const usedDisableDirectiveKeys = [] |
|
/** @type {Map<string,LintMessage>} */ |
|
const unusedDisableDirectiveReports = new Map() |
|
|
|
// Filter messages which are in disabled area. |
|
const filteredMessages = messages[0].filter((message) => { |
|
if (message.ruleId === 'vue/comment-directive') { |
|
const directiveType = message.messageId |
|
const data = message.message.split(' ') |
|
switch (directiveType) { |
|
case 'disableBlock': |
|
state.block.disableAllKeys.add(data[1]) |
|
break |
|
case 'disableLine': |
|
state.line.disableAllKeys.add(data[1]) |
|
break |
|
case 'enableBlock': |
|
state.block.disableAllKeys.clear() |
|
break |
|
case 'enableLine': |
|
state.line.disableAllKeys.clear() |
|
break |
|
case 'disableBlockRule': |
|
addDisableRule(state.block.disableRuleKeys, data[1], data[2]) |
|
break |
|
case 'disableLineRule': |
|
addDisableRule(state.line.disableRuleKeys, data[1], data[2]) |
|
break |
|
case 'enableBlockRule': |
|
state.block.disableRuleKeys.delete(data[1]) |
|
break |
|
case 'enableLineRule': |
|
state.line.disableRuleKeys.delete(data[1]) |
|
break |
|
case 'clear': |
|
state.block.disableAllKeys.clear() |
|
state.block.disableRuleKeys.clear() |
|
state.line.disableAllKeys.clear() |
|
state.line.disableRuleKeys.clear() |
|
break |
|
default: |
|
// unused eslint-disable comments report |
|
unusedDisableDirectiveReports.set(messageToKey(message), message) |
|
break |
|
} |
|
return false |
|
} else { |
|
const disableDirectiveKeys = [] |
|
if (state.block.disableAllKeys.size) { |
|
disableDirectiveKeys.push(...state.block.disableAllKeys) |
|
} |
|
if (state.line.disableAllKeys.size) { |
|
disableDirectiveKeys.push(...state.line.disableAllKeys) |
|
} |
|
if (message.ruleId) { |
|
const block = state.block.disableRuleKeys.get(message.ruleId) |
|
if (block) { |
|
disableDirectiveKeys.push(...block) |
|
} |
|
const line = state.line.disableRuleKeys.get(message.ruleId) |
|
if (line) { |
|
disableDirectiveKeys.push(...line) |
|
} |
|
} |
|
|
|
if (disableDirectiveKeys.length) { |
|
// Store used eslint-disable comment key |
|
usedDisableDirectiveKeys.push(...disableDirectiveKeys) |
|
return false |
|
} else { |
|
return true |
|
} |
|
} |
|
}) |
|
|
|
if (unusedDisableDirectiveReports.size) { |
|
for (const key of usedDisableDirectiveKeys) { |
|
// Remove used eslint-disable comments |
|
unusedDisableDirectiveReports.delete(key) |
|
} |
|
// Reports unused eslint-disable comments |
|
filteredMessages.push(...unusedDisableDirectiveReports.values()) |
|
filteredMessages.sort(compareLocations) |
|
} |
|
|
|
return filteredMessages |
|
}, |
|
|
|
supportsAutofix: true |
|
} |
|
|
|
/** |
|
* @param {Map<string, string[]>} disableRuleKeys |
|
* @param {string} rule |
|
* @param {string} key |
|
*/ |
|
function addDisableRule(disableRuleKeys, rule, key) { |
|
let keys = disableRuleKeys.get(rule) |
|
if (keys) { |
|
keys.push(key) |
|
} else { |
|
keys = [key] |
|
disableRuleKeys.set(rule, keys) |
|
} |
|
} |
|
|
|
/** |
|
* @param {LintMessage} message |
|
* @returns {string} message key |
|
*/ |
|
function messageToKey(message) { |
|
return `line:${message.line},column${ |
|
// -1 because +1 by ESLint's `report-translator`. |
|
message.column - 1 |
|
}` |
|
} |
|
|
|
/** |
|
* Compares the locations of two objects in a source file |
|
* @param {Position} itemA The first object |
|
* @param {Position} itemB The second object |
|
* @returns {number} A value less than 1 if itemA appears before itemB in the source file, greater than 1 if |
|
* itemA appears after itemB in the source file, or 0 if itemA and itemB have the same location. |
|
*/ |
|
function compareLocations(itemA, itemB) { |
|
return itemA.line - itemB.line || itemA.column - itemB.column |
|
}
|
|
|