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 turn on noUncheckedIndexedAccess option for TypeScript #5983

Merged
merged 20 commits into from Apr 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion lib/augmentConfig.js
Expand Up @@ -318,7 +318,7 @@ function addPluginFunctions(config) {

const normalizedPlugins = [config.plugins].flat();

/** @type {{[k: string]: Function}} */
/** @type {StylelintConfig['pluginFunctions']} */
const pluginFunctions = {};

for (const pluginLookup of normalizedPlugins) {
Expand Down
6 changes: 2 additions & 4 deletions lib/descriptionlessDisables.js
Expand Up @@ -22,13 +22,11 @@ module.exports = function descriptionlessDisables(results) {

const [enabled, options, stylelintResult] = settings;

const rangeData = stylelintResult.disabledRanges;

/** @type {Set<PostcssComment>} */
const alreadyReported = new Set();

for (const rule of Object.keys(rangeData)) {
for (const range of rangeData[rule]) {
for (const [rule, ruleRanges] of Object.entries(stylelintResult.disabledRanges)) {
for (const range of ruleRanges) {
if (range.description) continue;

if (alreadyReported.has(range.comment)) continue;
Expand Down
16 changes: 12 additions & 4 deletions lib/formatters/stringFormatter.js
Expand Up @@ -4,6 +4,8 @@ const path = require('path');
const stringWidth = require('string-width');
const table = require('table');
const { yellow, dim, underline, blue, red, green } = require('picocolors');

const { assertNumber } = require('../utils/validateTypes');
const terminalLink = require('./terminalLink');

const MARGIN_WIDTHS = 9;
Expand Down Expand Up @@ -98,19 +100,23 @@ function logFrom(fromValue, cwd) {
* @return {number}
*/
function getMessageWidth(columnWidths) {
const width = columnWidths[3];

assertNumber(width);

if (!process.stdout.isTTY) {
return columnWidths[3];
return width;
}

const availableWidth = process.stdout.columns < 80 ? 80 : process.stdout.columns;
const fullWidth = Object.values(columnWidths).reduce((a, b) => a + b);

// If there is no reason to wrap the text, we won't align the last column to the right
if (availableWidth > fullWidth + MARGIN_WIDTHS) {
return columnWidths[3];
return width;
}

return availableWidth - (fullWidth - columnWidths[3] + MARGIN_WIDTHS);
return availableWidth - (fullWidth - width + MARGIN_WIDTHS);
}

/**
Expand Down Expand Up @@ -154,8 +160,10 @@ function formatter(messages, source, cwd) {
function calculateWidths(columns) {
for (const [key, value] of Object.entries(columns)) {
const normalisedValue = value ? value.toString() : value;
const width = columnWidths[key];

columnWidths[key] = Math.max(columnWidths[key], stringWidth(normalisedValue));
assertNumber(width);
columnWidths[key] = Math.max(width, stringWidth(normalisedValue));
}

return columns;
Expand Down
7 changes: 4 additions & 3 deletions lib/formatters/verboseFormatter.js
Expand Up @@ -78,12 +78,13 @@ function groupBy(array, keyFn) {

for (const item of array) {
const key = keyFn(item);
let warnings = result[key];

if (!(key in result)) {
result[key] = [];
if (warnings === undefined) {
result[key] = warnings = [];
}

result[key].push(item);
warnings.push(item);
}

return result;
Expand Down
7 changes: 2 additions & 5 deletions lib/invalidScopeDisables.js
Expand Up @@ -22,15 +22,12 @@ module.exports = function invalidScopeDisables(results) {

usedRules.add('all');

const rangeData = stylelintResult.disabledRanges;
const disabledRules = Object.keys(rangeData);

for (const rule of disabledRules) {
for (const [rule, ruleRanges] of Object.entries(stylelintResult.disabledRanges)) {
if (usedRules.has(rule)) continue;

if (enabled === optionsMatches(options, 'except', rule)) continue;

for (const range of rangeData[rule]) {
for (const range of ruleRanges) {
if (!range.strictStart && !range.strictEnd) continue;

// If the comment doesn't have a location, we can't report a useful error.
Expand Down
2 changes: 1 addition & 1 deletion lib/lintPostcssResult.js
Expand Up @@ -129,7 +129,7 @@ function lintPostcssResult(stylelintOptions, postcssResult, config) {
*/
function isFixCompatible({ stylelint }) {
// Check for issue #2643
if (stylelint.disabledRanges.all.length) return false;
if (stylelint.disabledRanges.all && stylelint.disabledRanges.all.length) return false;

return true;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/needlessDisables.js
Expand Up @@ -46,14 +46,14 @@ module.exports = function needlessDisables(results) {
}
}

for (const range of rangeData.all) {
for (const range of rangeData.all || []) {
if (isWarningInRange(warning, range)) {
putIfAbsent(usefulDisables, range.comment, () => new Set()).add(rule);
}
}
}

const allRangeComments = new Set(rangeData.all.map((range) => range.comment));
const allRangeComments = new Set((rangeData.all || []).map((range) => range.comment));

for (const [rule, ranges] of Object.entries(rangeData)) {
for (const range of ranges) {
Expand Down
5 changes: 2 additions & 3 deletions lib/printConfig.js
Expand Up @@ -19,15 +19,14 @@ module.exports = async function printConfig({
files,
}) {
const isCodeNotFile = code !== undefined;
const filePath = files && files[0];

if (!files || files.length !== 1 || isCodeNotFile) {
if (!files || files.length !== 1 || !filePath || isCodeNotFile) {
return Promise.reject(
new Error('The --print-config option must be used with exactly one file path.'),
);
}

const filePath = files[0];

if (globby.hasMagic(filePath)) {
return Promise.reject(new Error('The --print-config option does not support globs.'));
}
Expand Down
2 changes: 1 addition & 1 deletion lib/rules/color-hex-length/index.js
Expand Up @@ -117,7 +117,7 @@ function longer(hex) {
let hexVariant = '#';

for (let i = 1; i < hex.length; i++) {
hexVariant += hex[i] + hex[i];
hexVariant += hex.charAt(i).repeat(2);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[note] .charAt() always returns a string (e.g. an empty string).

}

return hexVariant;
Expand Down
4 changes: 2 additions & 2 deletions lib/rules/color-named/colordUtils.js
Expand Up @@ -43,7 +43,7 @@ function parseHwbWithCommaString(input) {

const [hue, whiteness = '', blackness = '', alpha, ...extraArgs] = input.slice(4, -1).split(',');

if (!hue.trim() || !whiteness.trim() || !blackness.trim() || extraArgs.length > 0) {
if (!hue || !hue.trim() || !whiteness.trim() || !blackness.trim() || extraArgs.length > 0) {
return null;
}

Expand Down Expand Up @@ -72,7 +72,7 @@ function parseGrayString(input) {

const [lightness, alpha, ...extraArgs] = input.slice(5, -1).split(',');

if (extraArgs.length > 0) {
if (!lightness || extraArgs.length > 0) {
return null;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/rules/color-no-invalid-hex/index.js
Expand Up @@ -43,7 +43,7 @@ const rule = (primary) => {

const hexValue = hexMatch[0];

if (isValidHex(hexValue)) return;
if (!hexValue || isValidHex(hexValue)) return;

const index = declarationValueIndex(decl) + sourceIndex;
const endIndex = index + hexValue.length;
Expand Down
8 changes: 6 additions & 2 deletions lib/rules/comment-whitespace-inside/index.js
Expand Up @@ -68,11 +68,15 @@ const rule = (primary, _secondaryOptions, context) => {

const leftMatches = rawComment.match(/(^\/\*+)(\s)?/);

if (leftMatches == null) throw new Error(`Invalid comment: "${rawComment}"`);
if (leftMatches == null || leftMatches[1] == null) {
throw new Error(`Invalid comment: "${rawComment}"`);
}

const rightMatches = rawComment.match(/(\s)?(\*+\/)$/);

if (rightMatches == null) throw new Error(`Invalid comment: "${rawComment}"`);
if (rightMatches == null || rightMatches[2] == null) {
throw new Error(`Invalid comment: "${rawComment}"`);
}

const opener = leftMatches[1];
const leftSpace = leftMatches[2] || '';
Expand Down
4 changes: 3 additions & 1 deletion lib/rules/custom-media-pattern/index.js
Expand Up @@ -37,7 +37,9 @@ const rule = (primary) => {

const match = atRule.params.match(/^--(\S+)\b/);

if (match == null) throw new Error(`Unexpected at-rule params: "${atRule.params}"`);
if (match == null || match[0] == null) {
throw new Error(`Unexpected at-rule params: "${atRule.params}"`);
}

const customMediaName = match[1];

Expand Down
Expand Up @@ -101,7 +101,7 @@ const rule = (primary, secondaryOptions) => {
return;
}

const duplicateValue = values[indexDuplicate];
const duplicateValue = values[indexDuplicate] || '';

if (ignorePrefixlessSameValues) {
// fails if values of consecutive, unprefixed duplicates are equal
Expand Down
Expand Up @@ -72,23 +72,19 @@ const rule = (primary, secondaryOptions) => {

for (const shorthandProperty of shorthandProperties) {
const prefixedShorthandProperty = prefix + shorthandProperty;
let longhandDeclaration = longhandDeclarations[prefixedShorthandProperty];

if (!longhandDeclarations[prefixedShorthandProperty]) {
longhandDeclarations[prefixedShorthandProperty] = [];
if (!longhandDeclaration) {
longhandDeclaration = longhandDeclarations[prefixedShorthandProperty] = [];
}

longhandDeclarations[prefixedShorthandProperty].push(prop);
longhandDeclaration.push(prop);

const prefixedShorthandData = shorthandData[shorthandProperty].map(
const prefixedShorthandData = (shorthandData[shorthandProperty] || []).map(
(item) => prefix + item,
);

if (
!arrayEqual(
prefixedShorthandData.sort(),
longhandDeclarations[prefixedShorthandProperty].sort(),
)
) {
if (!arrayEqual(prefixedShorthandData.sort(), longhandDeclaration.sort())) {
continue;
}

Expand Down
Expand Up @@ -52,7 +52,7 @@ const rule = (primary) => {
ruleName,
result,
node: decl,
message: messages.rejected(prop, declarations[prefix + longhandProp]),
message: messages.rejected(prop, declarations[prefix + longhandProp] || ''),
});
}
});
Expand Down
4 changes: 3 additions & 1 deletion lib/rules/declaration-property-max-values/index.js
Expand Up @@ -7,7 +7,7 @@ const report = require('../../utils/report');
const ruleMessages = require('../../utils/ruleMessages');
const vendor = require('../../utils/vendor');
const validateOptions = require('../../utils/validateOptions');
const { isNumber } = require('../../utils/validateTypes');
const { isNumber, assertNumber } = require('../../utils/validateTypes');
const validateObjectWithProps = require('../../utils/validateObjectWithProps');

const ruleName = 'declaration-property-max-values';
Expand Down Expand Up @@ -55,6 +55,8 @@ const rule = (primary) => {

const max = primary[propKey];

assertNumber(max);

if (propLength <= max) {
return;
}
Expand Down
15 changes: 11 additions & 4 deletions lib/rules/function-calc-no-unspaced-operator/index.js
Expand Up @@ -8,6 +8,7 @@ const report = require('../../utils/report');
const ruleMessages = require('../../utils/ruleMessages');
const setDeclarationValue = require('../../utils/setDeclarationValue');
const validateOptions = require('../../utils/validateOptions');
const { assert } = require('../../utils/validateTypes');

const ruleName = 'function-calc-no-unspaced-operator';

Expand Down Expand Up @@ -56,8 +57,11 @@ const rule = (primary, _secondaryOptions, context) => {
function checkAroundOperator(nodes, operatorIndex, direction) {
const isBeforeOp = direction === -1;
const currentNode = nodes[operatorIndex + direction];
const operator = nodes[operatorIndex].value;
const operatorSourceIndex = nodes[operatorIndex].sourceIndex;
const node = nodes[operatorIndex];

assert(node);
const operator = node.value;
const operatorSourceIndex = node.sourceIndex;

if (currentNode && !isSingleSpace(currentNode)) {
if (currentNode.type === 'word') {
Expand Down Expand Up @@ -168,6 +172,7 @@ const rule = (primary, _secondaryOptions, context) => {
function checkForOperatorInFirstNode(nodes) {
const firstNode = nodes[0];

assert(firstNode);
const operatorIndex =
(firstNode.type === 'word' || -1) && firstNode.value.search(OPERATOR_REGEX);
const operator = firstNode.value.slice(operatorIndex, operatorIndex + 1);
Expand Down Expand Up @@ -233,6 +238,7 @@ const rule = (primary, _secondaryOptions, context) => {

const lastNode = nodes[nodes.length - 1];

assert(lastNode);
const operatorIndex =
(lastNode.type === 'word' || -1) && lastNode.value.search(OPERATOR_REGEX);

Expand All @@ -248,6 +254,7 @@ const rule = (primary, _secondaryOptions, context) => {

const operator = lastNode.value[operatorIndex];

assert(operator);
complain(
messages.expectedOperatorBeforeSign(operator),
decl,
Expand Down Expand Up @@ -337,11 +344,11 @@ function insertCharAtIndex(str, index, char) {
}

/**
* @param {import('postcss-value-parser').Node} node
* @param {import('postcss-value-parser').Node | undefined} node
* @returns {node is import('postcss-value-parser').SpaceNode & { value: ' ' } }
*/
function isSingleSpace(node) {
return node && node.type === 'space' && node.value === ' ';
return node != null && node.type === 'space' && node.value === ' ';
}

rule.ruleName = ruleName;
Expand Down
Expand Up @@ -66,15 +66,15 @@ const rule = (primary) => {
/^(-webkit-|-moz-|-o-)?linear-gradient$/i,
(expression, expressionIndex) => {
const args = expression.split(',');
const firstArg = args[0].trim();
const firstArg = (args[0] || '').trim();

// If the first arg is not standard, return early
if (!isStandardSyntaxValue(firstArg)) {
return;
}

// If the first character is a number, we can assume the user intends an angle
if (/[\d.]/.test(firstArg[0])) {
if (/[\d.]/.test(firstArg.charAt(0))) {
if (/^[\d.]+(?:deg|grad|rad|turn)$/.test(firstArg)) {
return;
}
Expand All @@ -99,7 +99,7 @@ const rule = (primary) => {

function complain() {
const index = declarationValueIndex(decl) + valueNode.sourceIndex + expressionIndex;
const endIndex = index + args[0].trimEnd().length;
const endIndex = index + (args[0] || '').trimEnd().length;

report({
message: messages.rejected,
Expand Down
9 changes: 7 additions & 2 deletions lib/rules/function-whitespace-after/index.js
Expand Up @@ -62,7 +62,9 @@ const rule = (primary, _secondaryOptions, context) => {
* @param {((index: number) => void) | undefined} fix
*/
function checkClosingParen(source, index, node, nodeIndex, fix) {
const nextChar = source[index];
const nextChar = source.charAt(index);

if (!nextChar) return;

if (primary === 'always') {
// Allow for the next character to be a single empty space,
Expand Down Expand Up @@ -132,7 +134,10 @@ const rule = (primary, _secondaryOptions, context) => {
applyFix = (index) => {
let whitespaceEndIndex = index + 1;

while (whitespaceEndIndex < value.length && isWhitespace(value[whitespaceEndIndex])) {
while (
whitespaceEndIndex < value.length &&
isWhitespace(value.charAt(whitespaceEndIndex))
) {
whitespaceEndIndex++;
}

Expand Down