eslint-plugin-uilib
Advanced tools
Comparing version 2.1.7 to 2.2.0
@@ -1,2 +0,2 @@ | ||
const {handleError} = require('../utils'); | ||
const {handleError, addToImports} = require('../utils'); | ||
@@ -53,9 +53,19 @@ const RULE_ID = 'no-direct-import'; | ||
create(context) { | ||
function reportDirectImport(node, rule) { | ||
function getErrorMessage(rule, type) { | ||
const {origin, destination, applyAutofix, customMessage} = rule; | ||
const autofixMessage = applyAutofix ? ' (autofix available)' : ''; | ||
return customMessage || `Do not ${type} directly from '${origin}'. Please use '${destination}'${autofixMessage}.`; | ||
} | ||
function checkAndReport(node, type, importedModuleNameToReplace) { | ||
const imports = []; | ||
addToImports(node, imports); | ||
const modules = new Set(collectModulesFromImports(imports)); | ||
const rule = getRules().find((rule) => modules.has(rule.origin)); | ||
if (!rule) { | ||
return; | ||
} | ||
try { | ||
const origin = rule.origin; | ||
const destination = rule.destination; | ||
const applyAutofix = rule.applyAutofix; | ||
const autofixMessage = applyAutofix ? ' (autofix available)' : ''; | ||
const message = `Do not import directly from '${origin}'. Please use '${destination}'${autofixMessage}.`; | ||
const {applyAutofix, destination} = rule; | ||
const message = getErrorMessage(rule, type); | ||
context.report({ | ||
@@ -66,3 +76,3 @@ node, | ||
if (node && applyAutofix && destination) { | ||
return fixer.replaceText(node.source, `'${destination}'`); | ||
return fixer.replaceText(importedModuleNameToReplace, `'${destination}'`); | ||
} | ||
@@ -81,15 +91,23 @@ } | ||
function checkImportDeclaration(node) { | ||
const source = node.source.value; | ||
const rule = getRules().find((rule) => rule.origin === source); | ||
if (rule) { | ||
reportDirectImport(node, rule); | ||
} | ||
function collectModulesFromImports(imports) { | ||
const collection = []; | ||
imports.forEach((moduleImports) => { | ||
collection.push(...Object.keys(moduleImports)); | ||
}); | ||
return collection; | ||
} | ||
function getModuleNameFromRequire(node) { | ||
return (node.init.object ? node.init.object.arguments : node.init.arguments)[0] | ||
} | ||
function getModuleNameFromImport(node) { | ||
return node.source; | ||
} | ||
return { | ||
ImportDeclaration: checkImportDeclaration | ||
ImportDeclaration: (node) => checkAndReport(node, 'import', getModuleNameFromImport(node)), | ||
VariableDeclarator: (node) => checkAndReport(node, 'require', getModuleNameFromRequire(node)), | ||
}; | ||
} | ||
}; |
{ | ||
"name": "eslint-plugin-uilib", | ||
"version": "2.1.7", | ||
"version": "2.2.0", | ||
"description": "uilib set of eslint rules", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
[ | ||
{ | ||
"component": "Avatar", | ||
"source": "module-with-deprecations", | ||
"props": [ | ||
{ | ||
"prop": "url", | ||
"message": "Please use the 'source' prop instead." | ||
} | ||
] | ||
}, | ||
{ | ||
"component": "Thumbnail", | ||
"source": "module-with-deprecations", | ||
"props": [ | ||
{ | ||
"prop": "url", | ||
"message": "Please use the 'uri' prop instead.", | ||
"fix": {"propName": "uri"} | ||
} | ||
] | ||
}, | ||
{ | ||
"component": "Button", | ||
"source": "module-with-deprecations", | ||
"props": [ | ||
{ | ||
"prop": "text", | ||
"message": "Please use the 'label' prop instead.", | ||
"fix": {"propName": "label"} | ||
} | ||
] | ||
}, | ||
{ | ||
"component": "List", | ||
"source": "another-module-with-deprecations", | ||
"props": [ | ||
{ | ||
"prop": "text", | ||
"message": "Please use the 'label' prop instead.", | ||
"fix": {"propName": "label"} | ||
} | ||
] | ||
}, | ||
{ | ||
"component": "List.Item", | ||
"source": "module-with-deprecations", | ||
"props": [ | ||
{ | ||
"prop": "text", | ||
"message": "Please use the 'label' prop instead.", | ||
"fix": {"propName": "label"} | ||
} | ||
] | ||
}, | ||
{ | ||
"component": "Text", | ||
"source": "module-with-deprecations", | ||
"props": [ | ||
{ | ||
"prop": "t", | ||
"message": "Please use the 'title' prop instead.", | ||
"fix": {"propName": "title"} | ||
}, | ||
{ | ||
"prop": "s", | ||
"message": "Please use the 'subtitle' prop instead.", | ||
"fix": {"propName": "subtitle"} | ||
} | ||
] | ||
}, | ||
{ | ||
"component": "Picker", | ||
"source": "module-with-deprecations", | ||
"props": [ | ||
{ | ||
"prop": "migrate", | ||
"message": "Please make sure to pass the 'migrate' prop.", | ||
"isRequired": true | ||
} | ||
] | ||
} | ||
] | ||
{ | ||
"component": "Keyboard.KeyboardAccessoryView", | ||
"source": "module-with-deprecations", | ||
"props": [ | ||
{ | ||
"prop": "iOSScrollBehavior", | ||
"message": "'iOSScrollBehavior' prop is deprecated. Please use 'scrollBehavior' prop instead and pass it 'Keyboard.KeyboardAccessoryView.scrollBehaviors' ('Keyboard.KeyboardAccessoryView.iosScrollBehaviors' enum is deprecated)." | ||
} | ||
] | ||
}, | ||
{ | ||
"component": "Avatar", | ||
"source": "module-with-deprecations", | ||
"props": [ | ||
{ | ||
"prop": "url", | ||
"message": "Please use the 'source' prop instead." | ||
} | ||
] | ||
}, | ||
{ | ||
"component": "Thumbnail", | ||
"source": "module-with-deprecations", | ||
"props": [ | ||
{ | ||
"prop": "url", | ||
"message": "Please use the 'uri' prop instead.", | ||
"fix": {"propName": "uri"} | ||
} | ||
] | ||
}, | ||
{ | ||
"component": "Button", | ||
"source": "module-with-deprecations", | ||
"props": [ | ||
{ | ||
"prop": "text", | ||
"message": "Please use the 'label' prop instead.", | ||
"fix": {"propName": "label"} | ||
} | ||
] | ||
}, | ||
{ | ||
"component": "List", | ||
"source": "another-module-with-deprecations", | ||
"props": [ | ||
{ | ||
"prop": "text", | ||
"message": "Please use the 'label' prop instead.", | ||
"fix": {"propName": "label"} | ||
} | ||
] | ||
}, | ||
{ | ||
"component": "List.Item", | ||
"source": "module-with-deprecations", | ||
"props": [ | ||
{ | ||
"prop": "text", | ||
"message": "Please use the 'label' prop instead.", | ||
"fix": {"propName": "label"} | ||
} | ||
] | ||
}, | ||
{ | ||
"component": "Text", | ||
"source": "module-with-deprecations", | ||
"props": [ | ||
{ | ||
"prop": "t", | ||
"message": "Please use the 'title' prop instead.", | ||
"fix": {"propName": "title"} | ||
}, | ||
{ | ||
"prop": "s", | ||
"message": "Please use the 'subtitle' prop instead.", | ||
"fix": {"propName": "subtitle"} | ||
} | ||
] | ||
}, | ||
{ | ||
"component": "Picker", | ||
"source": "module-with-deprecations", | ||
"props": [ | ||
{ | ||
"prop": "migrate", | ||
"message": "Please make sure to pass the 'migrate' prop.", | ||
"isRequired": true | ||
} | ||
] | ||
} | ||
] |
@@ -16,3 +16,7 @@ const RuleTester = require('eslint').RuleTester; | ||
const invalidExample = | ||
"import {Avatar} from 'module-with-deprecations'; const test = <Avatar url={'some_uri_string'}/>"; | ||
`import {Avatar} from 'module-with-deprecations'; const test = <Avatar url={'some_uri_string'}/>`; | ||
const validKeyboardExample = | ||
`import {Keyboard} from 'module-with-deprecations'; const test = <Keyboard.KeyboardAccessoryView scrollBehavior={Keyboard.KeyboardAccessoryView.scrollBehaviors.NONE}/>`; | ||
const invalidKeyboardExample = | ||
`import {Keyboard} from 'module-with-deprecations'; const test = <Keyboard.KeyboardAccessoryView iOSScrollBehavior={Keyboard.KeyboardAccessoryView.iosScrollBehaviors.NONE}/>`; | ||
@@ -23,2 +27,6 @@ ruleTester.run('component-prop-deprecation', rule, { | ||
options: ruleOptions, | ||
code: validKeyboardExample | ||
}, | ||
{ | ||
options: ruleOptions, | ||
code: `const Avatar = require('another-module').Avatar; | ||
@@ -122,4 +130,13 @@ const test = <Avatar source={{uri: 'some_uri_string'}}/>;` | ||
options: ruleOptions, | ||
code: invalidKeyboardExample, | ||
errors: [{ | ||
message: `The 'Keyboard.KeyboardAccessoryView' component's prop 'iOSScrollBehavior' is deprecated. 'iOSScrollBehavior' prop is deprecated. Please use 'scrollBehavior' prop instead and pass it 'Keyboard.KeyboardAccessoryView.scrollBehaviors' ('Keyboard.KeyboardAccessoryView.iosScrollBehaviors' enum is deprecated).` | ||
}] | ||
}, | ||
{ | ||
options: ruleOptions, | ||
code: invalidExample, | ||
errors: [{message: "The 'Avatar' component's prop 'url' is deprecated. Please use the 'source' prop instead."}] | ||
errors: [{ | ||
message: `The 'Avatar' component's prop 'url' is deprecated. Please use the 'source' prop instead.` | ||
}] | ||
}, | ||
@@ -132,3 +149,3 @@ { | ||
message: | ||
"The 'Avatar' component's prop 'url' is deprecated. Please use the 'source' prop instead. Please fix this issue by 10/11/18!" // eslint-disable-line | ||
`The 'Avatar' component's prop 'url' is deprecated. Please use the 'source' prop instead. Please fix this issue by 10/11/18!` | ||
} | ||
@@ -144,3 +161,3 @@ ] | ||
message: | ||
"The 'Thumbnail' component's prop 'url' is deprecated. Please use the 'uri' prop instead. Please fix this issue by 10/11/18!" // eslint-disable-line | ||
`The 'Thumbnail' component's prop 'url' is deprecated. Please use the 'uri' prop instead. Please fix this issue by 10/11/18!` | ||
} | ||
@@ -153,3 +170,3 @@ ] | ||
output: 'import {Button} from \'module-with-deprecations\'; <Button label="my button"/>', | ||
errors: [{message: "The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead."}] | ||
errors: [{message: `The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead.`}] | ||
}, | ||
@@ -160,3 +177,3 @@ { | ||
output: 'import {List} from \'another-module-with-deprecations\'; <List label="my list"/>', | ||
errors: [{message: "The 'List' component's prop 'text' is deprecated. Please use the 'label' prop instead."}] | ||
errors: [{message: `The 'List' component's prop 'text' is deprecated. Please use the 'label' prop instead.`}] | ||
}, | ||
@@ -171,3 +188,3 @@ { | ||
<Button {...props} value="value"/>`, | ||
errors: [{message: "The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead."}] | ||
errors: [{message: `The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead.`}] | ||
}, | ||
@@ -182,3 +199,3 @@ { | ||
<B {...props} value="value"/>`, | ||
errors: [{message: "The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead."}] | ||
errors: [{message: `The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead.`}] | ||
}, | ||
@@ -195,3 +212,3 @@ { | ||
<Button {...props} value="value"/>`, | ||
errors: [{message: "The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead."}] | ||
errors: [{message: `The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead.`}] | ||
}, | ||
@@ -206,3 +223,3 @@ { | ||
<module.Button {...props} value="value"/>`, | ||
errors: [{message: "The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead."}] | ||
errors: [{message: `The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead.`}] | ||
}, | ||
@@ -217,3 +234,3 @@ { | ||
<Button {...props} value="value"/>`, | ||
errors: [{message: "The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead."}] | ||
errors: [{message: `The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead.`}] | ||
}, | ||
@@ -228,3 +245,3 @@ { | ||
const test = <Button {...props} value="value"/>;`, | ||
errors: [{message: "The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead."}] | ||
errors: [{message: `The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead.`}] | ||
}, | ||
@@ -243,3 +260,3 @@ { | ||
const test2 = <TextField>Bla</TextField>;`, | ||
errors: [{message: "The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead."}] | ||
errors: [{message: `The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead.`}] | ||
}, | ||
@@ -269,15 +286,15 @@ { | ||
message: | ||
"The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead. Please fix this issue by 10/11/18!" | ||
`The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead. Please fix this issue by 10/11/18!` | ||
}, | ||
{ | ||
message: | ||
"The 'Avatar' component's prop 'url' is deprecated. Please use the 'source' prop instead. Please fix this issue by 10/11/18!" | ||
`The 'Avatar' component's prop 'url' is deprecated. Please use the 'source' prop instead. Please fix this issue by 10/11/18!` | ||
}, | ||
{ | ||
message: | ||
"The 'Thumbnail' component's prop 'url' is deprecated. Please use the 'uri' prop instead. Please fix this issue by 10/11/18!" | ||
`The 'Thumbnail' component's prop 'url' is deprecated. Please use the 'uri' prop instead. Please fix this issue by 10/11/18!` | ||
}, | ||
{ | ||
message: | ||
"The 'List' component's prop 'text' is deprecated. Please use the 'label' prop instead. Please fix this issue by 10/11/18!" | ||
`The 'List' component's prop 'text' is deprecated. Please use the 'label' prop instead. Please fix this issue by 10/11/18!` | ||
} | ||
@@ -311,15 +328,15 @@ ] | ||
message: | ||
"The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead. Please fix this issue by 10/11/18!" | ||
`The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead. Please fix this issue by 10/11/18!` | ||
}, | ||
{ | ||
message: | ||
"The 'Avatar' component's prop 'url' is deprecated. Please use the 'source' prop instead. Please fix this issue by 10/11/18!" | ||
`The 'Avatar' component's prop 'url' is deprecated. Please use the 'source' prop instead. Please fix this issue by 10/11/18!` | ||
}, | ||
{ | ||
message: | ||
"The 'Thumbnail' component's prop 'url' is deprecated. Please use the 'uri' prop instead. Please fix this issue by 10/11/18!" | ||
`The 'Thumbnail' component's prop 'url' is deprecated. Please use the 'uri' prop instead. Please fix this issue by 10/11/18!` | ||
}, | ||
{ | ||
message: | ||
"The 'List' component's prop 'text' is deprecated. Please use the 'label' prop instead. Please fix this issue by 10/11/18!" | ||
`The 'List' component's prop 'text' is deprecated. Please use the 'label' prop instead. Please fix this issue by 10/11/18!` | ||
} | ||
@@ -353,15 +370,15 @@ ] | ||
message: | ||
"The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead. Please fix this issue by 10/11/18!" | ||
`The 'Button' component's prop 'text' is deprecated. Please use the 'label' prop instead. Please fix this issue by 10/11/18!` | ||
}, | ||
{ | ||
message: | ||
"The 'Avatar' component's prop 'url' is deprecated. Please use the 'source' prop instead. Please fix this issue by 10/11/18!" | ||
`The 'Avatar' component's prop 'url' is deprecated. Please use the 'source' prop instead. Please fix this issue by 10/11/18!` | ||
}, | ||
{ | ||
message: | ||
"The 'Thumbnail' component's prop 'url' is deprecated. Please use the 'uri' prop instead. Please fix this issue by 10/11/18!" | ||
`The 'Thumbnail' component's prop 'url' is deprecated. Please use the 'uri' prop instead. Please fix this issue by 10/11/18!` | ||
}, | ||
{ | ||
message: | ||
"The 'List' component's prop 'text' is deprecated. Please use the 'label' prop instead. Please fix this issue by 10/11/18!" | ||
`The 'List' component's prop 'text' is deprecated. Please use the 'label' prop instead. Please fix this issue by 10/11/18!` | ||
} | ||
@@ -378,3 +395,3 @@ ] | ||
const test = <List.Item {...props} value="value"/>;`, | ||
errors: [{message: "The 'List.Item' component's prop 'text' is deprecated. Please use the 'label' prop instead."}] | ||
errors: [{message: `The 'List.Item' component's prop 'text' is deprecated. Please use the 'label' prop instead.`}] | ||
}, | ||
@@ -389,3 +406,3 @@ { | ||
<module.List.Item {...props} value="value"/>`, | ||
errors: [{message: "The 'List.Item' component's prop 'text' is deprecated. Please use the 'label' prop instead."}] | ||
errors: [{message: `The 'List.Item' component's prop 'text' is deprecated. Please use the 'label' prop instead.`}] | ||
}, | ||
@@ -397,4 +414,4 @@ { | ||
errors: [ | ||
{message: "The 'Text' component's prop 't' is deprecated. Please use the 'title' prop instead."}, | ||
{message: "The 'Text' component's prop 's' is deprecated. Please use the 'subtitle' prop instead."} | ||
{message: `The 'Text' component's prop 't' is deprecated. Please use the 'title' prop instead.`}, | ||
{message: `The 'Text' component's prop 's' is deprecated. Please use the 'subtitle' prop instead.`} | ||
] | ||
@@ -406,3 +423,3 @@ }, | ||
errors: [ | ||
{message: "The 'Picker' component's prop 'migrate' is required. Please make sure to pass the 'migrate' prop."} | ||
{message: `The 'Picker' component's prop 'migrate' is required. Please make sure to pass the 'migrate' prop.`} | ||
] | ||
@@ -409,0 +426,0 @@ } |
@@ -17,2 +17,7 @@ const RuleTester = require('eslint').RuleTester; | ||
customErrorMessage = 'This is a custom message'; | ||
const ruleWithCustomMessage = [ | ||
{origin: 'some-module', destination: 'another-module', applyAutofix: true, customMessage: customErrorMessage} | ||
] | ||
RuleTester.setDefaultConfig({ | ||
@@ -27,8 +32,15 @@ parser: 'babel-eslint', | ||
const validExample2 = `import {Component} from 'new-module';`; | ||
const validExample3 = `const {Component} = require('another-module');`; | ||
const validExample4 = `const test = require('new-module').test;`; | ||
const invalidExample1 = `import {Component} from 'some-module';`; | ||
const invalidExample2 = `import {Component} from 'old-module';`; | ||
const invalidExample3 = `const {Component} = require('some-module');`; | ||
const invalidExample4 = `const {Component} = require('old-module');`; | ||
const invalidExample5 = `const test = require(\'some-module\').test;`; | ||
const error1 = `Do not import directly from 'some-module'. Please use 'another-module' (autofix available).`; | ||
const error2 = `Do not import directly from 'old-module'. Please use 'new-module' (autofix available).`; | ||
const requireError1 = `Do not require directly from 'some-module'. Please use 'another-module' (autofix available).`; | ||
const requireError2 = `Do not require directly from 'old-module'. Please use 'new-module' (autofix available).`; | ||
@@ -39,5 +51,9 @@ ruleTester.run('no-direct-import', rule, { | ||
options: ruleOptions, | ||
code: validExample1 | ||
code: validExample1 | ||
}, | ||
{ | ||
options: ruleOptions, | ||
code: validExample3 | ||
}, | ||
{ | ||
options: ruleOptionsArray, | ||
@@ -48,3 +64,11 @@ code: validExample1 | ||
options: ruleOptionsArray, | ||
code: validExample2 | ||
code: validExample2 | ||
}, | ||
{ | ||
options: ruleOptionsArray, | ||
code: validExample3 | ||
}, | ||
{ | ||
options: ruleOptionsArray, | ||
code: validExample4 | ||
} | ||
@@ -76,4 +100,42 @@ ], | ||
] | ||
}, | ||
{ | ||
options: ruleOptions, | ||
code: invalidExample3, | ||
output: `const {Component} = require('another-module');`, | ||
errors: [ | ||
{message: requireError1} | ||
] | ||
}, | ||
{ | ||
options: ruleOptionsArray, | ||
code: invalidExample4, | ||
output: `const {Component} = require('new-module');`, | ||
errors: [ | ||
{message: requireError2} | ||
] | ||
}, | ||
{ | ||
options: ruleWithCustomMessage, | ||
code: invalidExample1, | ||
errors: [ | ||
{message: customErrorMessage} | ||
] | ||
}, | ||
{ | ||
options: ruleWithCustomMessage, | ||
code: invalidExample3, | ||
errors: [ | ||
{message: customErrorMessage} | ||
] | ||
}, | ||
{ | ||
options: ruleOptions, | ||
code: invalidExample5, | ||
output: 'const test = require(\'another-module\').test;', | ||
errors: [ | ||
{message: requireError1} | ||
] | ||
} | ||
] | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
167790
4757