Skip to content

Commit

Permalink
Add types to standalone.js, cli.js, index.js, and related utils (#4381)
Browse files Browse the repository at this point in the history
* add types to stringFormatter

* add types to standalone.js

* add types to index.js

* fix types for stylelint internal api

* add types to required utils

* add types to cli.js

* enable linting in CI

* fix stringFormatter types
  • Loading branch information
vankop authored and hudochenkov committed Oct 27, 2019
1 parent c5de3c5 commit 05f94c2
Show file tree
Hide file tree
Showing 13 changed files with 310 additions and 46 deletions.
128 changes: 107 additions & 21 deletions lib/cli.js
Expand Up @@ -19,6 +19,72 @@ const { default: chalk } = require('chalk');

const EXIT_CODE_ERROR = 2;

/**
* @typedef {object} CLIFlags
* @property {boolean} [cache]
* @property {string} [cacheLocation]
* @property {string | false} config
* @property {string} [configBasedir]
* @property {string} [customSyntax]
* @property {string} [printConfig]
* @property {string} [color]
* @property {string} [customFormatter]
* @property {boolean} [disableDefaultIgnores]
* @property {boolean} [fix]
* @property {string} [formatter="string"]
* @property {string} [help]
* @property {boolean} [ignoreDisables]
* @property {string} [ignorePath]
* @property {string} [ignorePattern]
* @property {string} [noColor]
* @property {string} [outputFile]
* @property {string} [stdinFilename]
* @property {boolean} [reportNeedlessDisables]
* @property {boolean} [reportInvalidScopeDisables]
* @property {number} [maxWarnings]
* @property {string | boolean} quiet
* @property {string} [syntax]
* @property {string} [version]
* @property {boolean} [allowEmptyInput]
*/

/**
* @typedef {object} CLIOptions
* @property {any} input
* @property {any} help
* @property {any} pkg
* @property {Function} showHelp
* @property {Function} showVersion
* @property {CLIFlags} flags
*/

/**
* @typedef {object} OptionBaseType
* @property {any} formatter
* @property {boolean} [cache]
* @property {string} [configFile]
* @property {string} [cacheLocation]
* @property {string} [customSyntax]
* @property {string} [codeFilename]
* @property {string} [configBasedir]
* @property {{ quiet?: any }} configOverrides
* @property {any} [printConfig]
* @property {any} [printConfig]
* @property {boolean} [fix]
* @property {boolean} [ignoreDisables]
* @property {any} [ignorePath]
* @property {string} [outputFile]
* @property {boolean} [reportNeedlessDisables]
* @property {boolean} [reportInvalidScopeDisables]
* @property {boolean} [disableDefaultIgnores]
* @property {number} [maxWarnings]
* @property {string} [syntax]
* @property {any} [ignorePattern]
* @property {boolean} [allowEmptyInput]
* @property {string} [files]
* @property {string} [code]
*/

/*:: type meowOptionsType = {
argv?: string[],
autoHelp: boolean,
Expand Down Expand Up @@ -395,11 +461,19 @@ const meowOptions /*: meowOptionsType*/ = {
},
},
pkg: require('../package.json'),
argv: /** @type {string[]} */ ([]),
};

