@stedi/eslint-plugin-stedi-aws-rules
Advanced tools
Comparing version 1.1.2 to 1.2.0
@@ -0,1 +1,8 @@ | ||
# [1.2.0](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/compare/v1.1.2...v1.2.0) (2020-10-22) | ||
### Features | ||
* extend instrumented-aws-clients rule to support more cases ([#16](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/issues/16)) ([0599729](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/commit/0599729ddb0b7bd6c46d7a262432a64af4b4e24a)) | ||
## [1.1.2](https://github.com/Stedi/eslint-plugin-stedi-aws-rules/compare/v1.1.1...v1.1.2) (2020-10-09) | ||
@@ -2,0 +9,0 @@ |
@@ -19,2 +19,6 @@ /** | ||
}, | ||
messages: { | ||
clientNotInstrumented: "AWS client not instrumented: {{client}}", | ||
}, | ||
fixable: null, // or "code" or "whitespace" | ||
@@ -28,31 +32,71 @@ schema: [ | ||
const code = context.getSourceCode() | ||
var awsVars | ||
var safe = false | ||
let awsClients | ||
let awsClientInstances | ||
/** | ||
* Reports an AST node as a rule violation. | ||
* @param {ASTNode} node The node to report. | ||
* @param {ASTNode|undefined} data The service client instance to report, defaults to `node` | ||
* @returns {void} | ||
*/ | ||
function report(node, data) { | ||
data = data || node | ||
context.report({ | ||
node, | ||
messageId: "clientNotInstrumented", | ||
data: { client: code.getText(data) }, | ||
}) | ||
} | ||
/** | ||
* Returns a variable for the current scope if exists. | ||
* @param {string} name The node to report. | ||
* @returns {Variable|undefined} | ||
*/ | ||
function varInScope(name) { | ||
return context.getScope().set.get(name) | ||
} | ||
return { | ||
Program: () => { | ||
awsVars = [] | ||
awsClients = new Set() | ||
awsClientInstances = new Map() | ||
}, | ||
ImportDeclaration: (node) => { | ||
if (node.source.value.startsWith("aws-sdk/clients/")) { | ||
awsVars.push(node.specifiers[0].local.name) | ||
node.specifiers.map((o) => awsClients.add(o.local.name)) | ||
} | ||
}, | ||
"CallExpression[callee.property.name='captureAWSClient'][arguments.length=1]": () => { | ||
safe = true | ||
"VariableDeclarator:has(NewExpression)": (node) => { | ||
const name = node.init.callee.name | ||
if (name && awsClients.has(name)) { | ||
const scopeVar = varInScope(node.id.name) | ||
awsClientInstances.set(scopeVar, node) | ||
} | ||
}, | ||
"CallExpression[callee.property.name='captureAWSClient'][arguments.length=1]:exit": () => { | ||
safe = false | ||
"Program:exit": () => { | ||
awsClientInstances.forEach((node) => report(node)) | ||
}, | ||
"NewExpression:has(Identifier)": (node) => { | ||
const name = node.callee.name | ||
if (name && awsVars.includes(name) && !safe) { | ||
context.report({ | ||
node, | ||
message: `AWS client not instrumented: ${code.getText(node)}`, | ||
}) | ||
CallExpression: (node) => { | ||
const scopeVar = varInScope(node.callee.object.name) | ||
if (scopeVar && awsClientInstances.has(scopeVar)) { | ||
report(node, awsClientInstances.get(scopeVar)) | ||
awsClientInstances.delete(scopeVar) | ||
} | ||
}, | ||
"CallExpression[callee.property.name='captureAWSClient'][arguments.length=1][arguments.0.type=Identifier]": ( | ||
node, | ||
) => { | ||
const scopeVar = varInScope(node.arguments[0].name) | ||
if (scopeVar && awsClientInstances.has(scopeVar)) { | ||
awsClientInstances.delete(scopeVar) | ||
} | ||
}, | ||
} | ||
}, | ||
} |
@@ -14,2 +14,3 @@ /** | ||
type: "problem", | ||
docs: { | ||
@@ -20,2 +21,7 @@ description: "Don't import AWS directly, use clients instead.", | ||
}, | ||
messages: { | ||
directImport: "'{{modules}}' imported directly. Use clients instead.", | ||
}, | ||
fixable: null, // or "code" or "whitespace" | ||
@@ -28,22 +34,10 @@ schema: [ | ||
create: function (context) { | ||
// variables should be defined here | ||
//---------------------------------------------------------------------- | ||
// Helpers | ||
//---------------------------------------------------------------------- | ||
// any helper functions should go here or else delete this section | ||
//---------------------------------------------------------------------- | ||
// Public | ||
//---------------------------------------------------------------------- | ||
return { | ||
ImportDeclaration: (node) => { | ||
const source = context.getSourceCode() | ||
const importLine = source.getText(node) | ||
if (importLine.match('"aws-sdk"')) { | ||
if (node.source.value == "aws-sdk") { | ||
const modules = node.specifiers.map((o) => o.local.name).join(", ") | ||
context.report({ | ||
node, | ||
message: importLine, | ||
messageId: "directImport", | ||
data: { modules }, | ||
}) | ||
@@ -50,0 +44,0 @@ } |
{ | ||
"name": "@stedi/eslint-plugin-stedi-aws-rules", | ||
"version": "1.1.2", | ||
"version": "1.2.0", | ||
"description": "AWS coding best practices by Stedi", | ||
@@ -19,3 +19,3 @@ "keywords": [ | ||
"scripts": { | ||
"test": "echo 'to be added using mocha tests --recursive'", | ||
"test": "npx mocha tests --recursive", | ||
"lint": "npx eslint .", | ||
@@ -35,3 +35,3 @@ "release": "semantic-release" | ||
"@semantic-release/git": "^9.0.0", | ||
"eslint": "^7.1.0", | ||
"eslint": "^7.11.0", | ||
"husky": "^4.3.0", | ||
@@ -38,0 +38,0 @@ "mocha": "^8.1.3", |
12859
204