Skip to content

Commit

Permalink
Refactor to improve types for no-extra-semicolons rule (#5768)
Browse files Browse the repository at this point in the history
- Remove `// @ts-nocheck` to enable type-checking.
- Narrow the scope of some local variables.
  • Loading branch information
ybiquitous committed Dec 20, 2021
1 parent b37be75 commit b9785cd
Showing 1 changed file with 47 additions and 18 deletions.
65 changes: 47 additions & 18 deletions lib/rules/no-extra-semicolons/index.js
@@ -1,5 +1,3 @@
// @ts-nocheck

'use strict';

const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule');
Expand All @@ -15,12 +13,25 @@ const messages = ruleMessages(ruleName, {
rejected: 'Unexpected extra semicolon',
});

/**
* @param {import('postcss').Node} node
* @returns {number}
*/
function getOffsetByNode(node) {
// @ts-expect-error -- TS2339: Property 'document' does not exist on type 'Document | Container<ChildNode>'
if (node.parent && node.parent.document) {
return 0;
}

const string = node.root().source.input.css;
const root = node.root();

if (!root.source) throw new Error('The root node must have a source');

if (!node.source) throw new Error('The node must have a source');

if (!node.source.start) throw new Error('The source must have a start position');

const string = root.source.input.css;
const nodeColumn = node.source.start.column;
const nodeLine = node.source.start.line;
let line = 1;
Expand All @@ -44,17 +55,19 @@ function getOffsetByNode(node) {
return index;
}

function rule(actual, options, context) {
/** @type {import('stylelint').Rule} */
const rule = (primary, _secondaryOptions, context) => {
return (root, result) => {
const validOptions = validateOptions(result, ruleName, { actual });
const validOptions = validateOptions(result, ruleName, { actual: primary });

if (!validOptions) {
return;
}

const rawAfterRoot = root.raws.after;
if (root.raws.after && root.raws.after.trim().length !== 0) {
const rawAfterRoot = root.raws.after;

if (rawAfterRoot && rawAfterRoot.trim().length !== 0) {
/** @type {number[]} */
const fixSemiIndices = [];

styleSearch({ source: rawAfterRoot, target: ';' }, (match) => {
Expand All @@ -64,6 +77,8 @@ function rule(actual, options, context) {
return;
}

if (!root.source) throw new Error('The root node must have a source');

complain(root.source.input.css.length - rawAfterRoot.length + match.startIndex);
});

Expand All @@ -82,13 +97,13 @@ function rule(actual, options, context) {
return;
}

const rawBeforeNode = node.raws.before;

if (rawBeforeNode && rawBeforeNode.trim().length !== 0) {
if (node.raws.before && node.raws.before.trim().length !== 0) {
const rawBeforeNode = node.raws.before;
const allowedSemi = 0;

const rawBeforeIndexStart = 0;

/** @type {number[]} */
const fixSemiIndices = [];

styleSearch({ source: rawBeforeNode, target: ';' }, (match, count) => {
Expand All @@ -107,22 +122,28 @@ function rule(actual, options, context) {

// fix
if (fixSemiIndices.length) {
node.raws.before = removeIndices(node.raws.before, fixSemiIndices);
node.raws.before = removeIndices(rawBeforeNode, fixSemiIndices);
}
}

const rawAfterNode = node.raws.after;
if ('after' in node.raws && node.raws.after && node.raws.after.trim().length !== 0) {
const rawAfterNode = node.raws.after;

if (rawAfterNode && rawAfterNode.trim().length !== 0) {
/**
* If the last child is a Less mixin followed by more than one semicolon,
* node.raws.after will be populated with that semicolon.
* Since we ignore Less mixins, exit here
*/
if (node.last && node.last.type === 'atrule' && !isStandardSyntaxAtRule(node.last)) {
if (
'last' in node &&
node.last &&
node.last.type === 'atrule' &&
!isStandardSyntaxAtRule(node.last)
) {
return;
}

/** @type {number[]} */
const fixSemiIndices = [];

styleSearch({ source: rawAfterNode, target: ';' }, (match) => {
Expand All @@ -148,11 +169,11 @@ function rule(actual, options, context) {
}
}

const rawOwnSemicolon = node.raws.ownSemicolon;

if (rawOwnSemicolon) {
if ('ownSemicolon' in node.raws && node.raws.ownSemicolon) {
const rawOwnSemicolon = node.raws.ownSemicolon;
const allowedSemi = 0;

/** @type {number[]} */
const fixSemiIndices = [];

styleSearch({ source: rawOwnSemicolon, target: ';' }, (match, count) => {
Expand Down Expand Up @@ -182,6 +203,9 @@ function rule(actual, options, context) {
}
});

/**
* @param {number} index
*/
function complain(index) {
report({
message: messages.rejected,
Expand All @@ -192,6 +216,11 @@ function rule(actual, options, context) {
});
}

/**
* @param {string} str
* @param {number[]} indices
* @returns {string}
*/
function removeIndices(str, indices) {
for (const index of indices.reverse()) {
str = str.slice(0, index) + str.slice(index + 1);
Expand All @@ -200,7 +229,7 @@ function rule(actual, options, context) {
return str;
}
};
}
};

rule.ruleName = ruleName;
rule.messages = messages;
Expand Down

0 comments on commit b9785cd

Please sign in to comment.