@atlaskit/eslint-plugin-design-system 10.18.0 → 10.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +1 -1
- package/dist/cjs/rules/no-legacy-icons/checks.js +29 -137
- package/dist/cjs/rules/no-legacy-icons/helpers.js +247 -16
- package/dist/cjs/rules/no-legacy-icons/index.js +1 -0
- package/dist/es2019/rules/no-legacy-icons/checks.js +30 -108
- package/dist/es2019/rules/no-legacy-icons/helpers.js +200 -15
- package/dist/es2019/rules/no-legacy-icons/index.js +1 -0
- package/dist/esm/rules/no-legacy-icons/checks.js +30 -137
- package/dist/esm/rules/no-legacy-icons/helpers.js +246 -15
- package/dist/esm/rules/no-legacy-icons/index.js +1 -0
- package/dist/types/rules/no-legacy-icons/helpers.d.ts +31 -60
- package/dist/types-ts4.5/rules/no-legacy-icons/helpers.d.ts +31 -60
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
|
-
import { addToListOfRanges, canAutoMigrateNewIconBasedOnSize, canMigrateColor,
|
|
2
|
+
import { addToListOfRanges, canAutoMigrateNewIconBasedOnSize, canMigrateColor, createAutoMigrationError, createCantFindSuitableReplacementError, createCantMigrateColorError, createCantMigrateFunctionUnknownError, createCantMigrateIdentifierError, createCantMigrateIdentifierMapOrArrayError, createCantMigrateReExportError, createCantMigrateSizeUnknown, createCantMigrateSpreadPropsError, createGuidance, createHelpers, getMigrationMapObject, getUpcomingIcons, isInsideLegacyButton, isInsideNewButton, isSize, locToString, throwAutoErrors, throwManualErrors } from './helpers';
|
|
3
3
|
export const createChecks = context => {
|
|
4
4
|
//create global variables to be shared by the checks
|
|
5
5
|
const {
|
|
@@ -13,7 +13,6 @@ export const createChecks = context => {
|
|
|
13
13
|
const errorsManual = {};
|
|
14
14
|
const errorsAuto = {};
|
|
15
15
|
let guidance = {};
|
|
16
|
-
let autoIconJSXElementOccurrenceCount = 0;
|
|
17
16
|
|
|
18
17
|
// Extract parameters
|
|
19
18
|
const shouldErrorForManualMigration = getConfigFlag('shouldErrorForManualMigration', true);
|
|
@@ -38,7 +37,8 @@ export const createChecks = context => {
|
|
|
38
37
|
legacyIconImports[spec.local.name] = {
|
|
39
38
|
packageName: moduleSource,
|
|
40
39
|
exported: false,
|
|
41
|
-
importNode: node
|
|
40
|
+
importNode: node,
|
|
41
|
+
importSpecifier: spec.local.name
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
}
|
|
@@ -51,7 +51,8 @@ export const createChecks = context => {
|
|
|
51
51
|
migrationIconImports[spec.local.name] = {
|
|
52
52
|
packageName: moduleSource,
|
|
53
53
|
exported: false,
|
|
54
|
-
importNode: node
|
|
54
|
+
importNode: node,
|
|
55
|
+
importSpecifier: spec.local.name
|
|
55
56
|
};
|
|
56
57
|
}
|
|
57
58
|
});
|
|
@@ -90,7 +91,9 @@ export const createChecks = context => {
|
|
|
90
91
|
if (Object.keys(legacyIconImports).includes(decl.init.name)) {
|
|
91
92
|
legacyIconImports[decl.id.name] = {
|
|
92
93
|
packageName: legacyIconImports[decl.init.name].packageName,
|
|
93
|
-
exported: legacyIconImports[decl.init.name].exported || isExported
|
|
94
|
+
exported: legacyIconImports[decl.init.name].exported || isExported,
|
|
95
|
+
importNode: legacyIconImports[decl.init.name].importNode,
|
|
96
|
+
importSpecifier: legacyIconImports[decl.init.name].importSpecifier
|
|
94
97
|
};
|
|
95
98
|
} else if (newButtonImports.has(decl.init.name)) {
|
|
96
99
|
newButtonImports.add(decl.id.name);
|
|
@@ -129,7 +132,7 @@ export const createChecks = context => {
|
|
|
129
132
|
* @param node The named export node found by ESLint
|
|
130
133
|
*/
|
|
131
134
|
const checkExportNamedVariables = node => {
|
|
132
|
-
// export {default as AddIcon} from '@atlaskit/icon/glyph/add';
|
|
135
|
+
// Case: export {default as AddIcon} from '@atlaskit/icon/glyph/add';
|
|
133
136
|
if (node.source && isNodeOfType(node.source, 'Literal') && Object.keys(node.source).includes('value')) {
|
|
134
137
|
const moduleSource = node.source.value;
|
|
135
138
|
if (typeof moduleSource === 'string' && ['@atlaskit/icon/glyph/', '@atlaskit/icon-object/glyph/'].find(val => moduleSource.startsWith(val)) && node.specifiers.length) {
|
|
@@ -143,7 +146,7 @@ export const createChecks = context => {
|
|
|
143
146
|
}
|
|
144
147
|
}
|
|
145
148
|
} else if (node.declaration && isNodeOfType(node.declaration, 'VariableDeclaration')) {
|
|
146
|
-
// export const Icon = AddIcon;
|
|
149
|
+
// Case: export const Icon = AddIcon;
|
|
147
150
|
for (const decl of node.declaration.declarations) {
|
|
148
151
|
if (isNodeOfType(decl, 'VariableDeclarator') && Object.keys(decl).includes('init') && decl.init && isNodeOfType(decl.init, 'Identifier') && Object.keys(legacyIconImports).includes(decl.init.name)) {
|
|
149
152
|
createCantMigrateReExportError(node, legacyIconImports[decl.init.name].packageName, decl.init.name, errorsManual);
|
|
@@ -166,7 +169,9 @@ export const createChecks = context => {
|
|
|
166
169
|
//update legacy imports to be exported
|
|
167
170
|
legacyIconImports[spec.local.name] = {
|
|
168
171
|
packageName: legacyIconImports[spec.local.name].packageName,
|
|
169
|
-
exported: true
|
|
172
|
+
exported: true,
|
|
173
|
+
importNode: legacyIconImports[spec.local.name].importNode,
|
|
174
|
+
importSpecifier: legacyIconImports[spec.local.name].importSpecifier
|
|
170
175
|
};
|
|
171
176
|
createCantMigrateReExportError(spec, legacyIconImports[spec.local.name].packageName, spec.exported.name, errorsManual);
|
|
172
177
|
addToListOfRanges(spec, errorRanges);
|
|
@@ -399,7 +404,6 @@ export const createChecks = context => {
|
|
|
399
404
|
const sizeProp = node.openingElement.attributes.find(attribute => attribute.type === 'JSXAttribute' && (attribute.name.name === 'size' || attribute.name.name === 'LEGACY_size'));
|
|
400
405
|
const shouldAddSpaciousSpacing = (sizeProp && sizeProp.type === 'JSXAttribute' && ((_sizeProp$value2 = sizeProp.value) === null || _sizeProp$value2 === void 0 ? void 0 : _sizeProp$value2.type) === 'Literal' && sizeProp.value.value === 'medium' || !sizeProp) && !insideNewButton && !insideLegacyButton;
|
|
401
406
|
if (!hasManualMigration && (newIcon || upcomingIcon) && isNewIconMigratable) {
|
|
402
|
-
autoIconJSXElementOccurrenceCount++;
|
|
403
407
|
createAutoMigrationError({
|
|
404
408
|
node,
|
|
405
409
|
importSource: legacyIconImports[name].packageName,
|
|
@@ -444,108 +448,26 @@ export const createChecks = context => {
|
|
|
444
448
|
* Throws the relevant errors in the correct order based on configs.
|
|
445
449
|
*/
|
|
446
450
|
const throwErrors = () => {
|
|
451
|
+
// Throw manual errors
|
|
447
452
|
if (shouldErrorForManualMigration) {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
456
|
-
if (isInRange && errorList.errors.length - 1 > 0 || !isInRange && errorList.errors.length > 0) {
|
|
457
|
-
const guidanceMessage = Object.keys(guidance).includes(key) ? guidance[key] : '';
|
|
458
|
-
context.report({
|
|
459
|
-
node,
|
|
460
|
-
messageId: 'noLegacyIconsManualMigration',
|
|
461
|
-
data: {
|
|
462
|
-
iconName: errorList.iconName,
|
|
463
|
-
importSource: errorList.importSource,
|
|
464
|
-
guidance: isQuietMode ? guidanceMessage : `${guidanceMessage}For more information see the below errors.\n`
|
|
465
|
-
}
|
|
466
|
-
});
|
|
467
|
-
if (!isQuietMode) {
|
|
468
|
-
for (const error of errorList.errors) {
|
|
469
|
-
if ('messageId' in error && (error.messageId !== 'cantMigrateIdentifier' || error.messageId === 'cantMigrateIdentifier' && !isInRange)) {
|
|
470
|
-
context.report(error);
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
}
|
|
453
|
+
throwManualErrors({
|
|
454
|
+
errorsManual,
|
|
455
|
+
errorRanges,
|
|
456
|
+
guidance,
|
|
457
|
+
context,
|
|
458
|
+
isQuietMode
|
|
459
|
+
});
|
|
477
460
|
}
|
|
478
461
|
if (shouldErrorForAutoMigration) {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
}
|
|
489
|
-
const node = 'node' in error ? error.node : null;
|
|
490
|
-
if (node) {
|
|
491
|
-
const guidanceMessage = Object.keys(guidance).includes(key) ? guidance[key] : '';
|
|
492
|
-
if (Object.keys(error).includes('data') && error.data) {
|
|
493
|
-
error.data.guidance = guidanceMessage;
|
|
494
|
-
}
|
|
495
|
-
context.report({
|
|
496
|
-
...error,
|
|
497
|
-
fix: fixer => {
|
|
498
|
-
var _legacyIconImports$er, _migrationIconImports;
|
|
499
|
-
// don't migration if the new icon is not available
|
|
500
|
-
if (!error.data || shouldUseMigrationPath && !checkIfNewIconExist(error)) {
|
|
501
|
-
return [];
|
|
502
|
-
}
|
|
503
|
-
const fixArguments = {
|
|
504
|
-
metadata: error.data,
|
|
505
|
-
legacyImportNode: (_legacyIconImports$er = legacyIconImports[error.data.iconName]) === null || _legacyIconImports$er === void 0 ? void 0 : _legacyIconImports$er.importNode,
|
|
506
|
-
migrationImportNode: (_migrationIconImports = migrationIconImports[error.data.iconName]) === null || _migrationIconImports === void 0 ? void 0 : _migrationIconImports.importNode,
|
|
507
|
-
shouldUseMigrationPath
|
|
508
|
-
};
|
|
509
|
-
const propsFixes = createPropFixes({
|
|
510
|
-
...fixArguments,
|
|
511
|
-
node,
|
|
512
|
-
fixer
|
|
513
|
-
});
|
|
514
|
-
let importFixes = [];
|
|
515
|
-
// Otherwise if there are multiple occurrences of the icon, import path will be handled after the prop fix
|
|
516
|
-
if (autoIconJSXElementOccurrenceCount <= 1) {
|
|
517
|
-
importFixes = createImportFix({
|
|
518
|
-
...fixArguments,
|
|
519
|
-
fixer
|
|
520
|
-
});
|
|
521
|
-
}
|
|
522
|
-
return [...propsFixes, ...importFixes];
|
|
523
|
-
}
|
|
524
|
-
});
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
// Update import path at the end if there are multiple occurrences of the icon
|
|
529
|
-
if (autoIconJSXElementOccurrenceCount > 1) {
|
|
530
|
-
for (const [_, error] of Object.entries(errorsAuto)) {
|
|
531
|
-
context.report({
|
|
532
|
-
...error,
|
|
533
|
-
fix: fixer => {
|
|
534
|
-
var _legacyIconImports$er2, _migrationIconImports2;
|
|
535
|
-
if (!error.data || shouldUseMigrationPath && !checkIfNewIconExist(error)) {
|
|
536
|
-
return [];
|
|
537
|
-
}
|
|
538
|
-
return createImportFix({
|
|
539
|
-
metadata: error.data,
|
|
540
|
-
fixer,
|
|
541
|
-
legacyImportNode: (_legacyIconImports$er2 = legacyIconImports[error.data.iconName]) === null || _legacyIconImports$er2 === void 0 ? void 0 : _legacyIconImports$er2.importNode,
|
|
542
|
-
migrationImportNode: (_migrationIconImports2 = migrationIconImports[error.data.iconName]) === null || _migrationIconImports2 === void 0 ? void 0 : _migrationIconImports2.importNode,
|
|
543
|
-
shouldUseMigrationPath
|
|
544
|
-
});
|
|
545
|
-
}
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
}
|
|
462
|
+
throwAutoErrors({
|
|
463
|
+
errorsManual,
|
|
464
|
+
errorsAuto,
|
|
465
|
+
legacyIconImports,
|
|
466
|
+
guidance,
|
|
467
|
+
migrationIconImports,
|
|
468
|
+
shouldUseMigrationPath,
|
|
469
|
+
context
|
|
470
|
+
});
|
|
549
471
|
}
|
|
550
472
|
};
|
|
551
473
|
return {
|
|
@@ -54,7 +54,7 @@ export const canAutoMigrateNewIconBasedOnSize = guidance => {
|
|
|
54
54
|
* @param iconPackage string
|
|
55
55
|
* @returns object of new icon name and import path
|
|
56
56
|
*/
|
|
57
|
-
|
|
57
|
+
const getNewIconNameAndImportPath = (iconPackage, shouldUseMigrationPath) => {
|
|
58
58
|
const legacyIconName = getIconKey(iconPackage);
|
|
59
59
|
const migrationMapObject = getMigrationMapObject(iconPackage);
|
|
60
60
|
if (!migrationMapObject || !migrationMapObject.newIcon) {
|
|
@@ -284,7 +284,7 @@ const pushManualError = (key, errors, myError, importSource, iconName) => {
|
|
|
284
284
|
};
|
|
285
285
|
}
|
|
286
286
|
};
|
|
287
|
-
|
|
287
|
+
const getLiteralStringValue = value => {
|
|
288
288
|
if (!value) {
|
|
289
289
|
return;
|
|
290
290
|
}
|
|
@@ -354,7 +354,7 @@ export const addToListOfRanges = (node, sortedListOfRangesForErrors) => {
|
|
|
354
354
|
});
|
|
355
355
|
}
|
|
356
356
|
};
|
|
357
|
-
|
|
357
|
+
const isInRangeList = (node, sortedListOfRangesForErrors) => {
|
|
358
358
|
const {
|
|
359
359
|
range
|
|
360
360
|
} = node;
|
|
@@ -395,6 +395,18 @@ export const isInsideLegacyButton = (node, legacyButtonImports) => {
|
|
|
395
395
|
return insideLegacyButton;
|
|
396
396
|
};
|
|
397
397
|
const findProp = (attributes, propName) => attributes.find(attr => attr.type === 'JSXAttribute' && attr.name.name === propName);
|
|
398
|
+
const getNewIconNameForRenaming = (isInManualArray, importSource, importSpecifier) => {
|
|
399
|
+
let newIconName;
|
|
400
|
+
if (isInManualArray) {
|
|
401
|
+
newIconName = getNewIconNameAndImportPath(importSource).iconName;
|
|
402
|
+
const keyToName = newIconName ? newIconName[0].toUpperCase() + newIconName.slice(1) + 'Icon' : undefined;
|
|
403
|
+
newIconName = keyToName;
|
|
404
|
+
if (newIconName === undefined || importSpecifier === keyToName) {
|
|
405
|
+
newIconName = `${keyToName}New`;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return newIconName;
|
|
409
|
+
};
|
|
398
410
|
|
|
399
411
|
/**
|
|
400
412
|
*
|
|
@@ -406,25 +418,25 @@ const findProp = (attributes, propName) => attributes.find(attr => attr.type ===
|
|
|
406
418
|
* @param migrationImportNode The migration import declaration node to replace, only present if shouldUseMigrationPath is false
|
|
407
419
|
* @returns A list of fixers to migrate the icon
|
|
408
420
|
*/
|
|
409
|
-
|
|
421
|
+
const createImportFix = ({
|
|
410
422
|
fixer,
|
|
411
423
|
legacyImportNode,
|
|
412
424
|
metadata,
|
|
413
425
|
shouldUseMigrationPath,
|
|
414
|
-
migrationImportNode
|
|
426
|
+
migrationImportNode,
|
|
427
|
+
newIconName
|
|
415
428
|
}) => {
|
|
416
429
|
const fixes = [];
|
|
417
430
|
const {
|
|
418
431
|
importSource
|
|
419
432
|
} = metadata;
|
|
420
433
|
const importPath = migrationImportNode ? importSource.replace('/migration', '').split('--')[0] : getNewIconNameAndImportPath(importSource, shouldUseMigrationPath).importPath;
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
if (
|
|
424
|
-
fixes.push(fixer.replaceText(legacyImportNode.source, `'${literal(importPath)}'`));
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
fixes.push(fixer.replaceText(migrationImportNode.source, `'${literal(importPath)}'`));
|
|
434
|
+
const useMigrationPath = legacyImportNode && importPath;
|
|
435
|
+
const useFinalPath = migrationImportNode && !shouldUseMigrationPath && importPath;
|
|
436
|
+
if (useMigrationPath) {
|
|
437
|
+
fixes.push(newIconName ? fixer.insertTextBefore(legacyImportNode, `import ${newIconName} from '${importPath}';\n`) : fixer.replaceText(legacyImportNode.source, `'${literal(importPath)}'`));
|
|
438
|
+
} else if (useFinalPath) {
|
|
439
|
+
fixes.push(newIconName ? fixer.insertTextBefore(migrationImportNode, `import ${newIconName} from '${importPath}';\n`) : fixer.replaceText(migrationImportNode.source, `'${literal(importPath)}'`));
|
|
428
440
|
}
|
|
429
441
|
return fixes;
|
|
430
442
|
};
|
|
@@ -439,13 +451,14 @@ export const createImportFix = ({
|
|
|
439
451
|
* @param migrationImportNode The migration import declaration node to replace, only present if shouldUseMigrationPath is false
|
|
440
452
|
* @returns A list of fixers to migrate the icon
|
|
441
453
|
*/
|
|
442
|
-
|
|
454
|
+
const createPropFixes = ({
|
|
443
455
|
node,
|
|
444
456
|
fixer,
|
|
445
457
|
legacyImportNode,
|
|
446
458
|
metadata,
|
|
447
459
|
shouldUseMigrationPath,
|
|
448
|
-
migrationImportNode
|
|
460
|
+
migrationImportNode,
|
|
461
|
+
newIconName
|
|
449
462
|
}) => {
|
|
450
463
|
const fixes = [];
|
|
451
464
|
const {
|
|
@@ -462,6 +475,9 @@ export const createPropFixes = ({
|
|
|
462
475
|
const {
|
|
463
476
|
openingElement
|
|
464
477
|
} = node;
|
|
478
|
+
if (newIconName) {
|
|
479
|
+
fixes.push(fixer.replaceText(openingElement.name, newIconName));
|
|
480
|
+
}
|
|
465
481
|
const {
|
|
466
482
|
attributes
|
|
467
483
|
} = openingElement;
|
|
@@ -520,6 +536,8 @@ export const createPropFixes = ({
|
|
|
520
536
|
}
|
|
521
537
|
});
|
|
522
538
|
}
|
|
539
|
+
} else if (node.type === 'Identifier' && newIconName) {
|
|
540
|
+
fixes.push(fixer.replaceText(node, newIconName));
|
|
523
541
|
}
|
|
524
542
|
return fixes;
|
|
525
543
|
};
|
|
@@ -527,7 +545,7 @@ export const createPropFixes = ({
|
|
|
527
545
|
/**
|
|
528
546
|
* Check if the new icon exists in the migration map
|
|
529
547
|
*/
|
|
530
|
-
|
|
548
|
+
const checkIfNewIconExist = error => {
|
|
531
549
|
var _error$data;
|
|
532
550
|
if (!((_error$data = error.data) !== null && _error$data !== void 0 && _error$data.importSource)) {
|
|
533
551
|
return false;
|
|
@@ -537,4 +555,171 @@ export const checkIfNewIconExist = error => {
|
|
|
537
555
|
newIcon
|
|
538
556
|
} = baseMigrationMap[iconKey] || {};
|
|
539
557
|
return Boolean(newIcon);
|
|
558
|
+
};
|
|
559
|
+
export const throwManualErrors = ({
|
|
560
|
+
errorsManual,
|
|
561
|
+
errorRanges,
|
|
562
|
+
guidance,
|
|
563
|
+
context,
|
|
564
|
+
isQuietMode
|
|
565
|
+
}) => {
|
|
566
|
+
for (const [key, errorList] of Object.entries(errorsManual)) {
|
|
567
|
+
const node = 'node' in errorList.errors[0] ? errorList.errors[0].node : null;
|
|
568
|
+
if (!node) {
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
const cantMigrateIdentifierError = errorList.errors.find(x => 'messageId' in x && x.messageId === 'cantMigrateIdentifier');
|
|
572
|
+
let isInRange = false;
|
|
573
|
+
if (cantMigrateIdentifierError && isInRangeList(node, errorRanges)) {
|
|
574
|
+
isInRange = true;
|
|
575
|
+
}
|
|
576
|
+
if (isInRange && errorList.errors.length - 1 > 0 || !isInRange && errorList.errors.length > 0) {
|
|
577
|
+
const guidanceMessage = Object.keys(guidance).includes(key) ? guidance[key] : '';
|
|
578
|
+
context.report({
|
|
579
|
+
node,
|
|
580
|
+
messageId: 'noLegacyIconsManualMigration',
|
|
581
|
+
data: {
|
|
582
|
+
iconName: errorList.iconName,
|
|
583
|
+
importSource: errorList.importSource,
|
|
584
|
+
guidance: isQuietMode ? guidanceMessage : `${guidanceMessage}For more information see the below errors.\n`
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
if (!isQuietMode) {
|
|
588
|
+
for (const error of errorList.errors) {
|
|
589
|
+
if ('messageId' in error && (error.messageId !== 'cantMigrateIdentifier' || error.messageId === 'cantMigrateIdentifier' && !isInRange)) {
|
|
590
|
+
context.report(error);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
// Loops through automatic errors and them after adding the required suggestion/fix
|
|
599
|
+
export const throwAutoErrors = ({
|
|
600
|
+
errorsManual,
|
|
601
|
+
errorsAuto,
|
|
602
|
+
legacyIconImports,
|
|
603
|
+
guidance,
|
|
604
|
+
migrationIconImports,
|
|
605
|
+
shouldUseMigrationPath,
|
|
606
|
+
context
|
|
607
|
+
}) => {
|
|
608
|
+
// Set of all the import sources that have manual errors (required later to check if a source has both manual and auto
|
|
609
|
+
// errors in one file making it impossible to just remove the legacy import)
|
|
610
|
+
const allManualErrorSources = Object.entries(errorsManual).reduce((result, option) => {
|
|
611
|
+
const [key, errorInfo] = option;
|
|
612
|
+
if (!errorsAuto.hasOwnProperty(key)) {
|
|
613
|
+
result.add(errorInfo.importSource);
|
|
614
|
+
}
|
|
615
|
+
return result;
|
|
616
|
+
}, new Set());
|
|
617
|
+
//group errors by import source and remove any unwanted errors
|
|
618
|
+
const groupedErrorList = Object.entries(errorsAuto).reduce((result, option) => {
|
|
619
|
+
const [key, error] = option;
|
|
620
|
+
//return early if no data
|
|
621
|
+
if (!error.data) {
|
|
622
|
+
return result;
|
|
623
|
+
}
|
|
624
|
+
if (Object.keys(errorsManual).includes(key)) {
|
|
625
|
+
const cantMigrateIdentifierError = errorsManual[key].errors.find(x => 'messageId' in x && x.messageId === 'cantMigrateIdentifier');
|
|
626
|
+
// If cantMigrateIdentifier is the only manual error found we still want to throw the auto error
|
|
627
|
+
if (!(cantMigrateIdentifierError && errorsManual[key].errors.length === 1)) {
|
|
628
|
+
return result;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
const importSource = error.data.importSource;
|
|
632
|
+
if (!result.hasOwnProperty(importSource)) {
|
|
633
|
+
result[importSource] = [];
|
|
634
|
+
}
|
|
635
|
+
result[importSource].push({
|
|
636
|
+
key,
|
|
637
|
+
...error
|
|
638
|
+
});
|
|
639
|
+
return result;
|
|
640
|
+
}, {});
|
|
641
|
+
for (const [importSource, errorList] of Object.entries(groupedErrorList)) {
|
|
642
|
+
const autoFixers = [];
|
|
643
|
+
// appliedErrorsForImport will contain all the errors FOR A SINGLE IMPORT and will be merged into errorListForReport
|
|
644
|
+
const appliedErrorsForImport = [];
|
|
645
|
+
// Loop over auto errors for a single import source
|
|
646
|
+
for (const [_, error] of errorList.entries()) {
|
|
647
|
+
var _legacyIconImports$er, _legacyIconImports$er2, _migrationIconImports;
|
|
648
|
+
const {
|
|
649
|
+
key
|
|
650
|
+
} = error;
|
|
651
|
+
const node = 'node' in error ? error.node : null;
|
|
652
|
+
// Check if there is a manual error for the same import source somewhere else in the same file
|
|
653
|
+
// If that is the case we'll need to provide a suggestion instead of auto-fixing as the suggestion will
|
|
654
|
+
// add another import without removing the old import and this needs to be validated
|
|
655
|
+
const isInManualArray = allManualErrorSources.has(importSource);
|
|
656
|
+
// New icon name for renaming if the icon is in the manual array
|
|
657
|
+
const newIconName = getNewIconNameForRenaming(isInManualArray, importSource, errorList[0].data ? (_legacyIconImports$er = legacyIconImports[errorList[0].data.iconName]) === null || _legacyIconImports$er === void 0 ? void 0 : _legacyIconImports$er.importSpecifier : undefined);
|
|
658
|
+
if (!node) {
|
|
659
|
+
continue;
|
|
660
|
+
}
|
|
661
|
+
const guidanceMessage = guidance.hasOwnProperty(key) ? guidance[key] : '';
|
|
662
|
+
if (Object.keys(error).includes('data') && error.data) {
|
|
663
|
+
error.data.guidance = guidanceMessage;
|
|
664
|
+
}
|
|
665
|
+
const fixArguments = error.data ? {
|
|
666
|
+
metadata: error.data,
|
|
667
|
+
legacyImportNode: (_legacyIconImports$er2 = legacyIconImports[error.data.iconName]) === null || _legacyIconImports$er2 === void 0 ? void 0 : _legacyIconImports$er2.importNode,
|
|
668
|
+
migrationImportNode: (_migrationIconImports = migrationIconImports[error.data.iconName]) === null || _migrationIconImports === void 0 ? void 0 : _migrationIconImports.importNode,
|
|
669
|
+
shouldUseMigrationPath,
|
|
670
|
+
newIconName: isInManualArray ? newIconName : undefined
|
|
671
|
+
} : null;
|
|
672
|
+
if (!error.data || shouldUseMigrationPath && !checkIfNewIconExist(error) || !fixArguments) {
|
|
673
|
+
continue;
|
|
674
|
+
}
|
|
675
|
+
if (isInManualArray) {
|
|
676
|
+
// provide suggestion if there is a manual error for the same import source and thus the legacy import can't be removed
|
|
677
|
+
error.suggest = [{
|
|
678
|
+
desc: 'Rename icon import, import from the new package, and update props.',
|
|
679
|
+
fix: fixer => {
|
|
680
|
+
return [...createPropFixes({
|
|
681
|
+
...fixArguments,
|
|
682
|
+
node,
|
|
683
|
+
fixer
|
|
684
|
+
}), ...createImportFix({
|
|
685
|
+
...fixArguments,
|
|
686
|
+
fixer
|
|
687
|
+
})];
|
|
688
|
+
}
|
|
689
|
+
}];
|
|
690
|
+
} else {
|
|
691
|
+
// Update Guidance message for auto-fixing
|
|
692
|
+
if (error.data) {
|
|
693
|
+
error.data.guidance = error.data.guidance + `\nTo automatically fix this icon, run the auto-fixer attached to the first use of ${importSource} in this file - either manually, or by saving this file.`;
|
|
694
|
+
}
|
|
695
|
+
// There should only be 1 import fix for each import source and thus only add this at the start of the list
|
|
696
|
+
if (autoFixers.length === 0) {
|
|
697
|
+
autoFixers.push(fixer => createImportFix({
|
|
698
|
+
...fixArguments,
|
|
699
|
+
fixer
|
|
700
|
+
}));
|
|
701
|
+
}
|
|
702
|
+
// Push the prop fix regardless
|
|
703
|
+
autoFixers.push(fixer => createPropFixes({
|
|
704
|
+
...fixArguments,
|
|
705
|
+
node,
|
|
706
|
+
fixer
|
|
707
|
+
}));
|
|
708
|
+
}
|
|
709
|
+
// Add the error to the appliedErrorsForImport, ready to be thrown later
|
|
710
|
+
appliedErrorsForImport.push(error);
|
|
711
|
+
}
|
|
712
|
+
// We want to have only 1 fix for each import source that is not in the manual array
|
|
713
|
+
// NOTE: If in the manual array, suggestions have been applied above and autoFixers.length will be 0 which will mean no fix is added
|
|
714
|
+
if (autoFixers.length > 0) {
|
|
715
|
+
// Add the fix to only one of the errors in the list of errors from the current import source
|
|
716
|
+
appliedErrorsForImport[0].fix = fixer => {
|
|
717
|
+
return autoFixers.flatMap(autoFixer => autoFixer(fixer));
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
// throw errors
|
|
721
|
+
appliedErrorsForImport.forEach(error => {
|
|
722
|
+
context.report(error);
|
|
723
|
+
});
|
|
724
|
+
}
|
|
540
725
|
};
|