Skip to content

Commit

Permalink
add types to assignDisabledRanges
Browse files Browse the repository at this point in the history
  • Loading branch information
vankop committed Oct 4, 2019
1 parent a8dc55f commit 8b31acf
Showing 1 changed file with 122 additions and 46 deletions.
168 changes: 122 additions & 46 deletions lib/assignDisabledRanges.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,26 @@ const disableLineCommand = COMMAND_PREFIX + 'disable-line';
const disableNextLineCommand = COMMAND_PREFIX + 'disable-next-line';
const ALL_RULES = 'all';

/*:: type disableRange = {
start: number,
end?: number,
strictStart: boolean,
strictEnd?: boolean
}
/** @typedef {import('postcss').Comment} PostcssComment */

/**
* @typedef {object} DisableRange
* @param {number} start
* @param {boolean} strictStart
* @param {number} [end]
* @param {boolean} [strictEnd]
*/

/*:: type disabledRangeObject = {
[ruleName: string]: Array<disableRange>
}*/
/** @typedef {{[ruleName: string]: Array<DisableRange> }} DisabledRangeObject */

function createDisableRange(
start /*: number*/,
strictStart /*: boolean*/,
end /*: ?number*/,
strictEnd /*: ?boolean*/,
) /*: disableRange*/ {
/**
* @param {number} start
* @param {boolean} strictStart
* @param {number} [end]
* @param {boolean} [strictEnd]
* @returns {DisableRange}
*/
function createDisableRange(start, strictStart, end, strictEnd) {
return {
start,
end: end || undefined,
Expand All @@ -35,13 +37,20 @@ function createDisableRange(
};
}

// Run it like a plugin ...
/**
* Run it like a plugin ...
* @param {TODO} root
* @param {TODO} result
* @return {TODO}
*/
module.exports = function(root /*: Object*/, result /*: Object*/) /*: postcss$result*/ {
result.stylelint = result.stylelint || {};

// Most of the functions below work via side effects mutating
// this object
const disabledRanges /*: disabledRangeObject*/ = {
/**
* Most of the functions below work via side effects mutating this object
* @type {DisabledRangeObject}
*/
const disabledRanges = {
all: [],
};

Expand All @@ -50,19 +59,38 @@ module.exports = function(root /*: Object*/, result /*: Object*/) /*: postcss$re

return result;

function processDisableLineCommand(comment /*: postcss$comment*/) {
getCommandRules(disableLineCommand, comment.text).forEach((ruleName) => {
disableLine(comment.source.start.line, ruleName, comment);
});
/**
* @param {PostcssComment} comment
*/
function processDisableLineCommand(comment) {
if (comment.source && comment.source.start) {
const line = comment.source.start.line;

getCommandRules(disableLineCommand, comment.text).forEach((ruleName) => {
disableLine(line, ruleName, comment);
});
}
}

function processDisableNextLineCommand(comment /*: postcss$comment*/) {
getCommandRules(disableNextLineCommand, comment.text).forEach((ruleName) => {
disableLine(comment.source.start.line + 1, ruleName, comment);
});
/**
* @param {PostcssComment} comment
*/
function processDisableNextLineCommand(comment) {
if (comment.source && comment.source.start) {
const line = comment.source.start.line;

getCommandRules(disableNextLineCommand, comment.text).forEach((ruleName) => {
disableLine(line + 1, ruleName, comment);
});
}
}

function disableLine(line /*: number*/, ruleName /*: string*/, comment /*: postcss$comment*/) {
/**
* @param {number} line
* @param {string} ruleName
* @param {PostcssComment} comment
*/
function disableLine(line, ruleName, comment) {
if (ruleIsDisabled(ALL_RULES)) {
throw comment.error('All rules have already been disabled', {
plugin: 'stylelint',
Expand All @@ -88,7 +116,10 @@ module.exports = function(root /*: Object*/, result /*: Object*/) /*: postcss$re
}
}

function processDisableCommand(comment /*: postcss$comment*/) {
/**
* @param {PostcssComment} comment
*/
function processDisableCommand(comment) {
getCommandRules(disableCommand, comment.text).forEach((ruleToDisable) => {
const isAllRules = ruleToDisable === ALL_RULES;

Expand All @@ -103,28 +134,48 @@ module.exports = function(root /*: Object*/, result /*: Object*/) /*: postcss$re
);
}

if (isAllRules) {
Object.keys(disabledRanges).forEach((ruleName) => {
startDisabledRange(comment.source.start.line, ruleName, ruleName === ALL_RULES);
});
} else {
startDisabledRange(comment.source.start.line, ruleToDisable, true);
if (comment.source && comment.source.start) {
const line = comment.source.start.line;

if (isAllRules) {
Object.keys(disabledRanges).forEach((ruleName) => {
startDisabledRange(line, ruleName, ruleName === ALL_RULES);
});
} else {
startDisabledRange(line, ruleToDisable, true);
}
}
});
}

function processEnableCommand(comment /*: postcss$comment*/) {
/**
* @param {PostcssComment} comment
*/
function processEnableCommand(comment) {
getCommandRules(enableCommand, comment.text).forEach((ruleToEnable) => {
// TODO TYPES
// need fallback if endLine will be undefined
const endLine =
/** @type {number} */ (comment.source && comment.source.end && comment.source.end.line);

if (ruleToEnable === ALL_RULES) {
if (_.values(disabledRanges).every((ranges) => _.isEmpty(ranges) || !!_.last(ranges.end))) {
if (
_.values(disabledRanges).every(
/**
* @param {Array<DisableRange>} ranges
* @return {boolean}
*/
(ranges) => _.isEmpty(ranges) || ranges.every((range) => !range.end),
)
) {
throw comment.error('No rules have been disabled', {
plugin: 'stylelint',
});
}

Object.keys(disabledRanges).forEach((ruleName) => {
if (!_.get(_.last(disabledRanges[ruleName]), 'end')) {
endDisabledRange(comment.source.end.line, ruleName, ruleName === ALL_RULES);
endDisabledRange(endLine, ruleName, ruleName === ALL_RULES);
}
});

Expand All @@ -141,13 +192,13 @@ module.exports = function(root /*: Object*/, result /*: Object*/) /*: postcss$re
disabledRanges[ruleToEnable].push(_.clone(_.last(disabledRanges[ALL_RULES])));
}

endDisabledRange(comment.source.end.line, ruleToEnable, true);
endDisabledRange(endLine, ruleToEnable, true);

return;
}

if (ruleIsDisabled(ruleToEnable)) {
endDisabledRange(comment.source.end.line, ruleToEnable, true);
endDisabledRange(endLine, ruleToEnable, true);

return;
}
Expand All @@ -158,7 +209,10 @@ module.exports = function(root /*: Object*/, result /*: Object*/) /*: postcss$re
});
}

function checkComment(comment /*: postcss$comment*/) {
/**
* @param {PostcssComment} comment
*/
function checkComment(comment) {
const text = comment.text;

// Ignore comments that are not relevant commands
Expand All @@ -178,7 +232,12 @@ module.exports = function(root /*: Object*/, result /*: Object*/) /*: postcss$re
}
}

function getCommandRules(command /*: string*/, fullText /*: string*/) /*: Array<string>*/ {
/**
* @param {string} command
* @param {string} fullText
* @returns {string[]}
*/
function getCommandRules(command, fullText) {
const rules = _.compact(fullText.slice(command.length).split(',')).map((r) => r.trim());

if (_.isEmpty(rules)) {
Expand All @@ -188,14 +247,24 @@ module.exports = function(root /*: Object*/, result /*: Object*/) /*: postcss$re
return rules;
}

function startDisabledRange(line /*: number*/, ruleName /*: string*/, strict /*: boolean*/) {
/**
* @param {number} line
* @param {string} ruleName
* @param {boolean} strict
*/
function startDisabledRange(line, ruleName, strict) {
const rangeObj = createDisableRange(line, strict);

ensureRuleRanges(ruleName);
disabledRanges[ruleName].push(rangeObj);
}

function endDisabledRange(line /*: number*/, ruleName /*: string*/, strict /*: boolean*/) {
/**
* @param {number} line
* @param {string} ruleName
* @param {boolean} strict
*/
function endDisabledRange(line, ruleName, strict) {
const lastRangeForRule = _.last(disabledRanges[ruleName]);

if (!lastRangeForRule) {
Expand All @@ -207,15 +276,22 @@ module.exports = function(root /*: Object*/, result /*: Object*/) /*: postcss$re
lastRangeForRule.strictEnd = strict;
}

function ensureRuleRanges(ruleName /*: string*/) {
/**
* @param {string} ruleName
*/
function ensureRuleRanges(ruleName) {
if (!disabledRanges[ruleName]) {
disabledRanges[ruleName] = disabledRanges.all.map(({ start, end }) =>
createDisableRange(start, false, end, false),
);
}
}

function ruleIsDisabled(ruleName /*: string*/) /*: boolean*/ {
/**
* @param {string} ruleName
* @returns {boolean}
*/
function ruleIsDisabled(ruleName) {
if (disabledRanges[ruleName] === undefined) return false;

if (_.last(disabledRanges[ruleName]) === undefined) return false;
Expand Down

0 comments on commit 8b31acf

Please sign in to comment.