/**
* @param {string[]} argv
* @returns {Promise<any>}
*/
module.exports = (argv /*: string[]*/) /*: Promise<void>|void*/ => {
meowOptions.argv = argv;
const cli /*: cliType*/ = meow(meowOptions);
/** @type {CLIOptions} */
const cli /*: cliType*/ =
// @ts-ignore TODO TYPES
meow(meowOptions);

const invalidOptionsMessage = checkInvalidCLIOptions(meowOptions.flags, cli.flags);

Expand All @@ -418,6 +492,7 @@ module.exports = (argv /*: string[]*/) /*: Promise<void>|void*/ => {
formatter = dynamicRequire(customFormatter);
}

/** @type {OptionBaseType} */
const optionsBase /*: optionBaseType*/ = {
formatter,
configOverrides: {},
Expand Down Expand Up @@ -506,37 +581,44 @@ module.exports = (argv /*: string[]*/) /*: Promise<void>|void*/ => {
optionsBase.maxWarnings = maxWarnings;
}

if (cli.flags.help || cli.flags.h) {
if (cli.flags.help) {
cli.showHelp(0);

return;
return Promise.resolve();
}

if (cli.flags.version || cli.flags.v) {
if (cli.flags.version) {
cli.showVersion();

return;
return Promise.resolve();
}

if (cli.flags.allowEmptyInput) {
optionsBase.allowEmptyInput = cli.flags.allowEmptyInput;
}

return Promise.resolve()
.then(() => {
// Add input/code into options
if (cli.input.length) {
return Object.assign({}, optionsBase, {
files: cli.input,
});
}

return getStdin().then((stdin) =>
Object.assign({}, optionsBase, {
code: stdin,
}),
);
})
.then(
/**
* @returns {Promise<OptionBaseType>}
*/
() => {
// Add input/code into options
if (cli.input.length) {
return Promise.resolve(
Object.assign({}, optionsBase, {
files: /** @type {string} */ (cli.input),
}),
);
}

return getStdin().then((stdin) =>
Object.assign({}, optionsBase, {
code: stdin,
}),
);
},
)
.then((options) => {
if (cli.flags.printConfig) {
return printConfig(options)
Expand All @@ -557,15 +639,15 @@ module.exports = (argv /*: string[]*/) /*: Promise<void>|void*/ => {
const reports = [];

if (reportNeedlessDisables) {
const report = disableOptionsReportStringFormatter(linted.needlessDisables);
const report = disableOptionsReportStringFormatter(linted.needlessDisables || []);

if (report) {
reports.push(report);
}
}

if (reportInvalidScopeDisables) {
const report = disableOptionsReportStringFormatter(linted.invalidScopeDisables);
const report = disableOptionsReportStringFormatter(linted.invalidScopeDisables || []);

if (report) {
reports.push(report);
Expand Down Expand Up @@ -604,6 +686,10 @@ module.exports = (argv /*: string[]*/) /*: Promise<void>|void*/ => {
});
};

/**
* @param {{ stack: any, code: any }} err
* @returns {void}
*/
function handleError(err /*: { stack: any, code: any }*/) /*: void */ {
console.log(err.stack); // eslint-disable-line no-console
const exitCode = typeof err.code === 'number' ? err.code : 1;
Expand Down
2 changes: 1 addition & 1 deletion lib/createStylelint.js
Expand Up @@ -20,7 +20,7 @@ const STOP_DIR = IS_TEST ? path.resolve(__dirname, '..') : undefined;
* The stylelint "internal API" is passed among functions
* so that methods on a stylelint instance can invoke
* each other while sharing options and caches
* @param {import('stylelint').StylelintOptions} options
* @param {import('stylelint').StylelintStandaloneOptions} options
* @returns {StylelintInternalApi}
*/
module.exports = function(options /*: stylelint$options*/) /*: stylelint$internalApi*/ {
Expand Down
62 changes: 53 additions & 9 deletions lib/formatters/stringFormatter.js
Expand Up @@ -6,7 +6,7 @@ const stringWidth = require('string-width');
const symbols = require('log-symbols');
const utils = require('postcss-reporter/lib/util');
const { default: chalk } = require('chalk');

/** @type {import('table')} */
let table;

const MARGIN_WIDTHS = 9;
Expand All @@ -15,8 +15,13 @@ const levelColors = {
info: 'blue',
warning: 'yellow',
error: 'red',
success: undefined,
};

/**
* @param {import('stylelint').StylelintResult[]} results
* @returns {string}
*/
function deprecationsFormatter(results) {
const allDeprecationWarnings = _.flatMap(results, 'deprecations');
const uniqueDeprecationWarnings = _.uniqBy(allDeprecationWarnings, 'text');
Expand All @@ -38,6 +43,10 @@ function deprecationsFormatter(results) {
}, '\n');
}

/**
* @param {import('stylelint').StylelintResult[]} results
* @return {string}
*/
function invalidOptionsFormatter(results) {
const allInvalidOptionWarnings = _.flatMap(results, (r) =>
r.invalidOptionWarnings.map((w) => w.text),
Expand All @@ -52,6 +61,10 @@ function invalidOptionsFormatter(results) {
}, '\n');
}

/**
* @param {string} fromValue
* @return {string}
*/
function logFrom(fromValue) {
if (fromValue.charAt(0) === '<') return fromValue;

Expand All @@ -61,6 +74,10 @@ function logFrom(fromValue) {
.join('/');
}

/**
* @param {{[k: number]: number}} columnWidths
* @return {number}
*/
function getMessageWidth(columnWidths) {
if (!process.stdout.isTTY) {
return columnWidths[3];
Expand All @@ -77,6 +94,11 @@ function getMessageWidth(columnWidths) {
return availableWidth - (fullWidth - columnWidths[3] + MARGIN_WIDTHS);
}

/**
* @param {import('stylelint').StylelintWarning[]} messages
* @param {string} source
* @return {string}
*/
function formatter(messages, source) {
if (!messages.length) return '';

Expand All @@ -87,10 +109,17 @@ function formatter(messages, source) {
(m) => m.column,
);

// Create a list of column widths, needed to calculate
// the size of the message column and if needed wrap it.
/**
* Create a list of column widths, needed to calculate
* the size of the message column and if needed wrap it.
* @type {{[k: string]: number}}
*/
const columnWidths = { 0: 1, 1: 1, 2: 1, 3: 1, 4: 1 };

/**
* @param {[string, string, string, string, string]} columns
* @return {[string, string, string, string, string]}
*/
const calculateWidths = function(columns) {
_.forOwn(columns, (value, key) => {
const normalisedValue = value ? value.toString() : value;
Expand All @@ -109,11 +138,16 @@ function formatter(messages, source) {

const cleanedMessages = orderedMessages.map((message) => {
const location = utils.getLocation(message);
const severity = message.severity;
const severity = /** @type {keyof import('log-symbols')} */ (message.severity);
/**
* @type {[string, string, string, string, string]}
*/
const row = [
location.line || '',
location.column || '',
symbols[severity] ? chalk[levelColors[severity]](symbols[severity]) : severity,
location.line ? location.line.toString() : '',
location.column ? location.column.toString() : '',
symbols[severity]
? chalk[/** @type {'blue' | 'red' | 'yellow'} */ (levelColors[severity])](symbols[severity])
: severity,
message.text
// Remove all control characters (newline, tab and etc)
.replace(/[\x01-\x1A]+/g, ' ') // eslint-disable-line no-control-regex
Expand Down Expand Up @@ -148,12 +182,22 @@ function formatter(messages, source) {
drawHorizontalLine: () => false,
})
.split('\n')
.map((el) => el.replace(/(\d+)\s+(\d+)/, (m, p1, p2) => chalk.dim(p1 + ':' + p2)))
.map(
/**
* @param {string} el
* @returns {string}
*/
(el) => el.replace(/(\d+)\s+(\d+)/, (m, p1, p2) => chalk.dim(p1 + ':' + p2)),
)
.join('\n');

return output;
}

/**
* @param {import('stylelint').StylelintResult[]} results
* @returns {string}
*/
module.exports = function(results) {
let output = invalidOptionsFormatter(results);

Expand All @@ -173,7 +217,7 @@ module.exports = function(results) {
);
}

output += formatter(result.warnings, result.source);
output += formatter(result.warnings, result.source || '');

return output;
}, output);
Expand Down
20 changes: 16 additions & 4 deletions lib/index.js
Expand Up @@ -13,13 +13,25 @@ const rules = require('./rules');
const standalone = require('./standalone');
const validateOptions = require('./utils/validateOptions');

/**
* TODO TYPES change any to appropriated options
* @type {import('postcss').Plugin<any> & Partial<import('stylelint').StylelintPublicAPI>}
*/
const api = postcssPlugin;

const requiredRules = rules.reduce((acc, cur) => {
acc[cur] = requireRule(cur);
const requiredRules = rules.reduce(
/**
* @param {{[k: string]: any}} acc
* @param {string} cur
* @return {{[k: string]: any}}
*/
(acc, cur) => {
acc[cur] = requireRule(cur);

return acc;
}, {});
return acc;
},
{},
);

api.utils = {
report,
Expand Down

0 comments on commit 05f94c2

Please sign in to comment.