Skip to content

Eslint/version 2 fixes #1261

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

Merged
merged 4 commits into from
Apr 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions eslint-rules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@ module.exports = {
'no-hard-coded-color': require('./lib/rules/no-hard-coded-color'),
'no-direct-import': require('./lib/rules/no-direct-import'),
'component-deprecation': require('./lib/rules/component-deprecation'),
'component-prop-deprecation': require('./lib/rules/component-prop-deprecation'),
'assets-deprecation': require('./lib/rules/assets-deprecation'),
'typography-deprecation': require('./lib/rules/typography-deprecation'),
'function-deprecation': require('./lib/rules/function-deprecation'),
'prop-value-shape-deprecation': require('./lib/rules/prop-value-shape-deprecation'),
// for duplicate rules usage
'component-deprecation_warn': require('./lib/rules/component-deprecation'),
'component-prop-deprecation_warn': require('./lib/rules/component-prop-deprecation'),
'assets-deprecation_warn': require('./lib/rules/assets-deprecation'),
'typography-deprecation_warn': require('./lib/rules/typography-deprecation'),
'function-deprecation_warn': require('./lib/rules/function-deprecation'),
'prop-value-shape-deprecation_warn': require('./lib/rules/prop-value-shape-deprecation'),
'component-deprecation_error': require('./lib/rules/component-deprecation'),
'component-prop-deprecation_error': require('./lib/rules/component-prop-deprecation'),
'assets-deprecation_error': require('./lib/rules/assets-deprecation'),
'typography-deprecation_error': require('./lib/rules/typography-deprecation'),
'function-deprecation_error': require('./lib/rules/function-deprecation'),
Expand Down
45 changes: 38 additions & 7 deletions eslint-rules/lib/rules/component-deprecation.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const _ = require('lodash');
const {addToImports, organizeDeprecations, getComponentLocalName, getComponentName} = require('../utils');
const {addToImports, organizeDeprecations, getComponentLocalName, getPossibleDeprecations} = require('../utils');

const MAP_SCHEMA = {
type: 'object',
Expand Down Expand Up @@ -43,10 +43,27 @@ module.exports = {
const organizedDeprecations = organizeDeprecations(deprecations);

const imports = [];
const parents = [];

function getParent(localName) {
const foundParents = parents.filter(parent => Object.keys(parent)[0] === localName);
return !_.isEmpty(foundParents) ? foundParents[0][localName] : undefined;
}

function isParent(foundDeprecation, localName) {
if (foundDeprecation.parent) {
const parent = getParent(localName);
if (foundDeprecation.parent === parent) {
return true;
}
}

return false;
}

function importDeprecationCheck(node) {
const previousImports = _.cloneDeep(imports);
addToImports(node, imports);
addToImports(node, imports, parents);
const addedImports = _.differenceWith(imports, previousImports, _.isEqual);
addedImports.forEach(currentImport => {
const source = Object.keys(currentImport)[0];
Expand All @@ -60,11 +77,20 @@ module.exports = {

if (foundDeprecations.length > 0) {
foundDeprecations.forEach(foundDeprecation => {
const localName = Object.keys(components).find(key => components[key] === foundDeprecation.component);
if (isParent(foundDeprecation, localName)) {
return;
}

let fixNode;
if (node.type === 'ImportDeclaration') {
fixNode = node.specifiers.filter(
const foundSpecifiers = node.specifiers.filter(
specifier => _.get(specifier, 'imported.name') === foundDeprecation.component
)[0].imported;
);

if (foundSpecifiers.length > 0) {
fixNode = foundSpecifiers[0].imported;
}
} else if (node.type === 'VariableDeclarator') {
const properties = _.get(node, 'id.properties');
if (properties) {
Expand All @@ -88,13 +114,18 @@ module.exports = {
const deprecationSource = organizedDeprecations[source];
if (deprecationSource) {
// There are deprecations from this source
const componentName = getComponentName(componentLocalName, imports);
const foundDeprecations = deprecationSource.filter(
currentDeprecationSource => currentDeprecationSource.component === componentName
const foundDeprecations = getPossibleDeprecations(
componentLocalName,
imports,
currentImport,
deprecationSource
);

if (foundDeprecations.length > 0) {
const foundDeprecation = foundDeprecations[0];
if (isParent(foundDeprecation, componentLocalName)) {
return;
}

// This is a little hacky, is there a better way?
if (componentLocalName.includes(foundDeprecation.component)) {
Expand Down
9 changes: 7 additions & 2 deletions eslint-rules/lib/rules/component-prop-deprecation.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const {
addToImports,
getComponentLocalName,
getComponentName,
getPossibleDeprecations,
findValueNodeOfIdentifier
} = require('../utils');

Expand Down Expand Up @@ -116,9 +117,13 @@ module.exports = {
if (deprecationSource) {
// There are deprecations from this source
const componentName = getComponentName(componentLocalName, imports);
const foundPossibleDeprecations = deprecationSource.filter(
currentDeprecationSource => currentDeprecationSource.component === componentName
const foundPossibleDeprecations = getPossibleDeprecations(
componentLocalName,
imports,
currentImport,
deprecationSource
);

foundPossibleDeprecations.forEach(foundPossibleDeprecation => {
const deprecatedPropList = foundPossibleDeprecation.props;
const attributes = node.attributes;
Expand Down
23 changes: 10 additions & 13 deletions eslint-rules/lib/rules/prop-value-shape-deprecation.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
const _ = require('lodash');
const {findValueNodeOfIdentifier, getComponentLocalName, addToImports, getComponentName} = require('../utils');
const {
getPrefix,
getSuffix,
findValueNodeOfIdentifier,
getComponentLocalName,
addToImports,
getComponentName
} = require('../utils');

const MAP_SCHEMA = {
type: 'object',
Expand Down Expand Up @@ -88,8 +95,8 @@ module.exports = {
}

function recursiveDeprecation(attribute, deprecationProp, deprecation, deprecationPath, node) {
const deprecationPrefix = getPathPrefix(deprecationProp);
const deprecationSuffix = getPathSuffix(deprecationProp);
const deprecationPrefix = getPrefix(deprecationProp);
const deprecationSuffix = getSuffix(deprecationProp);
let passedProps;
let attributeName = _.get(attribute, 'name.name') || _.get(attribute, 'key.name');
if (attribute.type === 'JSXSpreadAttribute' || attribute.type === 'ExperimentalSpreadProperty') {
Expand Down Expand Up @@ -132,16 +139,6 @@ module.exports = {
}
}

function getPathPrefix(str) {
const index = str.indexOf('.');
return index === -1 ? str : str.substring(0, index);
}

function getPathSuffix(str) {
const index = str.indexOf('.');
return index === -1 ? undefined : str.substring(index + 1);
}

function checkAttributeProperties(attributeProperties, attributeName, deprecation, node) {
for (let i = 0; i < attributeProperties.length; i++) {
const propertyType = _.get(attributeProperties[i], 'type');
Expand Down
20 changes: 16 additions & 4 deletions eslint-rules/lib/utils/componentUtils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const _ = require('lodash');
const {getPrefix} = require('./generalUtils');

function getComponentLocalName(node) {
if (!node) return;
Expand All @@ -10,17 +10,27 @@ function getComponentLocalName(node) {
return `${start}.${end}`; // <List.Part/> OR <module.List.Part/> etc.
}

function isNamespace(currentImport, componentLocalName) {
const components = Object.values(currentImport)[0];
const prefix = getPrefix(componentLocalName);
if (prefix && components[prefix]) {
return components[prefix].isNamespace;
}

return false;
}

function getComponentName(componentLocalName, imports) {
for (let index = 0; index < imports.length; ++index) {
const currentImport = imports[index];
const components = Object.values(currentImport)[0];
if (components[componentLocalName]) {
return components[componentLocalName];
} else if (componentLocalName.indexOf('.') > 0) {
const indexOfDot = componentLocalName.indexOf('.');
const prefix = componentLocalName.slice(0, indexOfDot);
const prefix = getPrefix(componentLocalName);
if (components[prefix]) {
if (components[prefix].isNamespace) {
const indexOfDot = componentLocalName.indexOf('.');
return componentLocalName.slice(indexOfDot + 1);
} else {
return componentLocalName.replace(prefix, components[prefix]);
Expand All @@ -34,5 +44,7 @@ module.exports = {
// The local name of the component (List as L --> L)
getComponentLocalName,
// Get the real name of the component
getComponentName
getComponentName,
// Is the localName comes from a namespace (module.Component)
isNamespace
};
25 changes: 24 additions & 1 deletion eslint-rules/lib/utils/deprecationsUtils.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
const {getPrefix} = require('./generalUtils');
const {getComponentName, isNamespace} = require('./componentUtils');

function _organizeDeprecationsBySource(deprecations, defaultSource) {
const obj = {};
deprecations.forEach(deprecation => {
Expand All @@ -21,6 +24,10 @@ function organizeDeprecations(deprecations, defaultSource) {
}

function getLocalizedFix(fix, currentImport) {
if (!fix) {
return;
}

let localizedFix = fix;
const indexOfDot = fix.indexOf('.');
if (indexOfDot > 0) {
Expand All @@ -38,7 +45,23 @@ function getLocalizedFix(fix, currentImport) {
return localizedFix;
}

function getPossibleDeprecations(componentLocalName, imports, currentImport, deprecationSource) {
const source = Object.keys(currentImport)[0];
const components = currentImport[source];
const componentName = getComponentName(componentLocalName, imports);
const prefix = getPrefix(componentLocalName);
return deprecationSource.filter(currentDeprecationSource => {
return (
(isNamespace(currentImport, componentLocalName) ||
components[componentLocalName] ||
(prefix && components[prefix])) &&
currentDeprecationSource.component === componentName
);
});
}

module.exports = {
organizeDeprecations,
getLocalizedFix
getLocalizedFix,
getPossibleDeprecations
};
12 changes: 12 additions & 0 deletions eslint-rules/lib/utils/generalUtils.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
function getPrefix(str) {
const indexOfDot = str.indexOf('.');
return indexOfDot === -1 ? str : str.substring(0, indexOfDot);
}

function getSuffix(str) {
const indexOfDot = str.indexOf('.');
return indexOfDot === -1 ? undefined : str.substring(indexOfDot + 1);
}

function findValueNodeOfIdentifier(identifierName, scope) {
const varsInScope = scope.variables;
let valueNode = false;
Expand All @@ -16,5 +26,7 @@ function findValueNodeOfIdentifier(identifierName, scope) {


module.exports = {
getPrefix,
getSuffix,
findValueNodeOfIdentifier
};
21 changes: 15 additions & 6 deletions eslint-rules/lib/utils/importUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,25 +38,34 @@ function _getSourceForComponent(component, imports) {
}
}

function _addToImports_fromSpreading(midSource, newImports, imports) {
function _addToImports_fromSpreading(midSource, newImports, imports, parents) {
if (midSource) {
const source = _getSourceForComponent(midSource, imports);
if (source) {
_addToImports_aggregate(imports, source, newImports);
if (parents) {
_.forEach(Object.keys(newImports), currentImport => {
if (!parents.includes(currentImport)) {
parents.push({[currentImport]: midSource});
}
});
}
}
}
}

function _getImportsFromProperties(node) {
const newImports = {};
_.map(node.id.properties, property => {
newImports[property.value.name] = property.key.name;
if (property.type === 'Property') {
newImports[property.value.name] = property.key.name;
}
});

return newImports;
}

function _addToImports_fromDeclaration(node, imports) {
function _addToImports_fromDeclaration(node, imports, parents) {
let newImports, source, midSource;
if (_.get(node, 'init.type') === 'CallExpression' && _.get(node, 'init.callee.name') === 'require') {
source = node.init.arguments[0].value;
Expand All @@ -81,19 +90,19 @@ function _addToImports_fromDeclaration(node, imports) {
}

_addToImports_aggregate(imports, source, newImports);
_addToImports_fromSpreading(midSource, newImports, imports);
_addToImports_fromSpreading(midSource, newImports, imports, parents);
}

/**
* Aggregate all components, from 'import', 'require' or 'spreading' of other components\imports
* to a single object.
*/
function addToImports(node, imports) {
function addToImports(node, imports, parents) {
if (!node) return;
if (node.type === 'ImportDeclaration') {
_addToImports_fromImport(node, imports); // import
} else if (node.type === 'VariableDeclarator') {
_addToImports_fromDeclaration(node, imports); // require + spreading of sub-components etc
_addToImports_fromDeclaration(node, imports, parents); // require + spreading of sub-components etc
} else {
console.log('Debug', 'addToImports', 'unknown type:', node.type);
}
Expand Down
7 changes: 5 additions & 2 deletions eslint-rules/lib/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
const {findValueNodeOfIdentifier} = require('./generalUtils');
const {organizeDeprecations, getLocalizedFix} = require('./deprecationsUtils');
const {getPrefix, getSuffix, findValueNodeOfIdentifier} = require('./generalUtils');
const {organizeDeprecations, getLocalizedFix, getPossibleDeprecations} = require('./deprecationsUtils');
const {addToImports} = require('./importUtils');
const {getComponentLocalName, getComponentName} = require('./componentUtils');
const {findAndReportHardCodedValues} = require('./noHardCodedUtils');
const {stringify} = require('./debugUtils');

module.exports = {
// General
getPrefix,
getSuffix,
findValueNodeOfIdentifier,
// Deprecations
organizeDeprecations,
getLocalizedFix,
getPossibleDeprecations,
// Imports
addToImports,
// Components
Expand Down
2 changes: 1 addition & 1 deletion eslint-rules/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "eslint-plugin-uilib",
"version": "2.0.0",
"version": "2.0.1",
"description": "uilib set of eslint rules",
"keywords": [
"eslint",
Expand Down
6 changes: 6 additions & 0 deletions eslint-rules/tests/component_deprecation.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,11 @@
"source": "another-module-with-deprecations",
"message": "Please use the 'ListList' component instead.",
"fix": {"componentName": "ListList"}
},
{
"component": "ScrollView",
"parent": "MyComponent",
"source": "module-with-deprecations",
"message": "Please use the 'MyComponent.ScrollView' component instead."
}
]
Loading