UNPKG

@atlaskit/eslint-plugin-design-system

Version:

The essential plugin for use with the Atlassian Design System.

179 lines (174 loc) 5.55 kB
import { isNodeOfType } from 'eslint-codemod-utils'; import { getConfig } from '../utils/get-deprecated-config'; import { isDeprecatedImportConfig } from '../utils/is-deprecated-import-config'; import { importNameWithCustomMessageId, pathWithCustomMessageId } from './constants'; import { getDeprecationIconHandler } from './handlers/icon'; export const createChecks = context => { const deprecatedIconHandler = getDeprecationIconHandler(context); const cachedConfig = (_context$options$ => { const config = ((_context$options$ = context.options[0]) === null || _context$options$ === void 0 ? void 0 : _context$options$.deprecatedConfig) || getConfig('imports'); if (!isDeprecatedImportConfig(config)) { throw new Error('Config is invalid for deprecated imports'); } return config; })(); const deprecatedImportSources = new Set(Object.keys(cachedConfig)); const throwErrors = () => { deprecatedIconHandler.throwErrors(); }; const getHandler = importSource => { if (importSource.startsWith('@atlaskit/icon')) { return deprecatedIconHandler; } }; /** * Report a restricted path. * @param {string} importSource path of the import * @param {string} type whether the node is an import or export * @param {node} node representing the restricted path reference * @param {Map<string,TSESTree.Node>} importNames Map of import names that are being imported * @returns {void} * @private */ function checkRestrictedPathAndReport({ importSource, type, node, importNames }) { if (!deprecatedImportSources.has(importSource)) { return; } const restrictedPathMessages = cachedConfig; const config = restrictedPathMessages[importSource]; const handler = getHandler(importSource); if (handler) { if (type === 'import') { handler.createImportError({ node, importSource, config }); } else { handler.createExportError({ node, importSource, config }); } } else { // Default behaviour // The message will only exist if the import is completely banned, // eg a deprecated package if ('message' in config) { context.report({ node, messageId: pathWithCustomMessageId, data: { importSource, customMessage: config.message } }); } // if there are specific named exports that are banned, // iterate through and check if they're being imported if ('importSpecifiers' in config) { var _config$importSpecifi; (_config$importSpecifi = config.importSpecifiers) === null || _config$importSpecifi === void 0 ? void 0 : _config$importSpecifi.forEach(restrictedImport => { if (importNames.has(restrictedImport.importName)) { context.report({ node: importNames.get(restrictedImport.importName), messageId: importNameWithCustomMessageId, data: { importName: restrictedImport.importName, importSource: importSource, customMessage: restrictedImport.message } }); } }); } } } /** * Checks a node to see if any problems should be reported. * @param {ASTNode} node The node to check. * @returns {void} * @private */ const checkImportNode = node => { const importSource = node.source.value.trim(); const importNames = new Map(); if ('specifiers' in node) { for (const specifier of node.specifiers) { let name; if (specifier.type === 'ImportDefaultSpecifier') { name = 'default'; } else if (specifier.type === 'ImportNamespaceSpecifier') { name = '*'; } else if (specifier.type === 'ImportSpecifier') { name = specifier.imported.type === 'Identifier' ? specifier.imported.name : ''; } if (name) { importNames.set(name, specifier); } } } checkRestrictedPathAndReport({ importSource, type: 'import', node, importNames }); }; /** * Checks a node to see if any problems should be reported. * @param {ASTNode} node The node to check. * @returns {void} * @private */ const checkExportNode = node => { if (!node.source || !node.source.value) { return; } const importSource = node.source.value.trim(); const importNames = new Map(); if ('specifiers' in node) { for (const specifier of node.specifiers) { let name; if (specifier.local) { name = specifier.local.type === 'Identifier' ? specifier.local.name : ''; } if (name) { importNames.set(name, specifier); } } } checkRestrictedPathAndReport({ importSource, type: 'export', node, importNames }); }; /** * Create a mapping of JSX elements by their name so they can be processed later. * @param node The JSX node found by ESLint */ const checkJSXElement = node => { if (!('openingElement' in node) || !isNodeOfType(node.openingElement.name, 'JSXIdentifier')) { return; } deprecatedIconHandler.checkJSXElement(node); }; const checkIdentifier = node => { deprecatedIconHandler.checkIdentifier(node); }; return { checkImportNode, checkExportNode, checkJSXElement, checkIdentifier, throwErrors }; };