Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor to improve types for no-eol-whitespace rule #5698

Merged
merged 1 commit into from
Nov 8, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
159 changes: 97 additions & 62 deletions lib/rules/no-eol-whitespace/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// @ts-nocheck

'use strict';

const styleSearch = require('style-search');

const isOnlyWhitespace = require('../../utils/isOnlyWhitespace');
const isStandardSyntaxComment = require('../../utils/isStandardSyntaxComment');
const optionsMatches = require('../../utils/optionsMatches');
const report = require('../../utils/report');
const ruleMessages = require('../../utils/ruleMessages');
const styleSearch = require('style-search');
const { isAtRule, isComment, isDeclaration, isRule } = require('../../utils/typeGuards');
const validateOptions = require('../../utils/validateOptions');

const ruleName = 'no-eol-whitespace';
Expand All @@ -17,10 +18,20 @@ const messages = ruleMessages(ruleName, {

const whitespacesToReject = new Set([' ', '\t']);

/**
* @param {string} str
* @returns {string}
*/
function fixString(str) {
return str.replace(/[ \t]+$/, '');
}

/**
* @param {number} lastEOLIndex
* @param {string} string
* @param {{ ignoreEmptyLines?: boolean, isRootFirst?: boolean }} [options]
* @returns {number}
*/
function findErrorStartIndex(
lastEOLIndex,
string,
Expand Down Expand Up @@ -53,17 +64,18 @@ function findErrorStartIndex(
return eolWhitespaceIndex;
}

function rule(on, options, context) {
/** @type {import('stylelint').Rule} */
const rule = (primary, secondaryOptions, context) => {
return (root, result) => {
const validOptions = validateOptions(
result,
ruleName,
{
actual: on,
actual: primary,
},
{
optional: true,
actual: options,
actual: secondaryOptions,
possible: {
ignore: ['empty-lines'],
},
Expand All @@ -74,13 +86,17 @@ function rule(on, options, context) {
return;
}

const ignoreEmptyLines = optionsMatches(options, 'ignore', 'empty-lines');
const ignoreEmptyLines = optionsMatches(secondaryOptions, 'ignore', 'empty-lines');

if (context.fix) {
fix(root);
}

const rootString = context.fix ? root.toString() : root.source.input.css;
const rootString = context.fix ? root.toString() : (root.source && root.source.input.css) || '';

/**
* @param {number} index
*/
const reportFromIndex = (index) => {
report({
message: messages.rejected,
Expand All @@ -104,9 +120,9 @@ function rule(on, options, context) {

/**
* Iterate each whitespace at the end of each line of the given string.
* @param {string} string the source code string
* @param {Function} callback callback the whitespace index at the end of each line.
* @param {boolean} isRootFirst set `true` if the given string is the first token of the root.
* @param {string} string - the source code string
* @param {(index: number) => void} callback - callback the whitespace index at the end of each line.
* @param {boolean} isRootFirst - set `true` if the given string is the first token of the root.
* @returns {void}
*/
function eachEolWhitespace(string, callback, isRootFirst) {
Expand All @@ -129,6 +145,9 @@ function rule(on, options, context) {
);
}

/**
* @param {import('postcss').Root} rootNode
*/
function fix(rootNode) {
let isRootFirst = true;

Expand All @@ -142,68 +161,79 @@ function rule(on, options, context) {
);
isRootFirst = false;

// AtRule
fixText(node.raws.afterName, (fixed) => {
node.raws.afterName = fixed;
});

if (node.raws.params) {
fixText(node.raws.params.raw, (fixed) => {
node.raws.params.raw = fixed;
});
} else {
fixText(node.params, (fixed) => {
node.params = fixed;
if (isAtRule(node)) {
fixText(node.raws.afterName, (fixed) => {
node.raws.afterName = fixed;
});

const rawsParams = node.raws.params;

if (rawsParams) {
fixText(rawsParams.raw, (fixed) => {
rawsParams.raw = fixed;
});
} else {
fixText(node.params, (fixed) => {
node.params = fixed;
});
}
}

// Rule
if (node.raws.selector) {
fixText(node.raws.selector.raw, (fixed) => {
node.raws.selector.raw = fixed;
});
} else {
fixText(node.selector, (fixed) => {
node.selector = fixed;
if (isRule(node)) {
const rawsSelector = node.raws.selector;

if (rawsSelector) {
fixText(rawsSelector.raw, (fixed) => {
rawsSelector.raw = fixed;
});
} else {
fixText(node.selector, (fixed) => {
node.selector = fixed;
});
}
}

if (isAtRule(node) || isRule(node) || isDeclaration(node)) {
fixText(node.raws.between, (fixed) => {
node.raws.between = fixed;
});
}

// AtRule or Rule or Decl
fixText(node.raws.between, (fixed) => {
node.raws.between = fixed;
});
if (isDeclaration(node)) {
if (node.raws.value) {
fixText(node.raws.value.raw, (fixed) => {
node.raws.value.raw = fixed;
});
} else {
fixText(node.value, (fixed) => {
node.value = fixed;
});
}
}

// Decl
if (node.raws.value) {
fixText(node.raws.value.raw, (fixed) => {
node.raws.value.raw = fixed;
});
} else {
fixText(node.value, (fixed) => {
node.value = fixed;
if (isComment(node)) {
fixText(node.raws.left, (fixed) => {
node.raws.left = fixed;
});
}

// Comment
fixText(node.raws.left, (fixed) => {
node.raws.left = fixed;
});
if (!isStandardSyntaxComment(node)) {
node.raws.right = node.raws.right && fixString(node.raws.right);
} else {
fixText(node.raws.right, (fixed) => {
node.raws.right = fixed;
});
}

if (node.raws.inline) {
node.raws.right = fixString(node.raws.right);
} else {
fixText(node.raws.right, (fixed) => {
node.raws.right = fixed;
fixText(node.text, (fixed) => {
node.text = fixed;
});
}

fixText(node.text, (fixed) => {
node.text = fixed;
});

fixText(node.raws.after, (fixed) => {
node.raws.after = fixed;
});
if (isAtRule(node) || isRule(node)) {
fixText(node.raws.after, (fixed) => {
node.raws.after = fixed;
});
}
});

fixText(
Expand All @@ -228,7 +258,12 @@ function rule(on, options, context) {
}
}

function fixText(value, fixFn, isRootFirst) {
/**
* @param {string | undefined} value
* @param {(text: string) => void} fixFn
* @param {boolean} isRootFirst
*/
function fixText(value, fixFn, isRootFirst = false) {
if (!value) {
return;
}
Expand All @@ -253,7 +288,7 @@ function rule(on, options, context) {
}
}
};
}
};

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